// FICHIER : Noeud.cp
// 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/>.


#include "Noeud.h"
#include "Util.h"
#include <iomanip>
#include "TypeQuelconqueParticulier.h"

// variable globale à la classe
short int Noeud::posi_type_quel = 1;
short int Noeud::posi_ddletendu = 1; 
list <Tableau <int > > Noeud::list_tab_enum;
List_io <Tableau <int > > Noeud::list_tab_posi_actif;
List_io <Tableau <int > > Noeud::list_tab_typeQuelconque; // au début il n'y a rien dans la liste
List_io <Tableau <int > > Noeud::list_tab_ddletendu; // au début il n'y a rien dans la liste

// ------ méthode concernant laclass Posi_ddl_noeud ----------------
// surcharge de l'operateur de lecture
istream & operator >> ( istream & ent, Posi_ddl_noeud & a)
  { // lecture du type et vérification
    string nomtype; ent >> nomtype;
    if (nomtype != "Posi_ddl_noeud")
      { Sortie(1);
        return ent;
       } 
    // lecture des data 
    ent >> a.nb_maillage >> a.nb_noeud >> a.enu ;
    return ent;      
  };

// surcharge de l'operateur d'ecriture
ostream & operator << ( ostream & sort,const  Posi_ddl_noeud & a)
  { // écriture du type 
    sort << " Posi_ddl_noeud " ;
    // les data 
    sort  << a.nb_maillage << " "<< a.nb_noeud << " "<< a.enu << " ";
    return sort;      
  };

// Affiche les donnees liees au noeud
void Posi_ddl_noeud::Affiche (ofstream& sort) const
{ // les data
  sort << " Posi_ddl_noeud " ;
  sort  << nb_maillage << " "<< nb_noeud << " "<< enu << " ";
};


// ------ fin des méthodes concernant la sous_class Posi_ddl_noeud ----------------

//=========================================================================

// Fait appel au constructeur par defaut de Coordonnee et de Tableau<Ddl>
// Constructeur se servant eventuellement d'un numero d'identification 
Noeud::Noeud (int num_id,int num_M):
   tab_0(),tab_ddl(),tab_tdt(),coord1()
   ,tab_var_actives(),tab_actif(),pos_enum(list_tab_enum.end())
   ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL)
   ,t_enum_s(),tab_type_quel(),update_type_quel(),nbTypeQ_update(0)
   ,tab_nb_Elem(),pos_Quelconque(list_tab_typeQuelconque.end())
   ,pos_ddletendu(list_tab_ddletendu.end())
   ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0)
   ,tab_enu_liaison(NULL),tab_ddl_lier(NULL)
     {  num_noeud=num_id;
        coord0 = NULL;
        coord2 = NULL;
        num_Mail = num_M;
        posi_type_quel = 1;
        MiseAjourEnum(); // mise en place de l'adressage directe
		      MiseAjourDdl_etendu(); // cas des ddl étendue
	       MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
     };

// Constructeur utile quand seuls le numero d'identification et la 
// dimension de l'espace sont connus
Noeud::Noeud (int num_id,int dimension,int num_M):
   tab_0(),tab_ddl(),tab_tdt(),coord1(),tab_var_actives(),tab_actif()
   ,pos_enum(list_tab_enum.end())
   ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL)
   ,t_enum_s(),tab_type_quel()
   ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem()
   ,pos_Quelconque(list_tab_typeQuelconque.end())
   ,pos_ddletendu(list_tab_ddletendu.end())
   ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) 
   ,tab_enu_liaison(NULL),tab_ddl_lier(NULL)
     {  num_noeud=num_id;
        coord0 = new Coordonnee(dimension);
        coord2 = NULL;
        num_Mail = num_M;
        posi_type_quel = 1;
        MiseAjourEnum(); // mise en place de l'adressage directe
		      MiseAjourDdl_etendu(); // cas des ddl étendue
	       MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
     };

// Constructeur pour un noeud dont le numero et les coordonnees initiales
// sont connus
Noeud::Noeud (int num_id,const Coordonnee& c0,int num_M):
    tab_0(),tab_ddl(),tab_tdt(),coord1(),tab_var_actives(),tab_actif()
    ,pos_enum(list_tab_enum.end())
    ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL)
    ,t_enum_s(),tab_type_quel()
    ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem()
    ,pos_Quelconque(list_tab_typeQuelconque.end())
    ,pos_ddletendu(list_tab_ddletendu.end())
    ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) 
    ,tab_enu_liaison(NULL),tab_ddl_lier(NULL)
      { num_noeud=num_id;
        coord0 = new Coordonnee(c0);
        coord2 = NULL;
        num_Mail = num_M;
        posi_type_quel = 1;
        MiseAjourEnum(); // mise en place de l'adressage directe
		      MiseAjourDdl_etendu(); // cas des ddl étendue
	       MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
      };
	
// Constructeur fonction d'un numero d'identification, des coordonnees
// initiales et du tableau des degres de liberte 
// les ddl t=0 sont initialises avec les valeurs du tableaux
// sauf coord0 qui est initialise avec c0 
// par defaut les tableaux de ddl a 0 et t sont initialises mais pas
// a t+dt
Noeud::Noeud (int num_id,const Coordonnee& c0,const Tableau<Ddl>& tab,int num_M):
     tab_ddl(tab),tab_0(tab_ddl.Taille()),tab_tdt(),coord1()
     ,tab_var_actives(),tab_actif()
     ,pos_enum(list_tab_enum.end())
     ,baseB(NULL),baseB_t(NULL),baseB_0(NULL)
     ,posiAssemb(),t_enum_s(),tab_type_quel()
     ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem()
     ,pos_Quelconque(list_tab_typeQuelconque.end())
     ,pos_ddletendu(list_tab_ddletendu.end())
     ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) 
     ,tab_enu_liaison(NULL),tab_ddl_lier(NULL)
      { num_noeud=num_id;
        coord0 = NULL;
        coord2 = NULL;        
        num_Mail = num_M;
        // init de tab_0
        for (int i=1;i<=tab_0.Taille();i++)
          tab_0(i) = tab_ddl(i).Valeur();
        // cas ou l'on est en coordonnees entrainees
        if ( Existe(X1) != 0)
          { Liaison_t(Existe(X1));
            *coord0 = c0;
          }
        // cas ou les ddl sont separes des coordonnees  
        else
         { coord0 = new Coordonnee(c0); 
         };
        posi_type_quel = 1;
        // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
        MiseAjourActif();
        MiseAjourEnum(); // mise en place de l'adressage directe
		      MiseAjourDdl_etendu(); // cas des ddl étendue
	       MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
      };
      
// Constructeur fonction d'un numero d'identification, des coordonnees
// initiales, a un instant t, et du tableau des degres de liberte 
// 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
// et il y a automatiquement liaison entre ddl et coordonnées
Noeud::Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Tableau<Ddl>& tab,int num_M):
     tab_ddl(tab),tab_0(tab_ddl.Taille()),tab_tdt(),coord1(c1.Dimension())
     ,tab_var_actives(),tab_actif()
     ,pos_enum(list_tab_enum.end())
     ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL)
     ,t_enum_s(),tab_type_quel()
     ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem()
     ,pos_Quelconque(list_tab_typeQuelconque.end()) 
     ,pos_ddletendu(list_tab_ddletendu.end())
     ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) 
     ,tab_enu_liaison(NULL),tab_ddl_lier(NULL)
      { num_noeud=num_id;
        coord0 = NULL;
        coord2 = NULL;        
        num_Mail = num_M;
        // init de tab_0
        #ifdef MISE_AU_POINT	 // vérification de la dimension de tab_ddl 
         if (tab.Taille() < c1.Dimension())
          { cout << "\nErreur : dans le constructeur de noeud : ";
            cout << " Noeud (int num_id,Coordonnee& c0,Coordonnee& c1,"
                 << "const Tableau<Ddl>& tab,int num_M)\n";
            Sortie(1);
          };
        #endif
        for (int i=1;i<=tab_0.Taille();i++)
          tab_0(i) = tab_ddl(i).Valeur();
        // cas ou l'on est en coordonnees entrainees
        int posi_X1=0; // init
        if ( Existe(X1) == 0)
          { // le ddl X1 n'existe pas on le rajoute
            int an = tab_ddl.Taille();
            tab_ddl.Change_taille(an+Dimension());
            tab_0.Change_taille(an+Dimension());
            for (int jj=1;jj<=Dimension();jj++)
               tab_ddl(an+jj).Change_nom(Enum_ddl(jj));
            posi_X1 = an+1; // c'est la position du ddl X1
          }
        else // sinon il existe on récupère sa position
          posi_X1 = Existe(X1) ;
        // on effectue la liaison ddl/ deplacement                 
        Liaison_t(posi_X1); // (Existe(X1));
        *coord0 = c0;
        for (int j=1;j<= Dimension();j++)
              *(coord1(j)) = c1(j);
        posi_type_quel = 1;
        // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
        MiseAjourActif();
        MiseAjourEnum(); // mise en place de l'adressage directe
		      MiseAjourDdl_etendu(); // cas des ddl étendue
	       MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
      };

