
// 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 "ElemMeca.h"
#include <iomanip>
#include "ConstMath.h"
#include "Util.h"
#include "CharUtil.h"
#include "Coordonnee2.h"
#include "Coordonnee3.h"
#include "TypeConsTens.h"
#include "TypeQuelconqueParticulier.h"

        
// retourne la liste de tous les  types de ddl interne actuellement utilisés
// par l'élément (actif ou non), sont exclu de cette liste les ddl des noeuds
// reliés à l'élément (ddl implique grandeur uniquement scalaire !)
// par contre sont inclus les ddl venant de l'élément, qui sont représenté directement aux noeuds
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <Ddl_enum_etendu> ElemMeca::Les_type_de_ddl_internes(bool absolue) const
  { List_io <Ddl_enum_etendu> ret;
    switch (this->Dim_sig_eps())
     { case 1 : 
        {ret.push_back(SIG11); ret.push_back(EPS11);ret.push_back(DEPS11);
         ret.push_back(string("Green-Lagrange11"));ret.push_back(string("Almansi11"));ret.push_back(string("logarithmique11"));
         ret.push_back(string("Cauchy_local11"));
         ret.push_back(string("Almansi_local11"));
         ret.push_back(string("Def_principaleI"));ret.push_back(string("Sigma_principaleI"));
         ret.push_back(string("Vit_principaleI"));ret.push_back(string("Delta_def11"));
         if (dilatation)
          {ret.push_back(string("Almansi_totale11"));ret.push_back(string("Green_Lagrange_totale11"));
           ret.push_back(string("logarithmique_totale11"));};
         break;
         }
       case 2 :
        {ret.push_back(SIG11); ret.push_back(SIG22);
         ret.push_back(SIG12); ret.push_back(EPS11);
         ret.push_back(EPS22); ret.push_back(EPS12);
         ret.push_back(DEPS11);ret.push_back(DEPS22);ret.push_back(DEPS12);
         ret.push_back(string("Green-Lagrange11")); ret.push_back(string("Green-Lagrange22"));
         ret.push_back(string("Green-Lagrange12")); ret.push_back(string("Almansi11"));
         ret.push_back(string("Almansi22")); ret.push_back(string("Almansi12"));
         ret.push_back(string("logarithmique11")); ret.push_back(string("logarithmique22"));
         ret.push_back(string("logarithmique12"));
         ret.push_back(string("Cauchy_local11")); ret.push_back(string("Cauchy_local22"));
         ret.push_back(string("Cauchy_local12"));
         ret.push_back(string("Almansi_local11"));
         ret.push_back(string("Almansi_local22")); ret.push_back(string("Almansi_local12"));
         ret.push_back(string("Def_principaleI"));ret.push_back(string("Def_principaleII"));
         ret.push_back(string("Sigma_principaleI"));ret.push_back(string("Sigma_principaleII"));
         ret.push_back(string("Vit_principaleI"));ret.push_back(string("Vit_principaleII"));
         ret.push_back(string("Delta_def11"));ret.push_back(string("Delta_def22"));ret.push_back(string("Delta_def12"));
         if (dilatation)
          {ret.push_back(string("Almansi_totale11"));ret.push_back(string("Almansi_totale12"));ret.push_back(string("Almansi_totale22"));
           ret.push_back(string("Green_Lagrange_totale11"));ret.push_back(string("Green_Lagrange_totale12"));
           ret.push_back(string("Green_Lagrange_totale22"));
           ret.push_back(string("logarithmique_totale11"));ret.push_back(string("logarithmique_totale12"));
           ret.push_back(string("logarithmique_totale22"));
           };
         break;
         }
       case 3 :
        {ret.push_back(SIG11); ret.push_back(SIG22);
         ret.push_back(SIG33); ret.push_back(SIG12);
         ret.push_back(SIG23); ret.push_back(SIG13);
         ret.push_back(EPS11); ret.push_back(EPS22);
         ret.push_back(EPS33); ret.push_back(EPS12);
         ret.push_back(EPS23); ret.push_back(EPS13);
         ret.push_back(DEPS11); ret.push_back(DEPS22);
         ret.push_back(DEPS33); ret.push_back(DEPS12);
         ret.push_back(DEPS23); ret.push_back(DEPS13);
         ret.push_back(string("Green-Lagrange11")); ret.push_back(string("Green-Lagrange22"));
         ret.push_back(string("Green-Lagrange33")); ret.push_back(string("Green-Lagrange12"));
         ret.push_back(string("Green-Lagrange23")); ret.push_back(string("Green-Lagrange13"));
         ret.push_back(string("Almansi11")); ret.push_back(string("Almansi22"));
         ret.push_back(string("Almansi33")); ret.push_back(string("Almansi12"));
         ret.push_back(string("Almansi23")); ret.push_back(string("Almansi13"));
         ret.push_back(string("logarithmique11")); ret.push_back(string("logarithmique22"));
         ret.push_back(string("logarithmique33")); ret.push_back(string("logarithmique12"));
         ret.push_back(string("logarithmique23")); ret.push_back(string("logarithmique13"));
         ret.push_back(string("Cauchy_local11")); ret.push_back(string("Cauchy_local22"));
         ret.push_back(string("Cauchy_local33")); ret.push_back(string("Cauchy_local12"));
         ret.push_back(string("Cauchy_local23")); ret.push_back(string("Cauchy_local13"));
         ret.push_back(string("Almansi_local11")); ret.push_back(string("Almansi_local22"));
         ret.push_back(string("Almansi_local33")); ret.push_back(string("Almansi_local12"));
         ret.push_back(string("Almansi_local23")); ret.push_back(string("Almansi_local13"));
         ret.push_back(string("Def_principaleI"));ret.push_back(string("Def_principaleII"));
         ret.push_back(string("Def_principaleIII"));
         ret.push_back(string("Sigma_principaleI"));ret.push_back(string("Sigma_principaleII"));
         ret.push_back(string("Sigma_principaleIII"));
         ret.push_back(string("Vit_principaleI"));ret.push_back(string("Vit_principaleII"));ret.push_back(string("Vit_principaleIII"));
         ret.push_back(string("Delta_def11"));ret.push_back(string("Delta_def22"));ret.push_back(string("Delta_def33"));
         ret.push_back(string("Delta_def12"));ret.push_back(string("Delta_def13"));ret.push_back(string("Delta_def23"));
         if (dilatation)
          {ret.push_back(string("Almansi_totale11"));ret.push_back(string("Almansi_totale22"));
           ret.push_back(string("Almansi_totale33"));ret.push_back(string("Almansi_totale12"));
           ret.push_back(string("Almansi_totale23"));ret.push_back(string("Almansi_totale13"));
           ret.push_back(string("Green_Lagrange_totale11"));ret.push_back(string("Green_Lagrange_totale22"));
           ret.push_back(string("Green_Lagrange_totale33"));ret.push_back(string("Green_Lagrange_totale12"));
           ret.push_back(string("Green_Lagrange_totale23"));ret.push_back(string("Green_Lagrange_totale13"));
           ret.push_back(string("logarithmique_totale11"));ret.push_back(string("logarithmique_totale22"));
           ret.push_back(string("logarithmique_totale33"));ret.push_back(string("logarithmique_totale12"));
           ret.push_back(string("logarithmique_totale23"));ret.push_back(string("logarithmique_totale13"));
           };
         ret.push_back(string("Spherique_eps"));ret.push_back(string("Q_eps"));ret.push_back(string("Cos3phi_eps"));
         ret.push_back(string("Spherique_sig"));ret.push_back(string("Q_sig"));ret.push_back(string("Cos3phi_sig"));
         break;
         }
      };
    // cas de mises et tresca  
    ret.push_back(string("contrainte_mises"));
    ret.push_back(string("contrainte_tresca"));
    // déformation duale de mises = sqrt(2/3 * eps_barre:eps_barre) 
    ret.push_back(string("def_duale_mises"));
	   // déformation cumulée: int_0^t sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. ))
	   ret.push_back(string("def_equivalente"));
	   // déformation duale de mises maxi
	   ret.push_back(string("def_duale_mises_maxi"));
	   // vitesse de déformation équivalente
	   ret.push_back(string("vitesse_def_equivalente"));
    // cas de l'existence de l'erreur
    if (sigErreur != NULL)  ret.push_back(ERREUR); 
    // cas de la plasticité classique
    string nom_comport(loiComp->Nom_comport()); 
    if ((strstr(nom_comport.c_str(),"PRANDTL_REUSS")!=NULL))
       ret.push_back(string("def_plastique_cumulee"));
    // cas des énergies locales
    ret.push_back(string("energie_elastique"));
    ret.push_back(string("dissipation_plastique"));
    ret.push_back(string("dissipation_visqueuse"));
    // cas des coordonnées du points
    switch (ParaGlob::Dimension())
      {case 3: ret.push_back(X3);
       case 2: ret.push_back(X2);
       case 1: ret.push_back(X1);
       };
    // cas des pressions éventuellement exercées sur les faces de l'élément
    // modif 15 juin 2019: on sort systématiquement même s'il n'y a pas de pression enregistrée
    // car  la pression peut ne pas être active au début puis ensuite elle devient active
    // et ret sert pour autoriser la sortie par la suite dans les résultats
    // de plus au moment de la sortie, lesChargeExtSurEle sera testé et si c'est non nul ce sera ok
    // si c'est nul, ce sera by passé
//    if (lesChargeExtSurEle != NULL)
//      if (lesChargeExtSurEle->LesPressionsExternes()  != NULL)
        ret.push_back(string("pression_ext"));
    // dans le cas d'un élément 2D, dans un espace 3D, on peut récupérer la normale
    if ((Type_geom_generique(this->Id_geometrie()) == SURFACE )
        && (ParaGlob::Dimension() == 3))
     {ret.push_back(string("N_surf_1"));ret.push_back(string("N_surf_2"));ret.push_back(string("N_surf_3"));
      ret.push_back(string("N_surf_1_t0"));ret.push_back(string("N_surf_2_t0"));ret.push_back(string("N_surf_3_t0"));
     };

    // retour
    return ret;   
   };

// retourne la liste abondée de tous les  données particulières interne actuellement utilisés
// par l'élément (actif ou non), sont exclu de cette liste les données particulières des noeuds
// reliés à l'élément
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_types_particuliers_internes(bool absolue) const
  { List_io <TypeQuelconque> ret;
    // on s'intéresse au information stockée au niveau des points d'intégration
    // 1° récupéreration les grandeurs 
    //    a) cas des grandeurs liées à la déformation
    def->ListeGrandeurs_particulieres(absolue,ret);
    //    b) cas des grandeurs liées à la loi de comportement mécanique 
    loiComp->ListeGrandeurs_particulieres(absolue,ret);
    //    c) cas des grandeurs liées à la loi de comportement thermo-physique 
    if (loiTP != NULL) loiTP->ListeGrandeurs_particulieres(absolue,ret);
    //    d) cas des infos stockés aux points d'intégration, donc par l'élément
    Grandeur_scalaire_double grand_courant; // def d'une grandeur courante
    Tableau <double> tab_1(1);
    Tab_Grandeur_scalaire_double tab_grand_courant(tab_1);
    // def d'un type quelconque représentatif à chaque grandeur
    // a priori ces grandeurs sont défini aux points d'intégration 
    //  $$$ cas de MODULE_COMPRESSIBILITE_TOTAL: intègre toutes les sous_lois par exemple
    TypeQuelconque typQ1(MODULE_COMPRESSIBILITE_TOTAL,SIG11,grand_courant);
    ret.push_back(typQ1);
    //  $$$ cas de MODULE_CISAILLEMENT_TOTAL: intègre toutes les sous_lois par exemple
    TypeQuelconque typQ2(MODULE_CISAILLEMENT_TOTAL,SIG11,grand_courant);
    ret.push_back(typQ2);
    //    e) cas des infos stockés à l'élément
    //  $$$ cas du volume total : 
    TypeQuelconque typQ3(VOLUME_ELEMENT,SIG11,grand_courant);
    ret.push_back(typQ3);
    //  $$$ cas du volume élémentaire associé au pti
    TypeQuelconque typQ34(VOLUME_PTI,SIG11,grand_courant);
    ret.push_back(typQ34);
    // $$$ cas éventuel d'intégrale de volume: INTEG_SUR_VOLUME
    if (integ_vol_typeQuel != NULL)
      {int nb_integration = integ_vol_typeQuel->Taille();
       // on va créer un conteneur particulier pour chaque intégrale
       Tableau <TypeQuelconque> & tab_integ = *integ_vol_typeQuel; //_t; // pour simplifier
       for (int i=1; i<= nb_integration;i++)
          { TypeQuelconque& tbinteg = tab_integ(i); // pour simplifier
            EnuTypeQuelParticulier type_interne =
               tbinteg.Const_Grandeur_pointee()->Type_enumGrandeurParticuliere();
            const TypeQuelconque_enum_etendu& enuTQetendu = tbinteg.EnuTypeQuelconque();
           
           {switch (type_interne)
               {case PARTICULIER_DDL_ETENDU:
                 { Grandeur_Ddl_etendu& gin
                      = *((Grandeur_Ddl_etendu*) tbinteg.Grandeur_pointee()); // pour simplifier
//                   // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
//                   // -- on crée le nom de référence
//                   string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
//                              +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
//                   TypeQuelconque_enum_etendu tqnevez =
//                               TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
//                                      (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
//                   // on enregistre pour la gestion future
//                   (*enu_integ_vol_TQ)(i)=tqnevez;
                   // on crée un exemplaire de conteneur pointé
                   Grandeur_Ddl_etendu  inter(gin);
                   // création du type conteneur
                   TypeQuelconque typQ91((*enu_integ_vol_TQ)(i),tbinteg.Enum(),inter);
                   ret.push_back(typQ91);
                   break;
                 };
                case PARTICULIER_VECTEUR_NOMMER:
                 { Grandeur_Vecteur_Nommer& gin
                      = *((Grandeur_Vecteur_Nommer*) tbinteg.Grandeur_pointee()); // pour simplifier
//                   // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
//                   // -- on crée le nom de référence
//                   string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
//                              +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
//                   TypeQuelconque_enum_etendu tqnevez =
//                               TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
//                                      (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
//                    // on enregistre pour la gestion future
//                   (*enu_integ_vol_TQ)(i)=tqnevez;
////                   //----- debug
////                  cout << "\n ElemMeca::Les_types_particuliers_internes( "
////                       << "\n (*enu_integ_vol_TQ)("<<i<<")=" <<(*enu_integ_vol_TQ)(i);
////                  //----- fin debug
                   // on crée un exemplaire de conteneur pointé
                   Grandeur_Vecteur_Nommer  inter(gin);
                   // création du type conteneur
                   TypeQuelconque typQ91((*enu_integ_vol_TQ)(i),tbinteg.Enum(),inter);
                   ret.push_back(typQ91);
                   break;
                 }
                default: // pas d'intégrale ad hoc dispo ici pour la demande
                  break;
               };
             };
         };
      };
    // $$$ cas éventuel d'intégrale de volume et en temps: INTEG_SUR_VOLUME_ET_TEMPS
    if (integ_vol_t_typeQuel != NULL)
      {int nb_integration = integ_vol_t_typeQuel->Taille();
       // on va créer un conteneur particulier pour chaque intégrale
       Tableau <TypeQuelconque> & tab_integ = *integ_vol_t_typeQuel; //_t; // pour simplifier
       for (int i=1; i<= nb_integration;i++)
          {TypeQuelconque& tbinteg = tab_integ(i); // pour simplifier
            EnuTypeQuelParticulier type_interne =
               tbinteg.Const_Grandeur_pointee()->Type_enumGrandeurParticuliere();
            const TypeQuelconque_enum_etendu& enuTQetendu = tbinteg.EnuTypeQuelconque();
           
           {switch (type_interne)
               {case PARTICULIER_DDL_ETENDU:
                 { Grandeur_Ddl_etendu& gin
                      = *((Grandeur_Ddl_etendu*) tbinteg.Grandeur_pointee()); // pour simplifier
//                   // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
//                   // -- on crée le nom de référence
//                   string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
//                              +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
//                   TypeQuelconque_enum_etendu tqnevez =
//                               TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
//                                      (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
//                   // on enregistre pour la gestion future
//                   (*enu_integ_vol_t_TQ)(i)=tqnevez;
                   // on crée un exemplaire de conteneur pointé
                   Grandeur_Ddl_etendu  inter(gin);
                   // création du type conteneur
                   TypeQuelconque typQ91((*enu_integ_vol_t_TQ)(i),tbinteg.Enum(),inter);
                   ret.push_back(typQ91);
                   break;
                 };
                case PARTICULIER_VECTEUR_NOMMER:
                 { Grandeur_Vecteur_Nommer& gin
                      = *((Grandeur_Vecteur_Nommer*) tbinteg.Grandeur_pointee()); // pour simplifier
//                   // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
//                   // -- on crée le nom de référence
//                   string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
//                              +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
//                   TypeQuelconque_enum_etendu tqnevez =
//                               TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
//                                      (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
//                   // on enregistre pour la gestion future
//                   (*enu_integ_vol_t_TQ)(i)=tqnevez;
                   // on crée un exemplaire de conteneur pointé
                   Grandeur_Vecteur_Nommer  inter(gin);
                   // création du type conteneur
                   TypeQuelconque typQ91((*enu_integ_vol_t_TQ)(i),tbinteg.Enum(),inter);
                   ret.push_back(typQ91);
                   break;
                 }
                default: // pas d'intégrale ad hoc dispo ici pour la demande
                  break;
               };
             };
         };
      };
    //  $$$ cas de l'énergie d'hourglasse :
    TypeQuelconque typQ31(ENERGIE_HOURGLASS,SIG11,grand_courant);
    ret.push_back(typQ31);
    //  $$$ cas de la puissance bulk :
    TypeQuelconque typQ32(PUISSANCE_BULK,SIG11,grand_courant);
    ret.push_back(typQ32);
    //  $$$ cas de l'énergie bulk :
    TypeQuelconque typQ33(ENERGIE_BULK,SIG11,grand_courant);
    ret.push_back(typQ33);
    //  $$$ cas de l'énergie de stabilisation membrane ou biel :
    TypeQuelconque typQ330(ENERGIE_STABMEMB_BIEL,SIG11,grand_courant);
    ret.push_back(typQ330);
    //  $$$ cas de la force de stabilisation membrane ou biel :
    TypeQuelconque typQ331(FORCE_STABMEMB_BIEL,SIG11,grand_courant);
    ret.push_back(typQ331);
    //  $$$ cas du temps cpu relativement à la loi de comp :
    TypeQuelconque typQ35(TEMPS_CPU_LOI_COMP,SIG11,grand_courant);
    ret.push_back(typQ35);
    //  $$$ cas du temps cpu relativement à la métrique :
    TypeQuelconque typQ36(TEMPS_CPU_METRIQUE,SIG11,grand_courant);
    ret.push_back(typQ36);
    
    //  $$$ cas des numéros
    Grandeur_scalaire_entier entier_courant;
    TypeQuelconque typQ37(NUM_ELEMENT,SIG11,entier_courant);
    ret.push_back(typQ37);
    TypeQuelconque typQ38(NUM_MAIL_ELEM,SIG11,entier_courant);
    ret.push_back(typQ38);
    TypeQuelconque typQ39(NUM_PTI,SIG11,entier_courant);
    ret.push_back(typQ39);

    //    f) cas des infos calculable à la demande sur l'élément
    //  $$$ cas des volumes entre les plans et l'élément dans le cas ou l'élément des de surface
    //      et que le calcul est 3D :
    if ((ParaGlob::Dimension()==3)&&(Type_geom_generique(id_geom)==SURFACE))
      {Grandeur_coordonnee grandCoordonnee(3); // un type courant
         TypeQuelconque typQ4(VOL_ELEM_AVEC_PLAN_REF,SIG11,grandCoordonnee);
         ret.push_back(typQ4);
      };

    // liberation des tenseurs intermediaires
    LibereTenseur(); 
    return ret;
    }; 
     
