// FICHIER : Biellette.h
// CLASSE : Biellette

// 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:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  // La classe Biellette permet de declarer des elements     *
 *  biellettes 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 1.                                           *
 *                                                                      *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
// -----------classe pour un calcul de mecanique---------



#ifndef BIELLETTE_H
#define BIELLETTE_H

#include "ParaGlob.h"
#include "ElemMeca.h"
//#include "Loi_comp_abstraite.h"
#include "Met_abstraite.h"
#include "Met_biellette.h"
#include "Noeud.h"
#include "UtilLecture.h"
#include "Tenseur.h"
#include "NevezTenseur.h"
#include "Deformation.h"
#include "ElFrontiere.h"
#include "GeomSeg.h"
#include "ParaAlgoControle.h"
#include "FrontSegLine.h"
#include "Section.h"

class ConstrucElementbiel;

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


class Biellette : public ElemMeca
{
		
	public :
	
     // CONSTRUCTEURS :
     // Constructeur par defaut
     Biellette ();
     
     // Constructeur fonction d'une section et eventuellement d'un numero
     // d'identification et de maillage
     Biellette (double sect,int num_maill=0,int num_id=-3);
     
     // Constructeur fonction  d'un numero de maillage et d'identification  
     Biellette (int num_maill,int num_id);
     
     // Constructeur fonction d'une section, d'un numero de maillage et d'identification,
     // du tableau de connexite des noeuds 
     Biellette (double sect,int num_maill,int num_id,const Tableau<Noeud *>& tab);
     
     // Constructeur de copie
     Biellette (const Biellette& biel);
 
		
     // DESTRUCTEUR :
     ~Biellette ();
       
     // création d'un élément de copie: utilisation de l'opérateur new et du constructeur de copie 
     // méthode virtuelle
     Element* Nevez_copie() const { Element * el= new Biellette(*this); return el;}; 

     // Surcharge de l'operateur = : realise l'egalite entre deux instances de Biellette
     Biellette& operator= (Biellette& biel);
     
     // METHODES :
     // 1) derivant des virtuelles pures
     // Lecture des donnees de la classe sur fichier
     void LectureDonneesParticulieres (UtilLecture *,Tableau<Noeud  *> * );
     
     // 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 Biellette::CalculResidu(false,pa);};
     
     // Calcul du residu local a tdt
     // pour le schema explicit par exemple 
     Vecteur* CalculResidu_tdt (const ParaAlgoControle & pa)
       { return Biellette::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(); 
                                      
     // retourne les tableaux de ddl associés aux noeuds, gere par l'element
     // ce tableau et specifique a l'element
     const DdlElement & TableauDdl() const ;

			
     // 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();
     
     // procesure permettant de completer l'element apres
     // sa creation avec les donnees du bloc transmis
     // peut etre appeler plusieurs fois
     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 l'element geometrique 
     ElemGeomC0& ElementGeometrique() const  { return doCo->segment;}; 
     // ramene l'element geometrique en constant
     const ElemGeomC0& ElementGeometrique_const() const { return doCo->segment;}; 
     
     // 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);

     // -- connaissances particulières sur l'élément
     // ramène  l'épaisseur de l'élément 
     // =0. si la notion d'épaisseurs ne veut rien dire pour l'élément
     virtual double Section(Enum_dure enu , const Coordonnee& ) {return S(enu);};
     // ramène  l'épaisseur moyenne de l'élément (indépendante du point)
     // =0. si la notion d'épaisseurs ne veut rien dire pour l'élément
     virtual double SectionMoyenne(Enum_dure enu ) {return S(enu);};

     // affichage dans la sortie transmise, des variables duales "nom"
     // dans le cas ou nom est vide, affichage de "toute" les variables
      void AfficheVarDual(ostream& sort, Tableau<string>& nom);
           
     // 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(2,entreePrinc,ordre,tabMaillageNoeud);};                         
           
     // 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);                         	

     // ramene vrai si la surface numéro ns existe pour l'élément
     // dans le cas de la biellette il n'y a pas de surface
     bool SurfExiste(int ) const 
       { return false;};
     
     // ramene vrai si l'arête numéro na existe pour l'élément
     bool AreteExiste(int na) const {if (na==1) return true; else return false;};

	 
	    //============= 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,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,int cas) ;
    
     // METHODES VIRTUELLES:
         // --------- calculs utils dans le cadre de la recherche du flambement linéaire		
     // Calcul de la matrice géométrique et initiale
     ElemMeca::MatGeomInit MatricesGeometrique_Et_Initiale (const ParaAlgoControle & pa) ;

     // retourne la liste des données particulières actuellement utilisés
     // par l'élément (actif ou non), sont exclu de cette liste les données particulières des noeuds
     // reliés à l'élément
     // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
     List_io <TypeQuelconque> Les_types_particuliers_internes(bool absolue) const;
     
     // récupération de grandeurs particulières au numéro d'ordre  = iteg  
     // celles-ci peuvent être quelconques
     // en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
     // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
     void Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ,int iteg);
 