// Constructeur pour un noeud dont le numero, les coordonnees initiales, aux 
// instant t et t+dt ainsi que le tableau des degres de liberte sont connus
// comme les coordonnées à t+dt sont données cela signifie qu'ils sont des 
// degrés de liberté
// les ddl corespondant a Xi sont ajoute s'ils n'existaient pas
// et il y a automatiquement liaison entre ddl et coordonnées
Noeud::Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Coordonnee& c2,
								      const Tableau<Ddl>& tab,int num_M):
     tab_ddl(tab),tab_0(tab.Taille()),tab_tdt(tab.Taille()),coord1(c1.Dimension())
     ,tab_var_actives(),tab_actif()
     ,pos_enum(list_tab_enum.end())
     ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL)
     ,t_enum_s(),tab_type_quel()
     ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem()
     ,pos_Quelconque(list_tab_typeQuelconque.end()) 
     ,pos_ddletendu(list_tab_ddletendu.end())
     ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) 
     ,tab_enu_liaison(NULL),tab_ddl_lier(NULL)
      { num_noeud=num_id;
        coord0 = NULL;
        coord2 = NULL;        
        num_Mail = num_M;
        // init de tab_0
        #ifdef MISE_AU_POINT	 // vérification de la dimension de tab_ddl 
        if (tab.Taille() < c1.Dimension()) 
	        { cout << "\nErreur : dans le constructeur de noeud : ";
		         cout << " Noeud (int num_id,Coordonnee& c0,Coordonnee& c1,Coordonnee& c2,"
                << "const Tableau<Ddl>& tab,int num_M)\n";
		         Sortie(1);
		       };
        #endif
        int tab0Taille = tab_0.Taille();
        for (int i=1;i<=tab0Taille;i++)
          tab_0(i) = tab_ddl(i).Valeur();
        // on est en coordonnees entrainees, on vérifie que les ddl XI
        // sont présent sinon on rajoute
        int posi_X1=0; // init
        if ( Existe(X1) == 0)
          { // le ddl X1 n'existe pas on  rajoute les XI
            int an = tab_ddl.Taille();
            tab_ddl.Change_taille(an+Dimension());
            tab_0.Change_taille(an+Dimension());
            tab_tdt.Change_taille(an+Dimension());
            for (int jj=1;jj<=Dimension();jj++)
               tab_ddl(an+jj).Change_nom(Enum_ddl(jj));
            posi_X1 = an+1; // c'est la position du ddl X1
          }
        else // sinon il existe on récupère sa position
          posi_X1 = Existe(X1) ;
        // on effectue la liaison ddl/ deplacement, donc la mémoire
        // des coordonnées est positionnée dans le tableau de ddl
        Liaison_tdt(posi_X1); // (Existe(X1));
//        Liaison_tdt(Existe(X1));
        *coord0 = c0; // recopie des valeurs
        *coord2 = c2; // """"
        for (int j=1;j<= Dimension();j++)
              *(coord1(j)) = c1(j);
        posi_type_quel = 1;
        // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
        MiseAjourActif();
        MiseAjourEnum(); // mise en place de l'adressage directe
		      MiseAjourDdl_etendu(); // cas des ddl étendue
	       MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
      };	


// Constructeur de copie
Noeud::Noeud (const Noeud& nd):
   tab_0(nd.tab_0),tab_ddl(nd.tab_ddl),tab_tdt(nd.tab_tdt),coord1()
   ,tab_var_actives(nd.tab_var_actives),tab_actif(nd.tab_actif)
   ,pos_enum(nd.pos_enum)
   ,posiAssemb(nd.posiAssemb),baseB(NULL),baseB_t(NULL) // on définit ensuite la base
   ,baseB_0(NULL)
   ,t_enum_s(nd.t_enum_s)
   ,tab_type_quel(nd.tab_type_quel),update_type_quel(nd.update_type_quel)
   ,nbTypeQ_update(0),tab_nb_Elem(nd.tab_nb_Elem)
   ,pos_Quelconque(list_tab_typeQuelconque.end()) // idem ddl étendues
   ,pos_ddletendu(list_tab_ddletendu.end()) // c'est dans la méthode MiseAjourDdl_etendu, que le pointeur sera mis à jour
   ,nbddletendu_update(nd.nbddletendu_update) 
	  ,tab_ddletendu(nd.tab_ddletendu),update_ddletendu(nd.update_ddletendu)
   // pour les liaisons cinématiques: pas de recopie, il s'agit d'un stockage uniquement:
   // l'utilisation et la manipulation est à la charge des classes appelantes
   ,tab_enu_liaison(NULL),tab_ddl_lier(NULL)
    { num_noeud=nd.num_noeud;
      coord2 = NULL; // initialisation
      num_Mail = nd.num_Mail;     
      if ( Existe(X1) != 0)
       { coord0 = NULL;
         // traitement des liaisons et avec du cas de coord1
         if ( tab_tdt.Taille() != 0)
           //  cas avec les coordonnees a t+dt
           //on effectue la liaison ddl/ deplacement                 
            Liaison_tdt(Existe(X1));
         else // sinon uniquement à t
            Liaison_t(Existe(X1));
       }
      else
       {if (nd.coord0 != NULL)
         {coord0 = new Coordonnee(*(nd.coord0));
         }
        else
         {coord0 = NULL;
         };
       };
      // cas d'une base locale éventuelle
      if (nd.baseB != NULL)
       {baseB = new BaseB(*nd.baseB);};
      if (nd.baseB_t != NULL)
       {baseB_t = new BaseB(*nd.baseB_t);};
      if (nd.baseB_0 != NULL)
       {baseB_0 = new BaseB(*nd.baseB_0);};

     
      posi_type_quel = nd.posi_type_quel;
      // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
      MiseAjourActif();
      // pour les grandeurs quelconques, a priori on les met "non a jour"
      // la mise à jour nécessite l'appel explicite à l'ordre de mise à jour
      if (update_type_quel.Taille() != 0)
       { int t_typTaille = update_type_quel.Taille();
         for (int titq=1;titq<= t_typTaille;titq++) update_type_quel(titq)=0;
       };
      MiseAjourDdl_etendu(); // cas des ddl étendue
      MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
    };

Noeud::~Noeud()
   // Destructeur de Noeud utilisant les destructeurs
   // de Coordonnee et de Tableau<Ddl>
   { delete coord0; // le choix de la destruction ou pas de la zone 
     //mémoire est fait dans coord0
     if (coord2 != NULL) delete coord2;

     // on n'efface pas le tableau coord2 car s'il existe (c-a-d différent de null) il représente aussi
     // des degrés de liberté, donc il se situe au même endroit que les éléments de tab_tdt
     // qui lui sera de toute façon détruit par le destructeur automatique
     // pour les enum étendus, on utilise la  méthode MiseAjourDdl_etendu(), pour que tout soit cohérent
     // on commence par supprimer les tableaux ad hoc et ensuite on met à jour
     tab_ddletendu.Libere();update_ddletendu.Libere();nbddletendu_update=0;
     MiseAjourDdl_etendu();
     // idem pour les grandeurs quelconques
     tab_type_quel.Libere(); update_type_quel.Libere(); nbTypeQ_update=0;
     MiseAjourTypeQuelconque(); // cas des grandeurs quelconques
     // dans le cas ou il existe des liaisons cinématiques on supprime les conteneurs
     Suppression_tous_liaisons_noeuds();
     // cas où il existe une base locale
     if (baseB_0 != NULL) delete baseB_0;
     if (baseB_t != NULL) delete baseB_t;
     if (baseB != NULL) delete baseB;
   };

// surcharge de l'operator de lecture, avec typage
istream & operator >> (istream & ent, Noeud & noe)
  {  // lecture du type et vérification
     string nomType,nom;
     ent >> nomType;
     if (nomType != "Noeud")
       { Sortie(1);
         return ent;
       };
     // puis le numéro de noeud et le numéro de maillage
     ent >>  noe.num_noeud >> noe.num_Mail ;

     // les liaisons éventuelles
     bool test;
     ent >> nom >> test; // tab_enu_liaison
     if (test)
       { int nb;int toto;
         ent >> nb;
         if (noe.tab_enu_liaison != NULL)
           {noe.tab_enu_liaison->Change_taille(nb);}
         else
           {noe.tab_enu_liaison = new Tableau <Enum_liaison_noeud>(nb);};
        for (int i=1;i<= nb;i++)
          { ent >> nom >> toto >> nom;
            (*noe.tab_enu_liaison)(i) = Id_nom_liaison_noeud(nom);
          };
       }
     else
       {if (noe.tab_enu_liaison != NULL)
          { delete noe.tab_enu_liaison; noe.tab_enu_liaison = NULL;}
       };

     ent >> nom >> test; // tab_ddl_lier
     if (test)
       { int nb;int toto;
         ent >> nb;
         if (noe.tab_ddl_lier != NULL)
           {noe.tab_ddl_lier->Change_taille(nb);}
         else
           {noe.tab_ddl_lier = new Tableau <Tableau <Posi_ddl_noeud> >(nb);};
         for (int i=1;i<= nb;i++)
           ent >> nom >> toto >> (*noe.tab_ddl_lier)(i);
       }
     else
       {if (noe.tab_ddl_lier != NULL)
          { delete noe.tab_ddl_lier; noe.tab_ddl_lier = NULL;}
       };
   
    // le tableau des degrés de liberté
    ent >> noe.tab_ddl;
    // coordonnee initiale on les récupère par défaut
    // ensuite on fera la mise à jour
    ent >> *(noe.coord0);
    ent >> nom >> noe.tab_0; // valeurs a l'instant 0 des ddl
    ent >> nom >> noe.tab_tdt; // valeurs a l'instant t+dt des ddl
    // les coordonnees a un instant t et tdt sont reconstruit avec
    // la mise à jour si nécessaire
    noe.MiseAjour();
    // vérif si les coordonnees a un instant t+dt existent
    // si oui liaison
    ent >> nom;
    if (nom == "coord2Existe")
      noe.Liaison_tdt(noe.Existe(X1)); 
    //	ent >>  nom >> noe.tab_var_actives; // les numéros des ddl actifs
    // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
    noe.MiseAjourActif();
    noe.MiseAjourEnum(); // mise en place de l'adressage directe
    // %% cas des types quelconques éventuelles %%
    noe.Lecture_grandeurs_quelconque(ent);
	   // idem pour les ddl_etendu
	   noe.Lecture_Ddl_etendu(ent);
  
    // cas d'une base locale éventuelle
    {int existe_base;
     ent >> existe_base;
     if (existe_base == 1)
      {if (noe.baseB_0 == NULL) {noe.baseB_0=new BaseB();};
       ent >> nom >> (*noe.baseB_0);
      };
     ent >> existe_base;
     if (existe_base == 1)
      {if (noe.baseB_t == NULL) {noe.baseB_t=new BaseB();};
       ent >> nom >> (*noe.baseB_t);
      };
     ent >> existe_base;
     if (existe_base == 1)
      {if (noe.baseB == NULL) {noe.baseB=new BaseB();};
       ent >> nom >> (*noe.baseB);
      };
    };

    return ent;
  };
   
