// FICHIER : TetraMemb.h
// CLASSE : TetraMemb

// 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/>.

 
 /************************************************************************
 *                                                                      *
 *     DATE:        15/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 * La classe TetraMemb permet de declarer des elements tetrahedriques et de realiser
 * le calcul du residu local et de la raideur locale pour une loi de comportement
 * donnee. La dimension de l'espace pour un tel element est 3
 *
 * l'interpolation  le nombre de point d'integration sont definit dans les classes derivees
 *
 * l'element est virtuel
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                      *
 *                                                                $     *
 *                                                                      *
 ************************************************************************/

// -----------classe pour un calcul de mecanique---------

// La classe TetraMemb permet de declarer des elements tetrahedriques et de realiser
// le calcul du residu local et de la raideur locale pour une loi de comportement
// donnee. La dimension de l'espace pour un tel element est 3
//
// l'interpolation  le nombre de point d'integration sont definit dans les classes derivees
//
// l'element est virtuel


#ifndef TETRAMEMB_H
#define TETRAMEMB_H

#include "ParaGlob.h"
#include "ElemMeca.h"
#include "Met_abstraite.h"
#include "ElemGeomC0.h"
#include "Noeud.h"
#include "UtilLecture.h"
#include "Tenseur.h"
#include "NevezTenseur.h"
#include "Deformation.h"
#include "GeomSeg.h"
#include "GeomTriangle.h"

/// @addtogroup groupe_des_elements_finis
///  @{
///


class TetraMemb : public ElemMeca
{
		
	public :
	
		// CONSTRUCTEURS :
		// Constructeur par defaut
		TetraMemb ();
		
        // Constructeur fonction  d'un numero
        // d'identification , d'identificateur d'interpolation et de geometrie 
		  // et éventuellement un string d'information annexe 
        TetraMemb (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,string info="");
		
        // Constructeur fonction  d'un numero de maillage et d'identification,
        // du tableau de connexite des noeuds, d'identificateur d'interpolation et de geometrie
		  // et éventuellement un string d'information annexe 
        TetraMemb (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,
                     const Tableau<Noeud *>& tab,string info="") ;
		
		// Constructeur de copie
		TetraMemb (const TetraMemb& tetraMem);
		
		
		// DESTRUCTEUR :
		~TetraMemb ();
		
		
		// Surcharge de l'operateur = : realise l'egalite entre deux instances de TetraMemb
		TetraMemb& operator= (TetraMemb& tetraMem);
		
		// METHODES :
// 1) derivant des virtuelles pures

		// Lecture des donnees de la classe sur fichier
		void LectureDonneesParticulieres (UtilLecture *,Tableau<Noeud  *> * );
		        
	    // affichage d'info en fonction de ordre
	    // ordre = "commande" : affichage d'un exemple d'entree pour l'élément
        void Info_com_Element(UtilLecture * entreePrinc,string& ordre,Tableau<Noeud  *> * tabMaillageNoeud) 
          { return Element::Info_com_El(nombre->nbne,entreePrinc,ordre,tabMaillageNoeud);};                         
        
		// ramene l'element geometrique 
		ElemGeomC0& ElementGeometrique() const { return *(unefois->doCoMemb->tetraed);};
		// ramene l'element geometrique en constant
		const ElemGeomC0& ElementGeometrique_const() const {return *(unefois->doCoMemb->tetraed);}; 
		
		// 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 & Point_physique(const Coordonnee& c_int,Coordonnee & co,Enum_dure temps);
		// 3) cas où l'on veut les coordonnées aux 1, 2 ou trois temps selon la taille du tableau t_co
		void Point_physique(const Coordonnee& c_int,Tableau <Coordonnee> & t_co);