// retourne la liste des grandeurs évoluées interne actuellement utilisés
// par l'élément, c'est-à-dire directement sous forme de vecteur, tenseurs ....		 
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_type_evolues_internes(bool absolue) const 
  { List_io <TypeQuelconque> liTQ;


//    // def de la dimension des tenseurs
//    // il y a deux pb a gérer: 1) le fait que la dimension absolue peut-être différente de la dimension des tenseurs
//    // 2) le fait que l'on veut une sortie dans une base ad hoc ou pas
//    int dim  = lesPtIntegMecaInterne->DimTens();int dim_sortie_tenseur = dim;
//    // dans le cas ou l'on veut une sortie en base absolue, il faut que dim_sortie_tenseur = la dimension de la base absolue
//    int dim_espace = ParaGlob::Dimension();
//    if (absolue)
//      dim_sortie_tenseur = dim_espace;
//    // pour ne faire qu'un seul test ensuite
//    bool prevoir_change_dim_tenseur = false;
//    if ((absolue) && (dim != dim_sortie_tenseur))
//      prevoir_change_dim_tenseur = true;


    // def des grandeurs courantes de type tenseur BB
    int dim_espace = ParaGlob::Dimension();
    int dim_tenseur_sortie = this->Dim_sig_eps(); // la dimension a priori
    if (absolue)
      dim_tenseur_sortie = dim_espace; // si on sort en absolue, on utilise la dim globale
   
   {TenseurBB* tens = NevezTenseurBB(dim_tenseur_sortie); // un tenseur typique
    // maintenant on définit une grandeur typique de type tenseurBB
    Grandeur_TenseurBB gtBB(*tens); 
    // def d'un type quelconque représentatif  pour chaque grandeur
    {TypeQuelconque typQ(DEFORMATION_COURANTE,EPS11,gtBB);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(VITESSE_DEFORMATION_COURANTE,DEPS11,gtBB);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(ALMANSI,EPS11,gtBB);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(GREEN_LAGRANGE,EPS11,gtBB);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(LOGARITHMIQUE,EPS11,gtBB);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(DELTA_DEF,EPS11,gtBB);liTQ.push_back(typQ);};
    if (dilatation)
      {{TypeQuelconque typQ(ALMANSI_TOTAL,EPS11,gtBB);liTQ.push_back(typQ);};
       {TypeQuelconque typQ(GREEN_LAGRANGE_TOTAL,EPS11,gtBB);liTQ.push_back(typQ);};
       {TypeQuelconque typQ(LOGARITHMIQUE_TOTALE,EPS11,gtBB);liTQ.push_back(typQ);};
      };
    delete tens; // car on n'en a plus besoin
   };
    // def des grandeurs courantes de type tenseur HH
   {TenseurHH* tens = NevezTenseurHH(dim_tenseur_sortie); // un tenseur typique
    // maintenant on définit une grandeur typique de type tenseurHH
    Grandeur_TenseurHH gtHH(*tens); 
    // def d'un type quelconque représentatif  pour chaque grandeur
    TypeQuelconque typQ(CONTRAINTE_COURANTE,SIG11,gtHH);liTQ.push_back(typQ);
    delete tens; // car on n'en a plus besoin
   };
    // def des grandeurs courantes de type coordonnee
   {Coordonnee coor(dim_tenseur_sortie); // un type coordonnee typique
    // maintenant on définit une grandeur typique de type Grandeur_coordonnee
    Grandeur_coordonnee gt(coor); 
    // def d'un type quelconque représentatif  pour chaque grandeur
    {TypeQuelconque typQ(DEF_PRINCIPALES,EPS11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(SIGMA_PRINCIPALES,SIG11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(VIT_PRINCIPALES,DEPS11,gt);liTQ.push_back(typQ);};
    // pour la position il s'agit de la position du point d'intégration
    {TypeQuelconque typQ(POSITION_GEOMETRIQUE,SIG11,gt);liTQ.push_back(typQ);};
   }
   
   {Coordonnee coor(dim_espace); // un type coordonnee typique
    // maintenant on définit une grandeur typique de type Grandeur_coordonnee
    Grandeur_coordonnee gt(coor);
// *** 21 avril 2020: on change la position d'expression: du noeuds au pti
//     donc on passe de X1 à SIG11 , mais il s'agit d'un pti spécifique de surface ou de ligne ...
    // le chargement de type pression, sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_PRESSION,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force volumique sous forme d'un vecteur charge, exprimée aux pti volume
    {TypeQuelconque typQ(VECT_FORCE_VOLUM,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force de direction fixe sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_DIR_FIXE,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force suiveuse sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_SURF_SUIV,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force hydrodynamique sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_HYDRODYNA_Fn,SIG11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(VECT_HYDRODYNA_Ft,SIG11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(VECT_HYDRODYNA_T,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force linéique sous forme d'un vecteur charge, exprimée aux pti ligne
    {TypeQuelconque typQ(VECT_LINE,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force linéique suiveuse sous forme d'un vecteur charge, exprimée aux pti ligne
    {TypeQuelconque typQ(VECT_LINE_SUIV,SIG11,gt);liTQ.push_back(typQ);};
// *** fin modif avril 2020
//    // les réaction sous forme d'un vecteur charge, exprimée aux noeuds
//    {TypeQuelconque typQ(VECT_REAC,X1,gt);liTQ.push_back(typQ);};
   };
    // def des grandeurs courantes de type scalaires
   {// on définit une grandeur typique de type Grandeur_scalaire_double
    Grandeur_scalaire_double scd(0.); 
    // def d'un type quelconque représentatif  pour chaque grandeur
    {TypeQuelconque typQ(CONTRAINTE_MISES,SIG11,scd);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(CONTRAINTE_TRESCA,SIG11,scd);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(DEF_DUALE_MISES,EPS11,scd);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(DEF_DUALE_MISES_MAXI,EPS11,scd);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(DEF_EQUIVALENTE,EPS11,scd);liTQ.push_back(typQ);};
    // cas de l'existence de l'erreur
//    if (sigErreur != NULL)
      {TypeQuelconque typQ(ERREUR_Q,ERREUR,scd);liTQ.push_back(typQ);}
//    if (sigErreur_relative != NULL)
      {TypeQuelconque typQ(ERREUR_SIG_RELATIVE,ERREUR,scd);liTQ.push_back(typQ);}

    // cas de la plasticité classique
    string nom_comport(loiComp->Nom_comport()); 
    if ((strstr(nom_comport.c_str(),"PRANDTL_REUSS")!=NULL))
      {TypeQuelconque typQ(DEF_PLASTIQUE_CUMULEE,EPS11,scd);liTQ.push_back(typQ);}
	 //     les infos sur la décomposition spherique,polaire des contraintes et déformations
	 //    seulement en 3D
	 if (ParaGlob::Dimension() == 3)
	  {{TypeQuelconque typQ(SPHERIQUE_EPS,EPS11,scd);liTQ.push_back(typQ);};
	   {TypeQuelconque typQ(Q_EPS,EPS11,scd);liTQ.push_back(typQ);};
	   {TypeQuelconque typQ(COS3PHI_EPS,EPS11,scd);liTQ.push_back(typQ);};
	   {TypeQuelconque typQ(SPHERIQUE_SIG,SIG11,scd);liTQ.push_back(typQ);};
	   {TypeQuelconque typQ(Q_SIG,SIG11,scd);liTQ.push_back(typQ);};
	   {TypeQuelconque typQ(COS3PHI_SIG,SIG11,scd);liTQ.push_back(typQ);}; 
	   {TypeQuelconque typQ(SPHERIQUE_DEPS,DEPS11,scd);liTQ.push_back(typQ);};
	   {TypeQuelconque typQ(Q_DEPS,DEPS11,scd);liTQ.push_back(typQ);};
	   {TypeQuelconque typQ(COS3PHI_DEPS,DEPS11,scd);liTQ.push_back(typQ);};
	  };     
    };

    //  $$$ cas du repère local ad hoc orthonormé d'expression des tenseurs
    {Coordonnee v_rep(dim_espace);
     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
     TypeQuelconque typQ6(REPERE_LOCAL_ORTHO,EPS11,grand5);
     liTQ.push_back(typQ6);
    };
   
    //  $$$ cas du repère local dual exprimé dans le repère global
    // par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
    {Coordonnee v_rep(dim_espace);
     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
     TypeQuelconque typQ6(REPERE_LOCAL_H,EPS11,grand5);
     liTQ.push_back(typQ6);
    };
    //  $$$ cas du repère local naturel exprimé dans le repère global
    // par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
    {Coordonnee v_rep(dim_espace);
     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
     TypeQuelconque typQ6(REPERE_LOCAL_B,EPS11,grand5);
     liTQ.push_back(typQ6);
    };
   
    //  $$$ cas du repère principal orthonormé du tenseur des contraintes
    {Coordonnee v_rep(dim_espace);
     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
     TypeQuelconque typQ6(DIRECTIONS_PRINC_SIGMA,SIG11,grand5);
     liTQ.push_back(typQ6);
    };
   
    //  $$$ cas du repère principal orthonormé du tenseur des déformations
    {Coordonnee v_rep(dim_espace);
     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
     TypeQuelconque typQ6(DIRECTIONS_PRINC_DEF,EPS11,grand5);
     liTQ.push_back(typQ6);
    };
   
    //  $$$ cas du repère principal orthonormé du tenseur des vitesses de déformation
    {Coordonnee v_rep(dim_espace);
     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
     TypeQuelconque typQ6(DIRECTIONS_PRINC_D,DEPS11,grand5);
     liTQ.push_back(typQ6);
    };
    // dans le cas d'un élément 2D, dans un espace 3D, on peut récupérer la normale
    if ((Type_geom_generique(this->Id_geometrie()) == SURFACE )
        && (ParaGlob::Dimension() == 3))
      {Grandeur_coordonnee grandCoordonnee(3); // un type courant
         TypeQuelconque typQ4(NN_SURF,EPS11,grandCoordonnee);
         liTQ.push_back(typQ4);
      };

    // retour
    return liTQ;   
   };
        
// retourne la liste de toutes les  grandeurs quelconques relatives aux faces de
// l'élément (actif ou non),
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_type_quelconque_de_face(bool absolue) const
  { List_io <TypeQuelconque> liTQ;


//    // def de la dimension des tenseurs
//    // il y a deux pb a gérer: 1) le fait que la dimension absolue peut-être différente de la dimension des tenseurs
//    // 2) le fait que l'on veut une sortie dans une base ad hoc ou pas
//    int dim  = lesPtIntegMecaInterne->DimTens();int dim_sortie_tenseur = dim;
//    // dans le cas ou l'on veut une sortie en base absolue, il faut que dim_sortie_tenseur = la dimension de la base absolue
//    int dim_espace = ParaGlob::Dimension();
//    if (absolue)
//      dim_sortie_tenseur = dim_espace;
//    // pour ne faire qu'un seul test ensuite
//    bool prevoir_change_dim_tenseur = false;
//    if ((absolue) && (dim != dim_sortie_tenseur))
//      prevoir_change_dim_tenseur = true;


    // def des grandeurs courantes de type tenseur BB
    int dim_espace = ParaGlob::Dimension();
    int dim_tenseur_sortie = this->Dim_sig_eps(); // la dimension a priori
    if (absolue)
      dim_tenseur_sortie = dim_espace; // si on sort en absolue, on utilise la dim globale
   
    // def des grandeurs courantes de type coordonnee
   {Coordonnee coor(dim_tenseur_sortie); // un type coordonnee typique
    // maintenant on définit une grandeur typique de type Grandeur_coordonnee
    Grandeur_coordonnee gt(coor);
    // pour la position il s'agit de la position du point d'intégration
    {TypeQuelconque typQ(POSITION_GEOMETRIQUE,SIG11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(POSITION_GEOMETRIQUE_t,SIG11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(POSITION_GEOMETRIQUE_t0,SIG11,gt);liTQ.push_back(typQ);};
   }
   
   {Coordonnee coor(dim_espace); // un type coordonnee typique
    // maintenant on définit une grandeur typique de type Grandeur_coordonnee
    Grandeur_coordonnee gt(coor);
    // le chargement de type pression, sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_PRESSION,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force de direction fixe sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_DIR_FIXE,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force suiveuse sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_SURF_SUIV,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force hydrodynamique sous forme d'un vecteur charge, exprimée aux pti surface
    {TypeQuelconque typQ(VECT_HYDRODYNA_Fn,SIG11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(VECT_HYDRODYNA_Ft,SIG11,gt);liTQ.push_back(typQ);};
    {TypeQuelconque typQ(VECT_HYDRODYNA_T,SIG11,gt);liTQ.push_back(typQ);};
//    // les réaction sous forme d'un vecteur charge, exprimée aux noeuds
//    {TypeQuelconque typQ(VECT_REAC,X1,gt);liTQ.push_back(typQ);};
   };
    // def des grandeurs courantes de type scalaires
   {// def d'un type quelconque représentatif  pour chaque grandeur

//    //  $$$ cas du repère local ad hoc orthonormé d'expression des tenseurs
//    {Coordonnee v_rep(dim_espace);
//     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
//     TypeQuelconque typQ6(REPERE_LOCAL_ORTHO,EPS11,grand5);
//     liTQ.push_back(typQ6);
//    };
//
//    //  $$$ cas du repère local dual exprimé dans le repère global
//    // par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
//    {Coordonnee v_rep(dim_espace);
//     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
//     TypeQuelconque typQ6(REPERE_LOCAL_H,EPS11,grand5);
//     liTQ.push_back(typQ6);
//    };
//    //  $$$ cas du repère local naturel exprimé dans le repère global
//    // par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
//    {Coordonnee v_rep(dim_espace);
//     Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
//     TypeQuelconque typQ6(REPERE_LOCAL_B,EPS11,grand5);
//     liTQ.push_back(typQ6);
//    };
      
      {Grandeur_coordonnee grandCoordonnee(3); // un type courant
         TypeQuelconque typQ4(NN_SURF,EPS11,grandCoordonnee);
         liTQ.push_back(typQ4);
      };
      {Grandeur_coordonnee grandCoordonnee(3); // un type courant
         TypeQuelconque typQ4(NN_SURF_t,EPS11,grandCoordonnee);
         liTQ.push_back(typQ4);
      };
      {Grandeur_coordonnee grandCoordonnee(3); // un type courant
         TypeQuelconque typQ4(NN_SURF_t0,EPS11,grandCoordonnee);
         liTQ.push_back(typQ4);
      };
   };
   
   //  $$$ cas des numéros
   Grandeur_scalaire_entier entier_courant;
   TypeQuelconque typQ37(NUM_ELEMENT,SIG11,entier_courant);
   liTQ.push_back(typQ37);
   TypeQuelconque typQ38(NUM_MAIL_ELEM,SIG11,entier_courant);
   liTQ.push_back(typQ38);
   TypeQuelconque typQ39(NUM_FACE,SIG11,entier_courant);
   liTQ.push_back(typQ39);
   TypeQuelconque typQ40(NUM_PTI,SIG11,entier_courant);
   liTQ.push_back(typQ40);
   
   Grandeur_scalaire_double double_courant;
   TypeQuelconque typQ41(PRESSION_SCALAIRE,SIG11,double_courant);
   liTQ.push_back(typQ41);

    // retour
    return liTQ;
   };
   
// retourne la liste de toutes les  grandeurs quelconques relatives aux arêtes de
// l'élément (actif ou non),
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_type_quelconque_de_arete(bool absolue) const
  { List_io <TypeQuelconque> liTQ;


//    // def de la dimension des tenseurs
//    // il y a deux pb a gérer: 1) le fait que la dimension absolue peut-être différente de la dimension des tenseurs
//    // 2) le fait que l'on veut une sortie dans une base ad hoc ou pas
//    int dim  = lesPtIntegMecaInterne->DimTens();int dim_sortie_tenseur = dim;
//    // dans le cas ou l'on veut une sortie en base absolue, il faut que dim_sortie_tenseur = la dimension de la base absolue
//    int dim_espace = ParaGlob::Dimension();
//    if (absolue)
//      dim_sortie_tenseur = dim_espace;
//    // pour ne faire qu'un seul test ensuite
//    bool prevoir_change_dim_tenseur = false;
//    if ((absolue) && (dim != dim_sortie_tenseur))
//      prevoir_change_dim_tenseur = true;


    // def des grandeurs courantes de type tenseur BB
    int dim_espace = ParaGlob::Dimension();
    int dim_tenseur_sortie = this->Dim_sig_eps(); // la dimension a priori
    if (absolue)
      dim_tenseur_sortie = dim_espace; // si on sort en absolue, on utilise la dim globale
   
     // def des grandeurs courantes de type coordonnee
    {Coordonnee coor(dim_tenseur_sortie); // un type coordonnee typique
     // maintenant on définit une grandeur typique de type Grandeur_coordonnee
     Grandeur_coordonnee gt(coor);
     // pour la position il s'agit de la position du point d'intégration
     {TypeQuelconque typQ(POSITION_GEOMETRIQUE,SIG11,gt);liTQ.push_back(typQ);};
     {TypeQuelconque typQ(POSITION_GEOMETRIQUE_t,SIG11,gt);liTQ.push_back(typQ);};
     {TypeQuelconque typQ(POSITION_GEOMETRIQUE_t0,SIG11,gt);liTQ.push_back(typQ);};
    }

   {Coordonnee coor(dim_espace); // un type coordonnee typique
    // maintenant on définit une grandeur typique de type Grandeur_coordonnee
    Grandeur_coordonnee gt(coor);
    // le chargement de type force linéique sous forme d'un vecteur charge, exprimée aux pti ligne
    {TypeQuelconque typQ(VECT_LINE,SIG11,gt);liTQ.push_back(typQ);};
    // le chargement de type force linéique suiveuse sous forme d'un vecteur charge, exprimée aux pti ligne
    {TypeQuelconque typQ(VECT_LINE_SUIV,SIG11,gt);liTQ.push_back(typQ);};
   };

   
    //  $$$ cas des numéros
    Grandeur_scalaire_entier entier_courant;
    TypeQuelconque typQ37(NUM_ELEMENT,SIG11,entier_courant);
    liTQ.push_back(typQ37);
    TypeQuelconque typQ38(NUM_MAIL_ELEM,SIG11,entier_courant);
    liTQ.push_back(typQ38);
    TypeQuelconque typQ39(NUM_ARETE,SIG11,entier_courant);
    liTQ.push_back(typQ39);
    TypeQuelconque typQ40(NUM_PTI,SIG11,entier_courant);
    liTQ.push_back(typQ40);

    // retour
    return liTQ;
   };


// récupération de grandeurs particulières au numéro d'ordre  = iteg  
// celles-ci peuvent être quelconques
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void ElemMeca::Grandeur_particuliere(bool absolue,List_io<TypeQuelconque>& liTQ,int iteg)
   { // on s'intéresse au information stockée au niveau des points d'intégration
	    // pour tenir compte du fait qu'il peut y avoir plusieurs fois la même information, ces dernières sont systématiquement
	    // stockées dans des tableaux, et on associe à ce tableau un indice qui indique aux méthodes appelées, à quel endroit
	    // elles doivent écrire les infos. les indices sont stockés dans une liste de même dim que liTQ
	    list <int> decal(liTQ.size(),0.);  // on initi tous les membres à 0

     // 0° on initialise les grandeurs à 0 pour éviter d'avoir des valeurs aléatoires
     // -- on commence par initialiser les conteneurs car certaines données peuvent ne pas exister
     List_io<TypeQuelconque>::iterator iquefin=liTQ.end();
     List_io<TypeQuelconque>::iterator ique,ique_deb=liTQ.begin();
     for (ique=ique_deb;ique!=iquefin;ique++) (*ique).Grandeur_pointee()->InitParDefaut();
    
     // 1° on change le numéro de point d'intégration courant
     def->ChangeNumInteg(iteg);
     // 2° on commence par récupérer les grandeurs
     //    a) cas des grandeurs liées à la déformation
	    // met à jour les données spécifiques du point considéré
	    def->Mise_a_jour_data_specif(tabSaveDefDon(iteg));		
     def->Grandeur_particuliere(absolue,liTQ);
     //    b) cas des grandeurs liées à la loi de comportement méca
     //  on commence par indiquer quel saveresult de pti a utiliser
     loiComp->IndiquePtIntegMecaInterne(&((*lesPtIntegMecaInterne)(iteg)));
     // puis on récupère les grandeurs
     loiComp->Grandeur_particuliere(absolue,liTQ,tabSaveDon(iteg),decal);
// pour le débug ----
//cout << "\n debug ElemMeca::Grandeur_particuliere  " <<  liTQ << endl; // débug
// fin pour le débug ----     
     //    c) cas des grandeurs liées à la loi de comportement thermo-physique 
     if (loiTP != NULL) loiTP->Grandeur_particuliere(absolue,liTQ,tabSaveTP(iteg),decal);
    
     // 3° on change éventuellement de repère (local en global) si nécessaire
     //    a) définition des grandeurs qui sont indépendante de la boucle qui suit
     // dimension des vecteurs de base de la métrique
     int dim = met->Dim_vec_base();
     // calcul des matrices de passages
     Mat_pleine* gamma0=NULL; Mat_pleine* gammat=NULL; Mat_pleine* gammatdt=NULL;
     Mat_pleine* beta0=NULL; Mat_pleine* betat=NULL; Mat_pleine* betatdt=NULL;

//     const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(gamma0,gammat,gammatdt);
//     Mat_pleine beta0(gamma0.Inverse().Transpose());
//     Mat_pleine betat(gammat.Inverse().Transpose());
//     Mat_pleine betatdt(gammatdt.Inverse().Transpose());
     List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
     for (il=liTQ.begin();il!=ilfin;il++)
      { TypeQuelconque& tipParticu = (*il); // pour simplifier
        // n'intervient que si la grandeur est active: 
        if ((*il).Activite())
        { // on regarde si c'est une grandeur locale ou pas 
          if (tipParticu.TypeExpressionGrandeur()==0)
            // cas d'une grandeur exprimée dans le repère locale, changement de repère
            { // calcul des matrices de passages, au premier passage
              if (gamma0 == NULL)
               { Mat_pleine Aa0(dim,dim),Aat(dim,dim),Aatdt(dim,dim);
                 const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(absolue,Aa0,Aat,Aatdt);
                 // a) ----- dans le sens: gi -> Ia
                 // on a: g^i = A^i_{.a} * I^a ou Ip^a suivant que absolue est true ou false
                 // si false, cela veut dire que Ip^a est un repère ad hoc
                 // sinon cela veut dire que c'est le repère absolu donc I_a = I^a
                 //  et  g_j = B_j^{.a} * I_a d'où [B_j^{.a}] = [A^i_{.a}]^{-1T}
                 //
                 // b) ----- dans le sens: Ia -> gi
                 // pour les formules de passage de repère il nous faut :
                 // Ip_a = beta_a^{.j} g_j et Ip^b = gamma^b_{.j} g^j
                 // on a alors : [beta_a^{.j}] = [Aa^j_{.a}]^T
                 // et [gamma^b_{.j}] = [beta_a^{.j}]^{-1T} = [Aa^j_{.a}]^{-1}
                 //
                 // au final: [beta_a^{.j}] = [Aa^j_{.a}]^T
                 //          [gamma^b_{.j}] = [Aa^j_{.a}]^{-1}
                 //          [B_j^{.a}] = [gamma^b_{.j}]^T
                
                 gamma0 = new Mat_pleine(Aa0.Inverse());
                 gammat = new Mat_pleine(Aat.Inverse());
                 gammatdt = new Mat_pleine(Aatdt.Inverse());
                 // on détermine également les matrices beta
                 beta0 = new Mat_pleine(Aa0.Transpose());
                 betat = new Mat_pleine(Aat.Transpose());
                 betatdt = new Mat_pleine(Aatdt.Transpose());
//---------- debug
/*
 {
cout << "\n debug en 3D ElemMeca::Grandeur_particuliere( ";
cout << "\n -- affichage de la sauvegarde du pti "<<iteg<<" de la loi de comp ---";
tabSaveDon(iteg)->Affiche();
cout << "\n Aatdt: "; Aatdt.Affiche();
cout << "\n betatdt: "; betatdt->Affiche();
cout << "\n gammatdt: "; gammatdt->Affiche();

Tableau <Vecteur > gB_itdt(3),gH_itdt(3);

for (int a=1; a<3;a++)
 { cout << "\n giB_tdt("<<a<<"): "; (*ex.giB_tdt)(a).Affiche();
   cout << "\n giH_tdt("<<a<<"): "; (*ex.giH_tdt)(a).Affiche();
   gH_itdt(a) = (*ex.giH_tdt)(a).Vect(); // il manque le 3ième
   gB_itdt(a) = (*ex.giB_tdt)(a).Vect(); // il manque le 3ième
 };
// calcul des g^i à l'aide des A^i_{.a}
for (int a=1; a<4;a++)
 { cout << "\n giH_tdt("<<a<<"): via A^i_{.a} " << Aatdt.Ligne (a);
   if (a == 3 )
     {gH_itdt(a) = gB_itdt(a) = Aatdt.Ligne(a);}
 };
// vérif des relations entre beta et gamma
Mat_pleine AA(*betatdt);
cout << "\n beta * gamma "; ((*gammatdt)* AA).Affiche();
Mat_pleine BB(betatdt->Transpose());
cout << "\n beta^T * gamma "; ((*gammatdt)* BB).Affiche();
 
// calcul des Ip_a à l'aide de betatdt
for (int a=1; a<4;a++)
 { Vecteur V(3);
   for (int j=1;j<4;j++)
      V += (*betatdt)(a,j) * gB_itdt(j);
//      V += BB(a,j) * gB_itdt(j);
   cout << "\n Ip("<<a<<"): via betatdt " << V;
 };
// idem calcul des Ip_a à l'aide de gamma
for (int a=1; a<4;a++)
 { Vecteur V(3);
   for (int j=1;j<4;j++)
      V += (*gammatdt)(a,j) * gH_itdt(j);
   cout << "\n Ip("<<a<<"): via gammatdt " << V;
 };
 
};
*/
//----------- fin debug
               };
              tipParticu.Change_repere(*beta0,*betat,*betatdt,*gamma0,*gammat,*gammatdt);
            };
          // on utilise la boucle également pour mettre à jour les grandeurs particulières liés à l'élément  
            
          // 1) -----cas du module de compressibilité ou de cisaillement totale
          switch (tipParticu.EnuTypeQuelconque().EnumTQ())
            {case MODULE_COMPRESSIBILITE_TOTAL:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=(*lesPtIntegMecaInterne)(iteg).ModuleCompressibilite();break;}
             case MODULE_CISAILLEMENT_TOTAL:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=(*lesPtIntegMecaInterne)(iteg).ModuleCisaillement();break;}
             //    e) cas des infos stockés à l'élément
             case  VOLUME_ELEMENT:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=volume;break;}
             case  VOLUME_PTI:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())
                  =(*lesPtIntegMecaInterne)(iteg).Volume_pti_const();break;
              }


             // $$$ cas éventuel d'intégrales de volume: INTEG_SUR_VOLUME
             case INTEG_SUR_VOLUME:
              // on utilise la valeur actuelle plutôt que la valeur à t, sinon on est en retard d'un incrément
              // et par exemple en relaxation dynamique sur un incrément, on ne voit rien car, tant que l'incrément
              // n'est pas fini, la valeur à t n'est pas abondée
               {if (integ_vol_typeQuel != NULL)  // cas où localement il y a une intégrale de définie
                 {int nb_integration = integ_vol_typeQuel->Taille();//_t->Taille();
                  Tableau <TypeQuelconque> & tab_integ = *integ_vol_typeQuel; //_t; // pour simplifier
                  const TypeQuelconque_enum_etendu& type_externe = tipParticu.EnuTypeQuelconque();
                  // maintenant il faut trouver la locale qui correspond: le plus simple
                  // mais pas le plus rapide !! est d'itérer
                  for (int i=1; i<= nb_integration;i++)
                    {EnuTypeQuelParticulier enuTQP = tipParticu.Grandeur_pointee()->Type_enumGrandeurParticuliere();
                    
//                   //----- debug
//                  cout << "\n ElemMeca::Grandeur_particuliere( ";
//                  cout << "\n type_externe " << type_externe
//                       << "\n (*enu_integ_vol_TQ)("<<i<<")=" <<(*enu_integ_vol_TQ)(i);
//                  //----- fin debug

                    
                     if (type_externe == (*enu_integ_vol_TQ)(i))
                      {switch (enuTQP)
                        {case PARTICULIER_DDL_ETENDU:
                          { Grandeur_Ddl_etendu& gex
                             = *((Grandeur_Ddl_etendu*) tipParticu.Grandeur_pointee()); // pour simplifier
                            Grandeur_Ddl_etendu& gin
                               = *((Grandeur_Ddl_etendu*) tab_integ(i).Grandeur_pointee()); // pour simplifier
                            if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
                               // là on a récupérer la même grandeur
                               {Ddl_etendu& ddl = *(gex.ConteneurDdl_etendu());// récup du ddl
                                ddl.Valeur() = gin.ConteneurDdl_etendu()->Valeur();
                               }
                            break;
                          };
                         case PARTICULIER_VECTEUR_NOMMER:
                          { Grandeur_Vecteur_Nommer& gex
                              = *((Grandeur_Vecteur_Nommer*) tipParticu.Grandeur_pointee()); // pour simplifier
                            Grandeur_Vecteur_Nommer& gin
                               = *((Grandeur_Vecteur_Nommer*) tab_integ(i).Grandeur_pointee()); // pour simplifier
                            if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
                               // là on a récupérer la même grandeur
                               {Vecteur& V = gex.ConteneurVecteur();
                                V = gin.ConteneurVecteur();
//                  //----- debug
//                  cout << "\n ElemMeca::Grandeur_particuliere( ";
//                  V.Affiche();
//                  //----- fin debug
                               }
                            break;
                          }
                         default: // pas d'intégrale ad hoc dispo ici pour la demande
                           break;
                        };
                      };
                    };
                 };
                break;
               }
             case INTEG_SUR_VOLUME_ET_TEMPS:
               {if (integ_vol_t_typeQuel != NULL)//_t != NULL)  // cas où localement il y a une intégrale de définie
                 {int nb_integration = integ_vol_t_typeQuel->Taille(); //_t->Taille();
                  Tableau <TypeQuelconque> & tab_integ = *integ_vol_t_typeQuel; //_t; // pour simplifier
                  const TypeQuelconque_enum_etendu& type_externe = tipParticu.EnuTypeQuelconque();
                  // maintenant il faut trouver la locale qui correspond: le plus simple
                  // mais pas le plus rapide !! est d'itérer
                  for (int i=1; i<= nb_integration;i++)
                    {EnuTypeQuelParticulier enuTQP = tipParticu.Grandeur_pointee()->Type_enumGrandeurParticuliere();
                     if (type_externe == (*enu_integ_vol_TQ)(i))
                      {switch (enuTQP)
                        {case PARTICULIER_DDL_ETENDU:
                          { Grandeur_Ddl_etendu& gex
                             = *((Grandeur_Ddl_etendu*) tipParticu.Grandeur_pointee()); // pour simplifier
                            Grandeur_Ddl_etendu& gin
                               = *((Grandeur_Ddl_etendu*) tab_integ(i).Grandeur_pointee()); // pour simplifier
                            if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
                               // là on a récupérer la même grandeur
                               {Ddl_etendu& ddl = *(gex.ConteneurDdl_etendu());// récup du ddl
                                ddl.Valeur() = gin.ConteneurDdl_etendu()->Valeur();
                               }
                            break;
                          };
                         case PARTICULIER_VECTEUR_NOMMER:
                          { Grandeur_Vecteur_Nommer& gex
                              = *((Grandeur_Vecteur_Nommer*) tipParticu.Grandeur_pointee()); // pour simplifier
                            Grandeur_Vecteur_Nommer& gin
                               = *((Grandeur_Vecteur_Nommer*) tab_integ(i).Grandeur_pointee()); // pour simplifier
                            if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
                               // là on a récupérer la même grandeur
                               {Vecteur& V = gex.ConteneurVecteur();
                                V = gin.ConteneurVecteur();
                               }
                            break;
                          }
                         default: // pas d'intégrale ad hoc dispo ici pour la demande
                           break;
                        };
                      };
                    };
                 };
                break;
               }

             case ENERGIE_HOURGLASS:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Energie_Hourglass();break;}
             case PUISSANCE_BULK:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Puissance_Bulk();break;}
             case ENERGIE_BULK:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Energie_Bulk();break;}
             case ENERGIE_STABMEMB_BIEL:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Energie_StabMembBiel(iteg);break;}
             case FORCE_STABMEMB_BIEL:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Force_StabMembBiel(iteg);break;}
             //    d) cas des infos calculable à la demande sur l'élément
             case VOL_ELEM_AVEC_PLAN_REF:
              { *((Grandeur_coordonnee*) tipParticu.Grandeur_pointee())=VolumePlan();break;}
                  // cas des temps d'exécution
             case TEMPS_CPU_LOI_COMP:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=
                     (*lesPtIntegMecaInterne)(iteg).Tps_cpu_loi_comp_const().Temps_CPU_User();break;}
             case TEMPS_CPU_METRIQUE:
              { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=
                     (*lesPtIntegMecaInterne)(iteg).TpsMetrique_const().Temps_CPU_User();break;}
             case NUM_ELEMENT:
              { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_elt; break;}
             case NUM_MAIL_ELEM:
              { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_maillage; break;}
             case NUM_PTI:
              { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= iteg; break;}

             default: ;
            };
        };

       };
      // suppression des bases de passages
      if (gamma0 != NULL)
       {delete gamma0; delete gammat; delete gammatdt; delete beta0; delete betat; delete betatdt;};
      // liberation des tenseurs intermediaires
      LibereTenseur();
      def->Retour_pti_precedant(); // on revient au pti initial
    };                             	
      