// surcharge de l'operator d'ecriture avec typage
ostream & operator << (ostream & sort , const Noeud & noe)
  { // le type, le numéro de noeud et le numéro de maillage
    sort << "Noeud " << noe.num_noeud << " " << noe.num_Mail ;
    // les liaisons éventuelles
    if (noe.tab_enu_liaison != NULL)
     { sort << "\n tab_enu_liaison " << 1 << " "; // on signale la présence du tableau
       int nb = (noe.tab_enu_liaison)->Taille();
       sort << nb << " ";
       for (int i=1;i<= nb;i++)
         sort << " ass: "<< i << Nom_liaison_noeud((*noe.tab_enu_liaison)(i)) << " ";
     }
    else
     sort << "\n tab_enu_liaison " << 0 << " "; // on signale l'absence  du tableau ;
   
    if (noe.tab_ddl_lier != NULL)
     { sort << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau
       int nb = (noe.tab_ddl_lier)->Taille();
       sort << nb << " ";
       for (int i=1;i<= nb;i++)
         sort << "\n   ass: "<< i <<  "  "<< (*noe.tab_ddl_lier)(i);
     }
    else
     sort << "\n tab_ddl_lier " << 0 << " "; // on signale l'absence  du tableau ;
   
    // le tableau des degrés de liberté
    sort << noe.tab_ddl;
    // coordonnee initiale on les sauvegarde par défaut
    // ensuite on fera la mise à jour
    sort << *(noe.coord0); 
    sort << " ddl_a_0 " << noe.tab_0; // valeurs a l'instant 0 des ddl
    sort << " ddl_a_tdt " << noe.tab_tdt; // valeurs a l'instant t+dt des ddl
    // les coordonnees a un instant t ne sont pas sauvegardées elles seront 
    // reconstruites si besoin avec la mise à jour
    // coordonnee a un instant t+dt on signale son existence
    if (noe.coord2 != NULL)
      sort << "coord2Existe \n"; 
    else 
      sort << "pascoord2 \n";		
    //	sort << "ddl_actif " << noe.tab_var_actives; // les numéros des ddl actifs
    // %% cas des types quelconques éventuelles %%
    noe.Ecriture_grandeurs_quelconque(sort);
    // idem pour les ddl_etendu
    noe.Ecriture_Ddl_etendu(sort);
  
    // cas d'une base locale éventuelle
    if (noe.baseB_0 != NULL)
        {sort << "\n 1 base_locale_0: " << (*noe.baseB_0);}
    else {sort << "\n 0 base_locale_0: "; };
    if (noe.baseB_t != NULL)
        {sort << "\n 1 base_locale_t: " << (*noe.baseB_t);}
    else {sort << "\n 0 base_locale_t: "; };
    if (noe.baseB != NULL)
        {sort << "\n 1 base_locale: " << (*noe.baseB);}
    else {sort << "\n 0 base_locale: "; };
   
	   return sort;
  };

//  lecture du noeud en mémoire
void Noeud::Lecture(UtilLecture *entreePrinc)
  { int numero; 
    Coordonnee co(Dimension()); // def d'un tableau de coordonnées
    *(entreePrinc->entree) >>  numero ;
    // lecture brut des coordonnées sans la dimension
    co.Lecture(*entreePrinc);
    Change_coord0(co);          // transmission a noeud
    if (numero != num_noeud)
      { cout << " ***ATTENTION dans la lecture du noeud ";
        cout << " le numero d identification du noeud attribue par "
        << " le constructeur (" << num_noeud << ") est different de celui lu  !!! "
        << " (" << numero << ") "
        << " Noeud::Lecture((UtilLecture *entreePrinc) " << endl ;
      };
  };
    
// affichage et definition interactive des commandes 
// coor: des coordonnees fixée  pour un affichage different pour chaque noeud
void Noeud::Info_commande_Noeud(UtilLecture * entreePrinc,Coordonnee& co,int numero)
  { ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier
    int dima = ParaGlob::Dimension();
    sort  << "\n" << setw (6) << numero <<" ";
    double sero = 0.;
    #ifndef ENLINUX_STREAM
      sort.setf(ios_base::scientific);
    #else  
      sort.setf(ios::scientific); 
    #endif
    // sort.setf(ios_base::scientific);
    for (int j=1;j<=3;j++)
       if (j<=dima)
          sort  << setw (18) << setprecision(ParaGlob::NbdigdoCA()) <<co(j) << " ";
       else   
          sort  << setw (18) << setprecision(ParaGlob::NbdigdoCA()) <<  sero << " ";
    Change_coord0(co);          // transmission a noeud
  };

		// Affiche les donnees liees au noeud
  // le niveau différent de 0 permet d'accèder à plus d'info
 void Noeud::Affiche (int niveau) const
 {	cout << "\n --noeud -- \nNumero  : " << num_noeud << ", du maillage: "<< num_Mail << '\n';

   // les liaisons éventuelles
   if (niveau > 0)
    {// les liaisons éventuelles
     if (tab_enu_liaison != NULL)
      { cout << "\n tab_enu_liaison " << 1 << " "; // on signale la présence du tableau
        int nb = (tab_enu_liaison)->Taille();
        cout << nb << " ";
        for (int i=1;i<= nb;i++)
          cout << " ass: "<< i << Nom_liaison_noeud((*tab_enu_liaison)(i)) << " ";
      }
     else
      cout << "\n tab_enu_liaison " << 0 << " "; // on signale l'absence  du tableau ;
    
     if (tab_ddl_lier != NULL)
      { cout << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau
        int nb = (tab_ddl_lier)->Taille();
        cout << nb << " ";
        for (int i=1;i<= nb;i++)
          cout << "\n   ass: "<< i <<  "  "<< (*tab_ddl_lier)(i);
      }
     else
      cout << "\n tab_ddl_lier " << 0 << " "; // on signale l'absence  du tableau ;
    };

			cout << "Coordonnee(s) initiale(s) du noeud : \n";
			coord0->Affiche();			
			if (coord1.Taille() != 0)
			  { cout << "Coordonnee(s) a l'instant t : \n";
			    Coord1().Affiche();
			   }
			if (coord2 != NULL)			    
			  { cout << "Coordonnee(s) a l'instant t+dt : \n";
			    coord2->Affiche();
			   } 
			cout << "Degre(s) de liberte lie(s) au noeud : \n";
			cout << "Taille du tableau : " << tab_ddl.Taille() << " , a 0, a t ( et t+dt ?)\n";
			for (int i=1;i<=tab_ddl.Taille();i++)
				{ if (tab_0.Taille() != 0) cout << tab_0(i) << " ";
				  tab_ddl(i).Affiche();
				  if (tab_tdt.Taille() != 0) cout << tab_tdt(i) << " ";
    };
			// affichage éventuelle des grandeurs enum étendue stockées au noeud
			int tail_tab_ddletendu = tab_ddletendu.Taille();
   if (tail_tab_ddletendu != 0)
			 {cout << "\nddl_etendu: ";
     for (int itq=1;itq<=tail_tab_ddletendu;itq++)
      {Ddl_etendu& ddlenum = tab_ddletendu(itq);
       if (ddlenum.DdlEnumEtendu().Nom_vide())
        { cout << Nom_ddl(ddlenum.DdlEnumEtendu().Enum()) ;}
       else
        { cout << ddlenum.DdlEnumEtendu().Nom() ;};
       cout << " " << ddlenum.ConstValeur()<< "  ";
      };
    };			

			// affichage éventuelle des grandeurs quelconques stockées au noeud
			int tail_tab_type_quel = tab_type_quel.Taille();
   if (tail_tab_type_quel != 0)
			 {cout << "\nddl_quelconque: ";
			  for (int itq=1;itq<=tail_tab_type_quel;itq++)
       {cout << tab_type_quel(itq).EnuTypeQuelconque().NomPlein() << " "
             << *(tab_type_quel(itq).Grandeur_pointee()) << " \n";
       };
    };
  
   // cas d'une base locale éventuelle
  if (baseB_0 != NULL)
    {cout << "\n base_locale_0: " << (*baseB_0);}
  if (baseB_t != NULL)
    {cout << "\n base_locale_t: " << (*baseB_t);}
  if (baseB != NULL)
    {cout << "\n base_locale: " << (*baseB);}
  
   // dans le cas ou la variable niveau est plus grande que 0 on affiche plus d'information
   if (niveau > 0)
    { cout << "\n le tableau d'adressage directe " << (* pos_enum) << endl;
    };
			cout << "-- fin noeud --\n";
 };

		// Affiche les donnees liees au noeud
 void Noeud::Affiche (ofstream& sort) const
		  {	// l'entete
		    sort << " Numero  : [ " << num_noeud 
		         << " ]****/////, du maillage: < "<< num_Mail 
		         << " > ";
      // les liaisons éventuelles
      if (tab_enu_liaison != NULL)
       { int nb = (tab_enu_liaison)->Taille();
         sort << nb << " liaison(s) (ass,type): ";
         for (int i=1;i<= nb;i++)
           sort << i << " " << Nom_liaison_noeud((*tab_enu_liaison)(i)) << " ";
       };
    
      if (tab_ddl_lier != NULL)
       { cout << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau
         int nb = (tab_ddl_lier)->Taille();
         sort << nb << " , ddl_lie(s) (ass,maill,noe,enu): ";
         for (int i=1;i<= nb;i++)
           sort << i <<  "  "<< (*tab_ddl_lier)(i);
       };

      sort << " =======================\n";
		    // les coordonnees     
      sort << "Coord t=0   : "; coord0->Affiche(sort,16); sort << ", " ;
      if (coord1.Taille() != 0)
         { sort << "\nCoord a t   : "; Coord1().Affiche(sort,16); sort << ", " ;};
      if (coord2 != NULL)			    
         {sort << "\nCoord a t+dt: " ; coord2->Affiche(sort,16); sort << ", " ;};
      // les ddl et variations   
      sort << '\n' << tab_ddl.Taille() << " Ddl a ";
      if (tab_0.Taille() != 0) sort << "        <<0>> ";
      sort << "            <<t>> ( et variation) ";
      if (tab_tdt.Taille() != 0) sort << "              <<tdt>> (et variation) : \n";
      
      for (int i=1;i<=tab_ddl.Taille();i++)
       { sort << tab_ddl(i).Nom() << " = ";  // le nom
         if (tab_0.Taille() != 0) sort <<  setw (16) << tab_0(i) << ", ";  // val a t=0
         sort <<  setw (16) << tab_ddl(i).Valeur() <<  " "; // val a t
         if (tab_0.Taille() != 0) 
            sort << "( " <<  setw (16) << (tab_ddl(i).Valeur() - tab_0(i)) << "), "; // delta 0 t				  
         if (tab_tdt.Taille() != 0) sort <<  setw (16) << tab_tdt(i) << " "; // val a tdt
         if ((tab_0.Taille() != 0)&&(tab_tdt.Taille() != 0)) 
            sort << "(" <<  setw (16) << (tab_tdt(i) - tab_0(i)) << " );"; // deltat 0 tdt			  
         
         // decalage pour la ligne suivante
          sort << "\n";  
       };
      // affichage éventuelle des grandeurs quelconques stockées au noeud
      int tail_tab_type_quel = tab_type_quel.Taille();
      for (int itq=1;itq<=tail_tab_type_quel;itq++)
        {sort << (tab_type_quel(itq).EnuTypeQuelconque()).NomPlein() << " "
              << *(tab_type_quel(itq).Grandeur_pointee()) << " \n";
        };
  
       // cas d'une base locale éventuelle
      if (baseB_0 != NULL)
        {sort << "\n base_locale_0: " << (*baseB_0);}
      if (baseB_t != NULL)
        {sort << "\n base_locale_t: " << (*baseB_t);}
      if (baseB != NULL)
        {sort << "\n base_locale: " << (*baseB);}
  
      sort << "\n";
		  };