        // inactive les ddl du problème primaire de mécanique
        inline void Inactive_ddl_primaire()
            {ElemMeca::Inact_ddl_primaire(unefois->doCoMemb->tab_ddl);};
        // active les ddl du problème primaire de mécanique
        inline void Active_ddl_primaire()
            {ElemMeca::Act_ddl_primaire(unefois->doCoMemb->tab_ddl);};
        // ajout des ddl de contraintes pour les noeuds de l'élément
        inline void Plus_ddl_Sigma() 
            {ElemMeca::Ad_ddl_Sigma(unefois->doCoMemb->tab_ddlErr);};
        // inactive les ddl du problème de recherche d'erreur : les contraintes
        inline void Inactive_ddl_Sigma()
            {ElemMeca::Inact_ddl_Sigma(unefois->doCoMemb->tab_ddlErr);};
        // active les ddl du problème de recherche d'erreur : les contraintes
        inline void Active_ddl_Sigma()
            {ElemMeca::Act_ddl_Sigma(unefois->doCoMemb->tab_ddlErr);};
        // active le premier ddl du problème de recherche d'erreur : SIGMA11
        inline void Active_premier_ddl_Sigma() 
            {ElemMeca::Act_premier_ddl_Sigma();};
 
        // lecture de données diverses sur le flot d'entrée
        void LectureContraintes(UtilLecture * entreePrinc) 
          { if (unefois->CalResPrem_t == 1) 
               ElemMeca::LectureDesContraintes (false,entreePrinc,lesPtMecaInt.TabSigHH_t());
            else
               { ElemMeca::LectureDesContraintes (true,entreePrinc,lesPtMecaInt.TabSigHH_t());
                 unefois->CalResPrem_t = 1;
                } 
           };
        
          // retour des contraintes en absolu retour true si elle existe sinon false
        bool ContraintesAbsolues(Tableau <Vecteur>& tabSig)
          { if (unefois->CalResPrem_t == 1) 
               ElemMeca::ContraintesEnAbsolues(false,lesPtMecaInt.TabSigHH_t(),tabSig);
            else
               { ElemMeca::ContraintesEnAbsolues(true,lesPtMecaInt.TabSigHH_t(),tabSig);
                 unefois->CalResPrem_t = 1;
                } 
            return true; }

		// Libere la place occupee par le residu et eventuellement la raideur
		// par l'appel de Libere de la classe mere et libere les differents tenseurs
		// intermediaires cree pour le calcul et les grandeurs pointee
		// de la raideur et du residu
		void Libere ();
		
		// acquisition  d'une loi de comportement
		void DefLoi (LoiAbstraiteGeneral * NouvelleLoi);
		
       // test si l'element est complet
       // = 1 tout est ok, =0 element incomplet
		int TestComplet();
		
		// procedure permettant de completer l'element apres
		// sa creation avec les donnees du bloc transmis
		// peut etre appeler plusieurs fois
		// ici pour l'instant ne fait rien
		Element* Complete(BlocGen & bloc,LesFonctions_nD*  lesFonctionsnD);
		// Compléter pour la mise en place de la gestion de l'hourglass
		Element* Complet_Hourglass(LoiAbstraiteGeneral * NouvelleLoi, const BlocGen & bloc);

		// ramene vrai si la surface numéro ns existe pour l'élément
		// dans le cas des éléments Tetraedrique il  peut y avoir de 1 à 4 surfaces
		bool SurfExiste(int ns) const 
		  { if ((ns>=1)&&(ns<=4)) return true; else return false;};
		
		// ramene vrai si l'arête numéro na existe pour l'élément
		bool AreteExiste(int na) const 
		  {if ((na <= 6) || (na>= 1)) return true; else return false;};

		// retourne les tableaux de ddl associés aux noeuds, gere par l'element
		// ce tableau et specifique a l'element
		const DdlElement & TableauDdl() const
           { return unefois->doCoMemb->tab_ddl; };
                         
		// Calcul du residu local et de la raideur locale,
		//  pour le schema implicite
		Element::ResRaid  Calcul_implicit (const ParaAlgoControle & pa);
		
		// Calcul du residu local a t
		// pour le schema explicit par exemple 
		Vecteur* CalculResidu_t (const ParaAlgoControle & pa)
		  { return TetraMemb::CalculResidu(false,pa);};
		