// récupération de grandeurs particulières pour une face au numéro d'ordre  = iteg
// celles-ci peuvent être quelconques
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void ElemMeca::Grandeur_particuliere_face (bool absolue,List_io<TypeQuelconque>& liTQ,int face, int iteg)
   { // on s'intéresse au information stockée au niveau des points d'intégration
     // pour tenir compte du fait qu'il peut y avoir plusieurs fois la même information, ces dernières sont systématiquement
     // stockées dans des tableaux, et on associe à ce tableau un indice qui indique aux méthodes appelées, à quel endroit
     // elles doivent écrire les infos. les indices sont stockés dans une liste de même dim que liTQ
     list <int> decal(liTQ.size(),0.);  // on initi tous les membres à 0

     // 0° on initialise les grandeurs à 0 pour éviter d'avoir des valeurs aléatoires
     // -- on commence par initialiser les conteneurs car certaines données peuvent ne pas exister
     List_io<TypeQuelconque>::iterator iquefin=liTQ.end();
     List_io<TypeQuelconque>::iterator ique,ique_deb=liTQ.begin();
     for (ique=ique_deb;ique!=iquefin;ique++) (*ique).Grandeur_pointee()->InitParDefaut();
    
     // 1° on change le numéro de point d'intégration courant si c'est possible
     // on récupère l'élément frontière associée
     int num_face = face; // init par défaut
//     if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
//         {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
//     if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
//       {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
//     const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();

     Deformation* definter=NULL; // variable de travail transitoire
     if (!(ParaGlob::AxiSymetrie()))
            { definter = defSurf(num_face); }   // le cas normal est non axisymétrique
     else   { definter = defArete(num_face);};  // en axisymétrie, c'est une def d'arête
     Deformation * defS = definter;  // pour simplifier l'écriture
     
     if (defS != NULL) // cas où la face existe
      { defS->ChangeNumInteg(iteg);

        // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
        // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
        Met_abstraite::Expli_t_tdt ex = (defS->Cal_explicit_tdt(true));
    
        // 3° on change éventuellement de repère (local en global) si nécessaire
        //    a) définition des grandeurs qui sont indépendante de la boucle qui suit
        // dimension des vecteurs de base de la métrique
        int dim = met->Dim_vec_base();
        // calcul des matrices de passages
        Mat_pleine* gamma0=NULL; Mat_pleine* gammat=NULL; Mat_pleine* gammatdt=NULL;
        Mat_pleine* beta0=NULL; Mat_pleine* betat=NULL; Mat_pleine* betatdt=NULL;

   //     const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(gamma0,gammat,gammatdt);
   //     Mat_pleine beta0(gamma0.Inverse().Transpose());
   //     Mat_pleine betat(gammat.Inverse().Transpose());
   //     Mat_pleine betatdt(gammatdt.Inverse().Transpose());
        List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
        for (il=liTQ.begin();il!=ilfin;il++)
         { TypeQuelconque& tipParticu = (*il); // pour simplifier
           // n'intervient que si la grandeur est active:
           if ((*il).Activite())
           { // on regarde si c'est une grandeur locale ou pas
             if (tipParticu.TypeExpressionGrandeur()==0)
               // cas d'une grandeur exprimée dans le repère locale, changement de repère
               { // calcul des matrices de passages, au premier passage
                 if (gamma0 == NULL)
                  { Mat_pleine Aa0(dim,dim),Aat(dim,dim),Aatdt(dim,dim);
                    const Met_abstraite::Info0_t_tdt& ex = defS->Remont0_t_tdt(absolue,Aa0,Aat,Aatdt);
                    // a) ----- dans le sens: gi -> Ia
                    // on a: g^i = A^i_{.a} * I^a ou Ip^a suivant que absolue est true ou false
                    // si false, cela veut dire que Ip^a est un repère ad hoc
                    // sinon cela veut dire que c'est le repère absolu donc I_a = I^a
                    //  et  g_j = B_j^{.a} * I_a d'où [B_j^{.a}] = [A^i_{.a}]^{-1T}
                    //
                    // b) ----- dans le sens: Ia -> gi
                    // pour les formules de passage de repère il nous faut :
                    // Ip_a = beta_a^{.j} g_j et Ip^b = gamma^b_{.j} g^j
                    // on a alors : [beta_a^{.j}] = [Aa^j_{.a}]^T
                    // et [gamma^b_{.j}] = [beta_a^{.j}]^{-1T} = [Aa^j_{.a}]^{-1}
                    //
                    // au final: [beta_a^{.j}] = [Aa^j_{.a}]^T
                    //          [gamma^b_{.j}] = [Aa^j_{.a}]^{-1}
                    //          [B_j^{.a}] = [gamma^b_{.j}]^T
                   
                    gamma0 = new Mat_pleine(Aa0.Inverse());
                    gammat = new Mat_pleine(Aat.Inverse());
                    gammatdt = new Mat_pleine(Aatdt.Inverse());
                    // on détermine également les matrices beta
                    beta0 = new Mat_pleine(Aa0.Transpose());
                    betat = new Mat_pleine(Aat.Transpose());
                    betatdt = new Mat_pleine(Aatdt.Transpose());
                  };
                 tipParticu.Change_repere(*beta0,*betat,*betatdt,*gamma0,*gammat,*gammatdt);
               };
             // on la boucle également pour mettre à jour les grandeurs quelconque liés à la face de l'élément
               
             // 1) -----cas du module de compressibilité ou de cisaillement totale
             switch (tipParticu.EnuTypeQuelconque().EnumTQ())
               {
               case POSITION_GEOMETRIQUE :
                {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                 (*gr.ConteneurCoordonnee())= defS->Position_tdt();
                  break;
                 }
                 case POSITION_GEOMETRIQUE_t :
                  {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                   (*gr.ConteneurCoordonnee())= defS->Position_t();
                    break;
                   }
                 case POSITION_GEOMETRIQUE_t0 :
                  {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                   (*gr.ConteneurCoordonnee())= defS->Position_0();
                    break;
                   }
                 case VECT_PRESSION:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    if (lesChargeExtSurEle != NULL)
                     {if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
                       { Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
                        // on se positionne  sur la face
                        if (lesPressionsExternes(num_face).Taille() != 0)
                          { Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(num_face)); // pour simplifier
                            if (tab_press_appliquee.Taille())
                             {(*gr.ConteneurCoordonnee())=tab_press_appliquee(iteg).P;
                             };
                          };
                       };
                      };
                    break;
                   }
                 case VECT_DIR_FIXE:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    if (lesChargeExtSurEle != NULL)
                     { if (lesChargeExtSurEle->LesEffortsDirFixe() != NULL) // cas où il existe des valeurs sauvegardées
                        { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesEffortsDirFixe();
                          // on se positionne  sur la face
                           if (lesForcesExternes(num_face).Taille() != 0)
                           { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(num_face)); // pour simplifier
                             if (tab_force_appliquee.Taille())
                              {(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
                              };
                           };
                        };
                     };
                    break;
                   }
                 case VECT_SURF_SUIV:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    if (lesChargeExtSurEle != NULL)
                     { if (lesChargeExtSurEle->LesPressDir() != NULL) // cas où il existe des valeurs sauvegardées
                        { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesPressDir();
                          // on se positionne  sur la num_face
                           if (lesForcesExternes(num_face).Taille() != 0)
                           { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(num_face)); // pour simplifier
                             if (tab_force_appliquee.Taille())
                              {(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
                              };
                           };
                        };
                     };
                    break;
                   }
                 case VECT_HYDRODYNA_Fn:case VECT_HYDRODYNA_Ft:case VECT_HYDRODYNA_T:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    if (lesChargeExtSurEle != NULL)
                     { if (lesChargeExtSurEle->LesHydroDyna() != NULL) // cas où il existe des valeurs sauvegardées
                        { Tableau <Tableau <Force_hydroDyna> >& lesForcesExternes = *lesChargeExtSurEle->LesHydroDyna();
                          // on se positionne  sur la face
                           if (lesForcesExternes(num_face).Taille() != 0)
                           { Tableau <Force_hydroDyna>& tab_force_appliquee = (lesForcesExternes(num_face)); // pour simplifier

                              switch (tipParticu.EnuTypeQuelconque().EnumTQ())
                               {case VECT_HYDRODYNA_Fn:
                                 (*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg).F_n;
                                 break;
                                case VECT_HYDRODYNA_Ft:
                                 (*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg).F_t;
                                 break;
                                case VECT_HYDRODYNA_T:
                                 (*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg).T;
                                 break;
                                default:
                                 break;
                               };
                            };
                        };
                     };
                    break;
                   }
                 case NN_SURF:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    // la normale vaut le produit vectoriel des 2 premiers vecteurs
                    (*gr.ConteneurCoordonnee()) = Util::ProdVec_coorBN( (*ex.giB_tdt)(1), (*ex.giB_tdt)(2));
                    gr.ConteneurCoordonnee()->Normer(); // que l'on norme
                    break;
                   };
                 case NN_SURF_t:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    // la normale vaut le produit vectoriel des 2 premiers vecteurs
                    (*gr.ConteneurCoordonnee()) = Util::ProdVec_coorBN( (*ex.giB_t)(1), (*ex.giB_t)(2));
                    gr.ConteneurCoordonnee()->Normer(); // que l'on norme
                    break;
                   };
                 case NN_SURF_t0:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    // la normale vaut le produit vectoriel des 2 premiers vecteurs
                    (*gr.ConteneurCoordonnee()) = Util::ProdVec_coorBN( (*ex.giB_0)(1), (*ex.giB_0)(2));
                    gr.ConteneurCoordonnee()->Normer(); // que l'on norme
                    break;
                   };
                 case NUM_ELEMENT:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_elt; break;}
                 case NUM_MAIL_ELEM:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_maillage; break;}
                 case NUM_FACE:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_face; break;}
                 case NUM_PTI:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= iteg; break;
                  }
                 case PRESSION_SCALAIRE:
                  {// on récupère les infos
                   Grandeur_scalaire_double& gr= *((Grandeur_scalaire_double*) (tipParticu.Grandeur_pointee()));
                   if (lesChargeExtSurEle != NULL)
                    {if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
                      { Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
                       // on se positionne  sur la face
                       if (lesPressionsExternes(num_face).Taille() != 0)
                         { Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(num_face)); // pour simplifier
                           if (tab_press_appliquee.Taille())
                            {(*gr.ConteneurDouble())=tab_press_appliquee(iteg).press;
//// --- debug
//cout << "\n debug ElemMeca::Grandeur_particuliere_face ( ";
//cout << "\n pression = "<<
                            };
                         };
                      };
                     };
                   break;
                  }


                default: ;
               };
           };

          };
         // suppression des bases de passages
         if (gamma0 != NULL)
          {delete gamma0; delete gammat; delete gammatdt; delete beta0; delete betat; delete betatdt;};
        // liberation des tenseurs intermediaires
        LibereTenseur();
        defS->Retour_pti_precedant(); // on revient au pti initial
      };
    };