// 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 Noeud::Insert_coord1(const Coordonnee& nouveau_coord1)
  {  // si les coordonnées n'existe pas encore il faut les créer
     if ( Existe(X1) == 0)
       { // le ddl X1 n'existe pas on le rajoute
         int an = tab_ddl.Taille();
         tab_ddl.Change_taille(an+Dimension());
         tab_0.Change_taille(an+Dimension());
         int dim = Dimension();
         for (int jj=1;jj<=dim;jj++)
            tab_ddl(an+jj).Change_nom(Enum_ddl(jj));
        // on effectue la liaison ddl/ deplacement                 
        Liaison_t(Existe(X1));
        // on met les XI hors service
        for (int i = 1; i<=dim; i++)
          tab_ddl(an+i).Met_hors_service();
        // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
        MiseAjourActif();
        MiseAjourEnum(); // mise en place de l'adressage directe
       };
     // copie des ddl
     for (int i=1;i<=coord1.Taille();i++)
        *(coord1(i)) = nouveau_coord1(i);
  };

// 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 Noeud::Insert_coord1()
  {  // si les coordonnées n'existe pas encore il faut les créer
     if ( Existe(X1) == 0)
       { // le ddl X1 n'existe pas on le rajoute
         int an = tab_ddl.Taille();
         tab_ddl.Change_taille(an+Dimension());
         tab_0.Change_taille(an+Dimension());
         int dim = Dimension();
         for (int jj=1;jj<=dim;jj++)
            tab_ddl(an+jj).Change_nom(Enum_ddl(jj));
         // on effectue la liaison ddl/ deplacement
         // donc le ddl X1 se situe maintenant à la place an+1 dans le tableau
         // des ddl
         Liaison_t(an+1); //(Existe(X1));
         // on met les XI hors service
         for (int i = 1; i<=dim; i++)
           tab_ddl(an+i).Met_hors_service();
         // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
         MiseAjourActif();
         MiseAjourEnum(); // mise en place de l'adressage directe
         // copie des ddl
         for (int i=1;i<=coord1.Taille();i++)
            *(coord1(i)) = (*coord0)(i);
       };
  };
 		
		
// Modifie les valeurs des coordonnees coord1 
void Noeud::Change_coord1(const Coordonnee& nouveau_coord1)
  {  // si les coordonnées n'existe pas encore il faudrait  les créer avant de les utiliser
     #ifdef MISE_AU_POINT	 // vérif 
       if ((nouveau_coord1.Dimension() != Dimension()) ||
           (coord1.Taille() == 0) ||  ((coord1(1)) == NULL)) 
	        { cout << "\nErreur : dans l'affectation de coordonnées à t, elles ne sont pas définies !\n";
		         cout << " Noeud::Change_coord1(Coordonnee& nouveau_coord1)\n";
		         Sortie(1);
		       }
     #endif
  
     for (int i=1;i<=coord1.Taille();i++)
        *(coord1(i)) = nouveau_coord1(i);
  };
		
		
// Retourne les coordonnees coord1 du noeud
// uniquement pour la lecture 
//Coordonnee Noeud::Coord1 ()
//   {  int nbcoo = coord1.Taille();
//      Coordonnee coo(nbcoo);
//      for (int i=1;i<=nbcoo;i++)
//        coo(i) = *(coord1(i));
//      return coo;  
//   };
   
// Retourne le nombre de degres de liberte du noeud
// qui sont actuellement actifs
//int Noeud::Nombre_var_ddl_actives ()
//  { int total = 0;
//     int imax = tab_ddl.Taille();
//     for (int i=1;i<=imax;i++)
//        if (tab_ddl(i).Service()) total ++;
//      return total;  
//   };
		
		 
// retourne la liste de tous les  types de ddl actuellement utilisé
// par le noeud (actif ou non)
List_io <Enum_ddl> Noeud::Les_type_de_ddl(bool)
 { int tail = tab_ddl.Taille();
   List_io <Enum_ddl> tab_enum;
   for (int i= 1;i<= tail;i++)
     tab_enum.push_back(tab_ddl(i).Id_nom());
   return tab_enum;  
 };

// retourne la liste de tous les Ddl_enum_etendu disponible
List_io <Ddl_enum_etendu> Noeud::Les_type_de_ddl_etendu(bool)
 { int tail = tab_ddletendu.Taille();
   List_io <Ddl_enum_etendu> tab_enum_etendu;
   for (int i= 1;i<= tail;i++)
     tab_enum_etendu.push_back(tab_ddletendu(i).Const_DdlEnumEtendu());
   return tab_enum_etendu;  
 };

// retourne la liste de tous les TypeQuelconque disponibles
List_io <TypeQuelconque> Noeud::Les_TypeQuelconque(bool )
 { int tail = tab_type_quel.Taille();
   List_io <TypeQuelconque> tab_TypeQuelconque;
   for (int i= 1;i<= tail;i++)
     tab_TypeQuelconque.push_back(tab_type_quel(i));
   return tab_TypeQuelconque;  
 };
   