		// Calcul du residu local a tdt
		// pour le schema explicit par exemple 
		Vecteur* CalculResidu_tdt (const ParaAlgoControle & pa)
		  { return TetraMemb::CalculResidu(true,pa);};
		
        // Calcul de la matrice masse pour l'élément
        Mat_pleine * CalculMatriceMasse (Enum_calcul_masse id_calcul_masse) ;

        // --------- calcul dynamique ---------
        // calcul  de la longueur d'arrête de l'élément minimal
        // divisé par la célérité  la plus rapide dans le matériau
        double Long_arrete_mini_sur_c(Enum_dure temps)
             { return ElemMeca::Interne_Long_arrete_mini_sur_c(temps);};

        //------- calcul d'erreur, remontée des contraintes -------------------
           // 1) calcul du résidu et de la matrice de raideur pour le calcul d'erreur
        Element::Er_ResRaid ContrainteAuNoeud_ResRaid();
          // 2) remontée aux erreurs aux noeuds
        Element::Er_ResRaid ErreurAuNoeud_ResRaid();
                                            
        // ------- affichage ou récupération d'informations --------------        
		// retourne un numero d'ordre d'un point le plus près ou est exprimé la grandeur enum
		// par exemple un point d'intégration, mais n'est utilisable qu'avec des méthodes particulières
		// par exemple CoordPtInteg, ou Valeur_a_diff_temps
		// car le numéro d'ordre peut-être différent du numéro d'intégration au sens classique 
		// temps: dit si c'est à 0 ou t ou tdt
		int PointLePlusPres(Enum_dure temps,Enum_ddl enu, const Coordonnee& M) 
		    { return PtLePlusPres(temps,enu,M);};
		         
        // recuperation des coordonnées du point de numéro d'ordre iteg pour 
        // la grandeur enu
		// temps: dit si c'est à 0 ou t ou tdt
        // si erreur retourne erreur à true
        Coordonnee CoordPtInteg(Enum_dure temps,Enum_ddl enu,int iteg,bool& erreur)
		    { return CoordPtInt(temps,enu,iteg,erreur);};
        
        // récupération des  valeurs au numéro d'ordre  = iteg pour
        // les grandeur enu
        Tableau <double> Valeur_a_diff_temps(bool absolue,Enum_dure enu_t,const List_io<Ddl_enum_etendu>& enu,int iteg);
        // 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 ValTensorielle_a_diff_temps(bool absolue,Enum_dure enu_t,List_io<TypeQuelconque>& enu,int iteg);                         	

	 	//============= 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 Lecture_base_info
	       (istream& ent,const Tableau<Noeud  *> * tabMaillageNoeud,const int cas) ;
       // cas donne le niveau de sauvegarde
       // = 1 : on sauvegarde tout
       // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
	   void Ecriture_base_info(ostream& sort,const int cas) ;

// 2) derivant des virtuelles 

	// retourne un tableau de ddl element, correspondant à la 
	// composante de sigma -> SIG11, pour chaque noeud qui contiend
	// des ddl de contrainte
	// -> utilisé pour l'assemblage de la raideur d'erreur
       DdlElement&  Tableau_de_Sig1() const
                         {return unefois->doCoMemb->tab_Err1Sig11;} ;
                         
    // actualisation des ddl et des grandeurs actives de t+dt vers t      
       void TdtversT();
    // actualisation des ddl et des grandeurs actives de t vers tdt      
       void TversTdt();

    // calcul de l'erreur sur l'élément. Ce calcul n'est disponible
    // qu'une fois la remontée aux contraintes effectuées sinon aucune
    // action. En retour la valeur de l'erreur sur l'élément
    // type indique le type de calcul d'erreur :
       void ErreurElement(int type,double& errElemRelative
                            ,double& numerateur, double& denominateur); 

