// FICHIER : Noeud.h
// CLASSE : Noeud

// 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-2021 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++                                            *
*                                                                $     *
************************************************************************
* Une instance de la classe Noeud est definie a partir d'un numero d'identification
* et du tableau de connexite des degres de liberte lies au noeud. Trois instances
* de la classe Coordonnee sont aussi associes a la classe Noeud (coordonnees initiales,
* aux instants t et t+dt).
*                                                                $     *
*     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
*     VERIFICATION:                                                    *
*                                                                      *
*     !  date  !   auteur   !       but                          !     *
*     ------------------------------------------------------------     *
*     !        !            !                                    !     *
*                                                                $     *
*     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
*     MODIFICATIONS:                                                   *
*     !  date  !   auteur   !       but                          !     *
*     ------------------------------------------------------------     *
*                                                                $     *
************************************************************************/

// Une instance de la classe Noeud est definie a partir d'un numero d'identification
// et du tableau de connexite des degres de liberte lies au noeud. Trois instances
// de la classe Coordonnee sont aussi associes a la classe Noeud (coordonnees initiales,
// aux instants t et t+dt).


#ifndef NOEUD_H
#define NOEUD_H


#include <iostream>


#include "Coordonnee.h"
#include "Ddl.h"
#include "Tableau_T.h"
#include "ParaGlob.h"
#include "Vecteur.h"
#include "Tenseur.h"
#include "List_io.h"
#include "EnumTypeGrandeur.h"
#include "MathUtil.h"
#include "TypeQuelconque.h"
#include "Ddl_etendu.h"
#include "Enum_liaison_noeud.h"


/// @addtogroup Les_Maillages
///  @{
///

//------------------------------------------------------------------
//!      Posi_ddl_noeud:  un conteneur qui associe numéro de noeud, de maillage, et enu ddl
//------------------------------------------------------------------
/// \author    Gérard Rio
/// \version   1.0
/// \date       23/01/97


    // --------- class de stockage -----
    class Posi_ddl_noeud
      { // surcharge lecture  écriture
        friend istream & operator >> (istream &, Posi_ddl_noeud &);
        friend ostream & operator << (ostream &, const Posi_ddl_noeud &);
        public :
        // constructeurs
        Posi_ddl_noeud () : nb_maillage(-1),nb_noeud(-1),enu(NU_DDL) {};
        Posi_ddl_noeud (int aa, Enum_ddl enuu,int bb) : 
          nb_maillage(aa),nb_noeud(bb),enu(enuu) {};
        Posi_ddl_noeud (const Posi_ddl_noeud & a):
         nb_maillage(a.nb_maillage),nb_noeud(a.nb_noeud),enu(a.enu) {};
        // opérateur 
        Posi_ddl_noeud& operator = ( const Posi_ddl_noeud & a)
         {nb_maillage=a.nb_maillage;nb_noeud=a.nb_noeud;enu=a.enu; return *this;};
        bool operator == ( const Posi_ddl_noeud & a)
         { if((nb_maillage==a.nb_maillage) && (nb_noeud==a.nb_noeud) 
             && (enu==a.enu)) return true; else return false; };
        bool operator != ( const Posi_ddl_noeud & a)
         { if((*this) == a) return false; else return true; };
		      // Affiche les donnees liees au noeud
        void Affiche (ofstream& sort) const;
        // récup des données en lecture écriture
        int&  Nb_maillage() {return nb_maillage;};
        int&  Nb_noeud() {return nb_noeud;};
        Enum_ddl&  Enu() {return enu;};
        // récup des données en lecture uniquement
        const int&  Const_Nb_maillage() const {return nb_maillage;};
        const int&  Const_Nb_noeud() const {return nb_noeud;};
        const Enum_ddl&  Const_Enu() const {return enu;};
       
  protected:
        // données
        int nb_maillage; // le numéro du maillage
        int nb_noeud;    // le numéro du noeud
        Enum_ddl enu;    // l'identifieur du ddl
      };
/// @}  // end of group


/// @addtogroup Les_Maillages
///  @{
///

//------------------------------------------------------------------
//!      Noeud:  un noeud
//------------------------------------------------------------------
/// \author    Gérard Rio
/// \version   1.0
/// \date       23/01/97


class Noeud
{    
    // surcharge de l'operator de lecture, avec typage
    friend istream & operator >> (istream &, Noeud &);
    // surcharge de l'operator d'ecriture avec typage
    friend ostream & operator << (ostream &, const Noeud &);

	public :

	
		// CONSTRUCTEURS :
		
		// IMPORTANT!!! : l'ordre de succession des ddl doit etre conforme
		// aux infos de l'enumeration (cf enum_ddl)
		
		// Constructeur par defaut
		Noeud (int num_id=-3,int num_maill=0);
		
		// Constructeur fonction d'un numero d'identification et de la 
		// dimension de l'espace du probleme et du nb de maillage
		Noeud (int num_id,int dimension,int num_maill);
		
		// Constructeur fonction d'un numero d'identification et des coordonnees
		// initiales et du nb de maillage
		Noeud (int num_id,const Coordonnee& c0,int num_Mail);
				