// 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>  Noeud::Valeur_multi_et_Tensorielle
    (const List_io <Ddl_enum_etendu>& li_enu_scal,List_io <TypeQuelconque >& li_quelc) const
 {int nb_ddl_enum_etendu = li_enu_scal.size(); // la taille du tableau de retour
  Tableau <double> tab_ret(nb_ddl_enum_etendu); // le tableau de retour
  // on balaie les ddl_enum_etendu pour les alimenter
  {List_io <Ddl_enum_etendu>::const_iterator il,il_fin = li_enu_scal.end();
   int i_tab=1; // init
   for (il= li_enu_scal.begin(); il != il_fin; il++,i_tab++)
    { // on regarde s'il s'agit d'un ddl pur
      const Ddl_enum_etendu& ddl = (*il); // pour simplifier
      if (ddl.Nom_vide())
       // cas d'un ddl pur
       { if (Existe_ici(ddl.Enum()))
           {tab_ret(i_tab)=  Valeur_tdt(ddl.Enum());}
         else
           {cout << "\n *** erreur d'acces, le ddl "<< Nom_ddl(ddl.Enum())
                 << " n'est pas disponible au temps tdt "
                 << "\n Noeud::Valeur_multi_et_Tensorielle(...";
            Noeud::Affiche(0);
            Sortie(1);
           };
       }
      else // cas d'un ddl étendu
       { if (Existe_ici_ddlEtendu(ddl))
           {tab_ret(i_tab)= DdlEtendue(ddl).ConstValeur();}
         else
           {cout << "\n *** erreur d'acces, le ddl etendue "<< ddl.Nom_plein()
                 << " n'est pas disponible au temps tdt "
                 << "\n Noeud::Valeur_multi_et_Tensorielle(...";
            Noeud::Affiche(0);
            Sortie(1);
           };
       };
    };
  };
  //on balaie les types quelconques
  {List_io <TypeQuelconque>::iterator il,il_fin = li_quelc.end();
   int i_tab=1; // init
   for (il= li_quelc.begin(); il != il_fin; il++,i_tab++)
    { TypeQuelconque& etq = (*il);  // pour simplifier
      // on regarde s'il existe
      TypeQuelconque_enum_etendu en = etq.EnuTypeQuelconque(); // pour simplifier
      if (Existe_ici(en))
       { etq = Grandeur_quelconque(en);}
      else
       {// on test s'il s'agit d'un type correspondant à une grandeur
        // stockée naturellement au noeud
        bool trouver = false; // init
        if(en.Nom_vide()) // on ne prend en compte que les types  initiaux
         {switch (en.EnumTQ())
          { case NUM_NOEUD:
              { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) (etq.Grandeur_pointee()));
                *(gr.ConteneurEntier()) = this->Num_noeud();
                trouver = true;
                break;
              }
            case NUM_MAIL_NOEUD:
              { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) (etq.Grandeur_pointee()));
                *(gr.ConteneurEntier()) = this->Num_Mail();
                trouver = true;
                break;
              }
            case POSITION_GEOMETRIQUE:
              {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee()));
               (*gr.ConteneurCoordonnee())= this->Coord2();
               trouver = true;
                break;
               }
            case POSITION_GEOMETRIQUE_t:
              {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee()));
               (*gr.ConteneurCoordonnee())= this->Coord1();
               trouver = true;
                break;
               }
            case POSITION_GEOMETRIQUE_t0:
              {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee()));
               (*gr.ConteneurCoordonnee())= this->Coord0();
               trouver = true;
                break;
               }

            //*** fin


            default:
              trouver = false;
              break;
           };
         };
        if (!trouver)
           {cout << "\n *** erreur d'acces, le ddl "<< en.NomPlein()
                 << " n'est pas disponible  "
                 << "\n Noeud::Valeur_multi_et_Tensorielle(...";
            Noeud::Affiche(0);
            Sortie(1);
           };
        };
    };
  };

  // retour
  return tab_ret;
 };

// 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 Noeud::Nombre_var_ddl_actives (Enum_ddl en) const
	{ int retour = 0;
  	  if ((Existe(en) != 0) && (En_service(en)) && (UneVariable(en))) 
		     { 	switch (TypeGrandeur(en))
	            { case SCALAIRE : 
			              retour=1;
			              break;
			            case VECTEUR : case COORDONNEE : // là il y a un mélange pas sain !
			              // dans le cas où le calcul est axisymétrique
                 // on ne  prend pas en compte le 3 ième ddl 
                 if (ParaGlob::AxiSymetrie()) 
                   {retour = 2; }// on est forcément en 3D
                 else
			                {retour=ParaGlob::Dimension();};
			              break;
			            case TENSEUR :
                 retour = ParaGlob::NbCompTens();
                 break;
               case RIEN_TYPEGRANDEUR :    
                 retour = 0;
                 break;
               default :
                 cout << "\nErreur : valeur incorrecte du type Enum_ddl !\n";
                 cout << "Nombre_var_ddl_actives (Enum_ddl en) \n";
                 Sortie(1);
             };
       };
		 return retour;
 };
		       
// surcharge de l'affectation entre deux noeuds
Noeud& Noeud::operator= (const Noeud& nd)
   { // recopie des tableaux
     tab_0 = nd.tab_0;
     tab_ddl = nd.tab_ddl;
     tab_tdt = nd.tab_tdt;
     num_Mail = nd.num_Mail;
//     // liaison éventuelle
//     enu_liaison = nd.enu_liaison;
//     noeud_lier = nd.noeud_lier;
     // puis les variables
     num_noeud=nd.num_noeud;
     posiAssemb = nd.posiAssemb;
     // cas d'une base locale éventuelle
     if (nd.baseB != NULL)
      {if (baseB != NULL)
        { (*baseB) = (*(nd.baseB));}
       else
        {baseB = new BaseB(*nd.baseB);};
      }
     else // cas où nulle
      { if (baseB != NULL) delete baseB;}
    
     if (nd.baseB_t != NULL)
      {if (baseB_t != NULL)
        { (*baseB_t) = (*(nd.baseB_t));}
       else
        {baseB_t = new BaseB(*nd.baseB_t);};
      }
     else // cas où nulle
      { if (baseB_t != NULL) delete baseB_t;}

     if (nd.baseB_0 != NULL)
      {if (baseB_0 != NULL)
        { (*baseB_0) = (*(nd.baseB_0));}
       else
        {baseB_0 = new BaseB(*nd.baseB_0);};
      }
     else // cas où nulle
      { if (baseB_0 != NULL) delete baseB_0;}

     coord2 = NULL; // initialisation
     if ( Existe(X1) != 0)
      { // on met à null coord0 pour éviter de prendre ses valeurs
        coord0 = NULL;
        if ( tab_tdt.Taille() != 0)
          //  cas avec les coordonnees a t+dt
          //on effectue la liaison ddl/ deplacement                 
           Liaison_tdt(Existe(X1));
        else
           Liaison_t(Existe(X1));
       }
     else  // cas où il n'y a pas de liaison
       {coord0 = new Coordonnee(*(nd.coord0));
        // la taille de coord1 est initialisé à 0 par défaut 
       };
     tab_var_actives = nd.tab_var_actives;tab_actif = nd.tab_actif;
     pos_enum = nd.pos_enum; // mise en place de l'adressage directe
     t_enum_s = nd.t_enum_s; // mise en place 
     // dans le cas où il y a des ddl_etendu
     // on recopie les différents tableaux et on met à jour
     tab_ddletendu=nd.tab_ddletendu; 
     update_ddletendu=nd.update_ddletendu;
     nbddletendu_update=nd.nbddletendu_update;
     // on ne recopie pas le pointeur pos_ddletendu, car se sera dans la méthode MiseAjourDdl_etendu
     // qu'il sera mis à jour
     MiseAjourDdl_etendu();
       // dans le cas où il y a des grandeurs quelconques (mêmes remarques que dans le cas des enum étendus)
     tab_type_quel = nd.tab_type_quel;
     update_type_quel = nd.update_type_quel;
     nbTypeQ_update = nd.nbTypeQ_update;
     MiseAjourTypeQuelconque();
     return (*this);
   }; 
   
// initialisation d'un ou de plusieurs nouveaux cas d'assemblage
void Noeud::InitNouveauCasAssemb(int nb_cas)
	{ // récup de la taille actuelle
	  int taille_actuelle = posiAssemb.Taille();
	  // nouvelle taille
	  int nouvelle_taille = taille_actuelle + nb_cas;
	  // changement de taille, normalement les anciennes valeurs sont gardée
	  // en début de tableau
      posiAssemb.Change_taille(nouvelle_taille); 
	  t_enum_s.Change_taille(nouvelle_taille);
	  // on initialise les nouveaux éléments -> pour l'instant pointe sur rien
	  // car c'est la fin de la liste
	  for (int i= taille_actuelle+1;i<= nouvelle_taille;i++)
	    t_enum_s(i)=list_tab_posi_actif.end();
 };
		
// 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 Noeud::Enreg_ordre_variable_ddl_actives(int nb_assemb)
 { // l'objectif est de déterminer ou de construire s'il n'existe pas, un tableau
   // indexé par les types énumérés des ddl actifs
   // le programme est construit sur le même modèle que MiseAjourEnum()
   // mais ici on ne s'intéresse qu'au ddl actif
   List_io <Tableau <int > >::iterator& pos_enum_s = t_enum_s(nb_assemb); // pour simplifier
   // tout d'abord on regarde si le dernier tableau construit dans la liste
   // list_tab_posi_actif, convient, car ce sera le cas pour le cas courant
   // le dernier tableau est positionné en début de liste.
   List_io <Tableau <int > >::iterator ideb;
   ideb =  list_tab_posi_actif.begin();
   List_io <Tableau <int > >::iterator iancien = pos_enum_s;
   int taille = tab_var_actives.Taille();
   // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position
   int ttail = (*ideb).Taille(); 
   bool okk = true;
   // le test n'est effectué que si la liste n'est pas vide
   if (list_tab_posi_actif.size() != 0)
    { // d'abort la taille, on compte le nombre d'élément non nul dans 
      int ttaile = (*ideb)(ttail); 
      if (taille != ttaile)
         okk = false;
      else 
       // maintenant le contenu 
       for (int i = 1; i<= taille;i++)
          if( (*ideb)(tab_ddl(tab_var_actives(i)).Id_nom()) != i)
           { okk = false; break;}
    }
   else
     okk = false;        
   // si le tableau convient on met à jour le pointeur et c'est fini
   // sinon on passe en revu toute la liste
   if (okk)
     pos_enum_s = ideb;
   else // ---- cas où on passe en revue la liste -----
    // ici la procédure est plus longue, mais normalement elle ne sera
    // utilisé que peut souvent
    {  
     // on reconstruit un tableau d'adressage indirect des ddl
     // la taille du tableau d'adressage est celui du nombre maxi
     // de type de ddl différent (donc certain ne serviron pas)
     // les données du tableau sont initialisées à 0, ainsi si l'on
     // cherche à utiliser un ddl indice 0, l'erreur sera détecté au 
     // niveau de Tableau_T
     // l'avant dernier élément du tableau sert à stocker le nombre de noeud
     // qui utilise le tableau
     // le dernier élément indique le nombre d'élément non nul
     Tableau <int> tab_indi_enum(NbEnum_ddl()+2,0);
     for (int i=1;i<=taille;i++)
       tab_indi_enum(tab_ddl(tab_var_actives(i)).Id_nom())=i;
     // on enregistre la taille  
     tab_indi_enum(NbEnum_ddl()+2) = taille;  
     // maintenant on va regarder si ce tableau existe dans la liste
     List_io <Tableau <int > >::iterator ifin = list_tab_posi_actif.end();
     List_io <Tableau <int > >::iterator iter;
     bool trouver = false;
     for (iter = ideb;ideb!= ifin;ideb++)
       if ((*iter) == tab_indi_enum)
         { trouver = true; break;}
     // si pas trouver on ajoute sinon on utilise la position déjà existante
     if (!trouver)
       // cas où on n'a pas trouvé de tableau
      { list_tab_posi_actif.push_front(tab_indi_enum);  // allocation
        // on attribue le nouveau pointage
        pos_enum_s = list_tab_posi_actif.begin(); // sauvegarde de la position 
      }
     else // cas où on a trouvé un tableau dans la liste
      pos_enum_s = iter; 
    };
      
   // on regarde si pos_enum_s était déjà attribué
   if (iancien != list_tab_posi_actif.end())
     // cas où ce n'est pas  la première initialisation
     {if ((*iancien)(NbEnum_ddl()+1) == 1)
      // cas où c'est le dernier noeud qui pointe sur ce tableau
      // on supprime le tableau
            list_tab_posi_actif.erase(iancien);
      else
      // sinon on décrémente le compteur
            ((*iancien)(NbEnum_ddl()+1))--;
      // maintenant on s'occupe du nouveau pointage
      ((*pos_enum_s)(NbEnum_ddl()+1))++;
     }
   else
   // c'est la première initialisation
   // on incrémente le compteur du tableau
      ((*pos_enum_s)(NbEnum_ddl()+1))++;
 };
		