// récupération de grandeurs particulières pour une arête au numéro d'ordre  = iteg
// celles-ci peuvent être quelconques
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void ElemMeca::Grandeur_particuliere_arete (bool absolue,List_io<TypeQuelconque>& liTQ,int arete, int iteg)
   { // on s'intéresse au information stockée au niveau des points d'intégration
     // pour tenir compte du fait qu'il peut y avoir plusieurs fois la même information, ces dernières sont systématiquement
     // stockées dans des tableaux, et on associe à ce tableau un indice qui indique aux méthodes appelées, à quel endroit
     // elles doivent écrire les infos. les indices sont stockés dans une liste de même dim que liTQ
     list <int> decal(liTQ.size(),0.);  // on initi tous les membres à 0

     // 0° on initialise les grandeurs à 0 pour éviter d'avoir des valeurs aléatoires
     // -- on commence par initialiser les conteneurs car certaines données peuvent ne pas exister
     List_io<TypeQuelconque>::iterator iquefin=liTQ.end();
     List_io<TypeQuelconque>::iterator ique,ique_deb=liTQ.begin();
     for (ique=ique_deb;ique!=iquefin;ique++) (*ique).Grandeur_pointee()->InitParDefaut();
    
     // 1° on change le numéro de point d'intégration courant si c'est possible
     Deformation * defA = defArete(arete); // pour simplifier l'écriture
     if (defA != NULL)
       {defA->ChangeNumInteg(iteg);

        // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
        // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
        Met_abstraite::Expli_t_tdt ex = (defA->Cal_explicit_tdt(true));
       
        // 3° on change éventuellement de repère (local en global) si nécessaire
        //    a) définition des grandeurs qui sont indépendante de la boucle qui suit
        // dimension des vecteurs de base de la métrique
        int dim = met->Dim_vec_base();
        // calcul des matrices de passages
        Mat_pleine* gamma0=NULL; Mat_pleine* gammat=NULL; Mat_pleine* gammatdt=NULL;
        Mat_pleine* beta0=NULL; Mat_pleine* betat=NULL; Mat_pleine* betatdt=NULL;

   //     const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(gamma0,gammat,gammatdt);
   //     Mat_pleine beta0(gamma0.Inverse().Transpose());
   //     Mat_pleine betat(gammat.Inverse().Transpose());
   //     Mat_pleine betatdt(gammatdt.Inverse().Transpose());
        List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
        for (il=liTQ.begin();il!=ilfin;il++)
         { TypeQuelconque& tipParticu = (*il); // pour simplifier
           // n'intervient que si la grandeur est active:
           if ((*il).Activite())
           { // on regarde si c'est une grandeur locale ou pas
             if (tipParticu.TypeExpressionGrandeur()==0)
               // cas d'une grandeur exprimée dans le repère locale, changement de repère
               { // calcul des matrices de passages, au premier passage
                 if (gamma0 == NULL)
                  { Mat_pleine Aa0(dim,dim),Aat(dim,dim),Aatdt(dim,dim);
                    const Met_abstraite::Info0_t_tdt& ex = defA->Remont0_t_tdt(absolue,Aa0,Aat,Aatdt);
                    // a) ----- dans le sens: gi -> Ia
                    // on a: g^i = A^i_{.a} * I^a ou Ip^a suivant que absolue est true ou false
                    // si false, cela veut dire que Ip^a est un repère ad hoc
                    // sinon cela veut dire que c'est le repère absolu donc I_a = I^a
                    //  et  g_j = B_j^{.a} * I_a d'où [B_j^{.a}] = [A^i_{.a}]^{-1T}
                    //
                    // b) ----- dans le sens: Ia -> gi
                    // pour les formules de passage de repère il nous faut :
                    // Ip_a = beta_a^{.j} g_j et Ip^b = gamma^b_{.j} g^j
                    // on a alors : [beta_a^{.j}] = [Aa^j_{.a}]^T
                    // et [gamma^b_{.j}] = [beta_a^{.j}]^{-1T} = [Aa^j_{.a}]^{-1}
                    //
                    // au final: [beta_a^{.j}] = [Aa^j_{.a}]^T
                    //          [gamma^b_{.j}] = [Aa^j_{.a}]^{-1}
                    //          [B_j^{.a}] = [gamma^b_{.j}]^T
                   
                    gamma0 = new Mat_pleine(Aa0.Inverse());
                    gammat = new Mat_pleine(Aat.Inverse());
                    gammatdt = new Mat_pleine(Aatdt.Inverse());
                    // on détermine également les matrices beta
                    beta0 = new Mat_pleine(Aa0.Transpose());
                    betat = new Mat_pleine(Aat.Transpose());
                    betatdt = new Mat_pleine(Aatdt.Transpose());
                  };
                 tipParticu.Change_repere(*beta0,*betat,*betatdt,*gamma0,*gammat,*gammatdt);
               };
             // on la boucle également pour mettre à jour les grandeurs quelconque liés à la arete de l'élément
               
             // 1) -----cas du module de compressibilité ou de cisaillement totale
             switch (tipParticu.EnuTypeQuelconque().EnumTQ())
               {
               case POSITION_GEOMETRIQUE :
                {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                 (*gr.ConteneurCoordonnee())= defA->Position_tdt();
                  break;
                 }
                 case POSITION_GEOMETRIQUE_t :
                  {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                   (*gr.ConteneurCoordonnee())= defA->Position_t();
                    break;
                   }
                 case POSITION_GEOMETRIQUE_t0 :
                  {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                   (*gr.ConteneurCoordonnee())= defA->Position_0();
                    break;
                   }
                 case VECT_LINE:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    if (lesChargeExtSurEle != NULL)
                     { if (lesChargeExtSurEle->LesLineique() != NULL) // cas où il existe des valeurs sauvegardées
                        { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineique();
                          // on se positionne  sur la arete
                           if (lesForcesExternes(arete).Taille() != 0)
                           { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(arete)); // pour simplifier
                             if (tab_force_appliquee.Taille())
                              {(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
                              };
                           };
                        };
                     };
                    break;
                   }
                 case VECT_LINE_SUIV:
                   {// on récupère les infos
                    Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
                    if (lesChargeExtSurEle != NULL)
                     { if (lesChargeExtSurEle->LesLineiqueSuiveuse() != NULL) // cas où il existe des valeurs sauvegardées
                        { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineiqueSuiveuse();
                          // on se positionne  sur la arete
                           if (lesForcesExternes(arete).Taille() != 0)
                           { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(arete)); // pour simplifier
                             if (tab_force_appliquee.Taille())
                              {(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
                              };
                           };
                        };
                     };
                    break;
                   }
                 case NUM_ELEMENT:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_elt; break;}
                 case NUM_MAIL_ELEM:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_maillage; break;}
                 case NUM_ARETE:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= arete; break;}
                 case NUM_PTI:
                  { *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= iteg; break;
                  }


                default: ;
               };
           };

          };
         // suppression des bases de passages
         if (gamma0 != NULL)
          {delete gamma0; delete gammat; delete gammatdt; delete beta0; delete betat; delete betatdt;};
         // liberation des tenseurs intermediaires
         LibereTenseur();
         defA->Retour_pti_precedant(); // on revient au pti initial
       };
    };


// --- transfert des grandeurs des points d'intégration aux noeuds 
// transfert de ddl des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds, on ne remplace pas)
// les ddl doivent déjà exister aux noeuds sinon erreur
// il doit s'agir du même type de répartition de pt d'integ pour toutes les grandeurs
// tab_val(i)(j) : valeur associée au i ième pt d'integ et au j ième ddl_enum_etendu
void ElemMeca::TransfertAjoutAuNoeuds(const List_io < Ddl_enum_etendu >& lietendu
                                     ,const Tableau <Tableau <double> > & tab_val,int cas) 
{List_io < Ddl_enum_etendu >::const_iterator ili,ilifin = lietendu.end();
 // on récupère l'élément géométrique associé au ddl pur du premier ddl étendu,
 ili = lietendu.begin();
 Enum_ddl enu = (*ili).Enum();
 
 int indice = 1;
 for (ili = lietendu.begin();ili!=ilifin;ili++,indice++)
  { // cas normal courant
    // récupération des tableaux d'indiçage pour le calcul aux noeuds
    const ElemGeomC0& elemgeom = ElementGeometrie(enu);
    // on récupère le nombre de noeud de l'élément géométrique (qui peut-être différent de celui de l'élément
    // par ex: element sfe, donc on utilise les noeuds de l'élément géom. On considère que ce sont les premiers
    // du tableau des noeuds
    int nbn = elemgeom.Nbne();
    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
    // calcul des valeurs aux noeuds
    // val_au_noeud(i) = somme_(de j=indir(i)(1) à indir(i)(taille(indice(i)) )) {tab(i)(j) * val_pt_integ(j) }
    
	   for (int ine=1;ine<=nbn;ine++)
     { Ddl_etendu& de = tab_noeud(ine)->ModifDdl_etendu(*ili);
       Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
       int nbindir = indir.Taille();
       for (int j=1; j<= nbindir; j++)
            de.Valeur() += contExtra.tab(ine)(indir(j)) * tab_val(indir(j))(indice);
     };
  };
};

