// FICHIER : PentaMemb.cc
// CLASSE : PentaMemb

// 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 <iostream>
using namespace std;  //introduces namespace std
#include <stdlib.h>
#include "Sortie.h"
#include "FrontQuadLine.h"

#include "PentaMemb.h"
#include "TypeConsTens.h"
#include "FrontPointF.h"

// -------------- definition de la classe conteneur de donnees communes ------------	
PentaMemb::DonnComPenta::DonnComPenta 
        (ElemGeomC0* penta1,DdlElement& tab,DdlElement&  tabErr,DdlElement&  tab_Err1Sig,
         Met_abstraite&  met_gene,Tableau <Vecteur *> & resEr,Mat_pleine& raidEr,
         ElemGeomC0* pentaeEr,GeomQuadrangle quadS,GeomTriangle triS,
         GeomSeg& seggHS,GeomSeg& seggFS,
         Vecteur&  residu_int,Mat_pleine&  raideur_int,
         Tableau <Vecteur* > & residus_extN,Tableau <Mat_pleine* >&  raideurs_extN,
         Tableau <Vecteur* > & residus_extA,Tableau <Mat_pleine* >&  raideurs_extA,
         Tableau <Vecteur* >&  residus_extS,Tableau <Mat_pleine* >&  raideurs_extS,
         Mat_pleine&  mat_masse,ElemGeomC0* pentaeMas,int nbi,ElemGeomC0* pentaeHourg
         ) :
	          tab_ddl(tab),tab_ddlErr(tabErr),tab_Err1Sig11(tab_Err1Sig),metrique(met_gene)
	          ,matGeom(tab.NbDdl(),tab.NbDdl()),matInit(tab.NbDdl(),tab.NbDdl())
	          ,d_epsBB(tab.NbDdl()),d_sigHH(tab.NbDdl()),d2_epsBB(nbi)
	          ,resErr(resEr),raidErr(raidEr)
	          ,quadraS(quadS),triaS(triS),segHS(seggHS),segFS(seggFS)
	          ,residu_interne(residu_int),raideur_interne(raideur_int)
	          ,residus_externeN(residus_extN),raideurs_externeN(raideurs_extN)
	          ,residus_externeA(residus_extA),raideurs_externeA(raideurs_extA)
	          ,residus_externeS(residus_extS),raideurs_externeS(raideurs_extS)
	          ,matrice_masse(mat_masse),pentaedHourg(pentaeHourg)
	            { pentaed = penta1; pentaedEr=pentaeEr ;pentaedMas=pentaeMas ; 
               int nbddl = tab.NbDdl();
               for (int ni=1;ni<=nbi;ni++)
                {d2_epsBB(ni).Change_taille(nbddl);
                 for (int i1=1; i1<= nbddl; i1++)
                  for (int i2=1; i2<= nbddl; i2++)
                   d2_epsBB(ni)(i1,i2) = NevezTenseurBB (3);
                };
               int tailledeps = d_epsBB.Taille();
	              for (int i=1;i<= tailledeps; i++)
	                  d_epsBB(i) = NevezTenseurBB (3);
               int tailledsig = d_sigHH.Taille();
	              for (int j=1;j<= tailledsig; j++)
	                 d_sigHH(j) = NevezTenseurHH (3);
             };
// Il ne doit exister  qu'un exemplaire de la classe, donc au niveau du constructeur de copie les tableaux
// de pointeurs pointes sur les mêmes entités que la valeur passée en paramètre	              
PentaMemb::DonnComPenta::DonnComPenta(DonnComPenta& a) :
	    pentaed(a.pentaed), tab_ddl(a.tab_ddl),tab_ddlErr(a.tab_ddlErr)
	    ,tab_Err1Sig11(a.tab_Err1Sig11),
	     metrique(a.metrique)
	    ,matGeom(a.matGeom),matInit(a.matInit),d2_epsBB(a.d2_epsBB)
	    ,resErr(a.resErr),raidErr(a.raidErr)
	    ,quadraS(a.quadraS),triaS(a.triaS),segHS(a.segHS),segFS(a.segFS)
	    ,pentaedEr(a.pentaedEr)
	    ,d_epsBB(a.d_epsBB),d_sigHH(a.d_sigHH)
	    ,residu_interne(a.residu_interne),raideur_interne(a.raideur_interne)
	    ,residus_externeN(a.residus_externeN),raideurs_externeN(a.raideurs_externeN)
	    ,residus_externeA(a.residus_externeA),raideurs_externeA(a.raideurs_externeA)
	    ,residus_externeS(a.residus_externeS),raideurs_externeS(a.raideurs_externeS)
	    ,matrice_masse(a.matrice_masse),pentaedMas(a.pentaedMas)
	    ,pentaedHourg(a.pentaedHourg)		 
	       { int nbddl = d_sigHH.Taille();
	         int nbi=d2_epsBB.Taille();
	         for (int ni=1;ni<=nbi;ni++)
            for (int i1=1; i1<= nbddl; i1++)
               for (int i2=1; i2<= nbddl; i2++)
                 d2_epsBB(ni)(i1,i2) = NevezTenseurBB (*(a.d2_epsBB(ni)(i1,i2)));
          int tailledeps = d_epsBB.Taille();
	         for (int i=1;i<= tailledeps; i++)
	             d_epsBB(i) = NevezTenseurBB (3);
          int tailledsig = d_sigHH.Taille();
	         for (int j=1;j<= tailledsig; j++)
	            d_sigHH(j) = NevezTenseurHH (3);
	       };
PentaMemb::DonnComPenta::~DonnComPenta()
    { int nbddl = tab_ddl.NbDdl();      
	     int nbi=d2_epsBB.Taille();
	     for (int ni=1;ni<=nbi;ni++)
       for (int i1=1; i1<= nbddl; i1++)
        for (int i2=1; i2<= nbddl; i2++)
          delete d2_epsBB(ni)(i1,i2);
      int tailledeps = d_epsBB.Taille();
	     for (int i=1;i<= tailledeps; i++)
	       delete d_epsBB(i);
      int tailledsig = d_sigHH.Taille();
	     for (int j=1;j<= tailledsig; j++)
	       delete d_sigHH(j);
   };

// ---------- fin definition de la  classe conteneur de donnees communes ------------	
// -+-+ definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
PentaMemb::UneFois::UneFois () : // constructeur par défaut
	doCoMemb(NULL),CalResPrem_t(0),CalResPrem_tdt(0),CalimpPrem(0),dualSortPenta(0)
	,CalSMlin_t(0),CalSMlin_tdt(0),CalSMRlin(0)
	,CalSMsurf_t(),CalSMsurf_tdt(),CalSMRsurf()
	,CalSMvol_t(0),CalSMvol_tdt(0),CalSMvol(0)
	,CalDynamique(0),CalPt_0_t_tdt(0)
	,nbelem_in_Prog(0)
	        {};
PentaMemb::UneFois::~UneFois ()
	 {	  delete doCoMemb;
	 };   

// -+-+ fin definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
	            

// CONSTRUCTEURS :
	// Constructeur par defaut
PentaMemb::PentaMemb () :
   ElemMeca(),lesPtMecaInt(),unefois(NULL),nombre(NULL)
  { lesPtIntegMecaInterne = &lesPtMecaInt; //  association avec le pointeur d'ElemMeca  
  };
// Constructeur fonction  d'un numero
// d'identification , d'identificateur d'interpolation et de geometrie 
PentaMemb::PentaMemb (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,string info) :
     ElemMeca(num_mail,num_id,id_interp_elt,id_geom_elt,info),lesPtMecaInt()
	    ,unefois(NULL),nombre(NULL)
       { lesPtIntegMecaInterne = &lesPtMecaInt; //  association avec le pointeur d'ElemMeca
       };
		
// Constructeur fonction  d'un numero de maillage et d'identification,
// du tableau de connexite des noeuds, d'identificateur d'interpolation et de geometrie
PentaMemb::PentaMemb (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,
                     const Tableau<Noeud *>& tab,string info) :
     ElemMeca(num_mail,num_id,tab,id_interp_elt,id_geom_elt,info),lesPtMecaInt()
     ,unefois(NULL),nombre(NULL)
       { lesPtIntegMecaInterne = &lesPtMecaInt; //  association avec le pointeur d'ElemMeca
       };
// Constructeur de copie
PentaMemb::PentaMemb (const PentaMemb& pentaMemb) :
 ElemMeca (pentaMemb)
 ,unefois(pentaMemb.unefois),nombre(pentaMemb.nombre)
 ,lesPtMecaInt(pentaMemb.lesPtMecaInt)
   { lesPtIntegMecaInterne = &lesPtMecaInt; //  association avec le pointeur d'ElemMeca
   		// --- cas des différentes  puissances et ... ---
     PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb; // pour simplifier l'écriture
     residu = &(CoPenta->residu_interne); // residu local
     raideur = &(CoPenta->raideur_interne); // raideur locale
	    // --- cas de la dynamique -----
	    mat_masse =  &(CoPenta->matrice_masse);
		   // --- cas des efforts externes concernant noeuds ------
     res_extN = &(CoPenta->residus_externeN); // pour les résidus et second membres
     raid_extN= &(CoPenta->raideurs_externeN);// pour les raideurs
		   // --- cas des efforts externes concernant les aretes ------
	    res_extA = &(CoPenta->residus_externeA); // pour les résidus et second membres
	    raid_extA= &(CoPenta->raideurs_externeA);// pour les raideurs
		   // --- cas des efforts externes concernant les faces  ------
	    res_extS= &(CoPenta->residus_externeS); // pour les résidus et second membres
	    raid_extS= &(CoPenta->raideurs_externeS); // pour les raideurs
  };   
	
// DESTRUCTEUR :
PentaMemb::~PentaMemb ()
{ /*  // on va libérer les déformations d'arrête et des surfaces qui sont un peu particulières
  if (defArete.Taille() != 0)
   if (defArete(1) != NULL) 
    { delete defArete(1);
      // on remet à null les pointeurs pour un appel correcte du destructeur d'elemMeca
      for (int ia=1;ia<= 9; ia++)
        defArete(ia) = NULL; 
     }    
  if (defSurf.Taille() != 0)
  { // ici on a une déformation par face il faut donc les supprimer un par un
    int nbdefSurf = defSurf.Taille();
    for (int i = 1; i<= nbdefSurf; i++) 
       if (defSurf(i) != NULL) {delete defSurf(i); defSurf(i) = NULL;} 
    }   */  
  LibereTenseur();
 };