// test si le noeud est complet
// = 1 tout est ok, =0 element incomplet
int Noeud::TestComplet() const
  { bool ret=true;
    if ((num_noeud == -3) || (num_Mail == -3)) 
     { if (num_noeud == -3) cout << "\n le numero du noeud n'est pas defini";
       if (num_Mail == -3) cout << "\n le numero de maillage n'est pas defini";
	   if (ParaGlob::NiveauImpression() >= 6) this->Affiche(); 
       ret = false;
      }
    if (tab_ddl.Taille() == 0)
     { cout << "\n ***** warning : il n'y a pas de ddl rattache au noeud " << num_noeud 
            << ", du maillage " << num_Mail; 
//       ret = false; 
       // maintenant normalement ce n'est plus un pb
     }
    else
      { int nbdd = tab_ddl.Taille();
        for (int i=1;i<= nbdd ;i++)
         if (tab_ddl(i).TestComplet() == 0) 
           { cout << "\n  probleme avec le ddl " << i << "du noeud " << num_noeud 
                  << ", du maillage " << num_Mail; 
             ret = false;
           };
//	if (posiAssemb.Taille() == 0) return 0;	
      };
    return ret;
  };

		
// ajout de ddl 
// 1) s'il n'y a pas de ddl il y a initialisation
// 2) si les ddl existent deja, on égalise au ddl passé en paramètre
// 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 Noeud::PlusDdl(Ddl& a)
  { // on regarde si le tableau des ddl existant est vide
    int taille = tab_ddl.Taille();
    if (taille == 0)
      { tab_ddl.Change_taille(1);
        tab_ddl(1) = a;
        // on peut maintenant mettre en place l'adressage directe
        // ce qui permettra d'utiliser Existe(..) dans MiseAjour
        MiseAjourEnum(); // mise en place de l'adressage directe    
        // mise a jour des tableaux et des liaisons ddl/deplacement
		      MiseAjour();
      }
    else 
     { // on regarde si le Ddl existe
       for (int i=1;i<= taille; i++)
        // on test uniquement sur l'identificateur du ddl, ces caractéristiques
        // pouvant être différents suite à un précédent calcul
        if ((tab_ddl(i)).Id_nom() == a.Id_nom())
          { tab_ddl(i) = a;
            MiseAjourActif();
            return;
          };
       // dans le cas où la dimension est supérieur à 1 et que le ddl appartient
       // à une famille dépendant de la dimension, on ajoute tous les ddl de la famille   
       Enum_ddl enu = a.Id_nom();
       if ((ParaGlob::Dimension()>1)&&FoncDim(enu)) 
       	{// on récupère tous les ddl de la famille
       	 Tableau<Enum_ddl> t_enu =TableauTypeDdl(enu);
       	 // fabrication d'un tableau de ddl associé
       	 int ttaille = t_enu.Taille();
       	 Tableau <Ddl > t_ddl(ttaille,a);// tous les nouveaux ddl on le même statut que a
       	 for (int il=1;il<=ttaille;il++)
       	   {t_ddl(il).Change_nom(t_enu(il));
       	    if (t_ddl(il).Id_nom() != enu)
       	      t_ddl(il).Valeur() = 0.; // mise à 0 pour les valeurs des ddl supplémentaires
       	   }
       	 // appel de la méthode gérant un tableau de ddl  
         PlusTabDdl(t_ddl);
         return;
       	};
       // dans le cas ou la dimension est supérieur à 1 et que les ddl est un XI
       // erreur
//       if ( (PremierDdlFamille(a.Id_nom())==X1) && (ParaGlob::Dimension() != 1))
//           { cout <<"\n Erreur, la dimension etant superieur a 1 il n'est pas "
//                  << " possible d'ajouter qu'un seul ddl de position \n";
//             cout << "void Noeud::PlusDdl(Ddl& a)" << endl;
//             Sortie (1);
//            } 
       // on regarde s'il y a une incompatibilite Xi Ui
       if  ((Existe_ici(X1) && (PremierDdlFamille(a.Id_nom())==UX)) ||
            (Existe_ici(UX) && (PremierDdlFamille(a.Id_nom())==X1)) ||
            (Existe_ici(UY) && (PremierDdlFamille(a.Id_nom())==X1)) ||
            (Existe_ici(UZ) && (PremierDdlFamille(a.Id_nom())==X1)) )
           { cout <<"\n Erreur, on ne peut pas avoir de coordonnees entrainees"
                  << " avec des ddl Ui \n";
             cout << "void Noeud::PlusDdl(Ddl& a)" << endl;
             Sortie (1);
           };
       // sauvegarde éventuelle des coordonnées
       if (coord0 != NULL) // il existe déjà des coordonnées 0
            // si les coordonnees existent deja on les sauvegarde dans une 
            //instance réelle et non éventuellement pointé
            // sera ensuite modifié avec MiseAjour() éventuellement
            { Coordonnee truc(*coord0);
              delete coord0;
              coord0 = new Coordonnee(truc);
            };
       int coord1Taille = coord1.Taille();
       Vecteur* toto = NULL;  
       if (coord1Taille != 0)
          // signifie qu'il y a une liaison entre les ddl à t et coord1
          if (coord1(1) != NULL) 
            // tableau existant et affecte, on cré un tableau 
            //intermédiaire, qui est supprimé à la fin de la routine
            toto = new Vecteur(coord1Taille);
       // réécriture dans toto, place qui sera utilisée dans mise à jour
       // puis après MiseAjour() suppression de toto
       for (int ii=1;ii<=coord1Taille;ii++)
              { (*toto)(ii) = *(coord1(ii));
                 coord1(ii) = &(*toto)(ii);
              };
       if (coord2 != NULL) // il existe déjà des coordonnées finales
            // si les coordonnees existent deja on les sauvegarde dans
            // une instance réelle et non éventuellement pointé
            { Coordonnee truc(*coord2);
              delete coord2;
              coord2 = new Coordonnee(truc);
            };
          // maintenant on peut changer le tableau de ddl          
       // on augmente la taille du tableau 
       tab_ddl.Change_taille(taille+1);
       tab_ddl(taille+1) = a;
       // on peut maintenant mettre en place l'adressage directe
       // ce qui permettra d'utiliser Existe(..) dans MiseAjour
       MiseAjourEnum(); // mise en place de l'adressage directe    
       // mise a jour des tableaux et des liaisons ddl/deplacement
       MiseAjour();
       if (toto != NULL) delete toto;      
     };
    // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
    MiseAjourActif();
 //   MiseAjourEnum(); // mise en place de l'adressage directe
  };
   