// transfert de type quelconque des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds, 
// on ne remplace pas). Les types quelconques doivent déjà exister.
// un tableau tab_liQ  correspondent aux grandeurs quelconque pour tous les pt integ. tab_liQ(i) est associé au pt d'integ i
// Toutes les listes sont identiques au niveau des descripteurs (types...) ce sont uniquement les valeurs numériques
// c-a-dire les valeurs associées à TypeQuelconque::Grandeur qui sont différentes (elles sont associées à chaque pt d'integ)
// liQ_travail: est une liste de travail qui sera utilisée dans le transfert                        
void ElemMeca::TransfertAjoutAuNoeuds(const Tableau <List_io < TypeQuelconque > >& tab_liQ
                                     ,List_io < TypeQuelconque > & liQ_travail,int cas)	  
{int nb_pt_integ = lesPtIntegMecaInterne->NbPti();
// ---- modif transitoire pour la sortie des coques !!!!
 // on s'occupe uniquement de la première couche d'élément
 if ((this->PoutrePlaqueCoque() == COQUE)||(this->PoutrePlaqueCoque() == PLAQUE))
   nb_pt_integ = this->NbPtIntegSurface(SIG11); // SIG11 arbitraire car c'est les pt d'integ classique


//------- fin modif transitoire --------
 if (tab_liQ.Taille() == 0)
    return; // cas où on n'a rien à faire
 #ifdef MISE_AU_POINT
    if (nb_pt_integ != tab_liQ.Taille())
      { cout << "\n erreur de dimension, la taille de tab_liQ= " << tab_liQ.Taille() << " n'est pas egale "
             << " au nombre de pt_d'integ de l'element : " << nb_pt_integ ;
        cout << "\n ElemMeca::TransfertAjoutAuNoeuds(... " << endl;
        Sortie(1);
      }  
 #endif
//---- pour le debug
//cout << " \n debug ElemMeca::TransfertAjoutAuNoeuds " << tab_liQ << endl;
//--- fin pour le debug 
 // sinon on a au moins un élément, on récupère la 1ère liste qui nous servira pour les descripteurs
 List_io <TypeQuelconque > & liQ_ref = tab_liQ(1); // pour simplifier
 List_io < TypeQuelconque >::const_iterator ili_ref,ilifin_ref=liQ_ref.end();
 // la liste de travail
 List_io < TypeQuelconque >::iterator ili_travail = liQ_travail.begin();
 // on définit un tableau d'itérator de dimension = le nb de pt d'integ
 static Tableau < List_io < TypeQuelconque >::const_iterator > tab_iterator;
 // on le redimentionne si besoin est
 tab_iterator.Change_taille(nb_pt_integ);
 // on définit ses éléments
 for (int ia=1;ia<=nb_pt_integ;ia++)
   tab_iterator(ia) = tab_liQ(ia).begin();
 // on boucle sur les éléments de la liste de référence
 for (ili_ref = liQ_ref.begin();ili_ref != ilifin_ref;ili_ref++,ili_travail++)
   { // on récupère l'élément géométrique associé au ddl pur dont les valeurs sont calculées aux mêmes
     // endroits que la grandeur quelconque
     Enum_ddl enu = (*ili_ref). Enum();
     const ElemGeomC0& elemgeom = ElementGeometrie(enu);
     // on récupère le nombre de noeud de l'élément géométrique (qui peut-être différent de celui de l'élément
     // par ex: element sfe, donc on utilise les noeuds de l'élément géom. On considère que ce sont les premiers
     // du tableau des noeuds
     int nbn = elemgeom.Nbne();
     // récupération des tableaux d'indiçage pour le calcul aux noeuds
     const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
     // on boucle sur les noeuds, ceci est due à la technique utilisée pour accumuler dans les conteneurs du noeud
     for (int ine=1;ine<=nbn;ine++)
        {TypeQuelconque& tq = tab_noeud(ine)->ModifGrandeur_quelconque((*ili_ref).EnuTypeQuelconque());
         TypeQuelconque::Grandeur & grandeur_au_noeud = *(tq.Grandeur_pointee());
	        // on récupère une grandeur du même type que les grandeurs à manipuler, ceci pour accumuler
	        TypeQuelconque::Grandeur & stockage_inter = *((*ili_travail).Grandeur_pointee());
         // calcul des valeurs aux noeuds
         // val_au_noeud(i) = somme_(de j=indir(i)(1) à indir(i)(taille(indice(i)) )) {tab(i)(j) * val_pt_integ(j) }
         Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
         int nbindir = indir.Taille();
         for (int j=1; j<= nbindir; j++)
       	  { stockage_inter *= 0.; // met à 0 la grandeur inter
       	    // tab_iterator(j) pointe sur la grandeur quelconque du point d'intégration voulu 
       	    stockage_inter = *((*(tab_iterator(indir(j)))).Const_Grandeur_pointee()); // récup de la grandeur pointée
//---- debug
//cout << "\n debug ElemMeca::TransfertAjoutAuNoeuds: stockage_inter 1= " << stockage_inter;
//-- fin debug
       	    stockage_inter *= contExtra.tab(ine)(indir(j)); // * par le coeff
       	    grandeur_au_noeud += stockage_inter; // stockage dans le noeud	
//---- debug
//cout << " stockage_inter 2= "<< stockage_inter << " grandeur_au_noeud= " << grandeur_au_noeud;
//if (Dabs(grandeur_au_noeud.GrandeurNumOrdre(2)) > 1.)
//   {cout << "\n ***** grandeur_au_noeud.GrandeurNumOrdre(2) = " << grandeur_au_noeud.GrandeurNumOrdre(2)
//         << "\n contExtra.tab= "<< contExtra.tab << " contExtra.indir= "<< contExtra.indir;
//   
//   };
//
//-- fin debug
       	  };
       };
     // on incrémente les itérators de points d'intégration
     for (int ib=1;ib<=nb_pt_integ;ib++)
         (tab_iterator(ib))++;
       	};
};
	     
 
// accumulation aux noeuds de grandeurs venant des éléments vers leurs noeuds (exemple la pression appliquée)
// autres que celles aux pti classiques, mais directements disponibles
// le contenu du conteneur stockées dans liQ est utilisé en variable intermédiaire
void ElemMeca::Accumul_aux_noeuds(const List_io < Ddl_enum_etendu >& lietendu
                                 ,List_io < TypeQuelconque > & liQ,int cas)
{// ... cas des ddl étendu ...
 {List_io < Ddl_enum_etendu >::const_iterator ili,ilifin = lietendu.end();
  ili = lietendu.begin();
  for (ili = lietendu.begin();ili!=ilifin;ili++)
   {// on traite en fonctions des cas particuliers
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " *ili = " << *ili << endl;
// fin debug
   
    switch ((*ili).Position()-NbEnum_ddl())
     { case 94 : // cas des pressions externes 
        {if (lesChargeExtSurEle != NULL)
          if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
           { Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
             int nb_face = lesPressionsExternes.Taille();
             for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
              if (lesPressionsExternes(n_face).Taille() != 0)
              { Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(n_face)); // pour simplifier
                int t_tail = tab_press_appliquee.Taille();
                if (t_tail != 0) // cas où on a une face chargée
                  { // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
                    int num_face = n_face; // init par défaut
                    if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
                      {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
                    const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
                    int nbn = elemgeom.Nbne();
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
                    for (int ine=1;ine<=nbn;ine++)
                      { Ddl_etendu& de = tab_noe(ine)->ModifDdl_etendu(*ili);
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        for (int j=1; j<= nbindir; j++)
{                           de.Valeur() += contExtra.tab(ine)(indir(j)) * tab_press_appliquee(indir(j)).press;
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
}                      };
                  };
              };
           };
          break;
        }
       default :
         break;
        // sinon on ne fait rien, cela signifie que ce n'est pas un ddl géré par l'élément
     };
   };
 };

 // ... cas des grandeurs quelconque ...
 // on traite d'abord le cas où on n'a rien à faire
 if (liQ.size() == 0)
    return; 
//---- pour le debug
//cout << " \n debug ElemMeca::TransfertAjoutAuNoeuds " << tab_liQ << endl;
//--- fin pour le debug 
 {List_io < TypeQuelconque >::const_iterator ili,ilifin=liQ.end();
  
  // on boucle sur les grandeurs de la liste 
  for (ili = liQ.begin();ili != ilifin;ili++)
   { // on récupère l'énuméré
     TypeQuelconque_enum_etendu enutq = (*ili).EnuTypeQuelconque();
     switch (enutq.EnumTQ())
      { case VECT_PRESSION:
         { // on récupère les infos pour extrapoler les valeurs
          if (lesChargeExtSurEle != NULL)
           if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
           { Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
             int nb_face = lesPressionsExternes.Taille();
             for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
              if (lesPressionsExternes(n_face).Taille() != 0)
              { Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(n_face)); // pour simplifier
                int t_tail = tab_press_appliquee.Taille();
                if (t_tail != 0) // cas où on a une face chargée
                  { // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
                    int num_face = n_face; // init par défaut
                    if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
                      {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
                    const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
                    int nbn = elemgeom.Nbne();
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
                    for (int ine=1;ine<=nbn;ine++)
                      { TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
                        // récup des coordonnées
                        Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
                        Coordonnee& coor = *(gr_coor->ConteneurCoordonnee()); 
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        for (int j=1; j<= nbindir; j++)
{                           coor += contExtra.tab(ine)(indir(j)) * tab_press_appliquee(indir(j)).P;
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
}                      };
                  };
              };
           };
         }
         break;
        case VECT_FORCE_VOLUM:
         { // on récupère les infos pour extrapoler les valeurs
          if (lesChargeExtSurEle != NULL)
           if (lesChargeExtSurEle->Force_volume() != NULL) // cas où il existe des F volume sauvegardées
              { Tableau <Coordonnee>& force_volume = *lesChargeExtSurEle->Force_volume();
                int t_tail = force_volume.Taille();
                if (t_tail != 0) // cas où on a des forces volumique
                  { // on récupère l'élément  géométrique associée
                    const ElemGeomC0& elemgeom = ElementGeometrie(X1);
                    // on récupère le nombre de noeud de l'élément géométrique (qui peut-être différent de celui de l'élément
                    // par ex: element sfe, donc on utilise les noeuds de l'élément géom. On considère que ce sont les premiers
                    // du tableau des noeuds
                    int nbn = elemgeom.Nbne();
                    // récupération des tableaux d'indiçage pour le calcul aux noeuds
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    // on boucle sur les noeuds, 
                    for (int ine=1;ine<=nbn;ine++)
                       {TypeQuelconque& tq = tab_noeud(ine)->ModifGrandeur_quelconque(enutq);
                        // récup des coordonnées
                        Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) tq.Const_Grandeur_pointee());
                        Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        for (int j=1; j<= nbindir; j++)
{                           coor +=  (contExtra.tab(ine)(indir(j))) * force_volume(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
}                      };
                  };
           };
         }
         break;
        case VECT_DIR_FIXE:
         { // on récupère les infos pour extrapoler les valeurs
          if (lesChargeExtSurEle != NULL)
           if (lesChargeExtSurEle->LesEffortsDirFixe() != NULL) // cas où il existe des pressions sauvegardées
           { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesEffortsDirFixe();
             int nb_face = lesForcesExternes.Taille();
             for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
              if (lesForcesExternes(n_face).Taille() != 0)
              { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
                int t_tail = tab_force_appliquee.Taille();
                if (t_tail != 0) // cas où on a une face chargée
                  { // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
                    int num_face = n_face; // init par défaut
                    if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
                      {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
                    const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
                    int nbn = elemgeom.Nbne();
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
                    for (int ine=1;ine<=nbn;ine++)
                      { TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
                        // récup des coordonnées
                        Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
                        Coordonnee& coor = *(gr_coor->ConteneurCoordonnee()); 
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        for (int j=1; j<= nbindir; j++)
{                           coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
}                      };
                  };
              };
           };
         }
         break;
        case VECT_SURF_SUIV:
         { // on récupère les infos pour extrapoler les valeurs
          if (lesChargeExtSurEle != NULL)
           if (lesChargeExtSurEle->LesPressDir() != NULL) // cas où il existe des pressions sauvegardées
           { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesPressDir();
             int nb_face = lesForcesExternes.Taille();
             for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
              if (lesForcesExternes(n_face).Taille() != 0)
              { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
                int t_tail = tab_force_appliquee.Taille();
                if (t_tail != 0) // cas où on a une face chargée
                  { // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
                    int num_face = n_face; // init par défaut
                    if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
                      {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
                    const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
                    int nbn = elemgeom.Nbne();
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
                    for (int ine=1;ine<=nbn;ine++)
                      { TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
                        // récup des coordonnées
                        Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
                        Coordonnee& coor = *(gr_coor->ConteneurCoordonnee()); 
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        for (int j=1; j<= nbindir; j++)
{                           coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
}                      };
                  };
              };
           };
         }
         break;
        case VECT_HYDRODYNA_Fn:case VECT_HYDRODYNA_Ft:case VECT_HYDRODYNA_T:
         { // on récupère les infos pour extrapoler les valeurs
          if (lesChargeExtSurEle != NULL)
           if (lesChargeExtSurEle->LesHydroDyna() != NULL) // cas où il existe des pressions sauvegardées
           { Tableau <Tableau <Force_hydroDyna> >& lesForcesExternes = *lesChargeExtSurEle->LesHydroDyna();
             int nb_face = lesForcesExternes.Taille();
             for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
              if (lesForcesExternes(n_face).Taille() != 0)
              { Tableau <Force_hydroDyna>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
                int t_tail = tab_force_appliquee.Taille();
                if (t_tail != 0) // cas où on a une face chargée
                  { // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
                    int num_face = n_face; // init par défaut
                    if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
                      {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
                    const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
                    int nbn = elemgeom.Nbne();
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
                    for (int ine=1;ine<=nbn;ine++)
                      { TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
                        // récup des coordonnées
                        Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
                        Coordonnee& coor = *(gr_coor->ConteneurCoordonnee()); 
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        switch (enutq.EnumTQ())
                         {case VECT_HYDRODYNA_Fn:
                           for (int j=1; j<= nbindir; j++)
                             coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j)).F_n;
                           break;
                          case VECT_HYDRODYNA_Ft:
                           for (int j=1; j<= nbindir; j++)
                             coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j)).F_t;
                           break;
                          case VECT_HYDRODYNA_T:
                           for (int j=1; j<= nbindir; j++)
                             coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j)).T;
                           break;
                          default:
                           break;
                         };
                      };
                  };
              };
           };
         }
         break;
        case VECT_LINE:
         { // on récupère les infos pour extrapoler les valeurs
          if (lesChargeExtSurEle != NULL)
           if (lesChargeExtSurEle->LesLineique() != NULL) // cas où il existe des pressions sauvegardées
           { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineique();
             int nb_face = lesForcesExternes.Taille();
             for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
              if (lesForcesExternes(n_face).Taille() != 0)
              { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
                int t_tail = tab_force_appliquee.Taille();
                if (t_tail != 0) // cas où on a une face chargée
                  { // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
                    int num_face = n_face; // init par défaut
                    if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les faces
                      {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
                    const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
                    int nbn = elemgeom.Nbne();
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
                    for (int ine=1;ine<=nbn;ine++)
                      { TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
                        // récup des coordonnées
                        Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
                        Coordonnee& coor = *(gr_coor->ConteneurCoordonnee()); 
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        for (int j=1; j<= nbindir; j++)
{                           coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
}                      };
                  };
              };
           };
         }
         break;
        case VECT_LINE_SUIV:
         { // on récupère les infos pour extrapoler les valeurs
          if (lesChargeExtSurEle != NULL)
           if (lesChargeExtSurEle->LesLineiqueSuiveuse() != NULL) // cas où il existe des pressions sauvegardées
           { Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineiqueSuiveuse();
             int nb_ligne = lesForcesExternes.Taille();
             for (int n_ligne=1;n_ligne<=nb_ligne;n_ligne++) // on boucle sur les lignes
              if (lesForcesExternes(n_ligne).Taille() != 0)
              { Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_ligne)); // pour simplifier
                int t_tail = tab_force_appliquee.Taille();
                if (t_tail != 0) // cas où on a une ligne chargée
                  { // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
                    int num_ligne = n_ligne; // init par défaut
                    if(ParaGlob::AxiSymetrie())  // dans le cas d'éléments axysymétriques, les lignes
                      {num_ligne += posi_tab_front_point;} // sont en faites les frontières points
                    else {num_ligne += posi_tab_front_lin;}; // sinon c'est des lignes
                    const ElemGeomC0 & elemgeom = tabb(num_ligne)->ElementGeometrique();
                    int nbn = elemgeom.Nbne();
                    const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
                    Tableau <Noeud *>& tab_noe = tabb(num_ligne)->TabNoeud(); // récup du tableau de noeuds de la frontière
                    for (int ine=1;ine<=nbn;ine++)
                      { TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
                        // récup des coordonnées
                        Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
                        Coordonnee& coor = *(gr_coor->ConteneurCoordonnee()); 
                        Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
                        int nbindir = indir.Taille();
                        for (int j=1; j<= nbindir; j++)
{                           coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
//     << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
}                      };
                  };
              };
           };
         }
         break;
//        case VECT_REAC:
//         // là on ne fait rien car la grandeur est directement à construire via les noeuds
//         // et ceci est fait dans la routine:
//         // lesMaillages->PassageInterneDansNoeud_composantes_vers_vectorielles()
//         break;

       default:
     // VECT_PRESSION pour l'instant il n'y a aucune grandeur a priori qui est disponible directement
     // donc message d'erreur
        cout << "\n cas de grandeur actuellement non traité "
             << "\n pas de grandeur " << (*ili).EnuTypeQuelconque().NomPlein()
             << "  dans l'element "
             << "\n ou cas non implante pour l'instant"
             << "\n ElemMeca::Accumul_aux_noeuds(....";
      };
   };
  };
};