     // inactive les ddl du problème primaire de mécanique
     inline void Inactive_ddl_primaire()
         {ElemMeca::Inact_ddl_primaire(doCo->tab_ddl);};
     // active les ddl du problème primaire de mécanique
     inline void Active_ddl_primaire()
         {ElemMeca::Act_ddl_primaire(doCo->tab_ddl);};
     // ajout des ddl de contraintes pour les noeuds de l'élément
     inline void Plus_ddl_Sigma() 
         {ElemMeca::Ad_ddl_Sigma(doCo->tab_ddlErr);};
     // inactive les ddl du problème de recherche d'erreur : les contraintes
     inline void Inactive_ddl_Sigma()
         {ElemMeca::Inact_ddl_Sigma(doCo->tab_ddlErr);};
     // active les ddl du problème de recherche d'erreur : les contraintes
     inline void Active_ddl_Sigma()
         {ElemMeca::Act_ddl_Sigma(doCo->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
            { unefois.CalResPrem_t = 1;
              ElemMeca::ContraintesEnAbsolues(true,lesPtMecaInt.TabSigHH_t(),tabSig);
            };
         return true; 
       };
 

     // 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
     inline   DdlElement&  Tableau_de_Sig1() const
                          {return doCo->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); 

     // mise à jour de la boite d'encombrement de l'élément, suivant les axes I_a globales
     // en retour coordonnées du point mini dans retour.Premier() et du point maxi dans .Second()
     // la méthode est différente de la méthode générale car il faut prendre en compte l'épaisseur de l'élément
     virtual const DeuxCoordonnees& Boite_encombre_element(Enum_dure temps);
     
     // 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 Biellette::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 Biellette::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 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 
     Vecteur SM_charge_lineique_E_t(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) 
       { return Biellette::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 Biellette::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 lineique suiveuse, sur l'arrête frontière de
     // la biellette (2D uniquement)
     // 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 
	    Vecteur SM_charge_lineique_Suiv_E_t(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa)
	     { return Biellette::SM_charge_lineique_Suiv_E(force,pt_fonct,numArete,false,pa);} ;
	    // -> explicite à tdt
	    Vecteur SM_charge_lineique_Suiv_E_tdt(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) 
	     { return Biellette::SM_charge_lineique_Suiv_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_Suiv_I(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & 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	   
     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);

     // Retourne la section de l'element
     inline double S(Enum_dure enu = TEMPS_tdt)
       { switch (enu)
            { case TEMPS_0: return donnee_specif.secti.section0; break;
              case TEMPS_t: return donnee_specif.secti.section_t; break;
              case TEMPS_tdt: return donnee_specif.secti.section_tdt; break;
             };
         return 0.; // cas n'arrivant normalement jamais
       };
 
     // ajout du tableau specific de ddl des noeuds de la  biellette
     // la procedure met a jour les ddl(relatif a l'element, c-a-d Xi)
     // des noeuds constituants l'element
     void ConstTabDdl();
     
    protected:
    		
     // ==== >>>> 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 1;};
 
 // -------------------- 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
     virtual ElFrontiere* new_frontiere_lin(int ,Tableau <Noeud *> & tab, DdlElement& ddelem)
       { return ((ElFrontiere*) (new FrontSegLine(tab,ddelem)));};
     virtual ElFrontiere* new_frontiere_surf(int ,Tableau <Noeud *> & tab, DdlElement& ddelem)
       {return NULL;} // il n'y a pas de surface possible
    
    
	private :

     // VARIABLES PRIVEES :
      	
          
	    class DonneeCommune
	      { public :
	        DonneeCommune (GeomSeg& seg,DdlElement& tab,DdlElement&  tabErr,DdlElement&  tab_Err1Sig,
	                       Met_biellette&  met_bie, 
	                       Tableau <Vecteur *> & resEr,Mat_pleine& raidEr,
	                       GeomSeg& seEr,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,
	                       Mat_pleine&  mat_masse ,GeomSeg& seMa,int nbi,GeomSeg* segHourg
                       ) ;
	        DonneeCommune(DonneeCommune& a);
	        ~DonneeCommune();    
          // variables
         GeomSeg segment ; // element geometrique correspondant
	        DdlElement  tab_ddl; // tableau des degres 
                     //de liberte des noeuds de l'element commun a tous les
                     // elements
         Met_biellette  met_biellette;
		       Mat_pleine  matGeom ; // matrice géométrique
         Mat_pleine  matInit  ; // matrice initile
         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
                 // 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 
         GeomSeg segmentEr; // 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 l' aretes
         Tableau <Mat_pleine* >  raideurs_externeA;  // pour l' aretes 
         // ------ données concernant la dynamique --------
         Mat_pleine matrice_masse;
         GeomSeg segmentMas; // contiend les fonctions d'interpolation et les dérivées
              // pour les calculs relatifs au calcul de la masse
         // ------ blocage éventuel d'hourglass
         // utiliser dans ElemMeca::Cal_mat_hourglass_comp, Cal_implicit_hourglass, Cal_explici_hourglass
         GeomSeg* segmentHourg; // 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 :
           DonneeCommune * 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  dualSortbiel; // 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  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 PROTÉGÉES :
	    // les données spécifiques sont grouppées dans une structure pour sécuriser
	    // le passage de paramètre dans init par exemple 
	    class Donnee_specif
	    { public :
	      Donnee_specif() : // défaut
			     secti(Element::section_defaut,Element::section_defaut,Element::section_defaut)
        ,fctnD_section(NULL),variation_section(true)
	    	 {};
		     Donnee_specif(double section) : // uniquement la section
        secti(section,section,section),fctnD_section(NULL),variation_section(true)
	    	 {};
	      Donnee_specif(double epai0,double epai_t,double epai_tdt,Fonction_nD* fctnD,bool variation) : //  tous
	         secti(epai0,epai_t,epai_tdt),fctnD_section(fctnD),variation_section(variation)
        {};
	      Donnee_specif(const Donnee_specif& a) : 
	        secti(a.secti ),fctnD_section(a.fctnD_section),variation_section(a.variation_section)
	           {}; // recopie via le constructeur de copie
	      ~Donnee_specif() {};
	      Donnee_specif & operator = ( const Donnee_specif& a)  
	        { secti = a.secti;fctnD_section=a.fctnD_section;variation_section=a.variation_section;
				       return *this;};
	      // data
	      // sections de l'element
	      Sect  secti; // épaisseur
       Fonction_nD* fctnD_section;// permet éventuellement de prendre en compte une évolution de la section
       bool variation_section; // permet éventuellement de ne pas prendre en compte la variation
	    };
	    Donnee_specif donnee_specif;
	    	    
	    // grandeurs aux points d'intégration: contraintes, déformations, vitesses de def etc.
	    LesPtIntegMecaInterne  lesPtMecaInt;
		
     // place memoire commune a tous les elements biellettes      
     static DonneeCommune * doCo;
     // idem mais pour les indicateurs qui servent pour l'initialisation
     static UneFois  unefois;

	    // type structuré pour construire les éléments
	    class NombresConstruire
	     { public:
	       NombresConstruire();
	       int nbne; // le nombre de noeud de l'élément
	       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 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 consistante
        int nbiHour; // éventuellement, le nombre de point d'intégration un blocage d'hourglass
      };
	    static NombresConstruire nombre_V; // les nombres propres à l'élément

     // fonction privee
     // fonction d'initialisation servant  au niveau du constructeur
     Biellette::DonneeCommune * Init(Donnee_specif donnee_specif = Donnee_specif()
                                     ,bool sans_init_noeud = false);  
     void Def_DonneeCommune();
     // destructions de certaines grandeurs pointées, créées  au niveau de l'initialisation
     void Destruction();

     // pour l'ajout d'element dans la liste : listTypeElemen, geree par la class Element
     class ConstrucElementbiel : public ConstrucElement
       { public :  ConstrucElementbiel () 
            { NouvelleTypeElement nouv(POUT,BIE1,MECA_SOLIDE_DEFORMABLE,this);
              if (ParaGlob::NiveauImpression() >= 4)
                 cout << "\n initialisation Biellette" << endl;
              Element::listTypeElement.push_back(nouv);
            };
         Element * NouvelElement(int nb_mail,int num) // un nouvel élément sans rien
            {Element * pt;
             pt  = new Biellette (nb_mail,num) ;
             return pt;};
          // ramene true si la construction de l'element est possible en fonction
          // des variables globales actuelles: ex en fonction de la dimension	
         bool Element_possible() {return true;};	
       };
     static ConstrucElementbiel construcElementbiel;
        
       // Calcul du residu local a t ou tdt en fonction du booleen
	   Vecteur* CalculResidu (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 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 lineique suiveuse, sur l'arete frontière 
    //de la biellette (2D uniquement)
	   // 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 
	   Vecteur SM_charge_lineique_Suiv_E
	                 (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & pa); 
	   // 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) ;
	                 	                 
    // calcul de la nouvelle section moyenne finale (sans raideur)
    // mise à jour des volumes aux pti
    // ramène la section moyenne calculée à atdt
    const double& CalSectionMoyenne_et_vol_pti(const bool atdt);
};
/// @}  // end of group
#endif