	   // 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
    // -> explicite à t
    Vecteur SM_charge_volumique_E_t
      (const Coordonnee& force,Fonction_nD* pt_fonct,const ParaAlgoControle & pa,bool sur_volume_finale_)
        { return TetraMemb::SM_charge_volumique_E(force,pt_fonct,false,pa,sur_volume_finale_);} ;
    // -> explicite à tdt
    Vecteur SM_charge_volumique_E_tdt
      (const Coordonnee& force,Fonction_nD* pt_fonct,const ParaAlgoControle & pa,bool sur_volume_finale_)
        { return TetraMemb::SM_charge_volumique_E(force,pt_fonct,true,pa,sur_volume_finale_);} ;
	   // -> 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
	   ResRaid SMR_charge_volumique_I
       (const Coordonnee& force,Fonction_nD* pt_fonct,const ParaAlgoControle & pa,bool sur_volume_finale_) ;
	   // 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
	   // -> version explicite à t
	   Vecteur SM_charge_surfacique_E_t(const Coordonnee& force,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & pa) 
	     { return TetraMemb::SM_charge_surfacique_E(force,pt_fonct,numFace,false,pa);} ;
	   // -> version explicite à tdt
	   Vecteur SM_charge_surfacique_E_tdt(const Coordonnee& force,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & pa) 
	     { return TetraMemb::SM_charge_surfacique_E(force,pt_fonct,numFace,true,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
	   ResRaid SMR_charge_surfacique_I
	            (const Coordonnee& force,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & 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 
	   Vecteur SM_charge_presUniDir_E_t(const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & pa)
	     { return TetraMemb::SM_charge_presUniDir_E(presUniDir,pt_fonct,numFace,false,pa);} ;
	   // -> explicite à tdt 
	   Vecteur SM_charge_presUniDir_E_tdt(const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & pa)
	     { return TetraMemb::SM_charge_presUniDir_E(presUniDir,pt_fonct,numFace,true,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
	   ResRaid SMR_charge_presUniDir_I(const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & 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
	   // -> explicite à t 
	   Vecteur SM_charge_lineique_E_t(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) 
	     { return TetraMemb::SM_charge_lineique_E(force,pt_fonct,numArete,false,pa);} ;
	   // -> explicite à tdt 
	   Vecteur SM_charge_lineique_E_tdt(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) 
	     { return TetraMemb::SM_charge_lineique_E(force,pt_fonct,numArete,true,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
	    ResRaid SMR_charge_lineique_I(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & 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 
	   Vecteur SM_charge_pression_E_t(double pression,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & pa)
	     { return TetraMemb::SM_charge_pression_E(pression,pt_fonct,numFace,false,pa);};
	   // -> explicite à tdt 
	   Vecteur SM_charge_pression_E_tdt(double pression,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & pa)
	     { return TetraMemb::SM_charge_pression_E(pression,pt_fonct,numFace,true,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
	   ResRaid SMR_charge_pression_I(double pression,Fonction_nD* pt_fonct,int numFace,const ParaAlgoControle & pa) ;

	   // cas d'un chargement surfacique hydrostatique, 
	   // 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
	   // -> explicite à t	   
	   Vecteur SM_charge_hydrostatique_E_t(const Coordonnee& dir_normal_liquide,const double& poidvol
                                           ,int numFace,const Coordonnee& M_liquide,Fonction_nD* pt_fonct
                                           ,const ParaAlgoControle & pa
                                           ,bool sans_limitation)
	     { return TetraMemb::SM_charge_hydrostatique_E(dir_normal_liquide,poidvol,numFace,M_liquide,false,pa,sans_limitation);};
	   // -> explicite à tdt	   
	   Vecteur SM_charge_hydrostatique_E_tdt(const Coordonnee& dir_normal_liquide,const double& poidvol
                                             ,int numFace,const Coordonnee& M_liquide,Fonction_nD* pt_fonct
                                             ,const ParaAlgoControle & pa
                                             ,bool sans_limitation)
	     { return TetraMemb::SM_charge_hydrostatique_E(dir_normal_liquide,poidvol,numFace,M_liquide,true,pa,sans_limitation);};
	   // -> 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
	    ResRaid SMR_charge_hydrostatique_I(const Coordonnee& dir_normal_liquide,const double& poidvol
                                           ,int numFace,const Coordonnee& M_liquide
                                           ,const ParaAlgoControle & pa
                                           ,bool sans_limitation) ;

	   // 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	   
	   Vecteur SM_charge_hydrodynamique_E_t(  Courbe1D* frot_fluid,const double& poidvol
	                                                 ,  Courbe1D* coef_aero_n,int numFace,const double& coef_mul
	                                                 ,  Courbe1D* coef_aero_t
                                                  ,const ParaAlgoControle & pa)
	      {return SM_charge_hydrodynamique_E(frot_fluid,poidvol,coef_aero_n,numFace,coef_mul,coef_aero_t,false,pa);};
	   // -> explicite à tdt	   
	   Vecteur SM_charge_hydrodynamique_E_tdt(  Courbe1D* frot_fluid,const double& poidvol
	                                                  ,  Courbe1D* coef_aero_n,int numFace,const double& coef_mul
	                                                  ,  Courbe1D* coef_aero_t
                                                   ,const ParaAlgoControle & pa)
	      {return SM_charge_hydrodynamique_E(frot_fluid,poidvol,coef_aero_n,numFace,coef_mul,coef_aero_t,true,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
	   ResRaid 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) ;
	 
     // ========= définition et/ou construction des frontières ===============
     			
		// 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 & Frontiere(bool force = false);
		
        // 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  Frontiere_points(int num,bool force = false);

		// 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  Frontiere_lineique(int num,bool force = false);
		
		// ramène la frontière surfacique
		// éventuellement création des 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  Frontiere_surfacique(int num,bool force = false);

	// 3) methodes propres a l'element
				
        // ajout du tableau specific de ddl des noeuds 
        // la procedure met a jour les ddl(relatif a l'element, c-a-d Xi)
        // des noeuds constituants l'element
        void ConstTabDdl();
        
     public :		
	 // -------------- definition de la classe conteneur de donnees communes ------------	
	    class DonnComTetra
	      { public :
	        // hexa1 doit pointer sur un element deja existant via un new
	        DonnComTetra (ElemGeomC0* tetra1,DdlElement& tab,DdlElement&  tabErr,DdlElement&  tab_Err1Sig,
	                       Met_abstraite&  met_gene, 
	                       Tableau <Vecteur *> & resEr,Mat_pleine& raidEr,ElemGeomC0* tetraeEr,
	                       GeomTriangle triS,GeomSeg& seggS,
	                       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* tetraeMas,int nbi,
								  ElemGeomC0* tetraeHourg
	                         );
	        DonnComTetra(DonnComTetra& a) ;
	        ~DonnComTetra();
          // variables
            ElemGeomC0* tetraed; // contiend les fonctions d'interpolation et
	                             // les derivees 
	         DdlElement  tab_ddl; // tableau des degres 
                     //de liberte des noeuds de l'element commun a tous les
                     // elements
            Met_abstraite  metrique; 
		      Mat_pleine  matGeom ; // matrice géométrique
            Mat_pleine  matInit  ; // matrice initiale
            Tableau <TenseurBB *> d_epsBB;  // place pour la variation des def
            Tableau <TenseurHH *> d_sigHH;  // place pour la variation des contraintes
            Tableau < Tableau2 <TenseurBB *> > d2_epsBB; // variation seconde des déformations
             // ---- concernant les frontières et particulièrement le calcul de second membre
            GeomTriangle triaS; // contiend les fonctions d'interpolation 
                               // et les derivees pour les  surfaces
            GeomSeg        segS;    // idem pour les arêtes

                // calcul d'erreur  
	         DdlElement  tab_ddlErr; // tableau des degres servant pour le calcul
	         // d'erreur : contraintes
	         DdlElement  tab_Err1Sig11;  // tableau du ddl SIG11 pour chaque noeud,  servant pour le calcul
	         // d'erreur : contraintes, en fait pour l'assemblage
                 
            Tableau <Vecteur *>  resErr;  // residu pour le calcul d'erreur
            Mat_pleine  raidErr; // raideur pour le calcul d'erreur 
            ElemGeomC0* tetraedEr; // contiend les fonctions d'interpolation et
	                           // les derivees  pour le calcul du hessien dans 
	                           //la résolution de la fonctionnelle d'erreur             
	        // -------- calcul de résidus, de raideur : interne ou pour les efforts extérieurs ----------
	        // on utilise des pointeurs pour optimiser la place (même place pointé éventuellement)
	         Vecteur  residu_interne;    
            Mat_pleine  raideur_interne; 
            Tableau <Vecteur* >  residus_externeN;   // pour les noeuds
            Tableau <Mat_pleine* >  raideurs_externeN;  // pour les noeuds 
            Tableau <Vecteur* >  residus_externeA;   // pour les aretes
            Tableau <Mat_pleine* >  raideurs_externeA;  // pour les aretes 
            Tableau <Vecteur* >  residus_externeS;   // pour les surfaces
            Tableau <Mat_pleine* >  raideurs_externeS;  // pour les surfaces 
            // ------ données concernant la dynamique --------
            Mat_pleine matrice_masse;
            ElemGeomC0* tetraedMas; // contiend les fonctions d'interpolation et ...
	                           // pour les calculs relatifs à la masse            
				// ------ blocage éventuel d'hourglass
				  // utiliser dans ElemMeca::Cal_mat_hourglass_comp, Cal_implicit_hourglass, Cal_explici_hourglass									 
            ElemGeomC0* tetraedHourg; // contiend les fonctions d'interpolation 
            };          
 
	  // classe contenant tous les indicateurs statique qui sont modifiés une seule fois
	  // et un pointeur sur les données statiques communes 
	  // la classe est interne, toutes les variables sont publique. Un pointeur sur une instance de la 
	  // classe est défini. Son allocation est effectuée dans les classes dérivées
	     class UneFois
	      { public :
	         UneFois () ; // constructeur par défaut
	        ~UneFois () ; // destructeur
	   
	      // VARIABLES :
	       public : 
           TetraMemb::DonnComTetra * doCoMemb;
        
           // incicateurs permettant de dimensionner seulement au premier passage
           // utilise dans "CalculResidu" et "Calcul_implicit"
           int CalResPrem_t; int CalResPrem_tdt; // à t ou à tdt
           int  CalimpPrem;
           int  dualSortTetra; // pour la sortie des valeurs au pt d'integ
           int  CalSMlin_t; // pour les seconds membres  concernant les arretes
           int  CalSMlin_tdt; // pour les seconds membres  concernant les arretes
           int  CalSMRlin; // pour les seconds membres  concernant les arretes
           int  CalSMsurf_t; // pour les seconds membres  concernant les surfaces
           int  CalSMsurf_tdt; // pour les seconds membres  concernant les surfaces
           int  CalSMRsurf; // pour les seconds membres  concernant les surfaces
           int  CalSMvol_t; // pour les seconds membres  concernant les volumes
           int  CalSMvol_tdt; // pour les seconds membres  concernant les volumes
           int  CalSMvol; // pour les seconds membres  concernant les volumes
           int  CalDynamique; // pour le calcul de la matrice de masse
           int  CalPt_0_t_tdt; // pour le calcul de point à 0 t et tdt
			  // ---------- sauvegarde du nombre d'élément en cours --------
			  int nbelem_in_Prog;
	       }; 

    // ------------------------------------------------------------------------------------   
        
	protected :

      // VARIABLES PRIVEES :
	    UneFois * unefois; // pointeur défini dans la classe dérivée
	    
	    // grandeurs aux points d'intégration: contraintes, déformations, vitesses de def etc.
	    LesPtIntegMecaInterne  lesPtMecaInt;
	    		
	  // type structuré et pointeur pour construire les éléments
	  // le pointeur est défini dans le type dérivé
	    class  NombresConstruire
	     { public:
	       int nbne; // le nombre de noeud de l'élément
	       int nbneS ; // le nombre de noeud des facettes
	       int nbneA ; // le nombre de noeud des aretes
	       int nbi; // le nombre de point d'intégration pour le calcul mécanique
	       int nbiEr; // le nombre de point d'intégration pour le calcul d'erreur
	       int nbiV; // le nombre de point d'intégration pour le calcul de second membre volumique
	       int nbiS; // le nombre de point d'intégration pour le calcul de second membre surfacique
	       int nbiA; // le nombre de point d'intégration pour le calcul de second membre linéique
			 int nbiMas; // le nombre de point d'intégration pour le calcul de la matrice masse 
			 int nbiHour; // éventuellement, le nombre de point d'intégration un blocage d'hourglass
	       };
	    NombresConstruire * nombre; // le pointeur défini dans la classe dérivée d'hexamemb
	    
	  // =====>>>> methodes appelees par les classes dérivees <<<<=====
	  
        // fonction d'initialisation servant dans les classes derivant
        // au niveau du constructeur
        // les pointeurs d'éléments géométriques sont non nul uniquement lorsque doCoMemb est null
        // c'est-à-dire pour l'initialisation 
        TetraMemb::DonnComTetra* Init (ElemGeomC0* tetra,ElemGeomC0* tetraEr,ElemGeomC0* tetraMas
                                     ,ElemGeomC0* tetraeHourg,bool sans_init_noeud = false); 
        // destructions de certaines grandeurs pointées, créées  au niveau de l'initialisation
        void Destruction();
        		
	  // ==== >>>> methodes virtuelles dérivant d'ElemMeca ============  
		// ramene la dimension des tenseurs contraintes et déformations de l'élément
		int Dim_sig_eps() const {return 3;}; 
	                 
	  //------------ fonctions uniquement a usage interne ----------   
	  private :    
        // definition des données communes : doCoTetra
        // nbiS est pour le nombre de point d'intégration de surface triangle pour le second membre
        TetraMemb::DonnComTetra* Def_DonneeCommune(ElemGeomC0* tetra,ElemGeomC0* tetraEr
		                             ,ElemGeomC0* tetraMas,ElemGeomC0* tetraeHourg);    
        // Calcul du residu local a t ou tdt en fonction du booleen
		Vecteur* CalculResidu (bool atdt,const ParaAlgoControle & 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
	   // -> explicite à t ou tdt en fonction de la variable booleenne atdt 
	   Vecteur SM_charge_pression_E(double pression,Fonction_nD* pt_fonct,int numFace,bool atdt,const ParaAlgoControle & 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 SM_charge_presUniDir_E
	               (const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int numFace,bool atdt,const ParaAlgoControle & 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
	   // -> explicite à t ou tdt en fonction de la variable booleenne atdt 
	   Vecteur SM_charge_lineique_E
	               (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & 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
	   // -> explicite à t ou tdt en fonction de la variable booleenne atdt 
	   Vecteur SM_charge_surfacique_E
	               (const Coordonnee& force,Fonction_nD* pt_fonct,int numFace,bool atdt,const ParaAlgoControle & pa);
	   // 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
	   // -> explicite à t ou tdt en fonction de la variable booleenne atdt 
       Vecteur SM_charge_volumique_E
                   (const Coordonnee& force,Fonction_nD* pt_fonct,bool atdt,const ParaAlgoControle & pa,bool sur_volume_finale_);
	   // cas d'un chargement surfacique hydrostatique, 
	   // 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
	   // -> explicite à t	   
	   Vecteur 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);
	   // cas d'un chargement surfacique hydro-dynamique, 
       // voir méthode explicite plus haut, pour les arguments
	   // retourne  le second membre résultant
	   // bool atdt : permet de spécifier à t ou a t+dt	   
	   Vecteur 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) ;
};
/// @}  // end of group


#endif
	
	
		