// procedure permettant de completer l'element, en ce qui concerne les variables gérés
// par ElemMeca, apres sa creation avec les donnees du bloc transmis
// peut etre appeler plusieurs fois
Element* ElemMeca::Complete_ElemMeca(BlocGen & bloc,LesFonctions_nD*  lesFonctionsnD)
    { // avant toute chose, une complétion hors bloc, concernant la stabilisation
      if (pt_StabMembBiel != NULL) // ne sert qu'après un démarrage initial sur un base_info
          // donc dans la pratique ne sert pas souvent, mais existe pour que
          // ElemMeca::StabMembBiel::Lecture_bas_inf soit correcte
          pt_StabMembBiel->Complete_StabMembBiel(lesFonctionsnD);
    
      // cas de la masse volumique
      if (bloc.Nom(1) == "masse_volumique")
       { masse_volumique = bloc.Val(1);
         return this;
       }
      // cas de données thermique   
      else if (bloc.Nom(1) == "dilatation_thermique")
       { if (bloc.Val(1) == 1) {dilatation=1;} else {dilatation = 0;};
         return this;
       };
     
      // cas de la définition d'une intégrale sur le volume
      // on prévoit une intégrale via les pti, on utilise donc le ddl EPS11 pour la position
      // (*index_Integ_vol_typeQuel)(ii) contient alors le numéro de l'intégrale qui a été
      // demandé par l'utilisateur = le numéro d'apparition dans le .info
      // idem pour (*index_Integ_vol_t_typeQuel)(ii)
      if (bloc.Nom(1) == "integrale_sur_volume_")
       { if (bloc.Nom(2) == "un_ddl_etendu_")
           { // il s'agit d'une intégrale d'un ddl étendu de nom: bloc.Nom(3)
             Ddl_etendu ddl(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc
             Grandeur_Ddl_etendu grand_courant(ddl,bloc.Nom(4));// le conteneur ad hoc
             TypeQuelconque typQ(INTEG_SUR_VOLUME,EPS11,grand_courant);

             // on garde en mémoire le TypeQuelconque_enum_etendu associé
             // -- on crée le nom de référence
//             string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_"
//                                          +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
             string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_");

             // on regarde si l'identificateur existe déjà, sinon on le crée
             if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
                    TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                         (INTEG_SUR_VOLUME,nom,typQ.EnuTypeGrandeur());
             // puis récupération
             TypeQuelconque_enum_etendu tqnevez =
                             TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);

              if (integ_vol_typeQuel == NULL)
                {// ici rien n'existe, donc on crée sans se poser des questions
                 int taille = 1;
                 integ_vol_typeQuel = new Tableau <TypeQuelconque>(1);
                 integ_vol_typeQuel_t = new Tableau <TypeQuelconque>(1);
                 (*integ_vol_typeQuel)(1) =  typQ;(*integ_vol_typeQuel_t)(1) = typQ;
                 index_Integ_vol_typeQuel = new Tableau <int>(1);
                 (*index_Integ_vol_typeQuel)(1) = (int) bloc.Val(1);
                 enu_integ_vol_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
                 (*enu_integ_vol_TQ)(1)=tqnevez;
                }
             else
                {// sinon, deux cas suivant que la grandeur a déjà été enregistrée
                 // suite à un restart par exemple , ou au contraire en n'existe pas encore
                 //  on utilise l'identificateur pour repérer l'intégrale
                 int indic = enu_integ_vol_TQ->Contient(tqnevez);
                 if (!indic)
                  {// cas où l'intégrale n'existe pas déjà
                   int taille = integ_vol_typeQuel->Taille()+1;
                   integ_vol_typeQuel->Change_taille(taille);
                   integ_vol_typeQuel_t->Change_taille(taille);
                   (*integ_vol_typeQuel)(taille) = typQ;
                   (*integ_vol_typeQuel_t)(taille) = typQ;
                   index_Integ_vol_typeQuel->Change_taille(taille);
                   (*index_Integ_vol_typeQuel)(taille) = (int) bloc.Val(1);
                   enu_integ_vol_TQ->Change_taille(taille);
                   (*enu_integ_vol_TQ)(taille)=tqnevez;
                  }
                 else // sinon les conteneurs existent déjà
                  // il faut juste mettre à jour l'index
                  { (*index_Integ_vol_typeQuel)(indic) = (int) bloc.Val(1);
                  } ;
                };
           }
         else if (bloc.Nom(2) == "une_fonction_nD_")
           { // il s'agit d'une intégrale d'une fonction nD de nom: bloc.Nom(3)
             // on récupère le pointeur de fonction correspondant:
             Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3));
             int nb_composante = fct->NbComposante();
             Grandeur_Vecteur_Nommer grand_courant(bloc.Nom(3),nb_composante,fct);
             TypeQuelconque typQ(INTEG_SUR_VOLUME,EPS11,grand_courant);
             // on garde en mémoire le TypeQuelconque_enum_etendu associé
             // -- on crée le nom de référence
//             string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_"
//                                          +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
             string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_");
             // on regarde si l'identificateur existe déjà, sinon on le crée
             if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
                    TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                         (INTEG_SUR_VOLUME,nom,typQ.EnuTypeGrandeur());
             // puis récupération
             TypeQuelconque_enum_etendu tqnevez =
                             TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);

             if (integ_vol_typeQuel == NULL)
               { // ici rien n'existe, donc on crée sans se poser des questions
                 int taille = 1;
                 integ_vol_typeQuel = new Tableau <TypeQuelconque>(1);
                 integ_vol_typeQuel_t = new Tableau <TypeQuelconque>(1);
                 (*integ_vol_typeQuel)(1) = typQ;(*integ_vol_typeQuel_t)(1) = typQ;
                 index_Integ_vol_typeQuel = new Tableau <int>(1);
                 (*index_Integ_vol_typeQuel)(1) = (int) bloc.Val(1);
                 enu_integ_vol_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
                 (*enu_integ_vol_TQ)(1)=tqnevez;
               }
             else
                {// sinon, deux cas suivant que la grandeur a déjà été enregistrée
                 // suite à un restart par exemple , ou au contraire en n'existe pas encore
                 //  on utilise l'identificateur pour repérer l'intégrale
                 int indic = enu_integ_vol_TQ->Contient(tqnevez);
                 if (!indic)
                  {// cas où l'intégrale n'existe pas déjà
                   int taille = integ_vol_typeQuel->Taille()+1;
                   integ_vol_typeQuel->Change_taille(taille);
                   integ_vol_typeQuel_t->Change_taille(taille);
                   (*integ_vol_typeQuel)(taille) = typQ;
                   (*integ_vol_typeQuel_t)(taille) = typQ;
                   index_Integ_vol_typeQuel->Change_taille(taille);
                   (*index_Integ_vol_typeQuel)(taille) = (int) bloc.Val(1);
                   enu_integ_vol_TQ->Change_taille(taille);
                    (*enu_integ_vol_TQ)(taille)=tqnevez;
                  }
                 else // sinon les conteneurs existent déjà
                  // il faut juste mettre à jour l'index
                  { (*index_Integ_vol_typeQuel)(indic) = (int)  bloc.Val(1);
                  } ;
                 };

           };
         return this;
       }
      // cas de la définition d'une intégrale sur le volume et le temps
      else if (bloc.Nom(1) == "integrale_sur_vol_et_temps_")
        { if (bloc.Nom(2) == "un_ddl_etendu_")
           { // il s'agit d'une intégrale d'un ddl étendu de nom: bloc.Nom(3)
             Ddl_etendu ddl(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc
             Grandeur_Ddl_etendu grand_courant(ddl,bloc.Nom(4));// le conteneur ad hoc
             TypeQuelconque typQ(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant);

             // on garde en mémoire le TypeQuelconque_enum_etendu associé
             // -- on crée le nom de référence
//             string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_"
//                                          +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
             string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_");

             // on regarde si l'identificateur existe déjà, sinon on le crée
             if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
                    TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                         (INTEG_SUR_VOLUME_ET_TEMPS,nom,typQ.EnuTypeGrandeur());
             // puis récupération
             TypeQuelconque_enum_etendu tqnevez =
                             TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);

             if (integ_vol_t_typeQuel == NULL)
                {// ici rien n'existe, donc on crée sans se poser des questions
                 int taille = 1;
                 integ_vol_t_typeQuel = new Tableau <TypeQuelconque>(1);
                 integ_vol_t_typeQuel_t = new Tableau <TypeQuelconque>(1);
                 (*integ_vol_t_typeQuel)(1) = typQ;(*integ_vol_t_typeQuel_t)(1) = typQ;
                 index_Integ_vol_t_typeQuel = new Tableau <int>(1);
                 (*index_Integ_vol_t_typeQuel)(1) = (int) bloc.Val(1);
                 enu_integ_vol_t_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
                 (*enu_integ_vol_t_TQ)(1)=tqnevez;
                }
             else
                {// sinon, deux cas suivant que la grandeur a déjà été enregistrée
                 // suite à un restart par exemple , ou au contraire en n'existe pas encore
                 //  on utilise l'identificateur pour repérer l'intégrale
                 int indic = enu_integ_vol_t_TQ->Contient(tqnevez);
                 if (!indic)
                  {int taille = integ_vol_t_typeQuel->Taille()+1;
                   integ_vol_t_typeQuel->Change_taille(taille);
                   integ_vol_t_typeQuel_t->Change_taille(taille);
                   (*integ_vol_t_typeQuel)(taille) = typQ;
                   (*integ_vol_t_typeQuel_t)(taille) = typQ;
                   index_Integ_vol_t_typeQuel->Change_taille(taille);
                   (*index_Integ_vol_t_typeQuel)(taille) = (int) bloc.Val(1);
                   enu_integ_vol_t_TQ->Change_taille(taille);
                   (*enu_integ_vol_t_TQ)(taille)=tqnevez;
                  }
                 else // sinon les conteneurs existent déjà
                  // il faut juste mettre à jour l'index
                  { (*index_Integ_vol_t_typeQuel)(indic) = (int) bloc.Val(1);
                  } ;
                };
           }
         else if (bloc.Nom(2) == "une_fonction_nD_")
           { // il s'agit d'une intégrale d'une fonction nD de nom: bloc.Nom(3)
             // on récupère le pointeur de fonction correspondant:
             Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3));
             int nb_composante = fct->NbComposante();
             Grandeur_Vecteur_Nommer grand_courant(bloc.Nom(3),nb_composante,fct);
             TypeQuelconque typQ(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant);

             // on garde en mémoire le TypeQuelconque_enum_etendu associé
             // -- on crée le nom de référence
//             string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_"
//                                          +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
            string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_");
            if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
                    TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                         (INTEG_SUR_VOLUME_ET_TEMPS,nom,typQ.EnuTypeGrandeur());
             // puis récupération
             TypeQuelconque_enum_etendu tqnevez =
                             TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);

             if (integ_vol_t_typeQuel == NULL)
                {// ici rien n'existe, donc on crée sans se poser des questions
                 int taille = 1;
                 integ_vol_t_typeQuel = new Tableau <TypeQuelconque>(1);
                 integ_vol_t_typeQuel_t = new Tableau <TypeQuelconque>(1);
                 (*integ_vol_t_typeQuel)(1) = typQ;(*integ_vol_t_typeQuel_t)(1) = typQ;
                 index_Integ_vol_t_typeQuel = new Tableau <int>(1);
                 (*index_Integ_vol_t_typeQuel)(1) = (int) bloc.Val(1);
                 enu_integ_vol_t_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
                 (*enu_integ_vol_t_TQ)(1)=tqnevez;
                }
              else
                {// sinon, deux cas suivant que la grandeur a déjà été enregistrée
                 // suite à un restart par exemple , ou au contraire en n'existe pas encore
                 //  on utilise l'identificateur pour repérer l'intégrale
                 int indic = enu_integ_vol_t_TQ->Contient(tqnevez);
                 if (!indic)
                  {int taille = integ_vol_t_typeQuel->Taille()+1;
                   integ_vol_t_typeQuel->Change_taille(taille);
                   integ_vol_t_typeQuel_t->Change_taille(taille);
                   (*integ_vol_t_typeQuel)(taille) = typQ;
                   (*integ_vol_t_typeQuel_t)(taille) = typQ;
                   index_Integ_vol_t_typeQuel->Change_taille(taille);
                   (*index_Integ_vol_t_typeQuel)(taille) = (int) bloc.Val(1);
                   enu_integ_vol_t_TQ->Change_taille(taille);
                   (*enu_integ_vol_t_TQ)(taille)=tqnevez;
                  }
                 else // sinon les conteneurs existent déjà
                  // il faut juste mettre à jour l'index
                  { (*index_Integ_vol_t_typeQuel)(indic) = (int) bloc.Val(1);
                  };
               };
           };
         return this;
       }
      // cas de la définition d'une stabilisation transversale pour membrane ou biel
      else if (bloc.Nom(1) == "stabilisation_transvers_membrane_biel_")
        {// on vérifie qu'il s'agit d'une géométrie membrane ou biel
         Enum_type_geom enu_type_geom = Type_geom_generique(this->Id_geometrie());
         if ((enu_type_geom != LIGNE) && (enu_type_geom != SURFACE))
          {cout << "\n **** erreur, la stabilisation n'est pas prevue pour ce type d'element: ";
           this->Affiche(1);
           Sortie(1);
          };
         // maintenant on va allouer le conteneur d'infos
         
         // pour savoir comment dimensionner le stockage
         // il faut prendre en compte le type de stabilisation
         Enum_StabMembraneBiel enu_stab = Id_Enum_StabMembraneBiel(bloc.Nom(2));
         int taille_stockage = 0; // init
         if (!Contient_Normale_au_noeud(enu_stab))
          // cas d'un stockage aux pti
          { // détermination de la taille en fonction du type d'élément
// ** non car finalement on ne prend que les pti de surface
//            Enum_type_geom enu_type_geom = Type_geom_generique(this->Id_geometrie());
//            switch (enu_type_geom)
//             { case SURFACE:
//                  taille_stockage = NbPtIntegSurface(X1) * NbPtIntegEpaiss(X1);
//                  break;
//               default:
//                 cout << "\n *** actuellement seule les elements de surface peuvent etre stabilise ** revoir la mise en donnees ...";
//                 Sortie(1);
//              };
          taille_stockage = this->ElementGeometrique().Nbi();
          }
         else // sinon c'est un stockage aux noeuds
          { taille_stockage = tab_noeud.Taille();};
         
         pt_StabMembBiel = new StabMembBiel(taille_stockage);
         // définition du type de stabilisation
         if (Type_Enum_StabMembraneBiel_existe(bloc.Nom(2)))
           {pt_StabMembBiel->Type_stabMembrane()= Id_Enum_StabMembraneBiel(bloc.Nom(2));}
         else
           {cout << "\n *** erreur en mise en place de la stabilisation de membrane et/ou biel: "
                 << " le type de stabilisation "<<bloc.Nom(2)<<" n'existe pas ! ";
            cout << "\n ElemMeca::Complete_ElemMeca(..."<<endl; this->Affiche(1);
            Sortie(1);
           };
         
         // choix entre valeur numérique ou une fonction nD
         if (bloc.Nom(3) == "une_valeur_numerique_")
          {// dans ce cas la valeur numémrique est en string
           pt_StabMembBiel->Valgamma() = ChangeReel(bloc.Nom(4));
          }
         else if (bloc.Nom(3) == "une_fonction_nD_")
          {// il s'agit d'une fonction nD: récupération de la fonction
           pt_StabMembBiel->Change_pt_fct_gamma(lesFonctionsnD->Trouve(bloc.Nom(4)));
// non modif 8 mai 2022           // pour l'instant seules les variables globales sont autorisées:
//           if (pt_StabMembBiel->Pt_fct_gamma()->Nom_variables().Taille() == 0)
//             //  cas où il n'y a que des variables globales
             {// on vérifie qu'en retour on a un scalaire
//              Tableau <double> & tava = pt_StabMembBiel->Pt_fct_gamma()->Valeur_pour_variables_globales(); // pour simplifier
              if (pt_StabMembBiel->Pt_fct_gamma()->NbComposante() != 1)
                {cout << "\n *** erreur en mise en place de la stabilisation de membrane et/ou biel : "
//                      << " la fonction nD avec grandeur(s) globale(s) ne renvoie pas un scalaire ! ";
                      << " la fonction nD " << bloc.Nom(4) << " ne renvoie pas un unique scalaire ! ";
                 cout << "\n element: "; this->Affiche(1);
                 cout << "\n fonction nD : "; pt_StabMembBiel->Pt_fct_gamma()->Affiche();
                 Sortie(1);
                }
             }
//           else
//             {cout << "\n *** erreur en mise en place de la stabilisation: "
//                   << " la fonction nD ne doit utiliser que des variables globales ! ";
//              cout << "\n element: "; this->Affiche(1);
//              cout << "\n fonction nD : "; pt_StabMembBiel->Pt_fct_gamma()->Affiche();
//              Sortie(1);
//             };
          }
         else
          {cout << "\n **** erreur, en mise en place de la stabilisation: "
                << " le mot cle: "<< bloc.Nom(3) << "n'est pas exploitable ";
           if (ParaGlob::NiveauImpression() > 2)
             cout << "\n ElemMeca::Complete_ElemMeca(..";
           Sortie(1);
          };
         // on regarde s'il y a des infos sur les limites
         int nb_info = (bloc.DimNom()-4)/2; // nombre de couples
         // on passe en revue les noms s'ils existent, > 4
         // on va de 2 en 2
         for (int i=1;i<= nb_info;i++)
           {if (bloc.Nom(3+i*2) == "affichage_stabilisation_")
             {pt_StabMembBiel->Change_affichage_stabilisation(ChangeEntier(bloc.Nom(4+i*2)));}
            else if (bloc.Nom(3+i*2) == "gestion_maxi_mini_")
             {pt_StabMembBiel->Change_gestion_maxi_mini(bool(ChangeEntier(bloc.Nom(4+i*2))));}
            else if (bloc.Nom(3+i*2) == "beta_")
             {pt_StabMembBiel->Change_beta(ChangeReel(bloc.Nom(4+i*2)));}
            else if (bloc.Nom(3+i*2) == "f_mini_")
             {pt_StabMembBiel->Change_f_mini(ChangeReel(bloc.Nom(4+i*2)));}
            else if (bloc.Nom(3+i*2) == "d_maxi_")
             {pt_StabMembBiel->Change_d_maxi(ChangeReel(bloc.Nom(4+i*2)));}
            else if (bloc.Nom(3+i*2) == "specifique_explicite_")
             {if (bloc.Nom(4+i*2) == "inactive_stabilisation_")
                pt_StabMembBiel->change_activite_en_explicite(false);
              else if (bloc.Nom(4+i*2) == "active_stabilisation_")
              pt_StabMembBiel->change_activite_en_explicite(true);
             }
            else if (bloc.Nom(3+i*2) == "ponderation_f_stab_t_")
             {// il s'agit d'une fonction nD: récupération de la fonction
              pt_StabMembBiel->Change_pt_fct_ponder_Ft(lesFonctionsnD->Trouve(bloc.Nom(4+i*2)));
              // on vérifie que c'est bien une fonction scalaire
              if (pt_StabMembBiel->Pt_fct_ponder_Ft()->NbComposante() != 1)
                 {cout << "\n *** erreur en mise en place de la stabilisation de membrane et/ou biel : "
                       << " la fonction nD " << bloc.Nom(4+i*2) << " n'est pas scalaire ";
                  cout << "\n element: "; this->Affiche(1);
                  cout << "\n fonction nD : "; pt_StabMembBiel->Pt_fct_ponder_Ft()->Affiche();
                  Sortie(1);
                 };
             }
           };
 
         return this;
        }
      // cas de la définition d'un repère d'anisotropie
      else if (bloc.Nom(1) == "repere_anisotropie_")
        {// pour l'instant le repère d'anisotropie est éventuellement
         // utilisable par la loi de comportement
         // 1) tout d'abord on doit définir le repère au niveau de chaque point d'intégration
         // définition d'un repère d'anisotropie à un point d'intégration
         // ici on ne fait que définir les conteneurs, la définition exacte des repères
         // ne se fera que pendant l'initialisation de l'algo et/ou pendant le calcul
         int nb_pti = lesPtIntegMecaInterne->NbPti();
         int dim = ParaGlob::Dimension();
         Coordonnee u(dim);
         Tableau <Coordonnee> tab_coor(dim,u);

         for (int ni=1;ni<= nb_pti;ni++)
           {// passage des infos
            if (tabSaveDon(ni) != NULL)
               tabSaveDon(ni)->Complete_SaveResul(bloc,tab_coor,loiComp);
           };
         return this;
        }

      // sinon rien  
      else
        { return NULL;};
    };       