// 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 Noeud::PlusTabDdl(Tableau<Ddl>& ta)
  { // on commence par ordonner le tableau ta
    OrdonnerTableauDdl(ta);
    // maintenant tous les ddl de ta sont dans le bonne ordre et à suivre
  
    // on regarde si le tableau est vide
    int taille = tab_ddl.Taille();
    if (taille == 0)
      { tab_ddl = ta;
        // on peut maintenant mettre en place l'adressage directe
        // ce qui permettra d'utiliser Existe(..) dans MiseAjour
        MiseAjourEnum(); // mise en place de l'adressage directe    
        // mise a jour des tableaux et des liaisons ddl/deplacement
	       MiseAjour();
      }
    else 
      {// on regarde combien de  Ddl existe deja
       // et on crée une liste des ddl à ajouter
       // les ddl qui existent déjà sont éventuellement updaté
       list<Ddl> liDdl;
       bool change_donn_var=false;
       ListeDdlAajouter(liDdl,ta,change_donn_var);
       // on augmente la taille du tableau en consequence
       // mais auparavant dans le cas où les coordonnées sont connues
       // que sous la forme de valeurs pointées il faut les sauvegarder
       if (liDdl.size() == 0) 
         { // dans le cas où on a aucun ddl a ajouter
           // on regarde cependant si il y a eu un changement de type
           if (change_donn_var) MiseAjourActif();
           return;   
         }
       else  
        { // sauvegarde éventuelle des coordonnées
          if (coord0 != NULL) // il existe déjà des coordonnées 0
            // si les coordonnees existent deja on les sauvegarde
            //  dans une instance réelle et non éventuellement pointé
            { Coordonnee truc(*coord0);
              delete coord0;
              coord0 = new Coordonnee(truc);
            };
          int coord1Taille = coord1.Taille();
          Vecteur* toto = NULL;  
          if (coord1Taille != 0)
           if (coord1(1) != NULL) 
            {// tableau existant et affecte, on crée un tableau intermédiaire,
             // qui est supprimé à la fin de la routine
             toto = new Vecteur(coord1Taille);
             // réécriture dans toto, place qui sera utilisée dans mise à jour
             // puis après MiseAjour() suppression de toto
             for (int ii=1;ii<=coord1Taille;ii++)
               { (*toto)(ii) = *(coord1(ii));
                  coord1(ii) = &(*toto)(ii);
               };
            };
          if (coord2 != NULL) // il existe déjà des coordonnées finales
            // si les coordonnees existent deja on les sauvegarde dans
            // une instance réelle et non éventuellement pointé
            { Coordonnee truc(*coord2);
              delete coord2;
              coord2 = new Coordonnee(truc);
            };
          // maintenant on peut changer le tableau de ddl 
          int nbddl_a_ajouter=liDdl.size();        
          tab_ddl.Change_taille(taille+nbddl_a_ajouter);
          // on rempli le tableau
          list <Ddl >::iterator il=liDdl.begin(); 
          for (int j1=1;j1<= nbddl_a_ajouter;j1++,il++)
                { tab_ddl(taille+j1)=(*il);};
          // on peut maintenant mettre en place l'adressage directe
          // ce qui permettra d'utiliser Existe(..) dans MiseAjour par exemple
          MiseAjourEnum(); // mise en place de l'adressage directe    
          // on regarde s'il y a une incompatibilite Xi Ui
          int tab_ddlTaille = tab_ddl.Taille();
          if (Existe_ici(X1)) 
           for (int i=1;i<= tab_ddlTaille;i++)
            if (Meme_famille(tab_ddl(i).Id_nom(),UX))
             { cout <<"\n Erreur, on ne peut pas avoir de coordonnees entrainees"
                    << " avec des ddl Ui \n";
               cout << "void Noeud::PlusTabDdl(Tableau<Ddl>& ta)" << endl;
               Sortie (1);
             };
          // mise a jour des tableaux et des liaisons ddl/deplacement
	         MiseAjour();
	         if (toto != NULL) delete toto;
        };
      };
    // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl
    MiseAjourActif();
//    MiseAjourEnum(); // mise en place de l'adressage directe    
   };

 
// ajout du tableau de ddl d'un autre noeud
void Noeud::PlusTabDdl(const Noeud & noe)
  { // on récupère le tableau de ddl géné par noe
    Tableau<Ddl> ta = noe.tab_ddl;
    if (ta.Taille() != 0)
      Noeud::PlusTabDdl(ta);
  };

// modification du statut d'un ddl 
// si en est inconnu, aucune action
void Noeud::Met_hors_service(Enum_ddl en)
    { tab_ddl(Existe(en)).Met_hors_service();
      MiseAjourActif();
    };

void Noeud::Met_en_service(Enum_ddl en)
    { tab_ddl(Existe(en)).Met_en_service();
      MiseAjourActif();
    };

// modification du statut d'un tableau de ddl  
// si un des elements du tableau est inconnu, aucune action
void Noeud::Met_hors_service(const Tableau<Enum_ddl>& taben)
    { int tabenTaille = taben.Taille();
      for (int i = 1; i<=tabenTaille; i++)
         tab_ddl(Existe(taben(i))).Met_hors_service();
      MiseAjourActif();   
    };

void Noeud::Met_en_service(const Tableau<Enum_ddl>& taben)		
    { int tabenTaille = taben.Taille();
      for (int i = 1; i<=tabenTaille; i++)
         tab_ddl(Existe(taben(i))).Met_en_service();
      MiseAjourActif();   
    };

// 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 Noeud::Met_hors_service()
    { int tab_ddlTaille = tab_ddl.Taille();
      for (int i = 1; i<=tab_ddlTaille; i++)
         tab_ddl(i).Met_hors_service();
      MiseAjourActif();   
    };

void Noeud::Met_en_service()
// y compris les données
    { int tab_ddlTaille = tab_ddl.Taille();
      for (int i = 1; i<=tab_ddlTaille; i++)
         tab_ddl(i).Met_en_service();
      MiseAjourActif();   
    };
// modification du statut de tous les ddl actuellements présent
// sauf les données qui ne sont pas modifiées
// si un des elements du tableau est inconnu, aucune action
void Noeud::Met_hors_service_ddl()
    { int tab_ddlTaille = tab_ddl.Taille();
      for (int i = 1; i<=tab_ddlTaille; i++)
         tab_ddl(i).Met_hors_service_ddl();
      MiseAjourActif();
    };

void Noeud::Met_en_service_ddl()
// y compris les données
    { int tab_ddlTaille = tab_ddl.Taille();
      for (int i = 1; i<=tab_ddlTaille; i++)
         tab_ddl(i).Met_en_service_ddl();
      MiseAjourActif();
    };
      
// changement du statut de variable à donnée pour un tableau d'enum de ddl 	
void Noeud::ChangeVariable_a_Donnee(const Tableau<Enum_ddl>& taben)
   { int tabenTaille = taben.Taille();
     for (int i = 1; i<=tabenTaille; i++)        
         tab_ddl(Existe(taben(i))).ChangeVariable_a_Donnee();
     MiseAjourActif();
   };

// changement du statut de donnée à variable pour un tableau d'enum de ddl 	
void Noeud::ChangeDonnee_a_Variable(const Tableau<Enum_ddl>& taben)
   { int tabenTaille = taben.Taille();
     for (int i = 1; i<=tabenTaille; i++)        
         tab_ddl(Existe(taben(i))).ChangeVariable_a_Donnee();
     MiseAjourActif();
   };

// 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 Noeud::ChangeToutesLesConditions(const Tableau<Ddl>& ta)
  { int taTaille = ta.Taille();
    for (int i = 1; i<=taTaille; i++)        
       { tab_ddl(Existe(ta(i).Id_nom())).CopieToutesLesConditions(ta(i).Retour_Fixe());};
    MiseAjourActif();
  };

// 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 Noeud::ChangeStatut(int cas,Enum_ddl enuta)
 { // on récupère tous les membres de la combinaison
   Tableau <Enum_ddl> tenu= Combinaison(cas); 
   int tenuTaille = tenu.Taille();
   Enum_boolddl enubold=tab_ddl(Existe(enuta)).Retour_Fixe();
   for (int i = 1; i<=tenuTaille; i++)        
       { tab_ddl(Existe(tenu(i))).CopieToutesLesConditions(enubold);};
    MiseAjourActif();
 };

// changement de statu des ddl d'une combinaison, (cf. Enum_ddl)
// les ddl de la combinaison, prennent le même statut que celui de enubold
// cas est la combinaison,
void Noeud::ChangeStatut(int cas,Enum_boolddl enubold)
 { // on récupère tous les membres de la combinaison
   Tableau <Enum_ddl> tenu= Combinaison(cas); 
   int tenuTaille = tenu.Taille();
   for (int i = 1; i<=tenuTaille; i++)
       { tab_ddl(Existe(tenu(i))).CopieToutesLesConditions(enubold);};
    MiseAjourActif();
 };

/*// retourne le numero du ddl recherche identifie par en,
// s'il existe sinon 0
int Noeud::Existe(const Enum_ddl en)
  { int tab_ddl_Taille = tab_ddl.Taille();
     // on commence par tester a partir de la derniere position sauvegardee
    for (short int i=(short)(posiddl);i<=  tab_ddl_Taille;i++)
      if (en == tab_ddl(i).Id_nom())
          { posiddl=i; return i; }
     // on continue la recherche   a partir du debut
    for (short int i=1;i< posiddl;i++)
      if (en == tab_ddl(i).Id_nom())
          { posiddl=i; return i; }
    // sinon retour 0      
	return 0;
  }; */
		
// indique que l'on va utiliser les ddl en 0, t et tdt
// les grandeurs en tdt sont cree s'ils n'existent pas 
// et initialisees par defaut 
void Noeud::Travail_tdt()
  { if (tab_tdt.Taille() == 0)
      tab_tdt.Change_taille(tab_ddl.Taille());
    // les grandeurs à tdt peuvent changer des coordonnées vers 
    // autre chose, pour cela on commence par les supprimer, ensuite
    // dans la procédure MiseAjour() elles sont recréées si besoin est
    // a partir du tableau de tab_tdt  
    if (coord2 != NULL)  delete coord2;
    coord2 = NULL;
    MiseAjour();  
 };
		
// indique que l'on va utiliser les ddl en 0, t
// si les grandeurs en tdt existaient, elles sont supprimées
void Noeud::Travail_t()
  { if (tab_tdt.Taille() != 0)
      { tab_tdt.Libere();
        if (coord2 != NULL)  delete coord2;
        coord2 = NULL;
      } 
    MiseAjour();  
 };
		