// Lecture des donnees de la classe sur fichier
void PentaMemb::LectureDonneesParticulieres 
    (UtilLecture * entreePrinc,Tableau<Noeud  *> * tabMaillageNoeud)
  { int nb; int nbne = nombre-> nbne;
    tab_noeud.Change_taille(nbne);
    for (int i=1; i<= nbne; i++)
     { *(entreePrinc->entree) >> nb;
       if ((entreePrinc->entree)->rdstate() == 0) 
       // pour mémoire ici on a 
           /*       enum io_state
                    {  badbit   = 1<<0, // -> 1 dans rdstate()
                       eofbit   = 1<<1, // -> 2 
                       failbit  = 1<<2, // -> 4 
                       goodbit  = 0     // -> O 
                     };*/
          tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
      #ifdef ENLINUX
      else  if ((entreePrinc->entree)->fail())
               // on a atteind la fin de la ligne et on appelle un nouvel enregistrement 
          {   entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
               *(entreePrinc->entree) >> nb;
              tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
          }
      #else
   /*   #ifdef SYSTEM_MAC_OS_X_unix
       else  if ((entreePrinc->entree)->fail())
               // on a atteind la fin de la ligne et on appelle un nouvel enregistrement 
          {   entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
               *(entreePrinc->entree) >> nb;
              tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
              }
      #else*/
      else  if ((entreePrinc->entree)->eof())
        // la lecture est bonne mais on a atteind la fin de la ligne
        {  tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture
           // si ce n'est pas la fin de la lecture on appelle un nouvel enregistrement 
           if (i != nbne) entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
        }
   //   #endif  
      #endif
      else // cas d'une erreur de lecture
        { cout << "\n erreur de lecture inconnue  ";
          entreePrinc->MessageBuffer("** lecture des données particulières **");
          cout << "PentaMemb::LecDonPart"; 
          Affiche();
          Sortie (1);
        };
     }
    // construction du tableau de ddl des noeuds de PentaMemb
    ConstTabDdl(); 
  };
  		
// calcul d'un point dans l'élément réel en fonction des coordonnées dans l'élément de référence associé
// temps: indique si l'on veut les coordonnées à t = 0, ou t ou tdt
// 1) cas où l'on utilise la place passée en argument
Coordonnee & PentaMemb::Point_physique(const Coordonnee& c_int,Coordonnee & co,Enum_dure temps)
 { PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
   // a) on commence par définir les bonnes grandeurs dans la métrique
   if( !(unefois->CalPt_0_t_tdt ))
      { unefois->CalPt_0_t_tdt += 1;
        Tableau<Enum_variable_metrique> tab(3);
        tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt;
        doCoPenta->metrique.PlusInitVariables(tab) ;
       };  
   // b) calcul de l'interpolation 
   const Vecteur& phi = doCoPenta->pentaed->Phi_point(c_int);
   // c) calcul du point
   switch (temps)
    { case TEMPS_0 : co = met->PointM_0(tab_noeud,phi); break;
      case TEMPS_t : co = met->PointM_t(tab_noeud,phi); break;
      case TEMPS_tdt : co = met->PointM_tdt(tab_noeud,phi); break;
     }       
   // d) retour
   return co;  
  };
  
// 3) cas où l'on veut les coordonnées aux 1, 2 ou trois temps selon la taille du tableau t_co
void PentaMemb::Point_physique(const Coordonnee& c_int,Tableau <Coordonnee> & t_co)
 { PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
   // a) on commence par définir les bonnes grandeurs dans la métrique
   if( !(unefois->CalPt_0_t_tdt ))
      { unefois->CalPt_0_t_tdt += 1;
        Tableau<Enum_variable_metrique> tab(3);
        tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt;
        doCoPenta->metrique.PlusInitVariables(tab) ;
       };  
   // b) calcul de l'interpolation 
   const Vecteur& phi = doCoPenta->pentaed->Phi_point(c_int);
   // c) calcul des point
   switch (t_co.Taille())
    { case 3 : t_co(3) = met->PointM_tdt(tab_noeud,phi); 
      case 2 : t_co(2) = met->PointM_t(tab_noeud,phi); 
      case 1 : t_co(1) = met->PointM_0(tab_noeud,phi); 
     }       
  };

// Calcul du residu local à t ou tdt en fonction du booleen atdt
Vecteur* PentaMemb::CalculResidu (bool atdt,const ParaAlgoControle & pa)

    {  PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
       Tableau <TenseurBB *>& d_epsBB = unefois->doCoMemb->d_epsBB;
       // dimensionnement de la metrique
       if (!atdt)
       {if(!( unefois->CalResPrem_t))
        { unefois->CalResPrem_t += 1;
         Tableau<Enum_variable_metrique> tab(10);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
          doCoPenta->metrique.PlusInitVariables(tab) ;
         };}  
       else 
       {if( !(unefois->CalResPrem_tdt ))
        {unefois->CalResPrem_tdt += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
         tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_tdt;tab(11) = iVtdt; 
         doCoPenta->metrique.PlusInitVariables(tab) ;
         };};  
       // initialisation du résidu 
       residu->Zero();  
       ElemMeca::Cal_explicit 
            (doCoPenta->tab_ddl,d_epsBB,nombre->nbI,(doCoPenta->pentaed)->TaWi(),pa,atdt);
       return residu;  
     };
  

// Calcul du residu local et de la raideur locale,
//  pour le schema implicite
Element::ResRaid  PentaMemb::Calcul_implicit (const ParaAlgoControle & pa)

    { PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
      Tableau <TenseurBB *>& d_epsBB = unefois->doCoMemb->d_epsBB;
      Tableau <TenseurHH *>& d_sigHH = unefois->doCoMemb->d_sigHH;
     // dans le cas ou cas=true on enchaine les deux cas, sinon uniquement le second cas
      bool cald_Dvirtuelle = false;
      if (!(unefois->CalimpPrem))
       { unefois->CalimpPrem += 1;
         Tableau<Enum_variable_metrique> tab(20);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
         tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
         doCoPenta->metrique.PlusInitVariables(tab) ;
         // on ne calcul la dérivée de la déformation virtuelle qu'une fois
         // car elle est constante dans le temps et indépendante des coordonnées
         cald_Dvirtuelle=true; 
        };

       // initialisation du résidu
       residu->Zero();   
       // initialisation de la raideur      
       raideur->Zero();       
       ElemMeca::Cal_implicit(doCoPenta->tab_ddl, d_epsBB,(doCoPenta->d2_epsBB),d_sigHH
                             ,nombre->nbI,(doCoPenta->pentaed)->TaWi(),pa,cald_Dvirtuelle);
       Element::ResRaid el;
       el.res = residu; 
       el.raid = raideur;       
       return el;
  };
		
// Calcul de la matrice masse pour l'élément
Mat_pleine * PentaMemb::CalculMatriceMasse (Enum_calcul_masse type_calcul_masse) 
 {    PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
      // dimensionement de la métrique si nécessaire
      if (!(unefois->CalDynamique ))
       { unefois->CalDynamique += 1;
         Tableau<Enum_variable_metrique> tab(5);
         tab(1) = igiB_0;  tab(2) = igiB_tdt; tab(3) = igijBB_0;
         tab(4) = igijBB_tdt; tab(5) = igradVmoyBB_t; 
         doCoPenta->metrique.PlusInitVariables(tab) ;
         // on vérifie le bon dimensionnement de la matrice
         if (type_calcul_masse == MASSE_CONSISTANTE)
           // dans le cas où la masse est consistante il faut la redimensionner
          { int nbddl = doCoPenta->tab_ddl.NbDdl();
            (doCoPenta->matrice_masse).Initialise (nbddl,nbddl,0.);
           } 
        };
       // appel de la routine générale 
       ElemMeca::Cal_Mat_masse (doCoPenta->tab_ddl,type_calcul_masse,
                            nombre->nbiMas,(doCoPenta->pentaedMas)->TaPhi(),nombre->nbne
                            ,(doCoPenta->pentaedMas)->TaWi());
       return mat_masse;                     
  };
		

//============= lecture écriture dans base info ==========
	
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void PentaMemb::Lecture_base_info
    (ifstream& ent,const Tableau<Noeud  *> * tabMaillageNoeud,const int cas) 
{// tout d'abord appel de la lecture de la classe elem_meca
 ElemMeca::Lecture_bas_inf(ent,tabMaillageNoeud,cas);
 // traitement du cas particulier de l'élément 
 switch (cas)
  { case 1 : // ------- on récupère tout -------------------------
     { // construction du tableau de ddl des noeuds du triangle
       ConstTabDdl(); 
       // récup contraintes et déformation
       lesPtMecaInt.Lecture_base_info(ent,cas);
       break;
     }
    case  2 : // ----------- lecture uniquement de se qui varie --------------------
     { // récup contraintes et déformation
       lesPtMecaInt.Lecture_base_info(ent,cas);
       break;
     }
    default :
     { cout << "\nErreur : valeur incorrecte du type de lecture !\n";
       cout << "PentaMemb::Lecture_base_info(ifstream& ent,const "
            << "Tableau<Noeud  *> * tabMaillageNoeud,const int cas)"
            << " cas= " << cas << endl;
       Sortie(1);
     };
  };
};
  
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void PentaMemb::Ecriture_base_info(ofstream& sort,const int cas) 
{// tout d'abord appel de l'écriture de la classe elem_meca
 ElemMeca::Ecriture_bas_inf(sort,cas);
 // traitement du cas particulier de l'élément 
 switch (cas)
  { case 1 : // ------- on sauvegarde tout -------------------------
     { 
       // des tenseurs déformation et contrainte,
       lesPtMecaInt.Ecriture_base_info(sort,cas);
	   break;
	 }
    case  2 : // ----------- sauvegarde uniquement de se qui varie --------------------
     { // des tenseurs déformation et contrainte, 
       lesPtMecaInt.Ecriture_base_info(sort,cas);
	   break;
	 }
    default :
	 { cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
	   cout << "PentaMemb::Ecriture_base_info(ofstream& sort,const int cas)"
			<< " cas= " << cas << endl;
	   Sortie(1);
	  }
   }
  };

// récupération des  valeurs au numéro d'ordre  = iteg pour
// les grandeur enu
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
Tableau <double> PentaMemb::Valeur_a_diff_temps(bool absolue,Enum_dure enu_t,const List_io<Ddl_enum_etendu>& enu,int iteg)
    { // appel de la procedure de elem meca
	  int cas;       
      if (!(unefois->dualSortPenta) && (unefois->CalimpPrem))
        { cas=1;unefois->dualSortPenta += 1;
         } 
      else if ((unefois->dualSortPenta) && (unefois->CalimpPrem))       
         { cas = 11;}
      else if (!(unefois->dualSortPenta) && (unefois->CalResPrem_tdt))       
        { cas=2;unefois->dualSortPenta += 1;
         }         
      else if ((unefois->dualSortPenta) && (unefois->CalResPrem_tdt))       
         { cas = 12;}
      // sinon problème
      else
        { cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul"
               << " pour inialiser les conteneurs des tenseurs  resultats ";
          if (ParaGlob::NiveauImpression() >= 4)     
            cout << "\n cas non prévu, unefois->dualSortPenta= " << unefois->dualSortPenta
               << " unefois->CalimpPrem= " << unefois->CalimpPrem
               << "\n PentaMemb::Valeur_a_diff_temps(Enum_dure enu_t...";
          Sortie(1);
         };       
      return ElemMeca::Valeur_multi(absolue,enu_t,enu,iteg,cas);
    };