// calcul de la contrainte modifiée en fonction du bulk viscosity
// ramène l'énergie par unité de volume, dépensée par le bulk
DeuxDoubles ElemMeca::ModifContrainteBulk(Enum_dure temps,const TenseurHH& gijHH,TenseurHH & sigHH
                                   ,const TenseurBB & DepsBB,TenseurHH & sigbulkHH )
  { DeuxDoubles ener_bulk_volumique; // pour le retour
    // on calcul la trace du tenseur de vitesse de déformation
    TenseurBH* DepsBH = NevezTenseurBH(DepsBB.Dimension());
    (*DepsBH) = DepsBB * gijHH; 
    double IDeps = DepsBH->Trace();
    // on intervient que si la trace est négative dans le cas où bulk_viscosity != 2
    //                                            ou dans tous les cas si == 2
    if ((bulk_viscosity == 2) || (IDeps < 0.))
     { // calcul d'une longueur caractéristique de l'élément
 //      cout << "\n c_carreBulk" << c_carreBulk << " c_traceBulk" << c_traceBulk << endl;
       double lon=this->LongueurGeometrique_mini(1); // cas 1 pour l'instant
       // on calcul la célérité       
       double cc = sqrt(ElemMeca::Calcul_maxi_E_qui(temps)/masse_volumique);
       // calcul de la pression
 //--     double q = masse_volumique * lon * ( c_carreBulk * lon * IDeps*IDeps + c_traceBulk * cc * IDeps );
 //-- modification car il y a une erreur / à la théorique concernant le signe de c_carreBulk
       double q = masse_volumique * lon * ( c_carreBulk * lon * IDeps*IDeps - c_traceBulk * cc * IDeps );
       // calcul de la modification du tenseur sigHH
 //--      sigHH += q * gijHH; 
       sigbulkHH = (-q) * gijHH; 
//--- debug
//cout << "\n sigbulkHH= " << sigbulkHH(1,1) << " 	sigHH= " << sigHH(1,1) 
//     << " lon="<<lon<<" cc="<< cc<<" q="<<q << " IDeps= " << IDeps << endl;
//--- fin debug	            
       sigHH += sigbulkHH;
       // -- on calcul également l'énergie par unité de volume non réversible visqueuse dépensée
       // on considère que la contrainte du bulk demeure constante sur l'incrément de temps
       // recup de l'incrément de temps
       double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
       ener_bulk_volumique.un = -q*IDeps*deltat;
       ener_bulk_volumique.deux = -q*IDeps;
     }
    else
     { sigbulkHH.Inita(0.);}; // dans le cas où le bulk n'est pas activé on le met à 0
    delete DepsBH;
    LibereTenseur();
    return ener_bulk_volumique;
   }; 
    
// récupération de la base locales au noeud noe, pour le temps: temps 
const BaseB & ElemMeca::Gib_elemeca(Enum_dure temps, const Noeud * noe)
   { int nb_noeud = tab_noeud.Taille(); // nombre de noeud de l'élément local
     // on fait une rotation sur les noeuds de l'élément 
     int num=1;
     for (num=1;num<= nb_noeud;num++)
       { if (noe == tab_noeud(num)) break; }
     // récupération des coordonnées locales du noeud
     ElemGeomC0& elem_geom = ElementGeometrique(); // recup de l'élément géométrique correspondant
     // récup de la référence des coordonnées locales du noeud num
     const Coordonnee & coo = elem_geom.PtelemRef()(num);
     // calcul de la dérivée des fonctions au point
     const Mat_pleine& ddphi = elem_geom.Dphi_point(coo);
     const Vecteur& pphi = elem_geom.Phi_point(coo);
     // en fonction du temps on calcul la base naturelle
     switch (temps)
      { case  TEMPS_0: return (met->BaseNat_0(tab_noeud,ddphi,pphi)); break;
        case  TEMPS_t: return (met->BaseNat_t(tab_noeud,ddphi,pphi)); break;
        case  TEMPS_tdt: return (met->BaseNat_tdt(tab_noeud,ddphi,pphi)); break;
       };
     // pour faire taire le compilateur
     cout << "\n erreur, on ne devrait jamais passer ici"
          << "\n ElemMeca::Gib_elemeca(...";
     Sortie(1);
     BaseB *toto = new BaseB(0);
     return (*toto);       
   };
   
// calcul du mini du module d'young équivalent pour tous les points d'intégrations
double ElemMeca::Calcul_mini_E_qui(Enum_dure temps)
 { double mini = 0.; // init
   int ni;
   for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
     { def->ChangeNumInteg(ni);def->Mise_a_jour_data_specif(tabSaveDefDon(ni));
       // si l'on a une thermo-dépendance il faut s'assurer que la température est mise à jour
       loiComp->Mise_a_jour_temperature(temps,*def);
       // indique également à la loi quelle valeur de saveResult il faut se référer
       double E_equi = loiComp->Module_young_equivalent(temps,*def,tabSaveDon(ni));
       if (E_equi < mini) mini = E_equi;
      }
   return mini;   
   };    
   
// calcul du  maxi du module d'young équivalent pour tous les points d'intégrations
double  ElemMeca::Calcul_maxi_E_qui(Enum_dure temps)
 { double maxi = 0.; // init
   int ni;
   for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
     { def->ChangeNumInteg(ni);def->Mise_a_jour_data_specif(tabSaveDefDon(ni));
       // si l'on a une thermo-dépendance il faut s'assurer que la température est mise à jour
       loiComp->Mise_a_jour_temperature(temps,*def);
      
       double E_equi = loiComp->Module_young_equivalent(temps,*def,tabSaveDon(ni));
       if (E_equi > maxi) maxi = E_equi;
      }
   return maxi;   
   };    

	    
        // cas d'un chargement aero-hydrodynamique, sur les frontières de l'élément 
        // Il y a trois forces: une suivant la direction de la vitesse: de type traînée aerodynamique
        // Fn = poids_volu * fn(V) * S * (normale*u) * u, u étant le vecteur directeur de V (donc unitaire)
        // une suivant la direction normale à la vitesse de type portance
        // Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire, normal à V, et dans le plan n et V
        // une suivant la vitesse tangente de type frottement visqueux
        // T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
        // retourne  le second membre résultant
        // calcul à l'instant tdt ou t en fonction de la variable atdt
        // coef_mul: est un coefficient multiplicateur global (de tout)
Vecteur& ElemMeca::SM_charge_hydrodyn_E (const double& poidvol,const Tableau <Vecteur>& taphi,int nbne
                                         ,Courbe1D* frot_fluid,const Vecteur& poids
                                         ,Courbe1D* coef_aero_n,int numfront,const double& coef_mul
                                         ,Courbe1D* coef_aero_t,const ParaAlgoControle & ,bool atdt)
   {  
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   




    // *** dans l'ensemble du sp on utilise des vecteurs et on gére directement la variance
    // *** sinon c'est intractable et long
    // remarque: l'initialisation du résidu n'est pas fait ici, mais dans les routines appelants
    Vecteur* SM_r;
    int dime = ParaGlob::Dimension();
    bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
                                  // donc il faut calculer tous les éléments de la métrique
    switch (dime)
     {case 3: // cas de la dimension 3
      { // définition du vecteur de retour 
        Vecteur& SM = *((*res_extS)(numfront));SM_r=&SM;
        // dans le cas ou le poid volumique est nul, on retourne sans calcul
        if (Dabs(poidvol) < ConstMath::trespetit) return SM;
        int ni; // compteur globale de point d'integration
        Deformation & defS = *defSurf(numfront); // pour simplifier l'écriture
    
        // éventuellement dimensionnement de la sauvegarde
        if (lesChargeExtSurEle == NULL)
          lesChargeExtSurEle = new LesChargeExtSurElement;
        if (lesChargeExtSurEle->LesHydroDyna() == NULL)
          {if(ParaGlob::AxiSymetrie())
            {lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());}
           else
            {lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbFe());}
          };
        Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
        if (tab_hydrodyna.Taille() != defS.Phi1_Taille())
          tab_hydrodyna.Change_taille(defS.Phi1_Taille());

        for (defS.PremierPtInteg(), ni = 1;defS.DernierPtInteg();defS.NevezPtInteg(),ni++)
         { // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
           // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
           Met_abstraite::Expli ex;
           if (atdt) {ex = (defS.Cal_explicit_tdt(premier_calcul)).Tdt_dans_t(); }
           else      {ex = defS.Cal_explicit_t(premier_calcul); };
           // détermination de la normale à la surface qui  vaut le produit vectoriel des 2 premiers vecteurs
                   // conversion explicite en coordonnées sans variance
           Coordonnee normale = Util::ProdVec_coorBN( (*ex.giB_t)(1), (*ex.giB_t)(2));
 //          cout << "\n normale avant normalisation";
 //          normale.Affiche();
           normale.Normer(); // on norme la normale
  //         cout << "\n normale après normalisation";
  //         normale.Affiche(); Sortie(1);

           // récupération de la vitesse
           const Coordonnee* Vp;
           if (atdt) {Vp = &(defS.VitesseM_tdt());} 
           else      {Vp = &(defS.VitesseM_t());};
           const Coordonnee& V = *Vp; double nV = V.Norme(); 
           // dans le cas où la vitesse est trop faible, le résidu est nul
           if (nV < ConstMath::trespetit) return SM;           
           Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
           double nVt = Vt.Norme(); // norme de la vitesse tangente
           if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
           Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
           double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
           Coordonnee w(3);
           if (coef_aero_t != NULL) 
             {w = Util::ProdVec_coor(u,Util::ProdVec_coor( u, normale));
              // si w est non nulle on le norme
              double norme_w = w.Norme();
              if (norme_w > ConstMath::trespetit) {w /= norme_w;};              
              };
           Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
           // calcul du résidu
           int ix=1; int dimf = 3;   // ne fonctionne qu'en dim 3  
           // cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
           double coef_frot_fluid=0.;
           if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_t);
                                     Fsauve.T += frot_fluid->Valeur(nVt) * Vt;};
           // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
           double coef_n=0.;
           if (coef_aero_n != NULL) 
              { coef_n += poidvol * coef_aero_n->Valeur(nV) *  poids(ni) * (*ex.jacobien_t) * cos_directeur;
                Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;};
           // cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
           double coef_t=0.;
           if (coef_aero_t != NULL) 
              { coef_t += poidvol * coef_aero_t->Valeur(nV) *  poids(ni) * (*ex.jacobien_t) * cos_directeur;
                Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
           for (int ne =1; ne<= nbne; ne++) 
             for (int i=1;i<= dimf;i++,ix++)
               { SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));};
          } // fin boucle sur les points d'intégrations
        break;   
      }; // fin du cas de la dimension 3
      case 2: // cas de la dimension 2
      { // définition du vecteur de retour 
        Vecteur& SM = *((*res_extA)(numfront));SM_r=&SM;
        // dans le cas ou le poid volumique est nul, on retourne sans calcul
        if (Dabs(poidvol) < ConstMath::trespetit) return SM;
        int ni; // compteur globale de point d'integration
        Deformation & defA = *defArete(numfront); // pour simplifier l'écriture
    
        // éventuellement dimensionnement de la sauvegarde
        if (lesChargeExtSurEle == NULL)
          lesChargeExtSurEle = new LesChargeExtSurElement;
        if (lesChargeExtSurEle->LesHydroDyna() == NULL)
          lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());
        Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
        if (tab_hydrodyna.Taille() != defA.Phi1_Taille())
          tab_hydrodyna.Change_taille(defA.Phi1_Taille());

        for (defA.PremierPtInteg(), ni = 1;defA.DernierPtInteg();defA.NevezPtInteg(),ni++)
         { // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
           // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
           Met_abstraite::Expli ex;
           if (atdt) {ex = (defA.Cal_explicit_tdt(premier_calcul)).Tdt_dans_t(); }
           else      {ex = defA.Cal_explicit_t(premier_calcul); };
           // détermination de la normale à la surface qui  vaut le vecteur perpendiculaire au g1
           // dans le sens directe 
           Coordonnee normale;  normale(1) = - (*ex.giB_t)(1)(2); normale(2) = (*ex.giB_t)(1)(1);
           normale.Normer(); // on norme la normale
           // récupération de la vitesse
           const Coordonnee* Vp;
           if (atdt) {Vp = &(defA.VitesseM_tdt());} 
           else      {Vp = &(defA.VitesseM_t());};
           const Coordonnee& V = *Vp; double nV = V.Norme();
           // dans le cas où la vitesse est trop faible, le résidu est nul
           if (nV < ConstMath::trespetit) return SM;           
           Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
           double nVt = Vt.Norme(); // norme de la vitesse tangente
           if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
           Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
           double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
           Coordonnee w(dime); // comme on est en 2D w ce calcul directement avec les composantes de u
           if (coef_aero_t != NULL) {w(1) = -u(2); w(2)=u(1);};
           Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
           // calcul du résidu
           int ix=1;      
           // cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
           double coef_frot_fluid=0.;
           if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_t);
                                     Fsauve.T+=frot_fluid->Valeur(nVt) * Vt;};
           // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
           double coef_n=0.;
           if (coef_aero_n != NULL) 
              { coef_n += poidvol * coef_aero_n->Valeur(nV) *  poids(ni) * (*ex.jacobien_t) * cos_directeur; 
                Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;};
           // cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
           double coef_t=0.;
           if (coef_aero_t != NULL) 
              { coef_t += poidvol * coef_aero_t->Valeur(nV) *  poids(ni) * (*ex.jacobien_t) * cos_directeur;
                Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
           for (int ne =1; ne<= nbne; ne++) 
             for (int i=1;i<= dime;i++,ix++)
               { SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));};
          } // fin boucle sur les points d'intégrations
         } // fin boucle sur les points d'intégrations
        break;   
      case 1: // cas de la dimension 1
      { // définition du vecteur de retour 
        Vecteur& SM = *((*res_extN)(numfront));SM_r=&SM;
        // dans le cas ou le poid volumique est nul, on retourne sans calcul
        if (Dabs(poidvol) < ConstMath::trespetit) return SM;
        // il n'y a pas plusieurs point d'intégration
        // en 1D il ne peut y avoir que deux extrémités, la première à une normale = -1 , la seconde 1
        Coordonnee normale(1); if (numfront == 1) {normale(1)=-1.;} else {normale(1)=1.;};
    
        // éventuellement dimensionnement de la sauvegarde
        if (lesChargeExtSurEle == NULL)
          lesChargeExtSurEle = new LesChargeExtSurElement;
        if (lesChargeExtSurEle->LesHydroDyna() == NULL)
          lesChargeExtSurEle->LesHydroDyna_Change_taille(2); // car deux extrémités au plus
        Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
        if (tab_hydrodyna.Taille() != 1)
          tab_hydrodyna.Change_taille(1); // un seul point d'intégration en un point !

        // récupération de la vitesse
        const Coordonnee* Vp;
        Noeud* noe = (tabb(posi_tab_front_point+numfront)->TabNoeud())(1); // on récupére tout d'abord le noeud fontière
        if (atdt) {Vp = &(def->VitesseM_tdt(noe));}   // on utilise la déformation générale, qui convient pour un noeud
        else      {Vp = &(def->VitesseM_t(noe));};
        const Coordonnee& V = *Vp; double nV = V.Norme();
        // dans le cas où la vitesse est trop faible, le résidu est nul
        if (nV < ConstMath::trespetit) return SM;
        // dans le cas 1D il n'y a qu'un effort de trainée (car pas de vitesse tangente)           
        Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
// inutile           double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
        Force_hydroDyna& Fsauve = tab_hydrodyna(1); // pour simplifier la sauvegarde
        // calcul du résidu
        int ix=1; int dimf = dime;     
        // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
        double coef_n=0.; 
        if (coef_aero_n != NULL) // le poids(1) contiend la section, et il n'y a pas de jacobien, cos directeur = 1
              { coef_n += poidvol * coef_aero_n->Valeur(nV) *  poids(1) ; 
                Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) ) * u ;};
        for (int ne =1; ne<= nbne; ne++)  // il n'y qu'un point d'intégration le noeud lui-même
          for (int i=1;i<= dimf;i++,ix++)
               { SM(ix) += taphi(1)(ne) * coef_mul * ( coef_n * u(i) );}; 
        break;   
      }; // fin du cas de la dimension 1 */
      
    }; //-- fin du switch sur la dimension  
    // retour du second membre  
    return *SM_r;  
  };
    
       // idem SM_charge_hydrodyn_E mais  -> implicite, 
	   // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur  
	   // retourne le second membre et la matrice de raideur correspondant
        // coef_mul: est un coefficient multiplicateur global (de tout)