// 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 Noeud::ZeroVariablesDdl(bool cas)
  { int nbactif = tab_var_actives.Taille();
    for (int j=1; j<= nbactif; j++)
      {int i = tab_var_actives(j);
       if (((tab_ddl(i)).Nom())[0] != 'X')
        { tab_ddl(i).Valeur() = 0.;
          tab_0(i) = 0.;
        }
       else // cas de coordonnees entrainees
        if (cas)
           tab_ddl(i).Valeur() =  tab_0(i);
      };
    if (tab_tdt.Taille() != 0) 
      // cas de l'utilisation du tableau a tdt   
      for (int j1=1; j1<= nbactif; j1++)
        {int ii = tab_var_actives(j1);
         if (((tab_ddl(ii)).Nom())[0] != 'X')
            tab_tdt(ii) = 0.;
         else
            tab_tdt(ii) = tab_0(ii);
        };
  };
    
// actualisation des ddl actifs (variable et donnee) de t+dt vers t      
void Noeud::TdtversT()
  { int nbactif = tab_actif.Taille();
    for (int j=1; j<= nbactif; j++)
     {int i = tab_actif(j);
      tab_ddl(i).Valeur() = tab_tdt(i);
     };
    // cas d'une base locale
    if (baseB != NULL)
     {(*baseB_t) = (*baseB);}
   
  };
    
// actualisation des ddl actifs (variables et donnees) de t vers t+dt      
void Noeud::TversTdt()
  { int nbactif = tab_actif.Taille();
    for (int j=1; j<= nbactif; j++)
     {int i = tab_actif(j);
      tab_tdt(i)= tab_ddl(i).Valeur();
     };
    // cas d'une base locale
    if (baseB != NULL)
     {(*baseB) = (*baseB_t);}
   
  };
  
          
// 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 Noeud::Contrainte(Vecteur& Sig)
  { int position = Existe(SIG11);
    int l_sigma; // dimension des contraintes
    // test pour l'existence des ddl de sigma
    if ( position != 0)
     { l_sigma = 1 ; // c'est au moins un tenseur d'ordre 1
       if (Existe(SIG22) != 0) 
           { l_sigma = 3 ; // c'est au moins un tenseur d'ordre 2
                           // donc trois coordonnées
             if (Existe(SIG33) != 0) 
               l_sigma = 6 ; // c'est un tenseur d'ordre 3
                             // donc 6 coordonnées
           };
       if (Sig.Taille() != l_sigma) Sig.Change_taille(l_sigma);
       int fin = position + l_sigma-1; int j = 1;
       for (int i=position;i<= fin; i++,j++)
          Sig(j) = tab_ddl(i).Valeur();
       return true;        
     } 
    else
       return false; // pas de contrainte         

   };
       
// 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&  Noeud::Contrainte(TenseurHB& Sig)
  { int position = Existe(SIG11);
    if (position == 0)  return Sig; // cas où il n'y a pas de contrainte
    // ----- sinon on remplit les composantes du tenseur ------
    int l_sigma = Sig.Dimension(); // dimension des contraintes
    #ifdef MISE_AU_POINT	 // vérif des dimensions pour le debug
      // comme position n'est pas nulle la dimension dans les ddl est au moins 1
      int dimm = 1; 
      if (Existe(SIG22) != 0) 
           { dimm = 2 ; // c'est au moins un tenseur d'ordre 2
             if (Existe(SIG33) != 0) 
               dimm = 3 ; // c'est un tenseur d'ordre 3
           };
      if (l_sigma != dimm)
        { cout << "\nErreur : dimensions du tenseur d'entrée incorrecte Sig = " << dimm << " !\n";
          cout << " Noeud::Contrainte(TenseurHB& Sig)\n";
          Sortie(1);
        };
    #endif
    switch (l_sigma)
     { case 1 : // cas à une dimension
             Sig.Coor(1,1) = tab_ddl(position).Valeur();
             break;	
       case 2 : // cas à 2 dimension
             Sig.Coor(1,1) = tab_ddl(position).Valeur();
             Sig.Coor(2,2) = tab_ddl(position+1).Valeur();
             Sig.Coor(1,2) = tab_ddl(position+2).Valeur();
             Sig.Coor(2,1) = tab_ddl(position+2).Valeur();
             break;	
       case 3 : // cas à 3 dimension
             Sig.Coor(1,1) = tab_ddl(position).Valeur();
             Sig.Coor(2,2) = tab_ddl(position+1).Valeur();
             Sig.Coor(3,3) = tab_ddl(position+2).Valeur();
             Sig.Coor(1,2) = tab_ddl(position+3).Valeur();Sig.Coor(2,1) = Sig(1,2);
             Sig.Coor(2,3) = tab_ddl(position+4).Valeur();Sig.Coor(3,2) = Sig(2,3);
             Sig.Coor(1,3) = tab_ddl(position+5).Valeur();Sig.Coor(3,1) = Sig(1,3);
             break;	
       default :
              { cout <<"\n Erreur, la dimension du tenseur Sig n'est pas correcte ";
                cout << "Noeud::Contrainte(TenseurHB& Sig)" << endl;
                Sortie (1);
               } 
     };
    return Sig;
  };
       
// lecture sur le flot d'entée de déplacement
// et mise à jour des positions à t et t+dt correspondantes
void Noeud::LectureDeplacements(UtilLecture *entreePrinc)
  { // récup de la dimension
    // définition du déplacement
    Coordonnee dep = *coord0;
    // lecture brut des coordonnées du déplacement sans la dimension
    dep.Lecture(*entreePrinc);
    // on ajoute aux coordonnées initiales pour avoir celles à t
    dep += (*coord0);
    // on insert les coordonnées à t qui sont créées si elles n'existent pas
    // elles ont le statut inactif par défaut
    Insert_coord1(dep);
  };
	 
//----- 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 Noeud::Lecture_base_info(ifstream& ent,int cas)
 { // traitement en fonction du cas 
   switch (cas)
    { case 1 : // ------- on récupère tout -------------------------
       { ent >> (*this) ;
         break;
       }
      case  2 : // ----------- récup uniquement de se qui varie --------------------
       { //  ici se sont les degrés de liberté
         string toto;int nb;
         ent >> toto >>  nb;
         #ifdef MISE_AU_POINT	 // vérification du numéro
          if (nb != num_noeud ) 
           { cout << "\nErreur : numero de noeud lu  : " << nb 
                  << " au lieu de " << num_noeud << " \n";;
             cout << " Noeud::Lecture_base_info";
             Sortie(1);
           };
         #endif
  /*       // ici on ne redimentionne pas, 
  ///       // cela signifie que le nombre de ddl augmente mais ne diminue pas !
  ///       Tableau<Ddl > * pt_tableau = tab_ddl.New_en_lecture_si_taille_superieur_a_lire(ent);
  ///       // on regarde si le tableau a été redimensionné
  ///       if (pt_tableau != NULL)
  ///         // cas d'une redimension on ajoute les ddl
  ///         PlusTabDdl(*pt_tableau); */

         // le code précédent pose des pb lorsque les ddl à lire sont différents de ceux existants
         // donc systématiquement, on en crée des nouveaux et on met à jour 
         Tableau<Ddl >  tableau;
         tableau.Entree(ent);
         // on ajoute les ddl
         PlusTabDdl(tableau);

         // on recopie les valeurs à t 
         int taille_tabddl=tab_ddl.Taille();
         
         // en fait ce n'est pas la peine, ça a été fait dans PlusTabDdl !!
         
         // cas de valeur à tdt
         if (tab_tdt.Taille() != 0)
           {for (int i=1;i<=taille_tabddl;i++)
                tab_tdt(i) = tab_ddl(i).Valeur();
           };
        
         // cas d'une base locale éventuelle
         {int existe_base;
          ent >> existe_base >> toto;
          if (existe_base == 1)
           {if (baseB == NULL) {baseB=new BaseB();};
            ent >> toto >> (*baseB);
            // dans le cas où la grandeur à t n'existe pas
            // on l'a crée et on lui donne la valeur de tdt
            // sinon on fait une affectation, pour redémarrer avec quelque chose de correcte à t
            if (baseB_t == NULL)
              {baseB_t=new BaseB(*baseB);}
            else // sinon on affecte
              {(*baseB_t) = (*baseB);};
            // cas à 0
            if (baseB_0 == NULL)
              {baseB_0=new BaseB(*baseB);};
            // sinon on ne fait rien car la base est sensée avoir été correctement
            // définit au départ
           };

         };
        
         break;
       }
    default :
	     { cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
	       cout << "Noeud::Ecriture_base_info(ofstream& sort,int cas)"
			          << " cas= " << cas << endl;
	       Sortie(1);
	     }
    }
  };

// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Noeud::Ecriture_base_info(ofstream& sort,int cas)
 { // traitement en fonction du cas 
   switch (cas)
   { case 1 : // ------- on sauvegarde tout -------------------------
      { sort << (*this) << "\n";
        break;
      }
     case  2 : // ----------- sauvegarde uniquement de se qui varie --------------------
      { //  ici se sont les degrés de liberté
        sort << "Noeud " << num_noeud << " ";
        sort << tab_ddl ;
        if (baseB != NULL)
          {sort << " 1 baseLoc: " << (*baseB);}
        else {sort << " 0 baseLoc: "; };

        sort << "\n";
       
        break;
      }
    default :
	     { cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
	       cout << "Noeud::Ecriture_base_info(ofstream& sort,int cas)"
			          << " cas= " << cas << endl;
	       Sortie(1);
	     }
   };
	// pour l'instant on ne sauvegarde pas les ddl_étendu et les type_quelconque car on considère
	// que ce sont des résultats et non pas des données indispensables.
 // idem pour enu_liaison et noeud_lier, qui sont liées aux conditions limites
 // A priori, c'est infos sont reconstruites
	// à chaque démarrage 
	 
};
   