// récupération des valeurs au numéro d'ordre = iteg pour les grandeurs enu
// ici il s'agit de grandeurs tensorielles, le retour s'effectue dans la liste
// de conteneurs quelconque associée
void PentaMemb::ValTensorielle_a_diff_temps(bool absolue,Enum_dure enu_t,List_io<TypeQuelconque>& enu,int iteg)
    { // appel de la procedure de elem meca
	  int cas;       
      if (!(unefois->dualSortPenta) && (unefois->CalimpPrem))
        { cas=1;unefois->dualSortPenta += 1;
         } 
      else if ((unefois->dualSortPenta) && (unefois->CalimpPrem))       
         { cas = 11;}
      else if (!(unefois->dualSortPenta) && (unefois->CalResPrem_tdt))       
        { cas=2;unefois->dualSortPenta += 1;
         }         
      else if ((unefois->dualSortPenta) && (unefois->CalResPrem_tdt))       
         { cas = 12;}
      // sinon problème
      else
        { cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul"
               << " pour inialiser les conteneurs des tenseurs  resultats ";
          if (ParaGlob::NiveauImpression() >= 4)     
            cout << "\n cas non prévu, unefois->dualSortPenta= " << unefois->dualSortPenta
               << " unefois->CalimpPrem= " << unefois->CalimpPrem
               << "\n PentaMemb::ValTensorielle_a_diff_temps(Enum_dure enu_t...";
          Sortie(1);
         };       
      ElemMeca::Valeurs_Tensorielles(absolue,enu_t,enu,iteg,cas);
    };

// calcul du résidu et de la matrice de raideur pour le calcul d'erreur
 Element::Er_ResRaid   PentaMemb::ContrainteAuNoeud_ResRaid()

    {  PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
       // dimensionnement de la metrique
       if(!( unefois->CalResPrem_t ))
       { unefois->CalResPrem_t += 1;
         Tableau<Enum_variable_metrique> tab(10);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
         doCoPenta->metrique.PlusInitVariables(tab) ;
        };  
       // appel du programme général
        ElemMeca:: SigmaAuNoeud_ResRaid(tab_noeud.Taille(),
               (doCoPenta->pentaed)->TaPhi(),
                  (doCoPenta->pentaed)->TaWi(),
                  doCoPenta-> resErr,doCoPenta->raidErr,
                  (doCoPenta->pentaedEr)->TaPhi(),
                  (doCoPenta->pentaedEr)->TaWi());
      return    (Element::Er_ResRaid( &(doCoPenta-> resErr),&(doCoPenta->raidErr)));       
     } ;

// calcul du résidu  pour le calcul d'erreur ramenée aux noeuds
Element::Er_ResRaid   PentaMemb::ErreurAuNoeud_ResRaid()

    { PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
      // dimensionnement de la metrique
       if(!( unefois->CalResPrem_t ))
       { unefois->CalResPrem_t += 1;
         Tableau<Enum_variable_metrique> tab(10);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
         doCoPenta->metrique.PlusInitVariables(tab) ;
        };  
      // appel du programme général
      ElemMeca::Cal_ErrAuxNoeuds(tab_noeud.Taille(),
                (doCoPenta->pentaed)->TaPhi(),(doCoPenta->pentaed)->TaWi()
                ,doCoPenta-> resErr );
      return    (Element::Er_ResRaid( &(doCoPenta-> resErr),&(doCoPenta->raidErr)));       
     } ;
     
// actualisation des ddl et des grandeurs actives de t+dt vers t      
void PentaMemb::TdtversT()
 { lesPtMecaInt.TdtversT(); // contrainte 
   for (int ni=1;ni<= nombre->nbI; ni++)
      {if (tabSaveDon(ni) != NULL)  tabSaveDon(ni)->TdtversT();
       if (tabSaveTP(ni) != NULL)  tabSaveTP(ni)->TdtversT();
       if (tabSaveDefDon(ni) != NULL)  tabSaveDefDon(ni)->TdtversT();
        }
   ElemMeca::TdtversT_(); // appel de la procédure mère
  };
// actualisation des ddl et des grandeurs actives de t vers tdt      
void PentaMemb::TversTdt()
 { lesPtMecaInt.TversTdt(); // contrainte
   for (int ni=1;ni<= nombre->nbI; ni++)
     {if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TversTdt();
      if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TversTdt();
      if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TversTdt();
       }
   ElemMeca::TversTdt_(); // appel de la procédure mère
  };

// calcul de l'erreur sur l'élément.
void PentaMemb::ErreurElement(int type,double& errElemRelative
                            ,double& numerateur, double& denominateur)
 
    { PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
      Tableau <TenseurBB *>& d_epsBB = unefois->doCoMemb->d_epsBB;
      Tableau <TenseurHH *>& d_sigHH = unefois->doCoMemb->d_sigHH;
      // dimensionnement de la metrique
       if(!( unefois->CalResPrem_t ))
       { unefois->CalResPrem_t += 1;
         Tableau<Enum_variable_metrique> tab(10);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
         doCoPenta->metrique.PlusInitVariables(tab) ;
        };  
      // appel du programme général
      ElemMeca::Cal_ErrElem(type,errElemRelative,numerateur,denominateur,tab_noeud.Taille()
                ,(doCoPenta->pentaed)->TaPhi(),(doCoPenta->pentaed)->TaWi(),
                (doCoPenta->pentaedEr)->TaPhi(),(doCoPenta->pentaedEr)->TaWi());
     } ;
	

// cas d'un chargement volumique, 
// force indique la force volumique appliquée
// retourne  le second membre résultant
// ici on considère l'épaisseur de l'élément pour constituer le volume
// -> explicite à t ou tdt en fonction du booleen atdt
Vecteur PentaMemb::SM_charge_volumique_E
    (const Coordonnee& force,Fonction_nD* pt_fonct
    ,bool atdt,const ParaAlgoControle & pa,bool sur_volume_finale_)
    { PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
      // dimensionnement de la metrique
     if (!atdt)
      {if(!(unefois->CalSMvol_t ))
       { unefois->CalSMvol_t += 1;
         Tableau<Enum_variable_metrique> tab(10);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
         CoPenta->metrique.PlusInitVariables(tab) ;
        };} 
      else
      {if(!(unefois->CalSMvol_tdt ))
       { unefois->CalSMvol_tdt += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
         tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_tdt;tab(11) = iVtdt; 
         CoPenta->metrique.PlusInitVariables(tab) ;
        };}; 
      // initialisation du résidu
      residu->Zero();   
    // appel du programme général d'elemmeca et retour du vecteur second membre
    // multiplié par l'épaisseur pour avoir le volume
    return  ElemMeca::SM_charge_vol_E (CoPenta->tab_ddl,(CoPenta->pentaed)->TaPhi()
               ,tab_noeud.Taille(),(CoPenta->pentaed)->TaWi(),force,pt_fonct,pa,sur_volume_finale_);
   };

// calcul des seconds membres suivant les chargements 
// cas d'un chargement volumique, 
// force indique la force volumique appliquée
// retourne  le second membre résultant
// ici on l'épaisseur de l'élément pour constituer le volume -> 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
Element::ResRaid PentaMemb::SMR_charge_volumique_I
            (const Coordonnee& force,Fonction_nD* pt_fonct
            ,const ParaAlgoControle & pa,bool sur_volume_finale_)
    { PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture

      // initialisation du résidu
      residu->Zero();   
      // initialisation de la raideur      
      raideur->Zero();       
      // -- définition des constantes de la métrique si nécessaire
      // en fait on fait appel aux même éléments que pour le calcul implicite
      if (!(unefois->CalSMvol_tdt))
       { unefois->CalSMvol_tdt += 1;
         Tableau<Enum_variable_metrique> tab(20);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
         tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
         CoPenta->metrique.PlusInitVariables(tab) ;
        };
      // appel du programme général d'elemmeca 
      ElemMeca::SMR_charge_vol_I (CoPenta->tab_ddl
                                ,(CoPenta->pentaed)->TaPhi(),tab_noeud.Taille()
                                ,(CoPenta->pentaed)->TaWi(),force,pt_fonct,pa,sur_volume_finale_);
      Element::ResRaid el;
      el.res = residu; 
      el.raid = raideur;       
      return el;
   };