		// Constructeur fonction d'un numero d'identification, des coordonnees
		// initiales et du tableau des degres de liberte, et du nb de maillage 
		// les ddl t=0 et t sont initialises avec les valeurs du tableaux
		// par defaut les tableaux de ddl a 0 et t sont initialises mais pas
		// a t+dt,
		Noeud (int num_id,const Coordonnee& c0,const Tableau<Ddl>& tab,int num_Mail);
		
        // Constructeur fonction d'un numero d'identification, des coordonnees
        // initiales, a un instant t, et du tableau des degres de liberte, et du nb de maillage 
        // les ddl t=0 sont initialises avec les valeurs du tableaux
        // par defaut les tableaux de ddl a 0 et t sont initialises mais pas
        // a t+dt
        // les ddl corespondant a Xi sont ajoute s'ils n'existaient pas
		Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Tableau<Ddl>& tab,int num_Mail);
		
		// Constructeur fonction d'un numero d'identification, de trois instances
		// de Coordonnee et du tableau des degres de liberte, et du nb de maillage 
		Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Coordonnee& c2,
														const Tableau<Ddl>& tab,int num_Mail); 
													
		// Constructeur de copie												
		Noeud (const Noeud& nd);
		
		
		// DESTRUCTEUR : 
		~Noeud ();
		
		
		// METHODES :
		
		// Affiche à l'ecran les donnees liees au noeud
  // le niveau différent de 0 permet d'accèder à plus d'info
		void Affiche(int niveau=0) const;
		// Affiche dans sort les donnees liees au noeud
		void Affiche(ofstream& sort) const;  
		
		inline void Change_num_noeud(int nouveau_num)
		// Modifie le numero d'identification du noeud
		// ATTENTION : Les modifications liees au changement de numero du noeud
		// sont a la charge de l'utilisateur.
		   {	num_noeud=nouveau_num;	};
		
		inline void Change_num_Mail(int nouveau_num)
		// Modifie le numero de maillage du noeud
		   {	num_Mail=nouveau_num;	};
 
  // récup du type de liaison entre noeud éventuel
  // pour le cas d'assemblage nb_assemb
  inline Enum_liaison_noeud Enu_liaison(int nb_assemb) const
    {if (tab_enu_liaison != NULL) return (*tab_enu_liaison)(nb_assemb);
     else return PAS_LIER;};

  // récup d'un pointeur de tableau des ddl affectés par une liaison entre noeud
  // pour le cas d'assemblage nb_assemb, NULL s'il n'y en a pas
  inline const Tableau <Posi_ddl_noeud >* Ddl_Noeud_lier(int nb_assemb) const
    {if (tab_ddl_lier != NULL) return &((*tab_ddl_lier)(nb_assemb));
     else return NULL; };
  // modification du type de laison entre noeud éventuel avec init des tableaux de liaison
  // pour le cas d'assemblage nb_assemb
  void Change_Enu_liason(int nb_assemb, Enum_liaison_noeud enu_liai
                         ,const Tableau <Posi_ddl_noeud>& tab__lier);
  // suppression de tous les liaisons noeuds
  void Suppression_tous_liaisons_noeuds();
 
		// Modifie les valeurs des coordonnees coord0
		inline void Change_coord0(const Coordonnee& nouveau_coord0) 
		   {  *coord0=nouveau_coord0;};
		
  // insert  des coordonnees coord1 si elles n'existent pas encore 
  // permet de définir des coordonnées à t, dans ce cas des ddl XI sont inclus
  // et sont mis inactif par défaut
  void Insert_coord1(const Coordonnee& nouveau_coord1);
  // idem mais sans paramètre indique que l'on initialise aux coordonnées à t=0
  // s'ils n'existent pas sinon on ne fait rien
  void Insert_coord1();
        
		// Modifie les valeurs des coordonnees coord1 
  void Change_coord1(const Coordonnee& nouveau_coord1);

		
		// Modifie les valeurs des coordonnees coord2 
  inline void Change_coord2(const Coordonnee& nouveau_coord2)
		   {  *coord2=nouveau_coord2; };
		
		
		// Modifie les valeurs des coordonnees coord2 par l'ajout d'un delta 
		inline void Ajout_coord2(const Coordonnee& delta_coord2)
		   {	*coord2=*coord2+delta_coord2;	}; 
		
		
		inline const Coordonnee& Coord0() const
		// Retourne les coordonnees initiales du noeud
		   {	return *coord0;	}; 
		
		// test si les coordonnées à t=0 existent
		inline bool ExisteCoord0() const
		   { if (coord0 == NULL) return false; else return true;};
		
		// Retourne les coordonnees coord1 du noeud
		// uniquement pour la lecture 
		inline Coordonnee Coord1() const
     { int nbcoo = coord1.Taille();
       Coordonnee coo(nbcoo);
       for (int i=1;i<=nbcoo;i++)
          coo(i) = *(coord1(i));
       return coo;  
     };
		
		// test si les coordonnées à t existent
		inline bool ExisteCoord1() const 
		   { if (coord1.Taille() == 0) return false; else return true;};
		
		// Retourne les coordonnees coord2 du noeud 
		inline const Coordonnee& Coord2() const
		   {	return *coord2;	};
		
		// retourne la valeur absolu du maximum de variation de coordonnée entre t et tdt
		inline double Max_var_coor_t_a_tdt() const
		   { double ret=0.;
       if (ExisteCoord2() && ExisteCoord1())
        {int nbcoo=coord2->Dimension();
		       for (int i=1;i<=nbcoo;i++) ret = MaX(Dabs((*coord2)(i) - *(coord1(i))),ret);
        };
       // sinon cela veut dire que le maillage n'a pas bougé (cas d'un solide fixe)
       return ret;
     };
		
		// test si les coordonnées à tdt existent
		inline bool ExisteCoord2() const
		   { if (coord2 == NULL) return false; else return true;};
		
		// Retourne le nombre de tous les degres de liberte du noeud
		// qu'ils soient actifs ou non, fixes ou non 
		inline int Nombre_ddl() const
		   {	return tab_ddl.Taille();	};   
		
		// Retourne le nombre de variables degres de liberte du noeud
		// qui sont actuellement actives
		inline int Nombre_var_ddl_actives() const
		   { return tab_var_actives.Taille();};
		 
		// Retourne le nombre de variables degres de liberte du noeud
		// qui sont actives pour un cas d'assemblage donné.
		// (ces ddl peuvent ne pas être actuellement actif !!)
		inline int NB_ddl_actif_casAssemb (int nb_assemb) const
		   { Tableau <int >& tib = (*t_enum_s(nb_assemb));
  return (tib(tib.Taille()));};
		 
        // ramene le nombre de variables ddl actives pour un type de ddl donné,
        // c'est-à-dire 1 ou la dimension, suivant que le type dépend
        // ou pas de la dimension
		int Nombre_var_ddl_actives (Enum_ddl en) const ;
		 
		// retourne la liste de tous les  types de ddl actuellement utilisé
		// par le noeud (actif ou non)
  // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
		List_io <Enum_ddl> Les_type_de_ddl(bool absolue);
		// retourne la liste de tous les Ddl_enum_etendu disponibles
		List_io <Ddl_enum_etendu> Les_type_de_ddl_etendu(bool absolue);
		// retourne la liste de tous les TypeQuelconque disponibles
		List_io <TypeQuelconque> Les_TypeQuelconque(bool absolue);
  
  // récupération d'une liste d'info
  // le tableau de retour à la taille de li_enu_scal et contient
  // les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud
  //    en fait ici on cumule les ddl pur "et" les ddl_étendue,
  // li_quelc : est modifié par les valeurs contenues au noeud
  Tableau <double>  Valeur_multi_et_Tensorielle
      (const List_io <Ddl_enum_etendu>& li_enu_scal,List_io <TypeQuelconque >& li_quelc) const;
		
		// Retourne le numero d'identification du noeud
		inline int Num_noeud() const
		   {	return num_noeud;	};
		 
		// Retourne le numero de maillage auquel appartiend le  noeud
		inline int Num_Mail() const
		   {	return num_Mail;	};
		
		// Retourne la dimension des coordonnées
		inline int Dimension() const
		   {	return coord0->Dimension();	};
		
		// surcharge de l'affectation entre deux noeuds
		// attention, le pointeur d'assemblage de this est identique a celui de n
		// il faut donc l'updater pour pouvoir l'utiliser!!
		Noeud& operator= (const Noeud& n);
		
		// acces en lecture au pointeur de position pour l'assemblage
		// i : donne le numéro du cas d'assemblage associé
		inline int PosiAssemb(int i ) const
		   { return posiAssemb(i);};
		   
		// initialisation d'un ou de plusieurs nouveau cas d'assemblage
		void InitNouveauCasAssemb(int nb_cas);
		
		// enregistrement de l'ordre des variables ddl actives, ceci pour un cas d'assemblage
		// donné, cette fonction permet ensuite d'utiliser la fonction
		// Position_ddl qui donne la position d'un ddl pour un cas d'assemblage
		// donné
		void Enreg_ordre_variable_ddl_actives(int nb_assemb);
		
		// position d'un ddl par rapport à un cas d'assemblage donné (de 1 à ..)
		// il n'y a pas de vérification que le ddl en question est actif ou pas
		// cette fonction ne peut être utilisé, que après l'utilisation 
		// de la fonction Enreg_ordre_variable_ddl_actives
		// si l'énuméré n'existe pas dans la liste des ddl actif du cas d'assemblage
		// on retourne -1
		inline int Position_ddl(Enum_ddl enu, int nb_assemb) const
		  { int pointe = (*(t_enum_s(nb_assemb)))(enu);
		    if (pointe == 0) return -1; else return pointe; }
		   
		// modification du pointeur de position du noeud pour l'assemblage
		// i : donne le numéro du cas d'assemblage associé
		inline void ChangePosiAssemb(int a,int i )
		   { posiAssemb(i) = a;};
		   
		// ramène le pointeur d'assemblage pour un ddl donné, et un cas d'assemblage
		// le résultat correspond à la position globale d'assemblage du noeud +
		// la position du ddl dans la liste des ddl actifs du cas d'assemblage
		// si l'énuméré ne correspond pas à un ddl actif du cas d'assemblage
		// on retourne -1, dans le cas ok, c'est un nombre de 1 à ...
		inline int Pointeur_assemblage(Enum_ddl enu, int nb_assemb) const
		  { int pointe = (*(t_enum_s(nb_assemb)))(enu);
		    if (pointe == 0) return -1;
		    return pointe + posiAssemb(nb_assemb); };  
 
  // le noeud peut contenir éventuellement une base rattachée
  // récupération de la base, si le pointeur en retour est null
  // cela signifie que la base n'existe pas
  //  a) en constant, la base actuelle
  const BaseB* Const_BaseB_Noeud() const {return baseB;};
  //  b) en constant, la base à t
  const BaseB* Const_BaseB_Noeud_t() const {return baseB_t;};
  //  c) en constant, la base initiale
  const BaseB* Const_BaseB_Noeud_0() const {return baseB_0;};

  //  d) en lecture écriture, la base actuelle
  BaseB* BaseB_Noeud() const {return baseB;};
  //  e) en lecture écriture, la base à t
  BaseB* BaseB_Noeud_t() const {return baseB_t;};
  //  f) en lecture écriture, la base à 0
  BaseB* BaseB_Noeud_0() const {return baseB_0;};

		// test si le noeud est complet
		// = 1 tout est ok, =0 element incomplet
		int TestComplet() const;
		
        // ajout de ddl 
        // 1) s'il n'y a pas de ddl il y a initialisation
		      // 2) si les ddl existent deja, on l'égalise au ddl passé en para
        // 3) lorsque le ddl appartient à une famille, tous les ddl de la famille sont
        //    ajoutées, les ddl supplémentaires ont une valeurs par défaut nulle
		void PlusDdl(Ddl& a);
		
		// ajout d'un tableau de ddl 
        // 1) s'il n'y a pas de ddl il y a initialisation
        // 2) si les ddl existent deja, on égalise avec les ddl passés en par
        // 3) lorsque un nouveau ddl appartient à une famille, et que tous les ddl de la famille
        // ne sont pas présents dans les ddl passés en paramètre, tous les ddl manquant de la famille sont
        // ajoutées, avec une valeurs par défaut nulle
		void PlusTabDdl(Tableau<Ddl>& ta);
 
  // ajout du tableau de ddl d'un autre noeud
  void PlusTabDdl(const Noeud & noe);

		// modification du blocage ou non d'un ddl
		inline void Change_fixe(Enum_ddl en,bool val)
		  { tab_ddl((*pos_enum)(en)).Change_fixe(val); };
		inline void Change_fixe(int nb,bool val)
		  { tab_ddl(nb).Change_fixe(val); };
		// test pour savoir si le ddl est fixé ou pas
		inline bool Ddl_fixe(Enum_ddl en) const
		   { return 	tab_ddl((*pos_enum)(en)).Fixe();};
		// test pour savoir si le ddl est SURFIXE ou SOUSLIBRE 
		// (c-a-d plusieurs fois fixé ou libre à la suite)
		inline bool Ddl_sous_ou_sur_fixe(Enum_ddl en) const
		   { return 	tab_ddl((*pos_enum)(en)).SousSurFixe();};
  // remise à normal si le ddl est en souslibre ou surfixe
  // s'il est en souslibre il passe en libre et s'il est en surfixe il passe en fixe  
  inline void Retour_a_la_normal_sur_ou_sous_fixe(Enum_ddl en)
     { tab_ddl((*pos_enum)(en)).Retour_normal_sur_ou_sous_fixe();};
		
		// modification du statut d'un ddl 
		// si est inconnu, aucune action
  void Met_hors_service(Enum_ddl en);
  void Met_en_service(Enum_ddl en);		
		// modification du statut d'un tableau de ddl  
		// si un des elements du tableau est inconnu, aucune action
  void Met_hors_service(const Tableau<Enum_ddl>& taben);
  void Met_en_service(const Tableau<Enum_ddl>& taben);
  // modification du statut de tous les ddl actuellements présent  
  // y compris les données
		// si un des elements du tableau est inconnu, aucune action
  void Met_hors_service();
  void Met_en_service();
  // idem mais restreint uniquement aux ddl (pas les données)
  void Met_hors_service_ddl();
  void Met_en_service_ddl();
  
  // test si un ddl est en service ou pas
  bool En_service (Enum_ddl en) const { return  tab_ddl((*pos_enum)(en)).Service();};
  // test si un ddl est une variable ou pas 	
  bool UneVariable(Enum_ddl en) const { return tab_ddl((*pos_enum)(en)).UneVariable();};
  // changement du statut de variable à donnée d'un ddl 	
  void ChangeVariable_a_Donnee(Enum_ddl en) 
        { tab_ddl((*pos_enum)(en)).ChangeVariable_a_Donnee();MiseAjourActif();};
  // changement du statut de donnée à variable d'un ddl 	
  void ChangeDonnee_a_Variable(Enum_ddl en)  
        { tab_ddl((*pos_enum)(en)).ChangeDonnee_a_Variable();MiseAjourActif();};
  // changement du statut de variable à donnée pour un tableau d'enum de ddl 	
  void ChangeVariable_a_Donnee(const Tableau<Enum_ddl>& taben); 
  // changement du statut de donnée à variable pour un tableau d'enum de ddl 	
  void ChangeDonnee_a_Variable(const Tableau<Enum_ddl>& taben); 
  // changement de toutes les conditions données (service, variable, fixage ..)  
  // selon le tableau de ddl passé en paramètre
  // par contre la valeur n'est pas utilisé donc la valeur actuelle reste inchangé
  void ChangeToutesLesConditions(const Tableau<Ddl>& ta);
  // changement de statu des ddl d'une combinaison, (cf. Enum_ddl)
  // les ddl de la combinaison, prennent le même statut que celui
  // actuellement stocké, correspondant à enuta
  // cas est la combinaison,
  void ChangeStatut(int cas,Enum_ddl enuta);
  // changement de statu des ddl d'une combinaison, (cf. Enum_ddl)
  // les ddl de la combinaison, prennent le même statut que celui de enuta
  // cas est la combinaison,
  void ChangeStatut(int cas,Enum_boolddl enubold);

