// FICHIER : BielletteQ.h
// CLASSE : BielletteQ

// 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:        26/01/2008                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  // La classe BielletteQ permet de declarer des elements    *
 *  biellettes quadratique du même type que biellette pour les élèments *
 *  linéaires. 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 BIELLETTEQ_H
#define BIELLETTEQ_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 "FrontSegQuad.h"
#include "Section.h"

class ConstrucElementbielQ;

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


class BielletteQ : public ElemMeca
{
		
	public :
	
		// CONSTRUCTEURS :
		// Constructeur par defaut
		BielletteQ ();
		
		// Constructeur fonction d'une section et eventuellement d'un numero
		// d'identification et de maillage
		BielletteQ (double sect,int num_maill=0,int num_id=-3);
		
		// Constructeur fonction  d'un numero de maillage et d'identification  
		BielletteQ (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 
		BielletteQ (double sect,int num_maill,int num_id,const Tableau<Noeud *>& tab);
		
		// Constructeur de copie
		BielletteQ (const BielletteQ& biel);
		
		
		// DESTRUCTEUR :
		~BielletteQ ();
				
		// 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 BielletteQ(*this); return el;};

		// Surcharge de l'operateur = : realise l'egalite entre deux instances de BielletteQ
		BielletteQ& operator= (BielletteQ& 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 BielletteQ::CalculResidu(false,pa);};
		
		// Calcul du residu local a tdt
		// pour le schema explicit par exemple 
		Vecteur* CalculResidu_tdt (const ParaAlgoControle & pa)
		  { return BielletteQ::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);

  // 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);};
		         
  // 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 BielletteQ 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,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) ;
 
  // 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 BielletteQ::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 BielletteQ::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 BielletteQ::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 BielletteQ::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 BielletteQ (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 BielletteQ::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 BielletteQ::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  BielletteQ
   // 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 FrontSegQuad(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_BielletteQ;
		       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 BielletteQs      
        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
     BielletteQ::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 ConstrucElementbielQ : public ConstrucElement
       { public :  ConstrucElementbielQ ()
            { NouvelleTypeElement nouv(POUT,BIE2,MECA_SOLIDE_DEFORMABLE,this);
              if (ParaGlob::NiveauImpression() >= 4)
                 cout << "\n initialisation BielletteQ" << endl;
              Element::listTypeElement.push_back(nouv);
             };
         Element * NouvelElement(int nb_mail,int num) // un nouvel élément sans rien
            {Element * pt;
             pt  = new BielletteQ (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 ConstrucElementbielQ construcElementbielQ;
        
     // 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 BielletteQ (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