// calcul des seconds membres suivant les chargements 
// cas d'un chargement surfacique, sur les frontières des éléments
// force indique la force surfacique appliquée
// numface indique le numéro de la face chargée
// retourne  le second membre résultant
// explicite à t et à tdt en fonction de la variable booléeenne atdt
Vecteur PentaMemb::SM_charge_surfacique_E(const Coordonnee& force,Fonction_nD* pt_fonct
                                          ,int numface,bool atdt,const ParaAlgoControle & pa)
  { PentaMemb::DonnComPenta* doCoPenta = unefois->doCoMemb; // pour simplifier l'écriture
    // initialisation du vecteur résidu
    ((*res_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
   
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément 
	   Met_abstraite * meta= tabb(numface)->Metrique();
    
    // définition des constantes de la métrique si nécessaire
    if (!atdt)
    {if ( !(unefois->CalSMsurf_t(numface) ))
       { unefois->CalSMsurf_t(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_t; tab(11) = iVt;
         meta->PlusInitVariables(tab) ;
        };}  
    else
     {if ( !(unefois->CalSMsurf_tdt(numface) ))
       { unefois->CalSMsurf_tdt(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
         tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_tdt;tab(11) = iVtdt; 
         meta->PlusInitVariables(tab) ;
        };};  
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
     {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (doCoPenta->triaS).TaDphi(),(doCoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (doCoPenta->quadraS).TaDphi(),(doCoPenta->quadraS).TaPhi());
     }
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SM_charge_surf_E (tabb(numface)->DdlElem(),numface
               ,(doCoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(doCoPenta->triaS).TaWi(),force,pt_fonct,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SM_charge_surf_E (tabb(numface)->DdlElem(),numface
               ,(doCoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(doCoPenta->quadraS).TaWi(),force,pt_fonct,pa);
   }; 

	   
// cas d'un chargement surfacique, sur les frontières des éléments
// force indique la force surfacique appliquée
// numface indique le numéro de la face chargée
// retourne  le second membre résultant
// -> 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
Element::ResRaid PentaMemb::SMR_charge_surfacique_I
        (const Coordonnee& force,Fonction_nD* pt_fonct,int numface,const ParaAlgoControle & pa)
  {  // initialisation du vecteur résidu et de la raideur
     ((*res_extS)(numface))->Zero();
     ((*raid_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
    Met_abstraite * meta= tabb(numface)->Metrique();
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // dimensionnement de la metrique
    // définition des constantes de la métrique si nécessaire
   if ( !(unefois->CalSMRsurf(numface) ))
       { unefois->CalSMRsurf(numface) += 1;
         Tableau<Enum_variable_metrique> tab(20);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
         tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
         meta->PlusInitVariables(tab) ;
        }; 
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
    {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->triaS).TaDphi(),(CoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->quadraS).TaDphi(),(CoPenta->quadraS).TaPhi());
     };
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SMR_charge_surf_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->triaS).TaWi(),force,pt_fonct,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SMR_charge_surf_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->quadraS).TaWi(),force,pt_fonct,pa);
   };

// cas d'un chargement de type pression, sur les frontières des éléments
// pression indique la pression appliquée
// numface indique le numéro de la face chargée
// retourne  le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de 
// surface externe -> message d'erreur  d'où le virtuel et non virtuel pur
// explicite à t et à tdt en fonction de la variable booléeenne atdt
Vecteur PentaMemb::SM_charge_pression_E
                      (double pression,Fonction_nD* pt_fonct,int numface,bool atdt,const ParaAlgoControle & pa)
  {  // initialisation du vecteur résidu
     ((*res_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
	 Met_abstraite * meta= tabb(numface)->Metrique();
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // définition des constantes de la métrique si nécessaire
    if (!atdt)
    {if ( !(unefois->CalSMsurf_t(numface) ))
       { unefois->CalSMsurf_t(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_t; tab(11) = iVt;
         meta->PlusInitVariables(tab) ;
        };}  
    else
     {if ( !(unefois->CalSMsurf_tdt(numface) ))
       { unefois->CalSMsurf_tdt(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
         tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_tdt;tab(11) = iVtdt; 
         meta->PlusInitVariables(tab) ;
        };};  
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
    {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->triaS).TaDphi(),(CoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->quadraS).TaDphi(),(CoPenta->quadraS).TaPhi());
     };
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SM_charge_pres_E (tabb(numface)->DdlElem(),numface
               ,(CoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->triaS).TaWi(),pression,pt_fonct,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SM_charge_pres_E (tabb(numface)->DdlElem(),numface
               ,(CoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->quadraS).TaWi(),pression,pt_fonct,pa);
   }; 
	   
// cas d'un chargement de type pression, sur les frontières des éléments
// pression indique la pression appliquée
// numface indique le numéro de la face chargée
// retourne  le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de 
// surface externe -> message d'erreur  d'où le virtuel et non virtuel pur
// -> 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
Element::ResRaid PentaMemb::SMR_charge_pression_I
       (double pression,Fonction_nD* pt_fonct,int numface,const ParaAlgoControle & pa)
  {  // initialisation du vecteur résidu et de la raideur
     ((*res_extS)(numface))->Zero();
     ((*raid_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
    Met_abstraite * meta= tabb(numface)->Metrique();
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // dimensionnement de la metrique
    // définition des constantes de la métrique si nécessaire
   if ( !(unefois->CalSMRsurf(numface) ))
       { unefois->CalSMRsurf(numface) += 1;
         Tableau<Enum_variable_metrique> tab(20);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
         tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
         meta->PlusInitVariables(tab) ;
        }; 
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
    {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->triaS).TaDphi(),(CoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->quadraS).TaDphi(),(CoPenta->quadraS).TaPhi());
    };
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SMR_charge_pres_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->triaS).TaWi(),pression,pt_fonct,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SMR_charge_pres_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->quadraS).TaWi(),pression,pt_fonct,pa);
   };

// cas d'un chargement de type pression unidirectionnelle, sur les frontières des éléments
// presUniDir indique le vecteur  appliquée
// numface indique le numéro de la face chargée
// retourne  le second membre résultant
// -> explicite à t ou tdt en fonction de la variable booleenne atdt 
Vecteur PentaMemb::SM_charge_presUniDir_E
                       (const Coordonnee& presUniDir,Fonction_nD* pt_fonct
                       ,int numface,bool atdt,const ParaAlgoControle & pa)
  {  // initialisation du vecteur résidu
     ((*res_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
    Met_abstraite * meta= tabb(numface)->Metrique();
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // définition des constantes de la métrique si nécessaire
    if (!atdt)
    {if ( !(unefois->CalSMsurf_t(numface) ))
       { unefois->CalSMsurf_t(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_t; tab(11) = iVt;
         meta->PlusInitVariables(tab) ;
        };}  
    else
     {if ( !(unefois->CalSMsurf_tdt(numface) ))
       { unefois->CalSMsurf_tdt(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
         tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_tdt;tab(11) = iVtdt; 
         meta->PlusInitVariables(tab) ;
        };};  
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
     {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->triaS).TaDphi(),(CoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->quadraS).TaDphi(),(CoPenta->quadraS).TaPhi());
     };
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SM_charge_surf_Suiv_E (tabb(numface)->DdlElem(),numface
               ,(CoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->triaS).TaWi(),presUniDir,pt_fonct,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SM_charge_surf_Suiv_E (tabb(numface)->DdlElem(),numface
               ,(CoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->quadraS).TaWi(),presUniDir,pt_fonct,pa);
   }; 

// -> 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
Element::ResRaid PentaMemb::SMR_charge_presUniDir_I
             (const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int numface,const ParaAlgoControle & pa)
  {  // initialisation du vecteur résidu et de la raideur
     ((*res_extS)(numface))->Zero();
     ((*raid_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
    Met_abstraite * meta= tabb(numface)->Metrique();
    
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // dimensionnement de la metrique
    // définition des constantes de la métrique si nécessaire
   if ( !(unefois->CalSMRsurf(numface) ))
       { unefois->CalSMRsurf(numface) += 1;
         Tableau<Enum_variable_metrique> tab(20);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
         tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
         meta->PlusInitVariables(tab) ;
        }; 
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
      {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->triaS).TaDphi(),(CoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->quadraS).TaDphi(),(CoPenta->quadraS).TaPhi());
      }
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SMR_charge_surf_Suiv_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->triaS).TaWi(),presUniDir,pt_fonct,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SMR_charge_surf_Suiv_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->quadraS).TaWi(),presUniDir,pt_fonct,pa);
   };

// cas d'un chargement lineique, sur les arêtes frontières des éléments
// force indique la force lineique appliquée
// numArete indique le numéro de l'arête chargée
// retourne  le second membre résultant
// explicite à t et à tdt en fonction de la variable booléeenne atdt
Vecteur PentaMemb::SM_charge_lineique_E
                       (const Coordonnee& force,Fonction_nD* pt_fonct
                       ,int numArete,bool atdt,const ParaAlgoControle & pa)
  {  // initialisation du vecteur résidu 
     ((*res_extA)(numArete))->Zero();
     // on récupère ou on crée la frontière arrête
     ElFrontiere* elf = Frontiere_lineique(numArete,true);
     // on  utilise la métrique des éléments de frontière
     // avec l'instance déformation dédiée pour
     // récupération de la métrique associée à l'élément qui est commune a tous les triangles
     // du même type
     Met_abstraite * meta= elf->Metrique();
   
     PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
     // dimensionnement de la metrique
     if (!atdt)
       {if( !(unefois->CalSMlin_t))
         { unefois->CalSMlin_t += 1;
           Tableau<Enum_variable_metrique> tab(8);
           tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
           tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
           tab(8) = igradVBB_t;
           meta->PlusInitVariables(tab) ;
         };
       }
     else
       {if( !(unefois->CalSMlin_tdt ))
          {unefois->CalSMlin_tdt = 1;
           Tableau<Enum_variable_metrique> tab(8);
           tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
           tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
           tab(8) = igradVBB_tdt;
           meta->PlusInitVariables(tab) ;
          };
       };

     // définition d'une déformation a doc
     if (defArete(numArete) == NULL)
       {if ((numArete == 4) || (numArete == 5) || (numArete == 6))
          // les arêtes verticales
          defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
                               (CoPenta->segHS).TaDphi(),(CoPenta->segHS).TaPhi());
        else // les arêtes des faces triangulaires
          defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
                               (CoPenta->segFS).TaDphi(),(CoPenta->segFS).TaPhi());
       };
     // appel du programme général d'elemmeca et retour du vecteur second membre
     if ((numArete == 4) || (numArete == 5) || (numArete == 6))
        // les arêtes verticales
       return ElemMeca::SM_charge_line_E (elf->DdlElem(),numArete
               ,(CoPenta->segHS).TaPhi(),(elf->TabNoeud()).Taille()
               ,(CoPenta->segHS).TaWi(),force,pt_fonct,pa);
     else // les arêtes des faces triangulaires
       return ElemMeca::SM_charge_line_E (elf->DdlElem(),numArete
               ,(CoPenta->segFS).TaPhi(),(elf->TabNoeud()).Taille()
               ,(CoPenta->segFS).TaWi(),force,pt_fonct,pa);
   };
    
// cas d'un chargement lineique, sur les aretes frontières des éléments
// force indique la force lineique appliquée
// numarete indique le numéro de l'arete chargée
// retourne  le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas 
// d'arete externe -> message d'erreur d'où le virtuel et non virtuel pur
// -> 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
Element::ResRaid PentaMemb::SMR_charge_lineique_I
                (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa)
  { // initialisation du vecteur résidu et de la raideur
    ((*res_extA)(numArete))->Zero();
    ((*raid_extA)(numArete))->Zero();
    // on récupère ou on crée la frontière arrête
    ElFrontiere* elf = Frontiere_lineique(numArete,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément qui est commune a tous les triangles
    // du même type
    Met_abstraite * meta= elf->Metrique();
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // dimensionnement de la metrique
    if( !(unefois->CalSMRlin ))
      {  unefois->CalSMRlin += 1;
         Tableau<Enum_variable_metrique> tab(15);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = igradVBB_tdt; 
         meta->PlusInitVariables(tab) ;
        }; 
    // définition d'une déformation a doc
    if (defArete(numArete) == NULL) 
     {if ((numArete == 4) || (numArete == 5) || (numArete == 6))
        // les arêtes verticales
        defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
            (CoPenta->segHS).TaDphi(),(CoPenta->segHS).TaPhi());
      else // les arêtes des faces triangulaires      
        defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
            (CoPenta->segFS).TaDphi(),(CoPenta->segFS).TaPhi());
     };
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numArete == 4) || (numArete == 5) || (numArete == 6))
        // les arêtes verticales
       return ElemMeca::SMR_charge_line_I (elf->DdlElem(),numArete
               ,(CoPenta->segHS).TaPhi(),(elf->TabNoeud()).Taille()
               ,(CoPenta->segHS).TaWi(),force,pt_fonct,pa);
    else // les arêtes des faces triangulaires       
       return ElemMeca::SMR_charge_line_I (elf->DdlElem(),numArete
               ,(CoPenta->segFS).TaPhi(),(elf->TabNoeud()).Taille()
               ,(CoPenta->segFS).TaWi(),force,pt_fonct,pa);
                  
   };