//   -------- manipulation de ddl identifié par un énuméré ------
//      *****!!!!!***** attention il n'y a pas vérification de l'existence
//      de ce type énuméré dans des ddl du noeud

		// change la valeur du ddl  identifie par en ,		
		inline void Change_val_0(Enum_ddl en,double val)  // t=0
		                  { tab_0((*pos_enum)(en)) = val; };
		inline void Change_val_t(Enum_ddl en,double val)  // t=t
		         { tab_ddl((*pos_enum)(en)).Valeur() = val;};
		inline void Change_val_tdt(Enum_ddl en,double val)  // t=tdt
                 { tab_tdt((*pos_enum)(en)) = val;};
		// incremente la valeur du ddl  identifie par en ,		
		inline void Ajout_val_0(Enum_ddl en,double val)  // t=0
		         { tab_0((*pos_enum)(en)) += val; };
		inline void Ajout_val_t(Enum_ddl en,double val)  // t=t
		         { tab_ddl((*pos_enum)(en)).Valeur() += val;};		
		inline void Ajout_val_tdt(Enum_ddl en,double val)  // t=tdt
                 { tab_tdt((*pos_enum)(en)) += val;};		
		// retourne la valeur du ddl identifie par en
		inline double Valeur_0(Enum_ddl en) const // t=0
		         { return tab_0((*pos_enum)(en)); };
		inline double Valeur_t(Enum_ddl en)  const // t=t
		         { return tab_ddl((*pos_enum)(en)).Valeur();};		
		inline double Valeur_tdt(Enum_ddl en)  const // t=tdt
                 { return tab_tdt((*pos_enum)(en));};
 		// Retourne le ddl à t=0 identifie par enu, en lecture
		inline Ddl Ddl_noeud_0(Enum_ddl enu) const
		  {return Ddl(enu,tab_0((*pos_enum)(enu)),tab_ddl((*pos_enum)(enu)).Retour_Fixe());};
 		// Retourne le ddl à t=t identifie par en, en lecture
		inline Ddl Ddl_noeud_t(Enum_ddl enu) const 
		  {return Ddl(enu,tab_ddl((*pos_enum)(enu)).Valeur(),tab_ddl((*pos_enum)(enu)).Retour_Fixe());};
 		// Retourne le ddl à t=tdt identifie par en, en lecture
		inline Ddl Ddl_noeud_tdt(Enum_ddl enu) const
		  {return Ddl(enu,tab_tdt((*pos_enum)(enu)),tab_ddl((*pos_enum)(enu)).Retour_Fixe());};
		                 				
		// indique que l'on va utiliser les ddl en 0, t et tdt
		// les grandeurs en tdt sont cree et initialisees par defaut 
		void Travail_tdt();
		
		// indique que l'on va utiliser les ddl en 0, t
		// si les grandeurs en tdt existaient, elles sont supprimées
		void Travail_t();
		
		// teste si un ddl existe
		inline bool Existe_ici(const Enum_ddl en) const
		  { if (Existe(en) == 0)
		      return false;
		    else
		      return true;
		   };     

		// mise a zero de tous les variables ddl actives
		// sauf dans le cas de coordonnees entrainees. dans ce dernier
		// cas les coordonnees correspondants a Xi pour t et t+dt
		// sont mis a la valeur de celles de t=0
		// a moins que le paramètre booléen est mis à false,
		// dans ce cas les coordonnées à t sont inchangées
		void ZeroVariablesDdl(bool cas);
    
  // actualisation des ddl actifs (variables et donnees) de t+dt vers t 
  // seuls sont actualisée, les ddl actifs     
  void TdtversT();
  // actualisation des ddl actifs (variables et donnees) de t vers t+dt
  // seuls sont actualisée, les ddl actifs     
  void TversTdt();
            
  // retourne true si le tableau a t+dt existe , false sinon
  inline bool Tdt()
    {if (tab_tdt.Taille() != 0) return true; else return false; };
     
  // retourne dans le vecteur d'entrée les  réels représentant les contraintes 
  // si les degrés de liberté contrainte existent
  // sinon retourne false, en ne modifiant pas l'entrée
  bool  Contrainte(Vecteur& Sig);
  
  // retourne dans le tenseur d'entrée les  réels représentant les contraintes 
  // si les degrés de liberté contrainte existent
  // sinon retourne  l'entrée sans modification
  // le tenseur est choisit mixte pour représenter tous les cas 
  // !!! important : le tenseur Sig doit avoir la bonne dimension
  // en entrée, car il n'est pas redimensionné dans la méthode      
  TenseurHB&  Contrainte(TenseurHB& Sig);
  
  // lecture du noeud dans la mémoire
  void Lecture (UtilLecture *entreePrinc);
   // sortie du schemaXML: en fonction de enu 
   static void SchemaXML_Noeud(ofstream& sort,const Enum_IO_XML enu);
  
  // affichage et definition interactive des commandes 
  // coor: des coordonnees fixée  pour un affichage different pour chaque noeud
  void Info_commande_Noeud(UtilLecture * entreePrinc,Coordonnee& coor,int nb_du_noeud);
  
  // lecture sur le flot d'entée de déplacement
  // et mise à jour des positions à t et t+dt correspondantes
  void LectureDeplacements(UtilLecture *entreePrinc);
	 
	 //----- 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)
     //       ( ici on ne redimentionne pas, 
     //         cela signifie que le nombre de ddl augmente mais ne diminue pas !!)
	 void Lecture_base_info(ifstream& ent,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(ofstream& sort,int cas);

//   -------- manipulation de types quelconques stockées aux noeuds ------
//     les opérations dans les types quelconques ne sont pas faites par le noeud
//     le noeud gère les grandeurs, mais ne les modifies pas directement

  // ajout d'un type quelconque au noeud (il s'agit ici de définir le conteneur)
  // dans le cas où les types existent déjà, on ne fait rien
  // cas d'un tableau
  void AjoutTabTypeQuelconque(const Tableau <TypeQuelconque > & tab_t_quel);
  // cas d'une seule grandeur quelconque
  void AjoutUnTypeQuelconque(const TypeQuelconque & t_quel);
  // supprime une grandeur quelconque (si elle est présente) 
  // opération aussi longue que l'ajout !!
  void SupprimeUnTypeQuelconque(const TypeQuelconque & t_quel);
  // supprime un tableau de grandeurs quelconques (si elles sont présentes)
  // opération aussi longue que l'ajout !!
  void SupprimeTabTypeQuelconque(const Tableau <TypeQuelconque > & tab_t_quel);
  // ramène un booléen indiquant si la grandeur quelconque existe ou pas
  inline bool Existe_ici(TypeQuelconque_enum_etendu en) const
 		  { if (Existe(en) == 0) return false; else return true;};     
  // récupération d'une grandeur quelconque pour modification
  // après l'appel de cette méthode, la grandeur quelconque est réputée updaté
  TypeQuelconque& ModifGrandeur_quelconque(TypeQuelconque_enum_etendu a);
  // récupération d'une grandeur quelconque pour lecture uniquement
  inline const TypeQuelconque& Grandeur_quelconque(TypeQuelconque_enum_etendu enu) const
           { return (tab_type_quel((*pos_Quelconque)(enu.Position())));};
  // ramène le nombre de fois où la grandeur quelconque a été updaté 
  inline int Grandeur_quelconque_update(TypeQuelconque_enum_etendu enu) const
       { return (update_type_quel((*pos_Quelconque)(enu.Position())));};
  // signale que toutes les grandeurs quelconques sont non-updatées
  // en particulier les grandeurs en question ne seront pas sauvegarder dans base_info
  void Mise_non_update_grandeurs_quelconques();      
  // signale qu'une grandeur quelconque est non-updatées
  // en particulier la grandeur en question ne sera pas sauvegarder dans base_info
  void Mise_non_update_grandeurs_quelconques(TypeQuelconque_enum_etendu enu);

//   -------- manipulation de types Ddl_etendu stockées aux noeuds ------
//     les opérations dans les types Ddl_enum_etendu ne sont pas faites par le noeud
//     le noeud gère les grandeurs, mais ne les modifies pas directement

  // ajout d'un type Ddl_enum_etendu au noeud (il s'agit ici de définir le conteneur)
  // dans le cas où les types existent déjà, on ne fait rien
  // cas d'un tableau
  void AjoutTabDdl_etendu(const Tableau <Ddl_enum_etendu > & tab_ddletendu);
  // cas d'un seul  Ddl_enum_etendu
  void AjoutUnDdl_etendu(const Ddl_enum_etendu & ddletendu);
  // supprime un Ddl_enum_etendu (si elle est présente) 
  // opération aussi longue que l'ajout !!
  void SupprimeUnDdl_etendu(const Ddl_enum_etendu & ddletendu);
  // supprime un tableau de  Ddl_enum_etendu (si ils sont présents)
  // opération aussi longue que l'ajout !!
  void SupprimeTabDdl_etendu(const Tableau <Ddl_enum_etendu > & tab_ddletendu);
  // ramène un booléen indiquant si le Ddl_enum_etendu existe ou pas
  inline bool Existe_ici_ddlEtendu(const Ddl_enum_etendu& ddletendu) const
 		  { if (Existe_ddlEtendu(ddletendu) == 0) return false; else return true;};     
  // récupération d'un Ddl_etendu pour modification
  // après l'appel de cette méthode, le Ddl_enum_etendu est réputée updaté
  Ddl_etendu& ModifDdl_etendu(const Ddl_enum_etendu& addletendu);
  // récupération d'un Ddl_etendu pour lecture uniquement
  inline const Ddl_etendu& DdlEtendue(const Ddl_enum_etendu& ddlenumetendu) const
           { return (tab_ddletendu((*pos_ddletendu)(ddlenumetendu.Position())));};
  // ramène le nombre de fois que le ddl a été updaté
  inline int DdlEtendue_update(const Ddl_enum_etendu& ddlenumetendu)
       { return (update_ddletendu((*pos_ddletendu)(ddlenumetendu.Position())));}; 
  // signale que tous les  Ddl_etendu sont non-updatées ( mise à zéro du nombre d'update)
  // en particulier les grandeurs en question ne seront pas sauvegarder dans base_info
  void Mise_non_update_Ddl_etendu();      
  // signale qu'un Ddl_etendu est non-updatées
  // en particulier le Ddl_etendu en question ne sera pas sauvegarder dans base_info
  void Mise_non_update_Ddl_etendu(Ddl_enum_etendu ddlenumetendu);      

//=====================================================================================
  protected : 			
//=====================================================================================

   // donnees de base
   
		int num_noeud; // numero d'identification dans le maillage
		int num_Mail; // numero de maillage auquel appartiend le noeud
		Tableau <Ddl > tab_ddl; // tableau des degres de liberte
		         // les valeurs sont celles a l'instant t
		Coordonnee* coord0; // coordonnee initiale
 
  // liaison entre noeuds : il s'agit d'un stockage uniquement: l'utilisation et la manipulation
  // est à la charge des classes appelantes
  Tableau <Enum_liaison_noeud>* tab_enu_liaison; // tab_enu_liaison(i) définit un type éventuel
    // de liaison pour le cas d'assemblage i
  Tableau < Tableau <Posi_ddl_noeud> >* tab_ddl_lier; // tab_ddl_lier(i) donne la liste des ddl liés
    // avec les noeuds associés
 
		// donnees evoluant avec le calcul
		// les differents tableaux si-desous peuvent ne pas etre affecte
		// cela depend du pb, certaines valeurs ont plusiurs meme nom
		// comme coord0 cood1 et cood2, mais un seul endroit de stockage
		Tableau<double> tab_0; // valeurs a l'instant 0 des ddl
		Tableau<double> tab_tdt; // valeurs a l'instant t+dt des ddl
		Tableau <double*> coord1; // coordonnee a un instant t
		// pour l'exterieur le tableau est transforme en coordonnees mais
		// en interne comme les infos peuvent etre en double avec le tableau de ddl
		// et non contigues, on utilise un adressage indirecte
		// Sa taille est différente de 0 si les coordonnées à t varie ou 
		// sont succeptibles de varier.
		// a priori si coord1 est affecté c'est uniquement en pointant sur tab_ddl
		// donc il ne crée pas avec new
		Coordonnee* coord2; // coordonnee a un instant t+dt
		// tableau pour une gestion rapide des ddl en service
		// et que l'on appelle par leur identification
		Tableau<short int> tab_var_actives; // les numéros des variables ddl actives
		Tableau<short int> tab_actif; // les numéros des donnees et variables ddl actives
				
		Tableau <int> posiAssemb; // tableau de pointeurs de position pour l'assemblage
		// defini l'endroit ou est mis le premier ddl ds les seconds
		//membres et raideurs globaux
 
  // le noeud peut contenir éventuellement une base rattachée
  BaseB* baseB_0;   // actuelle
  BaseB* baseB_t; //  et à t
  BaseB* baseB;   // actuelle

		Tableau <int>  tab_nb_Elem; // tableau éventuel des  numéros d'éléments qui contiennent le noeud               
		// --- cas des types quelconques
		Tableau <TypeQuelconque > tab_type_quel; // grandeur quelconques stockées aux noeuds
		Tableau <int> update_type_quel; // indique si la grandeur quelconque est update ou pas
		static short int posi_type_quel; // utilisée par la méthode Existe_quelconque(..
		                // pour memoriser la dernière position accèdée
		int nbTypeQ_update; // indique le nombre de type quelconque updaté actuel (pour optimiser vitesse)                

		// --- cas des ddl étendus
		Tableau <Ddl_etendu > tab_ddletendu; // ddl étendu stockées aux noeuds
		Tableau <int> update_ddletendu; // indique si le ddl étendu est update ou pas
		static short int posi_ddletendu; // utilisée par la méthode Existe_ddletendu(..
		                // pour memoriser la dernière position accèdée
		int nbddletendu_update; // indique le nombre de ddl étendu updaté actuel (pour optimiser vitesse)                
		                
  // --- pour un acces rapide à un ddl donné repéré par un type énuméré on met en place ---
  // une liste de type de succession d'enum ddl
  // en ce servant de l'équivalence enum int
  // il y a une liste pour tous les noeuds
  static list <Tableau <int > > list_tab_enum;
  // et un type de tableau pour chaque noeud
  list <Tableau <int > >::iterator pos_enum ;
  // (* posi_enum)(enum) = l'indice du ddl dans les 
  // tableau de ddl : tab_ddl, tab_0 etc..
  // la liste n'est jamais diminuée, par contre comme les noeuds
  // sont construit d'une manière automatique et systématique on
  // suppose qu'il y aura en fait très peu d'élément dans la liste
  
  // --- pour déterminer rapidement la position dans la liste
  // des ddl actifs, d'un ddl donné repéré par un type énuméré
  // même principe que pour list_tab_enum
  static List_io <Tableau <int > > list_tab_posi_actif;
  // et un tableau de pointeur d'élément de la liste,
  // chaque tableau étant relatif à untype de combinaison de ddl actif
  Tableau < List_io <Tableau <int > >::iterator > t_enum_s ;
  
  // ---- idem pour les types quelconques repéré par un type énuméré
  // même principe que pour list_tab_enum
  static List_io <Tableau <int > > list_tab_typeQuelconque;
  // et un type de tableau pour chaque noeud
  list <Tableau <int > >::iterator pos_Quelconque ;        

  // ---- idem pour les types Ddl_etendu repéré par un type énuméré
  // même principe que pour list_tab_enum
  static List_io <Tableau <int > > list_tab_ddletendu;
  // et un type de tableau pour chaque noeud
  list <Tableau <int > >::iterator pos_ddletendu ;        
		
  // fonctions internes
		
		// liaison des ddl et des deplacement a t et 0 
		// nb = le nb du début des  deplacement dans les ddl
		void Liaison_t(int nb);
		
		// liaison des ddl et des deplacement a t,tdt et 0 
		// nb = le nb du début des deplacement dans les ddl
		void Liaison_tdt(int nb);
		
		// liaison des ddl et des deplacement a tdt seulement 
		// nb = le nb du début des deplacement dans les ddl
		void LiaiSeuletdt(int nb);
		
		// mise a jour des liaisons ddl/deplacement
		void MiseAjour();
		
		// mise a jour  de l'adressage via l'identificateur d'énumération
		// c'est-à-dire la gestion via list_tab_enum et pos_enum
		// ne doit être appelé que si l'on a introduit un nouveau ddl !!
		// ou changé l'ordre etc..
		void MiseAjourEnum();
		
		// mise a jour du tableau de ddl des variables actives
		void MiseAjourActif();
		
		// retourne le numero du ddl recherche identifie par en,
		// s'il existe sinon 0
		int Existe(const Enum_ddl en) const { return (*pos_enum)(en);};
		// --- cas des grandeurs quelconques ----
		// lecture des grandeurs quelconques sur flot
		void Lecture_grandeurs_quelconque(istream & ent);
		// écriture des grandeurs quelconques sur flot
		void Ecriture_grandeurs_quelconque(ostream & sort) const;
		// récupe de l'indice d'une grandeur quelconque
		// si la grandeur n'existe pas -> ramène 0
		int Indice_grandeur_quelconque(TypeQuelconque_enum_etendu a);
		// mise a jour  de l'adressage via l'identificateur d'énumération
		// c'est-à-dire la gestion via list_tab_typeQuelconque et pos_Quelconque
		// ne doit être appelé que si l'on a introduit un nouveau type quelconque !!
		// ou changé l'ordre etc..
		void MiseAjourTypeQuelconque();
		// retourne le numero du type quelconque recherche identifie par en,
		// s'il existe sinon 0
		int Existe(TypeQuelconque_enum_etendu en) 
		  const { return ( (pos_Quelconque == list_tab_typeQuelconque.end()) ? 0 : (*pos_Quelconque)(en.Position()));};
		// --- cas des Ddl_etendu ----
		// lecture des Ddl_etendu sur flot
		void Lecture_Ddl_etendu(istream & ent);
		// écriture des Ddl_etendu sur flot
		void Ecriture_Ddl_etendu(ostream & sort) const;
		// récupe de l'indice d'un Ddl_etendu
		// si la grandeur n'existe pas -> ramène 0
		int Indice_Ddl_etendu(const Ddl_enum_etendu& a);
		// mise a jour  de l'adressage via l'identificateur d'énumération
		// c'est-à-dire la gestion via list_tab_ddletendu et pos_ddletendu
		// ne doit être appelé que si l'on a introduit un nouveau Ddl_etendu !!
		// ou changé l'ordre etc..
		void MiseAjourDdl_etendu();
		// retourne le numero du Ddl_enum_etendu recherche identifie par en,
		// s'il existe sinon 0
		int Existe_ddlEtendu(const Ddl_enum_etendu& en) 
		  const { return ( (pos_ddletendu == list_tab_ddletendu.end()) ? 0 : (*pos_ddletendu)(en.Position()));};
		
//		// ordonne et on met a suivre les ddl d'une même famille suivant un ordre croissant
//		// ceci pour des ddl que l'on vient d'ajouter, QUE L'ON CONSIDÈRE ÊTRE À LA FIN DE TAB_DDL !
//		// en paramètre le ou les ddl
//		void OrdonneDdlMemeFamille(const Ddl& a);
//		void OrdonneDdlMemeFamille(const Tableau<Ddl>& ta);
//		// permutation de deux ddl (sert pour OrdonneDdlMemeFamille)
//		void Permutation_2ddl(const int& ipo1,cont int& ipo2);
        // ordonner un tableau de ddl suivant un ordre croissant et avec des ddl à suivre
  void OrdonnerTableauDdl(Tableau<Ddl>& ta);
  // liste des ddl (en famille) à ajouter
  // recopie des ddl existant déjà
  // change_donn_var indique si les ddl existant on été modifiée
  void ListeDdlAajouter(list<Ddl>& liDdl,Tableau<Ddl>& ta,bool& change_donn_var);

};
/// @}  // end of group

	
#endif
		 