Element::ResRaid ElemMeca::SM_charge_hydrodyn_I (const double& poidvol,const Tableau <Vecteur>& taphi,int nbne
                                         ,Courbe1D* frot_fluid,const Vecteur& poids,DdlElement & ddls
                                         ,Courbe1D* coef_aero_n,int numfront,const double& coef_mul
                                         ,Courbe1D* coef_aero_t,const ParaAlgoControle & pa)
   { 
   
   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************   
   
    
    // *** dans l'ensemble du sp on utilise des vecteurs et on gére directement la variance
    // *** sinon c'est intractable et long
    // remarque: l'initialisation du résidu n'est pas fait ici, mais dans les routines appelants
    Element::ResRaid el;               
    int nbddl = ddls.NbDdl();
    bool avec_raid = pa.Var_charge_externe();  // controle
//    // dans le cas où la variation sur la raideur est demandé on s'assure que la variation
//    // du jacobien est bien effective sinon on l'impose
//    ParaAlgoControle pa_nevez(pa);
//    if (!pa_nevez.Var_jacobien()) pa_nevez.Modif_Var_jacobien(true); 
    int dime = ParaGlob::Dimension();
    bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
                                  // donc il faut calculer tous les éléments de la métrique
    switch (dime)
     {case 3: // cas de la dimension 3
      { // dans le cas ou le poid volumique est nul, on retourne sans calcul
        if (Dabs(poidvol) < ConstMath::trespetit)
        {  el.res = (*res_extS)(numfront); el.raid = (*raid_extS)(numfront);       
           return el;
         };
        Vecteur& SM = (*((*res_extS)(numfront)));  //  pour simplifier
        Mat_pleine & KM = (*((*raid_extS)(numfront))); //  "      "       "
        el.res = (*res_extS)(numfront); el.raid = (*raid_extS)(numfront); // pour le retour
        int ni; // compteur globale de point d'integration
        Deformation & defS = *defSurf(numfront); // pour simplifier l'écriture
    
        // éventuellement dimensionnement de la sauvegarde
        if (lesChargeExtSurEle == NULL)
          lesChargeExtSurEle = new LesChargeExtSurElement;
        if (lesChargeExtSurEle->LesHydroDyna() == NULL)
          {if(ParaGlob::AxiSymetrie())
            {lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());}
           else
            {lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbFe());}
          };
        Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
        if (tab_hydrodyna.Taille() != defS.Phi1_Taille())
          tab_hydrodyna.Change_taille(defS.Phi1_Taille());

        for (defS.PremierPtInteg(), ni = 1;defS.DernierPtInteg();defS.NevezPtInteg(),ni++)
         { // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
           // que pour un calcul primaire en implicit mais pour un calcul autre que mécanique
           const Met_abstraite::Impli& ex = defS.Cal_implicit(premier_calcul); 
           // détermination de la normale à la surface qui  vaut le produit vectoriel des 2 premiers vecteurs
           Coordonnee normale = Util::ProdVec_coorBN( (*ex.giB_tdt)(1), (*ex.giB_tdt)(2));
           normale.Normer(); // on norme la normale
           // récupération de la vitesse
           const Coordonnee V = defS.VitesseM_tdt(); double nV = V.Norme(); 
           // dans le cas où la vitesse est trop faible, le résidu est nul
           if (nV < ConstMath::trespetit) return el;           
           Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
           double nVt = Vt.Norme(); // norme de la vitesse tangente
           if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
           Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
           double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
           Coordonnee w(3);double norme_w=0.;
			        Coordonnee vecNul(3); // un vecteur nul pour l'initialisation
           if (coef_aero_t != NULL) 
             {w = Util::ProdVec_coor(u,Util::ProdVec_coor( u, normale));
              // si w est non nulle on le norme
              norme_w = w.Norme();
              if (norme_w > ConstMath::trespetit) {w /= norme_w;};              
              };
           // calcul éventuel des variations
           static Tableau <Coordonnee> D_Vt,D_u,D_w,D_w_non_normer;
           static Tableau <double> D_coef_frot_fluid,D_coef_n,D_coef_t;
           if (avec_raid)
            { // calcul de la variation de la normale
              // 1) variation du produit vectoriel
              Tableau <Coordonnee > D_pasnormale = 
                  Util::VarProdVect_coor((*ex.giB_tdt)(1).Coor(),(*ex.giB_tdt)(2).Coor(),(*ex.d_giB_tdt));
              // 2) de la normale        
              Tableau <Coordonnee> D_normale = Util::VarUnVect_coor(normale,D_pasnormale,normale.Norme());
              // récupération de la variation de vitesse
              bool ddl_vitesse;
              const Tableau <Coordonnee> D_V = defS.Der_VitesseM_tdt(ddl_vitesse);
              D_Vt.Change_taille(nbddl); // calcul de la variation de la vitesse tangente
              for (int ii=1;ii<=nbddl;ii++)
               {D_Vt(ii)=D_V(ii) - (D_V(ii) * normale + V * D_normale(ii)) * normale
                                 - (V*normale) * D_normale(ii);};
              // variation de u
              D_u.Change_taille(nbddl); D_u = Util::VarUnVect_coor( V, D_V,nV);
              // variation de la norme de V
              Tableau <double> D_nV = Util::VarNorme(D_V,V,nV);
              // variation de w s'il a une norme différente de 0
              D_w.Change_taille(nbddl,vecNul); // !! init obligatoire car peut ne pas rentrer dans les if qui suivent
              if (norme_w > ConstMath::trespetit)
               {if (coef_aero_t != NULL)
                 { D_w_non_normer.Change_taille(nbddl);
					    // tout d'abord la variation du produit vectoriel 
                   Coordonnee k = Util::ProdVec_coor( u, normale);              
                   Tableau <Coordonnee> D_k = Util::VarProdVect_coor(u,normale,D_u,D_normale);
                   D_w_non_normer=Util::VarProdVect_coor(u,k,D_u,D_k);
                   D_w = Util::VarUnVect_coor(w,D_w_non_normer,norme_w);
                  }
               };
              // variation des coefficients
              // cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
              D_coef_frot_fluid.Change_taille(nbddl);
              if (frot_fluid != NULL) 
                { Courbe1D::ValDer valder = frot_fluid->Valeur_Et_derivee(nVt);
                  for (int i=1;i<=nbddl;i++) 
                    D_coef_frot_fluid(i) = valder.derivee * D_nV(i) * poids(ni) * (*ex.jacobien_tdt)
                                           + valder.valeur * poids(ni) * (*ex.d_jacobien_tdt)(i);
                 }; 
              // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
              D_coef_n.Change_taille(nbddl);
              if (coef_aero_n != NULL) 
                { Courbe1D::ValDer valder = coef_aero_n->Valeur_Et_derivee(nV);
                  for (int i=1;i<=nbddl;i++) 
                    D_coef_n(i) = poidvol *  poids(ni) * (
                                  valder.derivee * D_nV(i)  * (*ex.jacobien_tdt) * cos_directeur
                                  + valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur 
                                  + valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
                                                        );
                 };                                       
              // cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
              D_coef_t.Change_taille(nbddl);
              if (coef_aero_t != NULL) 
               { Courbe1D::ValDer valder = coef_aero_t->Valeur_Et_derivee(nV);
                 for (int i=1;i<=nbddl;i++) 
                    D_coef_t(i) = poidvol *  poids(ni) * (
                                  valder.derivee * D_nV(i)  * (*ex.jacobien_tdt) * cos_directeur
                                  + valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur 
                                  + valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
                                                      );
                };
              };  //-- fin du if (avec_raid)
           Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
           // calcul du résidu
           int ix=1; int dimf = 3;   // ne fonctionne qu'en dim 3  
           // cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
           double coef_frot_fluid=0.;
           if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_tdt);
                                     Fsauve.T += frot_fluid->Valeur(nVt) * Vt;}; 
           // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
           double coef_n=0.;
           if (coef_aero_n != NULL) 
              { coef_n += poidvol * coef_aero_n->Valeur(nV) *  poids(ni) * (*ex.jacobien_tdt) * cos_directeur;
                Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;}; 
           // cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
           double coef_t=0.;
           if (coef_aero_t != NULL) 
              { coef_t += poidvol * coef_aero_t->Valeur(nV) *  poids(ni) * (*ex.jacobien_tdt) * cos_directeur;
                Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
           for (int ne =1; ne<= nbne; ne++) 
             for (int i=1;i<= dimf;i++,ix++)
               { SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));
                 if (avec_raid)
                  {for (int j =1; j<= nbddl; j++)  
                     { //cout << "\n taphi(ni)(ne)= " << taphi(ni)(ne) << endl;
							  //cout << "\n D_coef_frot_fluid(j) " << D_coef_frot_fluid(j) << endl;
							  //cout << "\n Vt(i) " << Vt(i) << endl;
							  //cout << "\n D_Vt(j)(i) " << D_Vt(j)(i) << endl;
							  //cout << "\n D_coef_n(j) " << D_coef_n(j) << endl;
							  //cout << "\n u(i) " << u(i) << endl;
							  //cout << "\n D_u(j)(i) " << D_u(j)(i) << endl;
							  //cout << "\n D_coef_t(j) " << D_coef_t(j) << endl;
							  //cout << "\n w(i) " << w(i) << endl;
							  //cout << "\n D_w(j)(i) " << D_w(j)(i) << endl;
							  
							  KM(ix,j) -= taphi(ni)(ne) * coef_mul *(
                                     D_coef_frot_fluid(j) * Vt(i) + coef_frot_fluid * D_Vt(j)(i)
                                   + D_coef_n(j) * u(i) + coef_n * D_u(j)(i) 
                                   + D_coef_t(j) * w(i) + coef_t * D_w(j)(i)
                                                   ); 
                      };
                  };
                };  
          } // fin boucle sur les points d'intégrations
        break;   
      }; // fin du cas de la dimension 3
      case 2: // cas de la dimension 2
      { // dans le cas ou le poid volumique est nul, on retourne sans calcul
        if (Dabs(poidvol) < ConstMath::trespetit)
        {  el.res = (*res_extS)(numfront); el.raid = (*raid_extS)(numfront);       
           return el;
         };
        Vecteur& SM = (*((*res_extA)(numfront)));  //  pour simplifier
        Mat_pleine & KM = (*((*raid_extA)(numfront))); //  "      "       "
        el.res = (*res_extA)(numfront); el.raid = (*raid_extA)(numfront); // pour le retour
        int ni; // compteur globale de point d'integration
        Deformation & defA = *defArete(numfront); // pour simplifier l'écriture
    
        // éventuellement dimensionnement de la sauvegarde
        if (lesChargeExtSurEle == NULL)
          lesChargeExtSurEle = new LesChargeExtSurElement;
        if (lesChargeExtSurEle->LesHydroDyna() == NULL)
          lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());
        Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
        if (tab_hydrodyna.Taille() != defA.Phi1_Taille())
          tab_hydrodyna.Change_taille(defA.Phi1_Taille());

        for (defA.PremierPtInteg(), ni = 1;defA.DernierPtInteg();defA.NevezPtInteg(),ni++)
         { // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
           // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
           const Met_abstraite::Impli& ex = defA.Cal_implicit(premier_calcul); 
           // détermination de la normale à la surface qui  vaut le vecteur perpendiculaire au g1
           // dans le sens directe 
           Coordonnee normale;  normale(1) = -(*ex.giB_tdt)(1)(2); normale(2) = (*ex.giB_tdt)(1)(1);
           normale.Normer(); // on norme la normale
           // récupération de la vitesse
           const Coordonnee V = defA.VitesseM_tdt(); double nV = V.Norme(); 
           // dans le cas où la vitesse est trop faible, le résidu est nul
           if (nV < ConstMath::trespetit) return el;           
           Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
           double nVt = Vt.Norme(); // norme de la vitesse tangente
           if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
           Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
           double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
           Coordonnee w(dime); // comme on est en 2D, w ce calcul directement avec les composantes de u
           if (coef_aero_t != NULL) {w(1) = -u(2); w(2)=u(1);};
           // calcul éventuel des variations
           static Tableau <Coordonnee> D_Vt,D_u,D_w;
           static Tableau <double> D_coef_frot_fluid,D_coef_n,D_coef_t;
           if (avec_raid)
            { // calcul de la variation de la normale
              // 1) variation du produit vectoriel
              Tableau <Coordonnee > D_pasnormale(nbddl);
              for (int i=1;i<=nbddl;i++)
                {D_pasnormale(i)(1) = -(*ex.d_giB_tdt)(i)(1)(2); D_pasnormale(i)(2) = (*ex.d_giB_tdt)(i)(1)(1);};
              // 2) de la normale        
              Tableau <Coordonnee> D_normale = Util::VarUnVect_coor(normale,D_pasnormale,normale.Norme());
              // récupération de la variation de vitesse
              bool ddl_vitesse;
              const Tableau <Coordonnee> D_V = defA.Der_VitesseM_tdt(ddl_vitesse);
              D_Vt.Change_taille(nbddl); // calcul de la variation de la vitesse tangente
              for (int ii=1;ii<=nbddl;ii++)
               {D_Vt(ii)=D_V(ii) - (D_V(ii) * normale + V * D_normale(ii)) * normale
                                 - (V*normale) * D_normale(ii);};
              // variation de u
              D_u.Change_taille(nbddl); D_u = Util::VarUnVect_coor( V, D_V,nV);
              // variation de la norme de V
              Tableau <double> D_nV = Util::VarNorme(D_V,V,nV);
              // variation de w
              D_w.Change_taille(nbddl);
              if (coef_aero_t != NULL)
               { for (int i=1;i<=nbddl;i++) {D_w(i)(1)=-D_u(i)(2);D_w(i)(2)=D_u(i)(1);}; 
                } 
              // variation des coefficients
              // cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
              D_coef_frot_fluid.Change_taille(nbddl);
              if (frot_fluid != NULL) 
                { Courbe1D::ValDer valder = frot_fluid->Valeur_Et_derivee(nVt);
                  for (int i=1;i<=nbddl;i++) 
                    D_coef_frot_fluid(i) = valder.derivee * D_nV(i) * poids(ni) * (*ex.jacobien_tdt)
                                           + valder.valeur * poids(ni) * (*ex.d_jacobien_tdt)(i);
                 }; 
              // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
              D_coef_n.Change_taille(nbddl);
              if (coef_aero_n != NULL) 
                { Courbe1D::ValDer valder = coef_aero_n->Valeur_Et_derivee(nV);
                  for (int i=1;i<=nbddl;i++) 
                    D_coef_n(i) = poidvol *  poids(ni) * (
                                  valder.derivee * D_nV(i)  * (*ex.jacobien_tdt) * cos_directeur
                                  + valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur 
                                  + valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
                                                        );
                 };                                       
              // cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
              D_coef_t.Change_taille(nbddl);
              if (coef_aero_t != NULL) 
               { Courbe1D::ValDer valder = coef_aero_t->Valeur_Et_derivee(nV);
                 for (int i=1;i<=nbddl;i++) 
                    D_coef_t(i) = poidvol *  poids(ni) * (
                                  valder.derivee * D_nV(i)  * (*ex.jacobien_tdt) * cos_directeur
                                  + valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur 
                                  + valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
                                                      );
                };
              };  //-- fin du if (avec_raid)
           Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
           // calcul du résidu
           int ix=1;    
           // cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
           double coef_frot_fluid=0.;
           if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_tdt);
                                     Fsauve.T+=frot_fluid->Valeur(nVt) * Vt;};
 
           // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
           double coef_n=0.;
           if (coef_aero_n != NULL) 
              { coef_n += poidvol * coef_aero_n->Valeur(nV) *  poids(ni) * (*ex.jacobien_tdt) * cos_directeur; 
                Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;}; 
           // cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
           double coef_t=0.;
           if (coef_aero_t != NULL) 
              { coef_t += poidvol * coef_aero_t->Valeur(nV) *  poids(ni) * (*ex.jacobien_tdt) * cos_directeur;
                Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
           for (int ne =1; ne<= nbne; ne++) 
             for (int i=1;i<= dime;i++,ix++)
               { SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));
                 if (avec_raid)
                  {for (int j =1; j<= nbddl; j++)  
                     {KM(ix,j) -= taphi(ni)(ne) * coef_mul * (
                                     D_coef_frot_fluid(j) * Vt(i) + coef_frot_fluid * D_Vt(j)(i)
                                   + D_coef_n(j) * u(i) + coef_n * D_u(j)(i) 
                                   + D_coef_t(j) * w(i) + coef_t * D_w(j)(i)
                                                   ); 
                      };
                  };
                };  
          } // fin boucle sur les points d'intégrations
        break; 
        };  
      case 1: // cas de la dimension 1
      { // dans le cas ou le poid volumique est nul, on retourne sans calcul
        if (Dabs(poidvol) < ConstMath::trespetit)
        {  Element::ResRaid el;    
           el.res = (*res_extN)(numfront); 
           el.raid = (*raid_extN)(numfront);       
           return el;
         };
        Vecteur& SM = (*((*res_extN)(numfront)));  //  pour simplifier
        Mat_pleine & KM = (*((*raid_extN)(numfront))); //  "      "       "
        el.res = (*res_extN)(numfront); el.raid = (*raid_extN)(numfront); // pour le retour
        // il n'y a pas plusieurs point d'intégration
        // en 1D il ne peut y avoir que deux extrémités, la première à une normale = -1 , la seconde 1
        Coordonnee normale(1); if (numfront == 1) {normale(1)=-1.;} else {normale(1)=1.;};
    
        // éventuellement dimensionnement de la sauvegarde
        if (lesChargeExtSurEle == NULL)
          lesChargeExtSurEle = new LesChargeExtSurElement;
        if (lesChargeExtSurEle->LesHydroDyna() == NULL)
          lesChargeExtSurEle->LesHydroDyna_Change_taille(2); // car deux extrémités au plus
        Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
        if (tab_hydrodyna.Taille() != 1)
          tab_hydrodyna.Change_taille(1); // un seul point d'intégration en un point !

        // récupération de la vitesse
        Noeud* noe = (tabb(posi_tab_front_point+numfront)->TabNoeud())(1); // on récupére tout d'abord le noeud fontière
        const Coordonnee& V = def->VitesseM_tdt(noe); double nV = V.Norme();
        // dans le cas où la vitesse est trop faible, le résidu est nul
        if (nV < ConstMath::trespetit) return el;
        // dans le cas 1D il n'y a qu'un effort de trainée (car pas de vitesse tangente)           
        Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
        // u en fait = 1 ou -1 d'où variation = 0
        // calcul éventuel des variations
        static Tableau <double> D_coef_n;
        if (avec_raid)
            { // calcul de la variation de la normale
              // récupération de la variation de vitesse
              bool ddl_vitesse;
              const Tableau <Coordonnee> D_V = def->Der_VitesseM_tdt(ddl_vitesse,noe);
              // variation de la norme de V
              Tableau <double> D_nV = Util::VarNorme(D_V,V,nV);
              // variation des coefficients
              // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
              D_coef_n.Change_taille(nbddl);
              if (coef_aero_n != NULL) 
                { Courbe1D::ValDer valder = coef_aero_n->Valeur_Et_derivee(nV);
                  for (int i=1;i<=nbddl;i++) 
                    D_coef_n(i) = poidvol *  poids(1) * valder.derivee * D_nV(i);
                 };                                       
            };  //-- fin du if (avec_raid)
           Force_hydroDyna& Fsauve = tab_hydrodyna(1); // pour simplifier la sauvegarde
        // calcul du résidu
        int ix=1; int dimf = dime;     
        // cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
        double coef_n=0.; 
        if (coef_aero_n != NULL) // le poids(1) contiend la section, et il n'y a pas de jacobien, cos directeur = 1
              { coef_n += poidvol * coef_mul * coef_aero_n->Valeur(nV) *  poids(1) ; 
                Fsauve.F_n = (poidvol * coef_aero_n->Valeur(nV) ) * u ;}; 
        for (int ne =1; ne<= nbne; ne++)  // il n'y qu'un point d'intégration le noeud lui-même
          for (int i=1;i<= dimf;i++,ix++)
               { SM(ix) += taphi(1)(ne) * ( coef_n * u(i) );
                 if (avec_raid)
                  {for (int j =1; j<= nbddl; j++)  
                     {KM(ix,j) -= taphi(1)(ne) * coef_mul * (D_coef_n(j) * u(i));}; 
                  };
               }; 
        break;   
      }; // fin du cas de la dimension 1 */
      
    }; //-- fin du switch sur la dimension  
    // retour   
    return el;  
  };
    	    