// cas d'un chargement de type pression hydrostatique, sur les frontières des éléments
// la charge dépend de la hauteur à la surface libre du liquide déterminée par un point
// et une  direction  normale à la surface libre: 
// nSurf : le numéro de la surface externe
// poidvol: indique le poids volumique du liquide
// M_liquide : un point de la surface libre
// dir_normal_liquide : direction normale à la surface libre
// retourne  le second membre résultant
// calcul à l'instant tdt ou t en fonction de la variable atdt
// retourne  le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de 
// surface externe -> message d'erreur  d'où le virtuel et non virtuel pur
// -> explicite à t ou à tdt en fonction de la variable booléenne atdt
Vecteur PentaMemb::SM_charge_hydrostatique_E(const Coordonnee& dir_normal_liquide,const double& poidvol
                              ,int numface,const Coordonnee& M_liquide,bool atdt
                              ,const ParaAlgoControle & pa
                              ,bool sans_limitation)
  {  // initialisation du vecteur résidu
     ((*res_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
	 Met_abstraite * meta= tabb(numface)->Metrique();        
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // définition des constantes de la métrique si nécessaire
    if (!atdt)
    {if ( !(unefois->CalSMsurf_t(numface) ))
       { unefois->CalSMsurf_t(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_t; tab(11) = iVt;
         meta->PlusInitVariables(tab) ;
        };}  
    else
     {if ( !(unefois->CalSMsurf_tdt(numface) ))
       { unefois->CalSMsurf_tdt(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
         tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_tdt;tab(11) = iVtdt; 
         meta->PlusInitVariables(tab) ;
        };};  
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
     {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->triaS).TaDphi(),(CoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->quadraS).TaDphi(),(CoPenta->quadraS).TaPhi());
     };
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SM_charge_hydro_E (tabb(numface)->DdlElem(),numface
               ,(CoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->triaS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SM_charge_hydro_E (tabb(numface)->DdlElem(),numface
               ,(CoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->quadraS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa);
   }; 

// cas d'un chargement de type pression hydrostatique, sur les frontières des éléments
// la charge dépend de la hauteur à la surface libre du liquide déterminée par un point
// et une  direction  normale à la surface libre: 
// nSurf : le numéro de la surface externe
// poidvol: indique le poids volumique du liquide
// M_liquide : un point de la surface libre
// dir_normal_liquide : direction normale à la surface libre
// retourne  le second membre résultant
// calcul à l'instant tdt ou t en fonction de la variable atdt
// retourne  le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de 
// surface externe -> message d'erreur  d'où le virtuel et non virtuel pur
// -> 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
Element::ResRaid PentaMemb::SMR_charge_hydrostatique_I (const Coordonnee& dir_normal_liquide,const double& poidvol
                                           ,int numface,const Coordonnee& M_liquide
                                           ,const ParaAlgoControle & pa
                                           ,bool sans_limitation)
  {  // initialisation du vecteur résidu et de la raideur
     ((*res_extS)(numface))->Zero();
     ((*raid_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
    Met_abstraite * meta= tabb(numface)->Metrique();
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // dimensionnement de la metrique
    // définition des constantes de la métrique si nécessaire
   if ( !(unefois->CalSMRsurf(numface) ))
       { unefois->CalSMRsurf(numface) += 1;
         Tableau<Enum_variable_metrique> tab(20);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
         tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
         meta->PlusInitVariables(tab) ;
        }; 
    // définition d'une déformation a doc
    if (defSurf(numface) == NULL) 
     {if ((numface == 1) || (numface == 4))
        // les faces 1 et 4 sont triangulaire
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->triaS).TaDphi(),(CoPenta->triaS).TaPhi());
      else // les autres surfaces sont quadrangulaires      
        defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            (CoPenta->quadraS).TaDphi(),(CoPenta->quadraS).TaPhi());
     };
    // appel du programme général d'elemmeca et retour du vecteur second membre
    if ((numface == 1) || (numface == 4))
       return ElemMeca::SMR_charge_hydro_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->triaS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->triaS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa);
    else // les autres surfaces sont quadrangulaires      
       return ElemMeca::SMR_charge_hydro_I (tabb(numface)->DdlElem(),numface
               ,(CoPenta->quadraS).TaPhi(),(tabb(numface)->TabNoeud()).Taille()
               ,(CoPenta->quadraS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa);
   };

	   // cas d'un chargement surfacique hydro-dynamique, 
       // 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
       // coef_mul: est un coefficient multiplicateur global (de tout)
	   // retourne  le second membre résultant
	   // // -> explicite à t ou à tdt en fonction de la variable booléenne atdt	   
Vecteur PentaMemb::SM_charge_hydrodynamique_E(  Courbe1D* frot_fluid,const double& poidvol
	                                                 ,  Courbe1D* coef_aero_n,int numface,const double& coef_mul
	                                                 ,  Courbe1D* coef_aero_t,bool atdt
                                                  ,const ParaAlgoControle & pa)
  {  // initialisation du vecteur résidu
     ((*res_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
    Met_abstraite * meta= tabb(numface)->Metrique();        
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // définition des constantes de la métrique si nécessaire
    if (!atdt)
    {if ( !(unefois->CalSMsurf_t(numface) ))
       { unefois->CalSMsurf_t(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
         tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_t; tab(11) = iVt;
         meta->PlusInitVariables(tab) ;
        };}  
    else
     {if ( !(unefois->CalSMsurf_tdt(numface) ))
       { unefois->CalSMsurf_tdt(numface) += 1;
         Tableau<Enum_variable_metrique> tab(11);
         tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
         tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
         tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
         tab(10) = igradVBB_tdt;tab(11) = iVtdt; 
         meta->PlusInitVariables(tab) ;
        };};  
    // définition d'une déformation a doc
    ElemGeomC0* elemGeom;
    if (defSurf(numface) == NULL) 
     {if ((numface == 1) || (numface == 4))  // les faces 1 et 4 sont triangulaire
         { elemGeom = & (CoPenta->triaS);}
      else // les autres surfaces sont quadrangulaires      
         { elemGeom = & (CoPenta->triaS);};
      defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            elemGeom->TaDphi(),elemGeom->TaPhi());
     };
    // appel du programme général d'ElemMeca et retour du vecteur second membre
    return  ElemMeca::SM_charge_hydrodyn_E (poidvol,elemGeom->TaPhi(),(tabb(numface)->TabNoeud()).Taille()
                                         ,frot_fluid,elemGeom->TaWi()
                                         ,coef_aero_n,numface,coef_mul,coef_aero_t,pa,atdt);
   }; 

	   // -> 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
Element::ResRaid PentaMemb::SMR_charge_hydrodynamique_I(  Courbe1D* frot_fluid,const double& poidvol
	                                                ,  Courbe1D* coef_aero_n,int numface,const double& coef_mul
	                                                ,  Courbe1D* coef_aero_t
                                                 ,const ParaAlgoControle & pa) 
  {  // initialisation du vecteur résidu et de la raideur
     ((*res_extS)(numface))->Zero();
     ((*raid_extS)(numface))->Zero();
    // on récupère ou on crée la frontière surfacique
    Frontiere_surfacique(numface,true);
    // on  utilise la métrique des éléments de frontière
    // avec l'instance déformation dédiée pour
    // récupération de la métrique associée à l'élément
    Met_abstraite * meta= tabb(numface)->Metrique();
    
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
    // dimensionnement de la metrique
    // définition des constantes de la métrique si nécessaire
   if ( !(unefois->CalSMRsurf(numface) ))
       { unefois->CalSMRsurf(numface) += 1;
         Tableau<Enum_variable_metrique> tab(20);
         tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
         tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
         tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) =  id_giH_tdt;
         tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; 
         tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
         tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
         meta->PlusInitVariables(tab) ;
        }; 
    // définition d'une déformation a doc
    ElemGeomC0* elemGeom;
    if (defSurf(numface) == NULL) 
     {if ((numface == 1) || (numface == 4))  // les faces 1 et 4 sont triangulaire
         { elemGeom = & (CoPenta->triaS);}
      else // les autres surfaces sont quadrangulaires      
         { elemGeom = & (CoPenta->triaS);};
      defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
            elemGeom->TaDphi(),elemGeom->TaPhi());
     };
    // appel du programme général d'ElemMeca et retour du vecteur second membre
    return  ElemMeca::SM_charge_hydrodyn_I (poidvol,elemGeom->TaPhi(),(tabb(numface)->TabNoeud()).Taille()
                                         ,frot_fluid,elemGeom->TaWi(),tabb(numface)->DdlElem()
                                         ,coef_aero_n,numface,coef_mul
                                         ,coef_aero_t,pa);
   };

// Calcul des frontieres de l'element
//  creation des elements frontieres et retour du tableau de ces elements
// la création n'a lieu qu'au premier appel
// ou lorsque l'on force le paramètre force a true
// dans ce dernier cas seul les frontière effacées sont recréée
Tableau <ElFrontiere*> const & PentaMemb::Frontiere(bool force)
  {  int cas = 1; // on veut des surfaces
     // --- on sauvegarde les indicateurs des tableaux intermédiaires
     int old_ind_front_surf = ind_front_surf;
     // appel de la méthode générale
     Frontiere_elemeca(cas,force);
     // si quelque chose a changé au niveau des surfaces on intervient sur les tableaux locaux
     if ( (old_ind_front_surf==0) && (ind_front_surf!=0))
       {// on redimensionne les tableaux locaux
        PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
        ElemGeomC0 & el = *(CoPenta->pentaed); 
        int tail_fa = el.NbFe(); // nombre potentiel de faces
        // on s'occupe également des indicateurs
        unefois->CalSMsurf_t.Change_taille(tail_fa);unefois->CalSMsurf_tdt.Change_taille(tail_fa);
        unefois->CalSMRsurf.Change_taille(tail_fa);
        };
     
//  {// le calcul et la création ne sont effectués qu'au premier appel
//   // ou lorsque l'on veut forcer une recréation
//	if (((ind_front_lin == 0) && (ind_front_surf == 0) && (ind_front_point == 0))
//	    || force )
////     if ( (ind_front_surf==0)|| force ||(ind_front_surf==2) )
//   {PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
//    ElemGeomC0 & el = *(CoPenta->pentaed);
//    DdlElement & tdd = CoPenta->tab_ddl;
//    int tail_s = el.Nonf().Taille(); // nombre de faces
//    // def de la taille
//    if (((ind_front_point > 0) || (ind_front_lin > 0)) && (ind_front_surf == 0))
//      // cas où les frontières points ou linéiques existent mais pas les frontières faces
//      // on redimentionne et on transfert
//      { int tail_af = nombre->nbne+el.NonS().Taille(); // nombre d'arête + noeud
//        int taille_f = tail_af + tail_s;
//        tabb.Change_taille(taille_f);
//        // on s'occupe également des indicateurs
//        unefois->CalSMsurf_t.Change_taille(taille_f);unefois->CalSMsurf_tdt.Change_taille(taille_f);
//        unefois->CalSMRsurf.Change_taille(taille_f); 
//        for (int i=1;i<= tail_af;i++)
//           { tabb(i+tail_s) = tabb(i);tabb(i) = NULL;
//             unefois->CalSMsurf_t(i+tail_s)=unefois->CalSMsurf_t(i);
//             unefois->CalSMsurf_tdt(i+tail_s)=unefois->CalSMsurf_tdt(i);
//             unefois->CalSMRsurf(i+tail_s)=unefois->CalSMRsurf(i);
//             unefois->CalSMsurf_t(i)=0;unefois->CalSMsurf_tdt(i)=0;unefois->CalSMRsurf(i)=0;
//             }
//        posi_tab_front_lin += tail_s; 
//        posi_tab_front_point += tail_s;   
//       }
//    else if (ind_front_surf == 0)
//      // cas où rien n'existe  
//       {tabb.Change_taille(tail_s); 
//        // on s'occupe également des indicateurs
//        unefois->CalSMsurf_t.Change_taille(tail_s);unefois->CalSMsurf_tdt.Change_taille(tail_s);
//        unefois->CalSMRsurf.Change_taille(tail_s);        
//        } 
//    // création éventuelle des faces   
//    for (int nface=1;nface<=tail_s;nface++)
//      { int nbnoe = el.Nonf()(nface).Taille(); // nb noeud de la face
//        Tableau <Noeud *> tab(nbnoe); // les noeuds des faces frontieres 
//        DdlElement ddelem(nbnoe);  // les ddlelements des noeuds frontieres
//        for (int i=1;i<= nbnoe;i++)
//          { int nib=el.Nonf()(nface)(i); // numéro dans l'élément du numéro i de la face
//            tab(i) = tab_noeud(nib);
//            DdlNoeudElement einter = tdd(nib);
//            ddelem.Change_un_ddlNoeudElement(i,einter);
//          //  ddelem(i) = tdd(el.Nonf()(nface)(i));
//           }  
//        if ((nface == 1) || (nface == 4))
//           // les faces 1 et 4 sont triangulaire
//           {if (tabb(nface) == NULL) tabb(nface) = new_frontiere_surf_tri(tab,ddelem);} 
//        else   
//           // les faces 2,3 et 5 sont quadrangulaire
//           {if (tabb(nface) == NULL) tabb(nface) = new_frontiere_surf_rec(tab,ddelem); }
//       }
//    // mise à jour de l'indicateur de création de faces
//    ind_front_surf = 1;   
//    }    
    return (Tableau <ElFrontiere*>&)tabb;
   };
   
//// ramène la frontière point
//// éventuellement création des frontieres points de l'element et stockage dans l'element 
//// si c'est la première fois  sinon il y a seulement retour de l'elements
//// a moins que le paramètre force est mis a true
//// dans ce dernier cas la frontière effacéee est recréée
//// num indique le numéro du point à créer (numérotation EF)
//ElFrontiere* const  PentaMemb::Frontiere_points(int num,bool force) 
// { // le calcul et la création ne sont effectués qu'au premier appel
//   // ou lorsque l'on veut forcer une recréation
//   #ifdef MISE_AU_POINT
//      if ((num > nombre->nbne)||(num <=0))
//        { cout << "\n *** erreur, le noeud demande pour frontiere: " << num << " esten dehors de la numeration de l'element ! "
//               << "\n Frontiere_points(int num,bool force)";
//          Sortie(1);
//         }       
//   #endif
//
//   if ((ind_front_point == 0) || force || (ind_front_point == 2)) 
//     {Tableau <Noeud *> tab(1); // les noeuds des points frontieres
//      DdlElement ddelem(1);  // les ddlelements des points frontieres
//      //   on regarde si les frontières points existent sinon on les crée
//      if (ind_front_point == 1)
//        return (ElFrontiere*)tabb(posi_tab_front_point+num); 
//      else if ( ind_front_point == 2)
//        // cas où certaines frontières existent
//        if (tabb(posi_tab_front_point+num) != NULL)            
//          return (ElFrontiere*)tabb(posi_tab_front_point+num);
//      // dans tous les autres cas on construit la frontière point
//      // on commence par dimensionner le tableau de frontière, comme les frontières points sont
//      // les dernières, il suffit de les ajouter, d'où on redimentionne le tableau mais on ne créra
//      // que la frontière adoc
//      // def de la taille
//      int taille_actuelle = tabb.Taille();
//      if ((ind_front_point == 0) && ((ind_front_lin > 0) || (ind_front_surf > 0)))
//        // cas où les frontières lignes ou surfaces existent, mais pas les points
//        { int tail_p = nombre->nbne; // le nombre de noeuds
//          int taille_f = taille_actuelle + tail_p;
//          tabb.Change_taille(taille_f);
//          for (int i=1;i<= tail_p;i++)
//           { tabb(i+taille_actuelle) = tabb(i);tabb(i) = NULL;};
//          posi_tab_front_point +=taille_actuelle; 
//          if (ind_front_lin > 0) posi_tab_front_lin += taille_actuelle;
//         }      
//       else if (ind_front_point == 0) 
//        // cas où aucune frontière n'existe
//         {tabb.Change_taille(nombre->nbne);};
//        // dans les autres cas, les frontières points exitent donc pas à dimensionner  
//      // on définit tous les points par simplicité
//      for (int i=1;i<=nombre->nbne;i++)
//       {tab(1) = tab_noeud(i);ddelem.Change_un_ddlNoeudElement(1,unefois->doCoMemb->tab_ddl(i));
//        if (tabb(i+posi_tab_front_point) == NULL)
//           tabb(i+posi_tab_front_point) = new  FrontPointF (tab,ddelem);
//        };   
//      };
//    return (ElFrontiere*)tabb(num+posi_tab_front_point); 
//   }; 

//// ramène la frontière linéique
//// éventuellement création des frontieres linéique de l'element et stockage dans l'element 
//// si c'est la première fois et en 3D sinon il y a seulement retour de l'elements
//// a moins que le paramètre force est mis a true
//// dans ce dernier cas la frontière effacéee est recréée
//// num indique le numéro de l'arête à créer (numérotation EF)
//ElFrontiere* const  PentaMemb::Frontiere_lineique(int num,bool force)
//  { // dimensionnement des tableaux d'indicateurs
//    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
//    ElemGeomC0 & el = *(CoPenta->pentaed);
//    int tail_ar = el.NonS().Taille(); // nombre d'arête
//    unefois->CalSMRlin.Change_taille(11);
//    unefois->CalSMRlin_t.Change_taille(tail_ar);
//    unefois->CalSMRlin_tdt.Change_taille(tail_ar);
//    // appel de la fonction d'ElemMeca
//    return ElemMeca::Frontiere_lineique(num,force);
//
//
//    // le calcul et la création ne sont effectués qu'au premier appel
//    // ou lorsque l'on veut forcer une recréation
//    if ((ind_front_lin == 0) || force || (ind_front_lin == 2)) 
//      {PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
//       ElemGeomC0 & el = *(CoPenta->pentaed);
//       DdlElement & tdd = CoPenta->tab_ddl;
//       int taille = tabb.Taille(); // la taille initiales des frontières
//       int tail_s = el.Nonf().Taille(); // nombre de faces
//       int tail_a = el.NonS().Taille(); // nombre d'arête
//       posi_tab_front_lin = 0; // init indice de début d'arrête dans tabb
//       // dimensionnement du tableau de frontières ligne si nécessaire
//       if (ind_front_lin == 0)
//       {if (ind_front_surf > 0)
//         // cas où il y a déjà des surfaces et pas de lignes
//         { tabb.Change_taille(tail_a + tail_s);
//          posi_tab_front_lin = tail_s;
//          // on s'occupe également des indicateurs
//          unefois->CalSMsurf_t.Change_taille(tail_a + tail_s);
//          unefois->CalSMsurf_tdt.Change_taille(tail_a + tail_s);
//          unefois->CalSMRsurf.Change_taille(tail_a + tail_s); 
//          }
//        else   // cas pas de lignes et de surfaces
//        { tabb.Change_taille(tail_a);
//          // et c'est ok pour posi_tab_front_lin
//          // on s'occupe également des indicateurs
//          unefois->CalSMsurf_t.Change_taille(tail_a);
//          unefois->CalSMsurf_tdt.Change_taille(tail_a);
//          unefois->CalSMRsurf.Change_taille(tail_a); 
//         }
//        }
//        // création éventuelle des lignes   
//        for (int nlign=1;nlign<=tail_a;nlign++)
//          if (tabb(posi_tab_front_lin+nlign) == NULL) 
//           { int nbnoe = el.NonS()(nlign).Taille(); // nb noeud de l'arête
//             Tableau <Noeud *> tab(nbnoe); // les noeuds de l'arête frontiere 
//             DdlElement ddelem(nbnoe);  // les ddlelements des noeuds frontieres
//             for (int i=1;i<= nbnoe;i++)
//               { tab(i) = tab_noeud(el.NonS()(nlign)(i));
//                 ddelem.Change_un_ddlNoeudElement(i,tdd(el.NonS()(nlign)(i)));
//               //  ddelem(i) = tdd(el.NonS()(nlign)(i));
//                }
//             if ((nlign == 4) || (nlign == 5) || (nlign == 6) ) 
//               // cas des lignes verticales    
//               {tabb(posi_tab_front_lin+nlign) = new_frontiere_lin_rec(tab,ddelem);}
//             else 
//               // cas des lignes horizontales  
//               {tabb(posi_tab_front_lin+nlign) = new_frontiere_lin_tri(tab,ddelem);}
//             }  
//       // mise à jour de l'indicateur
//       ind_front_lin = 1;     
//      }    
//    
//    return (ElFrontiere*)tabb(num + posi_tab_front_lin);          
//   };
//
// ramène la frontière surfacique
// éventuellement création d'une frontieres surfacique de l'element et stockage dans l'element 
// si c'est la première fois sinon il y a seulement retour de l'elements
// a moins que le paramètre force est mis a true
// dans ce dernier cas la frontière effacéee est recréée
// num indique le numéro de la surface à créer (numérotation EF)
ElFrontiere* const  PentaMemb::Frontiere_surfacique(int num,bool force)
{    // --- on sauvegarde les indicateurs des tableaux intermédiaires
     int old_ind_front_surf = ind_front_surf;
     // appel de la méthode générale
     ElemMeca::Frontiere_surfacique(num,force);
     // si quelque chose a changé au niveau des surfaces on intervient sur les tableaux locaux
     if ( (old_ind_front_surf==0) && (ind_front_surf!=0))
       {// on redimensionne les tableaux locaux
        PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
        ElemGeomC0 & el = *(CoPenta->pentaed); 
        int tail_fa = el.NbFe(); // nombre potentiel de faces
        // on s'occupe également des indicateurs
        unefois->CalSMsurf_t.Change_taille(tail_fa);unefois->CalSMsurf_tdt.Change_taille(tail_fa);
        unefois->CalSMRsurf.Change_taille(tail_fa);
        };
     // normalement la frontière est créé on la ramène
     return (ElFrontiere*)tabb(num);

};

//  { // dimensionnement des tableaux d'indicateurs
//    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
//    ElemGeomC0 & el = *(CoPenta->pentaed);
//    int tail_ar = el.NonS().Taille(); // nombre d'arête
//    unefois->CalSMRsurf.Change_taille(tail_ar);
//    unefois->CalSMRsurf.Change_taille(tail_ar);
//    unefois->CalSMRsurf.Change_taille(tail_ar);
//    // appel de la fonction d'ElemMeca
//    return ElemMeca::Frontiere_surfacique(num,force);
//    
////   // le calcul et la création ne sont effectués qu'au premier appel
////    // ou lorsque l'on veut forcer une recréation
////    //   on regarde si les frontières surfaciques existent sinon on les crée
////    if (ind_front_surf == 1)
////        return (ElFrontiere*)tabb(num); 
////    else if ( ind_front_surf == 2)
////      // cas où certaines frontières existent
////      {if (tabb(num) != NULL)            
////        return (ElFrontiere*)tabb(num);}
////    // dans tous les autres cas on reconstruit les frontières     
////    Frontiere(force);
////    return (ElFrontiere*)tabb(num); 
//   };

 // -------------------- calcul de frontières en protected -------------------
    
       //  --- fonction nécessaire pour la construction des Frontières linéiques ou surfaciques particulière à l'élément 
       // adressage des frontières linéiques et surfacique
       // définit dans les classes dérivées, et utilisées pour la construction des frontières
ElFrontiere* PentaMemb::new_frontiere_lin(int nlign,Tableau <Noeud *> & tab, DdlElement& ddelem)
{ElFrontiere* fro_retour=NULL;
 if ((nlign == 4) || (nlign == 5) || (nlign == 6) ) 
   // cas des lignes verticales    
   {fro_retour = new_frontiere_lin_rec(tab,ddelem);}
 else 
   // cas des lignes horizontales  
   {fro_retour = new_frontiere_lin_tri(tab,ddelem);}
 return fro_retour;
};
ElFrontiere* PentaMemb::new_frontiere_surf(int nface,Tableau <Noeud *> & tab, DdlElement& ddelem)
{ElFrontiere* fro_retour=NULL;
 if ((nface == 1) || (nface == 4))
    // les faces 1 et 4 sont triangulaire
    {fro_retour = new_frontiere_surf_tri(tab,ddelem);} 
 else   
    // les faces 2,3 et 5 sont quadrangulaire
    {fro_retour = new_frontiere_surf_rec(tab,ddelem); }
 return fro_retour;
};

// liberation de la place pointee
void PentaMemb::Libere ()
  {Element::Libere (); // liberation de residu et raideur
   LibereTenseur() ; // liberation des tenseur intermediaires
  };
// acquisition ou modification d'une loi de comportement
void PentaMemb::DefLoi (LoiAbstraiteGeneral * NouvelleLoi)
    { // verification du type de loi
      if ((NouvelleLoi->Dimension_loi() != 3) && (NouvelleLoi->Dimension_loi() != 4))
        { cout << "\n Erreur, la loi de comportement a utiliser avec des PentaMembs";
          cout << " doit etre de type 3D, \n ici elle est de type = " 
               << (NouvelleLoi->Dimension_loi()) << "D !!! " << endl;
          Sortie(1);     
        }
      // cas d'une loi mécanique
      if (GroupeMecanique(NouvelleLoi->Id_categorie()))
       {loiComp = (Loi_comp_abstraite *) NouvelleLoi;
        // initialisation du stockage particulier, ici en fonction du nb de pt d'integ
        int imax = tabSaveDon.Taille();
        for (int i=1;i<= imax;i++) tabSaveDon(i) = loiComp->New_et_Initialise();          
        // idem pour le type de déformation mécanique associé            
        int iDefmax = tabSaveDefDon.Taille();
        for (int i=1;i<= iDefmax;i++) tabSaveDefDon(i) = def->New_et_Initialise(); 
        // définition du type de déformation associé à la loi
        loiComp->Def_type_deformation(*def);
        // on active les données particulières nécessaires au fonctionnement de la loi de comp
        loiComp->Activation_donnees(tab_noeud,dilatation,lesPtMecaInt); 
        };
      // cas d'une loi thermo physique
      if (GroupeThermique(NouvelleLoi->Id_categorie()))
       {loiTP = (CompThermoPhysiqueAbstraite *) NouvelleLoi;
        // initialisation du stockage particulier thermo physique, 
        int imax = tabSaveTP.Taille();
        for (int i=1;i<= imax;i++) tabSaveTP(i) = loiTP->New_et_Initialise(); 
        // on active les données particulières nécessaires au fonctionnement de la loi de comp
        loiTP->Activation_donnees(tab_noeud); 
        };
      // cas d'une loi de frottement 
      if (GroupeFrottement(NouvelleLoi->Id_categorie()))
        loiFrot = (CompFrotAbstraite *) NouvelleLoi;
    };
  
// test si l'element est complet
int PentaMemb::TestComplet()
  { int res = ElemMeca::TestComplet(); // test dans la fonction mere
    if ( tab_noeud(1) == NULL)
     { cout << "\n les noeuds de l\'element pentaedre ne sont pas defini  \n";
       res = 0; }
    else 
     { int testi =1;
       int posi = Id_nom_ddl("X1") -1; 
       int dim = ParaGlob::Dimension();
       int jmax = tab_noeud.Taille();   
       for (int i =1; i<= dim; i++)
          for (int j=1;j<=jmax;j++)
           if(!(tab_noeud(j)->Existe_ici(Enum_ddl(posi+i))))
              testi = 0;
       if(testi == 0)
         { cout << "\n les ddls Xi  des noeuds  ne sont pas defini  \n";
           cout << " \n utilisez PentaMemb::ConstTabDdl() pour completer " ;
           res = 0; }            
      }          
    return res;   
  };
		
// procesure permettant de completer l'element apres
// sa creation avec les donnees du bloc transmis
// ici la masse volumique
Element* PentaMemb::Complete(BlocGen & bloc,LesFonctions_nD*  lesFonctionsnD)
  {   // complétion avec bloc
      return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD);
    };       
	       
// Compléter pour la mise en place de la gestion de l'hourglass
Element* PentaMemb::Complet_Hourglass(LoiAbstraiteGeneral * loiHourglass, const BlocGen & bloc)
{ // on initialise le traitement de l'hourglass
  string str_precision; // string vide indique que l'on veut utiliser un élément normal
  // dans le cas où il s'agit d'élément Quadratique il faut utiliser 9 pti par défaut
  if ((id_interpol == QUADRATIQUE) || (id_interpol == QUADRACOMPL))
       str_precision = "_cm9pti";  
  
  ElemMeca::Init_hourglass_comp(*(unefois->doCoMemb->pentaedHourg),str_precision,loiHourglass,bloc); 
  // dans le cas où l'hourglass a été activé mais que l'élément n'a pas
  // de traitement particulier associé, alors on désactive l'hourglass
  if ( ((type_stabHourglass == STABHOURGLASS_PAR_COMPORTEMENT) || (type_stabHourglass == STABHOURGLASS_PAR_COMPORTEMENT_REDUIT))
     &&(unefois->doCoMemb->pentaedHourg == NULL))
		  type_stabHourglass = STABHOURGLASS_NON_DEFINIE;
  return this;
};
        
// ajout du tableau de ddl des noeuds 
 void PentaMemb::ConstTabDdl()
    {  
    Tableau <Ddl> ta(ParaGlob::Dimension());
    int posi = Id_nom_ddl("X1") -1;
    int dim =  ParaGlob::Dimension();   
    for (int i =1; i<= dim; i++)
	    {Ddl inter((Enum_ddl(i+posi)),0.,LIBRE);
	     ta(i) = inter;
	     }
    // attribution des ddls aux noeuds
    for (int ne=1; ne<= nombre->nbne; ne++)    
       tab_noeud(ne)->PlusTabDdl(ta); 
    };
  
//------- calcul d'erreur, remontée des contraintes -------------------

// fonction d'initialisation servant dans les classes derivant
// au niveau du constructeur
// les pointeurs d'éléments sont non nul uniquement lorsque doCoMemb est null
// c'est-à-dire pour l'initialisation 
PentaMemb::DonnComPenta* PentaMemb::Init 
   (ElemGeomC0* penta,ElemGeomC0* pentaEr,ElemGeomC0* pentaMas
	,ElemGeomC0* pentaeHourg,bool sans_init_noeud) 
{  
    id_geom=PENTAEDRE;      //
    // le fait de mettre les pointeurs a null permet
    // de savoir que l'element n'est pas complet
    // dans le cas d'un constructeur avec tableau de noeud, il ne faut pas mettre
    // les pointeurs à nuls d'où le test
    if (!sans_init_noeud)
        for (int i =1;i<= nombre->nbne;i++) tab_noeud(i) = NULL;
    // definition des donnees communes aux PentaMembxxx
    // a la premiere definition d'une instance
    if (unefois->doCoMemb == NULL)
      unefois->doCoMemb = PentaMemb::Def_DonneeCommune(penta,pentaEr,pentaMas,pentaeHourg);
    PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb; // pour simplifier l'écriture
    met = &(CoPenta->metrique); // met est defini dans elemeca
    // def pointe sur la deformation specifique a l'element
    def = new Deformation(*met,tab_noeud,(CoPenta->pentaed)->TaDphi(),(CoPenta->pentaed)->TaPhi());
    // idem pour la remonte aux contraintes et le calcul d'erreur
    defEr = new Deformation(*met,tab_noeud,(CoPenta->pentaedEr)->TaDphi(),(CoPenta->pentaedEr)->TaPhi());
    // idem pour le calcul de la masse
    defMas = new Deformation(*met,tab_noeud,(CoPenta->pentaedMas)->TaDphi(),(CoPenta->pentaedMas)->TaPhi());
    // idem pour le calcul de second membre
    defSurf.Change_taille(5); // une seule surface pour le second membre
    for (int ii=1;ii<=5;ii++)
       defSurf(ii) = NULL; // la déformation sera construite si nécessaire au moment du calcul de
                       // second membre
    // idem pour le calcul de second membre
    defArete.Change_taille(9); // 9 arrêtes utilisées pour  le second membre
    // la déformation sera construite si nécessaire au moment du calcul de second membre
    for (int ia=1;ia<=9;ia++)
      defArete(ia) = NULL;

    //dimensionnement des deformations et contraintes etc..
    int dimtens = 3;
    lesPtMecaInt.Change_taille_PtIntegMeca(nombre->nbI,dimtens);
    // attribution des numéros de référencement dans le conteneur
    for (int ni = 1; ni<= nombre->nbI; ni++)
       {lesPtMecaInt(ni).Change_Nb_mail(this->num_maillage);
        lesPtMecaInt(ni).Change_Nb_ele(this->num_elt);
        lesPtMecaInt(ni).Change_Nb_pti(ni);
       };

	   int nbddl = CoPenta->tab_ddl.NbDdl();
    // stockage des donnees particulieres de la loi de comportement mécanique au point d'integ
    tabSaveDon.Change_taille(nombre->nbI);
    // stockage des donnees particulieres de la loi de comportement thermo physique au point d'integ
    tabSaveTP.Change_taille(nombre->nbI);
    // stockage des donnees particulieres de la déformation mécanique au point d'integ
    tabSaveDefDon.Change_taille(nombre->nbI);
    tab_energ.Change_taille(nombre->nbI);
    tab_energ_t.Change_taille(nombre->nbI);
    // initialisation des pointeurs définis dans la classe Element concernant les résidus et
    // raideur
    // --- cas de la puissance interne ---
    residu = &(CoPenta->residu_interne); // residu local
    raideur = &(CoPenta->raideur_interne); // raideur locale
        // --- cas de la dynamique -----
    mat_masse =  &(CoPenta->matrice_masse);
     // --- cas des efforts externes concernant les points ------
    res_extN = &(CoPenta->residus_externeN); // pour les résidus et second membres
    raid_extN= &(CoPenta->raideurs_externeN);// pour les raideurs
     // --- cas des efforts externes concernant les aretes ------
    res_extA = &(CoPenta->residus_externeA); // pour les résidus et second membres
    raid_extA= &(CoPenta->raideurs_externeA);// pour les raideurs
     // --- cas des efforts externes concernant les faces  ------
    res_extS= &(CoPenta->residus_externeS); // pour les résidus et second membres
    raid_extS= &(CoPenta->raideurs_externeS); // pour les raideurs

    return CoPenta;
};  

// fonction permettant le calcul de doCoPenta
PentaMemb::DonnComPenta* PentaMemb::Def_DonneeCommune
 (ElemGeomC0* penta,ElemGeomC0* pentaEr,ElemGeomC0* pentaMas, ElemGeomC0* pentaeHourg)
  {	 
    // degre de liberte
    int dim = ParaGlob::Dimension();
    DdlElement  tab_ddl(nombre->nbne,dim);
    int posi = Id_nom_ddl("X1") -1;
	   for (int i =1; i<= dim; i++)
	    for (int j=1; j<= nombre->nbne; j++)
	//    tab_ddl (j,i) = Enum_ddl(i+posi);
	      tab_ddl.Change_Enum(j,i,Enum_ddl(i+posi));
    // cas des ddl éléments secondaires pour le calcul d'erreur
    // def du nombre de composantes du tenseur de contrainte en absolu
    // en fait 6 ici
    int nbcomposante = 6;
    DdlElement  tab_ddlErr(nombre->nbne,nbcomposante);
    posi = Id_nom_ddl("SIG11") -1;
    // uniquement un cas est considéré  6 composantes
    for (int j=1; j<= nombre->nbne; j++)
      { // on definit le nombre de composante de sigma en absolu
        // les composantes sont a suivre dans l'enumération   
        for (int i= 1;i<= nbcomposante; i++)
   //      tab_ddlErr (j,i) = Enum_ddl(i+posi);
	          tab_ddlErr.Change_Enum(j,i,Enum_ddl(i+posi));
       }  
    // egalement pour tab_Err1Sig11, def d'un tableau de un ddl : enum SIG11
    // par noeud
    DdlElement tab_Err1Sig11(nombre->nbne,DdlNoeudElement(SIG11));
    // pour le calcul des seconds membres, def de l'élément géométrique de facette
    GeomTriangle triaS(nombre->nbiST,nombre->nbneST);
    GeomQuadrangle quadraS(nombre->nbiSQ,nombre->nbneSQ);
    GeomSeg seggHS(nombre->nbiAQ,nombre->nbneAQ);
    GeomSeg seggFS(nombre->nbiAT,nombre->nbneAT);

	   // def metrique
	   // on definit les variables a priori toujours utiles
    Tableau<Enum_variable_metrique> tab(24);
    tab(1) = iM0;          tab(2) = iMt;            tab(3) = iMtdt ;
    tab(4) = igiB_0;       tab(5) = igiB_t;         tab(6) = igiB_tdt;
    tab(7) = igiH_0;       tab(8) = igiH_t;         tab(9) = igiH_tdt ;
    tab(10)= igijBB_0;     tab(11)= igijBB_t;       tab(12)= igijBB_tdt;
    tab(13)= igijHH_0;     tab(14)= igijHH_t;       tab(15)= igijHH_tdt ;
    tab(16)= id_gijBB_tdt; tab(17)= id_giH_tdt;     tab(18)= id_gijHH_tdt;
    tab(19)= idMtdt ;      tab(20)= id_jacobien_tdt;tab(21)= id2_gijBB_tdt; 
    tab(22)= igradVBB_tdt; tab(23) = iVtdt;         tab(24)= idVtdt;
	   // dim du pb , nb de vecteur de la base  = 3 ici, tableau de ddl et la def de variables
	   Met_abstraite  metri(dim,3,tab_ddl,tab,nombre->nbne) ;
	   // ---- cas du calcul d'erreur sur sigma ou epsilon
    Tableau <Vecteur *>  resEr(nbcomposante);
    for (int i=1; i<= nbcomposante; i++)
        resEr(i)=new Vecteur (nombre->nbne);
    Mat_pleine  raidEr(nombre->nbne,nombre->nbne); // la raideur pour l'erreur
    // dimensionnement des différents résidus et raideurs pour le calcul mécanique
    int nbddl = tab_ddl.NbDdl();
    int nbA = penta->NbSe(); // nombre d'arêtes
    int nbS = penta->NbFe(); // nombre de faces
    Vecteur  residu_int(nbddl); Mat_pleine  raideur_int(nbddl,nbddl);
       // cas de la dynamique
    Mat_pleine  matmasse(1,nbddl);  // a priori on dimensionne en diagonale 
       // cas des noeuds
    Tableau <Vecteur* >  residus_extN(nombre->nbne); residus_extN(1) = new Vecteur(dim); 
    Tableau <Mat_pleine* >  raideurs_extN(nombre->nbne); raideurs_extN(1) = new Mat_pleine(dim,dim);
    for (int i = 2;i<= nombre->nbne;i++)
       { residus_extN(i) = residus_extN(1); 
         raideurs_extN(i) = raideurs_extN(1);
       }
       // cas des arêtes
    int nbddlAQ = nombre->nbneAQ * dim; // ddl pour les arêtes verticales 
    int nbddlAT = nombre->nbneAT * dim; // ddl pour les arêtes des faces triangulaires 
    Tableau <Vecteur* >  residus_extA(nbA); 
    residus_extA(1) = new Vecteur(nbddlAT);residus_extA(4) = new Vecteur(nbddlAQ); 
    Tableau <Mat_pleine* >  raideurs_extA(nbA); 
    raideurs_extA(1) = new Mat_pleine(nbddlAT,nbddlAT);
    raideurs_extA(4) = new Mat_pleine(nbddlAQ,nbddlAQ);
    
    residus_extA(2) = residus_extA(1);residus_extA(3) = residus_extA(1);
    residus_extA(7) = residus_extA(1);residus_extA(8) = residus_extA(1);
    residus_extA(9) = residus_extA(1);
    residus_extA(5) = residus_extA(4);residus_extA(6) = residus_extA(4);
    
    raideurs_extA(2) = raideurs_extA(1);raideurs_extA(3) = raideurs_extA(1);
    raideurs_extA(7) = raideurs_extA(1);raideurs_extA(8) = raideurs_extA(1);
    raideurs_extA(9) = raideurs_extA(1);
    raideurs_extA(5) = raideurs_extA(4);raideurs_extA(6) = raideurs_extA(4);

        //   cas des faces
    int nbddlSQ = nombre->nbneSQ * dim; // ddl pour les faces quadrangulaires 
    int nbddlST = nombre->nbneST * dim; // ddl pour les faces triangulaires 
    Tableau <Vecteur* >  residus_extS(nbS); 
    residus_extS(1) = new Vecteur(nbddlST);residus_extS(2) = new Vecteur(nbddlSQ);
    Tableau <Mat_pleine* >  raideurs_extS(nbS);
    raideurs_extS(1) = new Mat_pleine(nbddlST,nbddlST);
    raideurs_extS(2) = new Mat_pleine(nbddlSQ,nbddlSQ);
    residus_extS(4) = residus_extS(1);
    residus_extS(3) = residus_extS(2);residus_extS(5) = residus_extS(2);
    raideurs_extS(4) = raideurs_extS(1);
    raideurs_extS(3) = raideurs_extS(2);raideurs_extS(5) = raideurs_extS(2);

    // definition de la classe static contenant toute les variables communes aux PentaMemb
    PentaMemb::DonnComPenta* dodo;
    dodo = new DonnComPenta
           (penta,tab_ddl,tab_ddlErr,tab_Err1Sig11,metri,resEr,raidEr,pentaEr
            ,quadraS,triaS,seggHS,seggFS,residu_int,raideur_int,residus_extN
            ,raideurs_extN,residus_extA,raideurs_extA,residus_extS,raideurs_extS
            ,matmasse,pentaMas,nombre->nbI,pentaeHourg
           );
    return dodo;
  };    

 
// destructions de certaines grandeurs pointées, créées  au niveau de l'initialisation
void PentaMemb::Destruction()
  { // tout d'abord l'idée est de détruire certaines grandeurs pointées que pour le dernier élément
    if ((unefois->nbelem_in_Prog == 0)&& (unefois->doCoMemb != NULL))
      // cas de la destruction du dernier élément
      { PentaMemb::DonnComPenta* CoPenta = unefois->doCoMemb;         // pour simplifier l'écriture
        int  resErrTaille = CoPenta->resErr.Taille();
        for (int i=1;i<= resErrTaille;i++)
          delete CoPenta->resErr(i);
        delete CoPenta->residus_externeN(1);
        delete CoPenta->raideurs_externeN(1);
        delete CoPenta->residus_externeA(1);
        delete CoPenta->residus_externeA(4);
        delete CoPenta->raideurs_externeA(1);
        delete CoPenta->raideurs_externeA(4);
        for (int i=1;i<= 2;i++)
          delete CoPenta->residus_externeS(i);
        for (int i=1;i<= 2;i++)
          delete CoPenta->raideurs_externeS(i);
		  if (CoPenta->pentaedHourg != NULL) delete CoPenta->pentaedHourg;
       }
   };
   
