// FICHIER : Noeud2.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"

// 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 Noeud::AjoutTabTypeQuelconque(const Tableau <TypeQuelconque > & tab_t_quel)
 {// on passe en revue le tableau transmis 
  int tailt = tab_t_quel.Taille();
  int tailtab = tab_type_quel.Taille();
  // pour ne faire qu'une passe on crée un tableau d'existence
  Tableau <int> tab_ex(tailt);
  int a_ajouter=0; // le nombre de grandeur à ajouter
  for (int i=1;i<=tailt;i++)
   { bool trouver = false;
     for (int j=1;j<=tailtab;j++)
     if (tab_type_quel(j).EnuTypeQuelconque()==tab_t_quel(i).EnuTypeQuelconque())
        {trouver = true;break;};
     if (!trouver)
        {a_ajouter++; tab_ex(i)=1;}; 
    };
  // dans le cas où il n'y a rien n'a ajouter on retourne  
  if (a_ajouter == 0) return;  
  // maintenant on ajoute vraiment
  tab_type_quel.Change_taille(tailtab+a_ajouter);
  update_type_quel.Change_taille(tailtab+a_ajouter); // =0 par défaut
  int compteur=1;
  for (int ii=1;ii<=tailt;ii++)
    {if (tab_ex(ii)==1) {tab_type_quel(tailtab+compteur).ChangeGrandeur(tab_t_quel(ii));compteur++;} };
  // on peut maintenant mettre en place l'adressage directe
  // ce qui permettra d'utiliser Existe(..) dans MiseAjour
  MiseAjourTypeQuelconque(); // mise en place de l'adressage directe    
  };
  
// cas d'une seule grandeur quelconque
void Noeud::AjoutUnTypeQuelconque(const TypeQuelconque & t_quel)
 {int tailtab = tab_type_quel.Taille();
  // on n'ajoute que si la grandeur n'existe pas déjà
  bool existe=false;
  for (int j=1;j<=tailtab;j++)
    if (tab_type_quel(j).EnuTypeQuelconque()==t_quel.EnuTypeQuelconque())
      {existe = true;break;};
  if (!existe)
   { tab_type_quel.Change_taille(tailtab+1);
     update_type_quel.Change_taille(tailtab+1,0); // =0 par défaut
     tab_type_quel(tailtab+1).ChangeGrandeur(t_quel);
     // on peut maintenant mettre en place l'adressage directe
     // ce qui permettra d'utiliser Existe(..) dans MiseAjour
     MiseAjourTypeQuelconque(); // mise en place de l'adressage directe    
    };
  };
  
// supprime une grandeur quelconque (si elle est présente)
void Noeud::SupprimeUnTypeQuelconque(const TypeQuelconque & t_quel)
 { // récup du type
   TypeQuelconque_enum_etendu en = t_quel.EnuTypeQuelconque();
   int nb=Existe(en);
   if ( nb != 0)
    {// dans le cas où la grandeur existe  on la supprime
     int tai=tab_type_quel.Taille();
     if ( update_type_quel(nb) != 0) nbTypeQ_update--;
     for (int i= nb;i<tai;i++)
      { tab_type_quel(i).ChangeGrandeur(tab_type_quel(i+1)); 
        update_type_quel(i)=update_type_quel(i+1);
       };
     tab_type_quel.Change_taille(tai-1);    
     update_type_quel.Change_taille(tai-1,0); // =0 par défaut
     // on met à jour le tableau de gestion d'indiçage indirecte
     MiseAjourTypeQuelconque();
     };
  };
// supprime un tableau de grandeurs quelconques (si elles sont présentes)
void Noeud::SupprimeTabTypeQuelconque(const Tableau <TypeQuelconque > & tab_t_quel)
 {// on passe en revue le tableau transmis 
  int tailt = tab_t_quel.Taille();
  int tailtab = tab_type_quel.Taille();
  // pour ne faire qu'une passe on crée un tableau d'existence
  Tableau <int> tab_in(tailtab);
  bool on_supprime=false;  
  for (int i=1;i<=tailt;i++)
   { // on passe en revue le tableau fourni
     int num = Existe(tab_t_quel(i).EnuTypeQuelconque());
     if (num != 0) 
       {tab_in(num)=1; 
        if ( update_type_quel(num) != 0) nbTypeQ_update--;
        on_supprime=true;};
    };
  // retour s'il n'y a rien à supprimer
  if (!on_supprime) return;  
  // maintenant on supprime vraiment
  int i=1; // pointeur des grandeurs restantes
  for (int j=1;i<=tailtab;i++,j++)
   { // on passe en revue
     if (tab_in(j)!=1)
      { // grandeur à garder
        tab_type_quel(i).ChangeGrandeur(tab_type_quel(j));
        update_type_quel(i)=update_type_quel(j);
        i++;
       };
     };
  // la valeur de i-1 = la taille à conserver
  tab_type_quel.Change_taille(i-1);   
  // on met à jour le tableau de gestion d'indiçage indirecte
  MiseAjourTypeQuelconque();
 };

// 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& Noeud::ModifGrandeur_quelconque(TypeQuelconque_enum_etendu enu)
 {  // récup de l'indice de la grandeur
    int indice = (*pos_Quelconque)(enu.Position());
    // si le type n'était pas updaté on met à jour les 2 indicateurs
    if (update_type_quel(indice) == 0) {update_type_quel(indice)=1; nbTypeQ_update++;}
    else                               {update_type_quel(indice)++; };
    return (tab_type_quel(indice));
  };

// signale que toutes les grandeurs quelconques sont non-updatées
void Noeud::Mise_non_update_grandeurs_quelconques()
 { int tailupdate = update_type_quel.Taille();
   for (int i=1;i<=tailupdate;i++) update_type_quel(i)=0;
   nbTypeQ_update=0; // reset du nombre total
  };      
  
// signale qu'une grandeur quelconque est non-updatées
// en particulier la grandeur en question ne sera pas sauvegarder dans base_info
void Noeud::Mise_non_update_grandeurs_quelconques(TypeQuelconque_enum_etendu enu)
 { // récup de l'indice
   int nb=Existe(enu);
   update_type_quel(nb)=0;
   nbTypeQ_update--; // met à jour du nombre total
  };        

// ajout d'un ddl étendu (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 Noeud::AjoutTabDdl_etendu(const Tableau <Ddl_enum_etendu > & t_ddletendu)
 {// on passe en revue le tableau transmis 
  int tailt = t_ddletendu.Taille();
  int tailtab = tab_ddletendu.Taille();
  // pour ne faire qu'une passe on crée un tableau d'existence
  Tableau <int> tab_ex(tailt,0);
  int a_ajouter=0; // le nombre de grandeur à ajouter
  int ttaill = tab_ddletendu.Taille();
  for (int i=1;i<=tailt;i++)
   { bool trouver = false;
     // on passe en revue le tableau actuel
     for (int j=1;j<=tailtab;j++)
     if (tab_ddletendu(j).DdlEnumEtendu()==t_ddletendu(i))
        {trouver = true;break;};
     if (!trouver)
        {a_ajouter++; tab_ex(i)=1;}; 
    };
  // dans le cas où il n'y a rien n'a ajouter on retourne  
  if (a_ajouter == 0) return;  
  // maintenant on ajoute vraiment
  tab_ddletendu.Change_taille(tailtab+a_ajouter);
  update_ddletendu.Change_taille(tailtab+a_ajouter,0); // =0 par défaut
  int compteur=1;
  for (int ii=1;ii<=tailt;ii++)
    {if (tab_ex(ii)==1) 
	   {tab_ddletendu(tailtab+compteur)=t_ddletendu(ii); compteur++;}; 
	  };
  // on peut maintenant mettre en place l'adressage directe
  // ce qui permettra d'utiliser Existe(..) dans MiseAjour
  MiseAjourDdl_etendu(); // mise en place de l'adressage directe    
  };
  
// cas d'un seul ddl étendu
void Noeud::AjoutUnDdl_etendu(const Ddl_enum_etendu & ddlenumetendu)
 {int tailtab = tab_ddletendu.Taille();
  // on n'ajoute que si la grandeur n'existe pas déjà
  bool existe=false;
  for (int j=1;j<=tailtab;j++)
    if (tab_ddletendu(j).DdlEnumEtendu()==ddlenumetendu)
      {existe = true;break;};
  if (!existe)
   { tab_ddletendu.Change_taille(tailtab+1);
     update_ddletendu.Change_taille(tailtab+1,0); // =0 par défaut
     tab_ddletendu(tailtab+1)=Ddl_etendu(ddlenumetendu);
     // on peut maintenant mettre en place l'adressage directe
     // ce qui permettra d'utiliser Existe(..) dans MiseAjour
     MiseAjourDdl_etendu(); // mise en place de l'adressage directe    
    };
  };
  
// supprime un ddl étendu (si il est présent)
void Noeud::SupprimeUnDdl_etendu(const Ddl_enum_etendu & ddletendu)
 { // récup du type
   int nb=Existe_ddlEtendu(ddletendu);
   if ( nb != 0)
    {// dans le cas où la grandeur existe  on la supprime
     int tai=tab_ddletendu.Taille();
     if ( update_ddletendu(nb) != 0) nbddletendu_update--;
     for (int i= nb;i<tai;i++)
      { tab_ddletendu(i)=tab_ddletendu(i+1); 
        update_ddletendu(i)=update_ddletendu(i+1);
       };
     tab_ddletendu.Change_taille(tai-1); 
     update_ddletendu.Change_taille(tai-1);  
     // on met à jour le tableau de gestion d'indiçage indirecte
     MiseAjourDdl_etendu();
     };
  };
// supprime un tableau de grandeurs quelconques (si elles sont présentes)
void Noeud::SupprimeTabDdl_etendu(const Tableau <Ddl_enum_etendu > & t_ddletendu)
 {// on passe en revue le tableau transmis 
  int tailt = t_ddletendu.Taille();
  int tailtab = tab_ddletendu.Taille();
  // pour ne faire qu'une passe on crée un tableau d'existence
  Tableau <int> tab_in(tailtab);
  bool on_supprime=false;  
  for (int i=1;i<=tailt;i++)
   { // on passe en revue le tableau fourni
     int num = Existe_ddlEtendu(t_ddletendu(i));
     if (num != 0) 
       {tab_in(num)=1; 
        if ( update_type_quel(num) == 1) nbTypeQ_update--;
        on_supprime=true;};
    };
  // retour s'il n'y a rien à supprimer
  if (!on_supprime) return;  
  // maintenant on supprime vraiment
  int i=1; // pointeur des grandeurs restantes
  for (int j=1;i<=tailtab;i++,j++)
   { // on passe en revue
     if (tab_in(j)!=1)
      { // grandeur à garder
        tab_ddletendu(i)=tab_ddletendu(j);
        update_ddletendu(i)=update_ddletendu(j);
        i++;
       };
     };
  // la taille à conserver
  update_ddletendu.Change_taille(i-1); 
  tab_ddletendu.Change_taille(i-1);  
  // on met à jour le tableau de gestion d'indiçage indirecte
  MiseAjourDdl_etendu();
 };

// récupération d'un ddl étendu pour modification
// après l'appel de cette méthode, le ddl étendu est réputée updaté
Ddl_etendu& Noeud::ModifDdl_etendu(const Ddl_enum_etendu& ddletendu)
 {  // récup de l'indice de la grandeur
    int indice = Existe_ddlEtendu(ddletendu);
    // si le type n'était pas updaté on met à jour les 2 indicateurs
    if (update_ddletendu(indice) == 0) {update_ddletendu(indice)=1; nbddletendu_update++;}
    else                               {update_ddletendu(indice)++;};
    return (tab_ddletendu(indice));
  };
  
// signale que toutes les ddl étendus sont non-updatées
void Noeud::Mise_non_update_Ddl_etendu()
 { int tailupdate = update_ddletendu.Taille();
   for (int i=1;i<=tailupdate;i++) update_ddletendu(i)=0;
   nbddletendu_update=0; // reset du nombre total
  };        
  
// signale qu'un Ddl_etendu est non-updatées
// en particulier le Ddl_etendu en question ne sera pas sauvegarder dans base_info
void Noeud::Mise_non_update_Ddl_etendu(Ddl_enum_etendu ddlenumetendu)
 { // récup de l'indice de la grandeur
   int indice = Existe_ddlEtendu(ddlenumetendu);
   update_ddletendu(indice)=0;
   nbddletendu_update--; // met à jour du nombre total
  };        

// ------------------------  procedures protegees ------------------------

		
// liaison des ddl et des deplacement a t et 0 
// nb = le numero correspondant aux début des coordonnees dans les tableaux
// de ddl 
void Noeud::Liaison_t(int nb)
  { // cas ou l'on est en coordonnees entrainees
    // 1) cas des coord0
    // positionnement a l'adresse des coordonnees
    double * pt = &(tab_0(nb));
    if (coord0 != NULL) 
     // si les coordonnees existent deja on les sauvegarde
     // et on remplace les valeurs des ddl par les coor
      { Coordonnee truc(*coord0);
        delete coord0;
        // on passe un pointeur donc il n'y a pas de creation de memoire
        // dans le new
        coord0 = new Coordonnee(ParaGlob::Dimension(),pt);
        *coord0 = truc;
       }
     else
      // sinon on cree coord0 a la meme place que les ddl a t = 0
       {coord0 = new Coordonnee(ParaGlob::Dimension(),pt);
        } 
    // 2) cas des coord1 
    int dim = ParaGlob::Dimension();
    if (coord1.Taille() == 0)
      { // il faut construire le tableau
        coord1.Change_taille(dim);
        for (int ii=1;ii<=dim;ii++)
           coord1(ii) = &(tab_ddl(nb+ii-1).Valeur());
       }
    else if (coord1(1) == NULL)
       // tableau existant mais non affecte 
        for (int ii=1;ii<=dim;ii++)
           coord1(ii) = &(tab_ddl(nb+ii-1).Valeur());
    else 
      // tableau existant et affecte, donc ici pas de pb a priori car lorsque les coordonnées à t
      // sont affectées elles le sont obligatoirement sur le tableau de ddl
      //les valeurs du tableau 
      // de coordonnées vont etre misent a la place des valeurs de ddl
        for (int ii=1;ii<=dim;ii++)
          { double sa = *(coord1(ii));
            // on ne supprime pas la valeur pointée car il n'y a jamais eu de new avec
            // l'allocation de coord1
            // on réaffecte
            coord1(ii) = &(tab_ddl(nb+ii-1).Valeur());
            // récup de la valeur
            *(coord1(ii)) = sa;
           } 
   };
		
// liaison des ddl et des deplacement a tdt seulement 
// nb = le nb du début des deplacement dans les ddl
void Noeud::LiaiSeuletdt(int nb)
  { 
    // positionnement a l'adresse des coordonnees
    double * pt = &(tab_tdt(nb));
    if (coord2 != NULL) 
     // si les coordonnees existent deja on les sauvegarde
     // et on remplace les valeurs des ddl par les coor
      { Coordonnee truc(*coord2);
        delete coord2;
        coord2 = new Coordonnee(ParaGlob::Dimension(),pt);
        *coord2 = truc;
       }
     else
      // sinon on cree coord2 a la meme place que les ddl a tdt
        {coord2 = new Coordonnee(ParaGlob::Dimension(),pt);
         }
           
   };

// liaison des ddl et des deplacement a t,tdt et 0 
// nb = le nb du début des deplacement dans les ddl
void Noeud::Liaison_tdt(int nb)
  { // cas ou l'on est en coordonnees entrainees
    // 1) cas des coord0 et des coord1
    Liaison_t(nb);
    // 2) cas des coord2
    LiaiSeuletdt(nb);
   };

// mise a jour des tableaux et des liaisons
void Noeud::MiseAjour()
  { // tout d'abord on regarde si tab_0 est correctement dimensionne
    int t1 = tab_0.Taille();
    int t2 = tab_ddl.Taille();
    if (t1 != t2)
    // cas ou le tableau de ddl a ete agrandi
    // on change la taille des tableaux. 
    // on sauvegarde les coordonnées à 0 si elles sont liées
    if (Existe(X1))
     {  Coordonnee truc(*coord0);
        delete coord0;
        coord0 = new Coordonnee(truc);
      };
    // maintenant on peut changer les tableaux
    { tab_0.Change_taille(t2);
      for (int i=t1+1;i<=t2;i++)
         tab_0(i) = tab_ddl(i).Valeur();
      if ( tab_tdt.Taille() != 0)
        // cas ou le tableau tdt est en service
        tab_tdt.Change_taille(t2);
     }       
    // on regarde ensuite s'il y a des liaisons entre ddl et deplacements
    int nb = Existe(X1);
    if (nb != 0) // cas ou il y a une liaison ddl coordonnées
     {double * pt0 = &((*coord0)(1));
      if (pt0 != &(tab_0(nb)))
        // cas d'une mauvaise liaison, on remet à jour 
        if (tab_tdt.Taille() == 0) // choix t ou t et tdt         
          Liaison_t(nb);
        else
          Liaison_tdt(nb);  
      else if (tab_tdt.Taille() != 0)
        // cas d'une bonne liaison pour t=0, reste le cas à tdt
         { if (coord2 != NULL)
             // cas ou les coord2 sont deja affectees
             { double * pt2 = &((*coord2)(1)); 
               if  (pt2 != &(tab_tdt(nb))) 
                  LiaiSeuletdt(nb); // cas pas affectees au bonne endroit
              }
           else // cas où il n'y avait pas encore de liaison
             LiaiSeuletdt(nb); // on affecte les coordonnees       
          }
     }         
   };         
		
// 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 Noeud::MiseAjourEnum()
 { // tout d'abord on regarde si le dernier tableau construit dans la liste
   // convient, car ce sera le cas pour le cas courant
   // le dernier tableau est positionné en début de liste.
   list <Tableau <int > >::iterator ideb = list_tab_enum.begin();
   list <Tableau <int > >::iterator iancien = pos_enum;
   int taille = tab_ddl.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_enum.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(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 = 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(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 <Tableau <int > >::iterator ifin = list_tab_enum.end();
     list <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_enum.push_front(tab_indi_enum);  // allocation
        // on attribue le nouveau pointage
        pos_enum = list_tab_enum.begin(); // sauvegarde de la position 
       }
     else // cas où on a trouvé un tableau dans la liste
      pos_enum = iter; 
    } 
   // --- gestions des tableaux ----  
   // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau
   //    (permet de supprimer les tableaux qui ne servent plus)
   // on regarde si pos_enum était déjà attribué
   if (iancien != list_tab_enum.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_enum.erase(iancien);
      else
      // sinon on décrémente le compteur
            ((*iancien)(NbEnum_ddl()+1))--;
      // maintenant on s'occupe du nouveau pointage
      ((*pos_enum)(NbEnum_ddl()+1))++;
      } 
   else
   // c'est la première initialisation
   // on incrémente le compteur du tableau
      ((*pos_enum)(NbEnum_ddl()+1))++;
  };
		
// mise a jour du tableau des ddl de variable actives
// et du tableau de ddl actives (variables et données)
void Noeud::MiseAjourActif()
 { // ------- cas des variables uniquement --------
   // tout d'abord on regarde le nombre de ddl actif
   int nbddlactif = 0;
   int tab_ddlTaille = tab_ddl.Taille();
   for (int i = 1; i<=tab_ddlTaille; i++)
     if ((tab_ddl(i).Service())&&(tab_ddl(i).UneVariable())) nbddlactif++;
   // dimensionnement du tableau de pointeur
   if (tab_var_actives.Taille() != nbddlactif) tab_var_actives.Change_taille(nbddlactif);
   // remplissage du tableau
   int indice  = 1;
   for (short int i = 1; i<=tab_ddlTaille; i++)
     if ((tab_ddl(i).Service())&&(tab_ddl(i).UneVariable())) 
       {tab_var_actives(indice) = i; indice++; }
   // -------- cas des données et des variables ----------
   nbddlactif = 0;
   for (int i = 1; i<=tab_ddlTaille; i++)
     if (tab_ddl(i).Service()) nbddlactif++;
   // dimensionnement du tableau de pointeur
   if (tab_actif.Taille() != nbddlactif) tab_actif.Change_taille(nbddlactif);
   // remplissage du tableau
   indice  = 1;
   for (short int i = 1; i<=tab_ddlTaille; i++)
     if (tab_ddl(i).Service()) 
       {tab_actif(indice) = i; indice++; }

  };        
   
// lecture des grandeurs quelconques sur flot
void Noeud::Lecture_grandeurs_quelconque(istream & ent)
 {  // la lecture est longue, ne sert que pour la visualisation en faite
    string nom;
    ent >> nom >> nbTypeQ_update;
    if (nbTypeQ_update != 0) // lecture que s'il y a des types updatées enregistrées
     { // tout d'abord on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes
       TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE);
       // lecture de l'entête et récup d'enu
       EnuTypeQuelParticulier enu = pour_lire.Lecture_un(ent);
       // on regarde si ce type quelconque existe déjà
       int indice = Indice_grandeur_quelconque(pour_lire.EnuTypeQuelconque());
       if (indice == 0)
        { // cas d'une grandeur qui n'existe pas déjà, on la crée 
          int tailtab = tab_type_quel.Taille();tailtab++;
          tab_type_quel.Change_taille(tailtab);
          update_type_quel.Change_taille(tailtab); // =0 par défaut
          // création d'une grandeur associée et lecture des information sur le flot
          TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent);
          // création d'un type quelconque
          TypeQuelconque tq(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur);
          delete grandeur; // car il ne sert plus à rien
          // affectation    
          tab_type_quel(tailtab)=tq;update_type_quel(tailtab)=1; //normalement update
         }
       else
        { // cas d'une grandeur qui existe déjà
          ent >> tab_type_quel(indice);update_type_quel(indice)=1; //normalement update
         };  
     };
  };
  
// écriture des grandeurs quelconques sur flot
void Noeud::Ecriture_grandeurs_quelconque(ostream & sort) const
 {  // on ne sauvegarde que les grandeurs updatées et qui sont prévu pour une sauvegarde
    sort << " G_quel " << nbTypeQ_update << " "; // en tête et nombre de grandeurs updatées
    int tailupdate = update_type_quel.Taille();
    for (int i=1;i<=tailupdate;i++) 
     { if (update_type_quel(i) != 0) sort << tab_type_quel(i) << " ";};
  };
  
// récupe de l'indice d'une grandeur quelconque
// si la grandeur n'existe pas -> ramène 0
int Noeud::Indice_grandeur_quelconque(TypeQuelconque_enum_etendu a)
 { int tailtab = tab_type_quel.Taille();
   for (int i=posi_type_quel;i<=tailtab;i++)
     { if ( tab_type_quel(i).EnuTypeQuelconque() == a)
        { posi_type_quel=i; return i;}
      };
   // cas on la grandeur a chercher est peut-être au début du tableau
   for (int j=1;j< posi_type_quel;j++)
     { if ( tab_type_quel(j).EnuTypeQuelconque() == a)
        { posi_type_quel=j;  return j;}
      };
   // cas où l'on n'a pas trouvé la grandeur
   return 0;     
  };

// mise a jour  de l'adressage via l'identificateur d'énumération
// c'est-à-dire la gestion via list_tab_typeQuelconque et popos_Quelconque
// ne doit être appelé que si l'on a introduit un nouveau type quelconque !!
// ou changé l'ordre etc..
void Noeud::MiseAjourTypeQuelconque()
 { // la méthode sert à mettre à jour les différents indicateurs d'adressage rapides
   // 1-- s'il n'y a pas de type quelconque, on regarde si le pointeur de tableau a changé
	  //     utilisé par exemple par le destructeur, ou les constructeurs
   
   // on récupère le nombre maxi de type de grandeurs quelconques existantes actuellement
   // (ce nombre n'est pas forcément fixe pendant le calcul, on peut avoir de nouvelle grandeur qui
   //  sont définit pendant le calcul : typiquement associée à de nouvelles grandeurs globales créées par
   //  l'utilisateur: ex: le calcul d'une intégrale)
   int nbmaxTypeQ = TypeQuelconque_enum_etendu::NBmax_TypeQuelconque_enum_etendue();
   if (tab_type_quel.Taille() == 0) // -> pas de type quelconque stocké
    { if (pos_Quelconque == list_tab_typeQuelconque.end()) 
        // cela signifie qu'il n'y a jamais eu de type quelconque pour tous les noeuds
        // et qu'il n'y a rien à faire, retour directe
        {return;}
      else // sinon c'est le cas d'une destruction de types quelconques
        // on met à jour les indicateurs ad hoc
        { // l'avant dernier  élément du tableau contient le nombre de noeud qui utilise ce type
          int taille_pos_quelconque = (*pos_Quelconque).Taille();
// on n'utilise pas  nbmaxTypeQ car il peut varier pendant le calcul         if ((*pos_Quelconque)(nbmaxTypeQ+1) == 1)
          if ((*pos_Quelconque)(taille_pos_quelconque-1) == 1)
             // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau
              list_tab_typeQuelconque.erase(pos_Quelconque);
          else
              // sinon on décrémente le compteur
              ((*pos_Quelconque)(taille_pos_quelconque-1))--;
          // puis on met à jour le pointeur
          pos_Quelconque = list_tab_typeQuelconque.end(); // -> veut dire pas de tableau associé	
                // et retour
          return;
        };
    };
  
   // 2-- la suite concerne le cas où des types quelconque existent
   // tout d'abord on regarde si le dernier tableau construit dans la liste
   // convient, car ce sera le cas pour le cas courant
   // le dernier tableau est positionné en début de liste.
   list <Tableau <int > >::iterator ideb = list_tab_typeQuelconque.begin();
   list <Tableau <int > >::iterator iancien = pos_Quelconque;
   int taille = tab_type_quel.Taille(); // nombre d'éléments quelconques actuellement stocké
   // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position
   bool okk = true;
   // le test n'est effectué que si la liste n'est pas vide
   if (list_tab_typeQuelconque.size() != 0)
    { // d'abort la taille, on compte le nombre d'élément non nul  
      int ttail = (*ideb).Taille();// les deux dernières valeurs = le nombre de noeuds associés, le nombre de quelconque à considérer
      int ttaile = (*ideb)(ttail); // == le nombre de quelconque qui sont considérer
      if (taille != ttaile) // -> là c'est sûr que cela ne convient pas car déjà le nombre est différent
         okk = false;
      else // sinon on test les contenues
       // maintenant le contenu 
       for (int i = 1; i<= taille;i++)
         if( (*ideb)(tab_type_quel(i).EnuTypeQuelconque().Position()) != i)
           { okk = false; break;}
    }
   else // si n'existe pas encore, il faut le créer
    {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_Quelconque = ideb;} // cas ou on n'a pas à faire de création
   else // ---- cas où on passe en revue la liste : cas d'une création -----
    // ici la procédure est plus longue, mais normalement elle ne sera
    // utilisé que peut souvent
    {  
     // on reconstruit un tableau d'adressage indirect des types quelconques
     // la taille du tableau d'adressage est celui du nombre maxi
     // de type quelconques différent (donc certain ne serviront pas)
     // les données du tableau sont initialisées à 0, ainsi si l'on
     // cherche à utiliser un type quelconque 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_TypeQ(nbmaxTypeQ+2,0);
     for (int i=1;i<=taille;i++)
       tab_indi_TypeQ(tab_type_quel(i).EnuTypeQuelconque().Position())=i;
     // on enregistre la taille  
     tab_indi_TypeQ(nbmaxTypeQ+2) = taille;  
     // maintenant on va regarder si ce tableau existe dans la liste
     list <Tableau <int > >::iterator ifin = list_tab_typeQuelconque.end();
     list <Tableau <int > >::iterator iter;
     bool trouver = false;
     for (iter = ideb;ideb!= ifin;ideb++)
       if ((*iter) == tab_indi_TypeQ)
         { 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_typeQuelconque.push_front(tab_indi_TypeQ);  // allocation
        // on attribue le nouveau pointage
        pos_Quelconque = list_tab_typeQuelconque.begin(); // sauvegarde de la position 
       }
     else // cas où on a trouvé un tableau dans la liste
      pos_Quelconque = iter; 
    }; 
   // --- gestions des tableaux ----  
   // l'idée est ici la suivante: si le pointeur de tableau: pos_Quelconque a changé par rapport à iancien
   // et que iancien était associé à un seul noeud, alors il faut le supprimer car il n'est plus associé à aucun noeud
   // évidemment ceci n'est a considérer que si iancien pointait sur quelque chose de valide

   int taille_pos_quelconque = (*pos_Quelconque).Taille(); // récup de la taille actuelle
   // on regarde si pos_Quelconque était déjà attribué
   // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau
   //    (permet de supprimer les tableaux qui ne servent plus)
	  if (iancien != pos_Quelconque)
    { // cas où on a changé de pointeur de tableau
	     if (iancien != list_tab_typeQuelconque.end())
        // cas où ce n'est pas  la première initialisation
        {int taille_pos_ancien = (*iancien).Taille();
         if ((*iancien)(taille_pos_ancien-1) == 1)
         // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau
                 list_tab_typeQuelconque.erase(iancien);
         else
         // sinon on décrémente le compteur
                 ((*iancien)(taille_pos_ancien-1))--;
         // maintenant on s'occupe du nouveau pointage
         ((*pos_Quelconque)(taille_pos_quelconque-1))++;
         } 
      else
        // c'est la première initialisation
        // on incrémente le compteur du tableau: -> on ajoute 1 noeud
        ((*pos_Quelconque)(taille_pos_quelconque-1))++;
	   };
	 // si iancien == pos_Quelconque, il n'y a pas eu de nouveau noeud ajouté, donc rien à faire
 };

// --- cas des Ddl_enum_etendu ----

// lecture des Ddl_enum_etendu sur flot
void Noeud::Lecture_Ddl_etendu(istream & ent)
 {  string nom;
    ent >> nom >> nbddletendu_update;
    tab_ddletendu.Change_taille(nbddletendu_update);
    ent >> nom >> update_ddletendu;
    int tailupdate = update_ddletendu.Taille();
    for (int i=1;i<=tailupdate;i++) 
     { if (update_ddletendu(i) != 0) ent >> tab_ddletendu(i) ;};
  }; 

// écriture des Ddl_enum_etendu sur flot
void Noeud::Ecriture_Ddl_etendu(ostream & sort) const
 {  // on ne sauvegarde que les grandeurs updatées et qui sont prévu pour une sauvegarde
    sort << "\n G_ddletendu " << nbddletendu_update << " "; // en tête et nombre de grandeurs updatées
    // écriture du tableau d'update
    sort << "\n update_ddletendu: "<< update_ddletendu << " ";
    // sortie conditionnelle de tab_ddletendu 
    int tailupdate = update_ddletendu.Taille();
    for (int i=1;i<=tailupdate;i++) 
     { if (update_ddletendu(i) != 0) sort << tab_ddletendu(i) << " ";};
  };

// récupe de l'indice d'un Ddl_enum_etendu
// si la grandeur n'existe pas -> ramène 0
int Noeud::Indice_Ddl_etendu(const Ddl_enum_etendu& a)
 { int tailtab = tab_ddletendu.Taille();
   for (int i=posi_ddletendu;i<=tailtab;i++)
     { if ( tab_ddletendu(i).Const_DdlEnumEtendu() == a)
        { posi_ddletendu=i; return i;}
      };
   // cas ou la grandeur a chercher est peut-être au début du tableau
   for (int j=1;j< posi_ddletendu;j++)
     { if ( tab_ddletendu(j).Const_DdlEnumEtendu() == a)
        { posi_ddletendu=j;  return j;}
      };
   // cas où l'on n'a pas trouvé la grandeur
   return 0;     
  };

// 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_enum_etendu !!
// ou changé l'ordre etc..
void Noeud::MiseAjourDdl_etendu() 
 { // la méthode sert à mettre à jour les différents indicateurs d'adressage rapides
   // 1-- s'il n'y a pas de ddl étendue, on regarde si le pointeur de tableau a changé 
	//     utilisé par exemple par le destructeur, ou les constructeurs
   int nbmaxddleten = Ddl_enum_etendu::NBmax_ddl_enum_etendue();
	if (tab_ddletendu.Taille() == 0)
	 { if (pos_ddletendu == list_tab_ddletendu.end()) 
	     // cela signifie qu'il n'y a jamais eu de ddl étendue et qu'il n'y a rien à faire, retour directe
		  {return;}
		else // sinon c'est le cas d'une destruction des ddl étendue
		  // on met à jour les indicateurs ad hoc
		  { if ((*pos_ddletendu)(nbmaxddleten+1) == 1)
           // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau
            list_tab_ddletendu.erase(pos_ddletendu);
          else
            // sinon on décrémente le compteur
            ((*pos_ddletendu)(nbmaxddleten+1))--;
			 // puis on met à jour le pointeur 
			 pos_ddletendu = list_tab_ddletendu.end(); // -> veut dire pas de tableau associé	
          // et retour
			 return;
		  };
	 };
  
   // 2-- la suite concerne le cas où il y a des ddl étendue
	// tout d'abord on regarde si le dernier tableau construit dans la liste
   // convient, car ce sera le cas  courant
   // le dernier tableau est positionné en début de liste.
   list <Tableau <int > >::iterator ideb = list_tab_ddletendu.begin();
   list <Tableau <int > >::iterator iancien = pos_ddletendu;
   int taille = tab_ddletendu.Taille();
   // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position
   bool okk = true; // init
   // le test n'est effectué que si la liste n'est pas vide
   if (list_tab_ddletendu.size() != 0)
    { // d'abort la taille, on compte le nombre d'élément non nul 
	   int ttail = (*ideb).Taille(); // les deux dernières valeurs = le nombre de noeuds associés, le nombre de ddl enum étendu à considérer 
      int ttaile = (*ideb)(ttail); 
      if (taille != ttaile)
         okk = false;
      else 
       // maintenant le contenu 
       for (int i = 1; i<= taille;i++)
         if( (*ideb)(tab_ddletendu(i).Const_DdlEnumEtendu().Position()) != 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_ddletendu = ideb;
   else // ---- cas où on passe en revue la liste -----
    // ici la procédure est plus longue, mais normalement elle ne sera
    // utilisé que peu souvent
    {  
     // on reconstruit un tableau d'adressage indirect des ddl étendu
     // la taille du tableau d'adressage est celui du nombre maxi
     // de ddl étendu différents (donc certain ne serviron pas)
     // les données du tableau sont initialisées à 0, ainsi si l'on
     // cherche à utiliser un ddl étendu 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_ddletendu(nbmaxddleten+2,0);
     for (int i=1;i<=taille;i++)
       tab_indi_ddletendu(tab_ddletendu(i).Const_DdlEnumEtendu().Position())=i;
     // on enregistre la taille  
     tab_indi_ddletendu(nbmaxddleten+2) = taille;  
     // maintenant on va regarder si ce tableau existe dans la liste
     list <Tableau <int > >::iterator ifin = list_tab_ddletendu.end();
     list <Tableau <int > >::iterator iter;
     bool trouver = false;
     for (iter = ideb;ideb!= ifin;ideb++)
       if ((*iter) == tab_indi_ddletendu)
         { 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_ddletendu.push_front(tab_indi_ddletendu);  // allocation
        // on attribue le nouveau pointage
        pos_ddletendu = list_tab_ddletendu.begin(); // sauvegarde de la position 
       }
     else // cas où on a trouvé un tableau dans la liste
      pos_ddletendu = iter; 
    }; 
   // --- gestions des tableaux ----  
	// l'idée est ici la suivante: si le pointeur de tableau: pos_ddletendu a changé par rapport à iancien
	// et que iancien était associé à un seul noeud, alors il faut le supprimer car il n'est plus associé à aucun noeud
	// évidemment ceci n'est a considérer que si iancien pointait sur quelque chose de valide
	
   // on regarde si pos_ddletendu était déjà attribué
   // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau
   //    (permet de supprimer les tableaux qui ne servent plus)
	if (iancien != pos_ddletendu)
    { // cas où on a changé de pointeur de tableau
	   if (iancien != list_tab_ddletendu.end())
       // cas où ce n'est pas  la première initialisation
       {if ((*iancien)(nbmaxddleten+1) == 1)
        // cas où c'est le dernier noeud qui pointe sur ce tableau
        // on supprime le tableau
            list_tab_ddletendu.erase(iancien);
        else
        // sinon on décrémente le compteur
            ((*iancien)(nbmaxddleten+1))--;
        // maintenant on s'occupe du nouveau pointage
		  ((*pos_ddletendu)(nbmaxddleten+1))++;
       } 
      else
       // c'est la première initialisation
       // on incrémente le compteur du tableau
       ((*pos_ddletendu)(nbmaxddleten+1))++;
	  };
	 // si iancien == pos_ddletendu, il n'y a pas eu de nouveau noeud ajouté, donc rien à faire
  };

// 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 Noeud::OrdonneDdlMemeFamille(const Ddl& a)
{ // on ne traite que si la dimension est supérieur à 1 ou que le ddl fait partie d'une famille
  if ((ParaGlob::Dimension()>1)&&FoncDim(a.Id_nom())) 
  	{Enum_ddl enu=a.Id_nom(); int dim = ParaGlob::Dimension();// pour simplifier
  	 // On parcourt le tableau pour trouver les autres ddl de la même famille
  	 // et on en profite pour ordonner les ddl
  	 Tableau<int> ptin(dim); int irecup=0;
  	 int taille=tab_ddl.Taille();
  	 for (int i=0; i<= taille-1;i++)
  	  if (Meme_famille(tab_ddl(i).Id_nom(),enu))
  	  	{if (tab_ddl(i).Id_nom() > enu)
  	  	     Permutation_2ddl(i,taille);
  	  	irecup++; ptin(irecup)=i;
  	  	};
  	 // -- maintenant les ddl de la même famille sont dans un ordre croissant, il reste
  	 // -- à les mettre à suivre 	
  	 // on continu que si effectivement il y a des autre ddl de la même famille
  	 if (irecup == 0)  return; // retour car aucun ddl de la meme famille
  	 // on traite en fonction de irecup  	 
  	 if (irecup == 1)
  	 {// cas sympathique ou l'on a simplement à permutter deux positions du tableau
  	  Enum_ddl enu1=tab_ddl(ptin(irecup)).Id_nom();
  	  if (ptin(irecup)==taille-1)
  	  	{return;}// cas déjà à suivre 
  	  else // sinon on permutte le suivant de enu1 et enu
  	    {Permutation_2ddl(ptin(irecup)+1,taille);}
  	 }
  	 else // cas
		
};
	
void Noeud::OrdonneDdlMemeFamille(const Tableau<Ddl>& ta)
	{
		
	};
	
// permutation de deux ddl (sert pour OrdonneDdlMemeFamille)
void Noeud::Permutation_2ddl(const int& ipo1,cont int& ipo2)
 { // tout d'abord le ddl
   Ddl intir=tab_ddl(ipo1); 
   tab_ddl(ipo1)=tab_ddl(ipo2); tab_ddl(ipo2)=intir;
   // maintenant les valeurs à 0
   double xnia0=tab_0(ipo1);
   tab_0(ipo1)=tab_0(ipo2); tab_0(ipo2)=xnia0;
   // éventuellement les valeurs à tdt
   if (tab_tdt.Taille()!=0)
   	{ double xniatdt=tab_tdt(ipo1);
      tab_tdt(ipo1)=tab_tdt(ipo2); tab_tdt(ipo2)=xniatdt;
   	};
 }; */
	
// ordonner un tableau de ddl suivant un ordre croissant et avec des ddl à suivre
void Noeud::OrdonnerTableauDdl(Tableau<Ddl>& ta)
 { int tataille = ta.Taille();
   for (int i1=1;i1<=tataille;i1++)
   	{for (int j1=i1+1;j1<=tataille;j1++)
   	   if (ta(i1).Id_nom() > ta(j1).Id_nom())
   	   	{// il ne sont pas dans le bonne ordre on permutte
   	   	 Ddl intir = ta(i1); 
   	     ta(i1)=ta(j1);
   	     ta(j1)=intir;
   	   	}
   	}
 };

// liste des ddl (en famille) à ajouter
// (la liste est initialisée au début)
// recopie des ddl existant déjà
// change_donn_var indique si les ddl existant on été modifiée
void Noeud::ListeDdlAajouter(list<Ddl>& liDdl,Tableau<Ddl>& ta,bool& change_donn_var)
{ // dans la liste existante tous les ddl des familles existantes, sont présents
  // et ordonné dans chaque famille mais par forcément globalement, 
  // par contre dans ta on peut avoir que certains représentants de famille
  // mais ta est également ordonnée
  // on regarde combien de  Ddl existe deja
  list <Ddl >::iterator il;
  liDdl.clear(); // init au début
  list <Enum_ddl> li_travail; // une liste de travaille
  int j=1;
  int taille=tab_ddl.Taille();
  int tataille=ta.Taille();
  if (j>tataille) return; // cas d'un tableau vide  
  do  
    { bool rel = false;Enum_ddl enu=ta(j).Id_nom();
      // on cherche si le ddl existe déjà
      for (int i=1;i<= taille; i++)
        {if (tab_ddl(i).Id_nom() == enu)
           { rel = true; 
             tab_ddl(i) = ta(j);
             change_donn_var=true;
             j++; // on passe au suivant
             break;
            };
        };
        
      // cas où il n'y a pas de ddl existant  
      if (!rel) 
           	{// dans le cas d'une famille: 
           	 // on regarde si tous les ddl de la famille font partie de la liste
           	 if (FoncDim(enu) && (ParaGlob::Dimension()!=1))
           	  {// on récupère tous les ddl de la famille
       	       Tableau<Enum_ddl> t_enu =TableauTypeDdl(enu);
       	       int ttlle = t_enu.Taille();
       	       // on regarde tout d'abord si les premiers ddl sont présents
       	       // sachant que enu est le plus petit de la famille ! (car ta est ordonné)
       	       int iy=0;
       	       for (iy=1;iy<=ttlle;iy++)
       	        {if (t_enu(iy)!=enu)
       	       	 { // on regarde également s'il est déjà dans la liste, si oui, on passe
                   if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end())
                    {li_travail.push_back(t_enu(iy));
                     // on ajoute le ddl pour l'instant hors service et a priori libre
       	       	     Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE);
        	            liDdl.push_back(addl);
                    };
       	       	 }
       	       	else
       	       	 { // on regarde également s'il est déjà dans la liste, si oui, on passe
                   if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end())
                    {li_travail.push_back(t_enu(iy));
                     // il n'existe pas , on ajoute le bon ddl
       	       	     liDdl.push_back(ta(j));
                    }
                   else // il exite, on met la bonne valeur
                    { list <Ddl >::iterator ith,ithfin=liDdl.end();
                      for (ith = liDdl.begin();ith!=ithfin;ith++)
                       { if ((*ith).Id_nom() == t_enu(iy))
                           {(*ith)=ta(j);break;}
                       };
                    };
       	       	   break;
       	       	 };
       	        };
       	        
           	    iy++; // on passe à l'enu suivant des ddl de la famille
       	        // maintenant on balaie les enu restants si nécessaire
       	        j++; //on incrémente car on regarde l'élément suivant du tableau
       	        for (;iy<=ttlle;iy++)
       	         { if(j <= tataille) // donc j est valide 
       	            { if ((t_enu(iy)!=ta(j).Id_nom()))
       	       	       { // on regarde également s'il est déjà dans la liste, si oui, on passe
                         if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end())
                          {li_travail.push_back(t_enu(iy));
                           // on ajoute le ddl pour l'instant hors service et a priori libre
                           Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE);
                           liDdl.push_back(addl);
                          };
       	       	        }
                      else
                       { // on regarde également s'il est déjà dans la liste, si oui, on passe
                         if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end())
                          {li_travail.push_back(t_enu(iy));
                           // il n'existe pas , on ajoute le bon ddl
                           liDdl.push_back(ta(j));
                          }
                         else // il exite, on met la bonne valeur
                          { list <Ddl >::iterator ith,ithfin=liDdl.end();
                            for (ith = liDdl.begin();ith!=ithfin;ith++)
                             { if ((*ith).Id_nom() == t_enu(iy))
                                 {(*ith)=ta(j);break;}
                             };
                          };
                         break;
                       };
       	            }
       	           else // cas ou le j n'est plus valide on rajoute les ddl manquants
       	       	    { // on regarde également s'il est déjà dans la liste, si oui, on passe
                      if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end())
                       {li_travail.push_back(t_enu(iy));
                        // on ajoute le ddl pour l'instant hors service et a priori libre
                        Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE);
                        liDdl.push_back(addl);
                       };
       	       	    };
       	         };
           	  } 
           	 else // cas d'un ddl qui n'appartient pas à une famille 
       	       	  // on l'ajoute tout simplement
       	      { liDdl.push_back(ta(j));
       	        j++;
       	       };
           	}//-- fin du cas on on ajoute des ddl à la liste
     }  while (j<=tataille) ;  

};

// modification du type de laison entre noeud éventuel avec init des tableaux de liaison
// pour le cas d'assemblage nb_assemb
void Noeud::Change_Enu_liason(int nb_assemb, Enum_liaison_noeud enu_liai
                              ,const Tableau <Posi_ddl_noeud>& tab_N_lier)
   {
     // on fait tout d'abord une petite vérification
     if (enu_liai && ((tab_N_lier.Taille() == 0)))
      { cout << "\n inchoerence !! on veut une liaison entre noeud mais le tableau de liaison est vide ! "
             << "\n nb_assemb= "<< nb_assemb << " Enum_liaison_noeud= "<< Nom_liaison_noeud(enu_liai)
             << " taille de tab_N_lier= " << tab_N_lier.Taille()
             << "\n Noeud::Change_Enu_liason(... "<<endl;
        Sortie(1);
      };
     if (!enu_liai && ((tab_N_lier.Taille() != 0)))
      { cout << "\n inchoerence !! on ne veut pas de liaison entre noeud mais le tableau de liaison n'est pas vide ! "
             << "\n nb_assemb= "<< nb_assemb << " Enum_liaison_noeud= "<< Nom_liaison_noeud(enu_liai)
             << " taille de tab_N_lier= " << tab_N_lier.Taille()
             << "\n Noeud::Change_Enu_liason(... "<<endl;
        Sortie(1);
      };
   
     // puis on met à jour les dimensions des tableaux en fonction du numéro d'assemblage
     if (tab_enu_liaison == NULL) // cas où rien n'existe
       {tab_enu_liaison = new Tableau <Enum_liaison_noeud>;
        tab_ddl_lier = new Tableau < Tableau <Posi_ddl_noeud> > ;
       };
     // cas où il faut augmenter les tailles
     if (nb_assemb > tab_enu_liaison->Taille())
       {tab_enu_liaison->Change_taille(nb_assemb);
        tab_ddl_lier->Change_taille(nb_assemb);
       };
     // maintenant on renseigne les valeurs
     (*tab_enu_liaison)(nb_assemb) = enu_liai;
     (*tab_ddl_lier)(nb_assemb) = tab_N_lier;
   };

// suppression de tous les liaisons noeuds
void Noeud::Suppression_tous_liaisons_noeuds()
  {  if (tab_enu_liaison != NULL)
       delete tab_enu_liaison;
     if (tab_ddl_lier != NULL)
       delete tab_ddl_lier;
  };

// sortie du schemaXML: en fonction de enu  
void Noeud::SchemaXML_Noeud(ofstream& sort,const Enum_IO_XML enu)
 { switch (enu)  
    {case XML_TYPE_GLOBAUX:
 	  {// on définit des types pour un maillage 
  	   sort << "\n <!--  *************************** un noeud de maillage ***************************  -->"
  	         << "\n<xs:complexType name=\"Noeud\" >"
  	         << "\n    <xs:annotation>"
  	         << "\n      <xs:documentation> un numero et 3 coordonnees </xs:documentation>"
  	         << "\n    </xs:annotation>"
  	         << "\n    <xs:sequence>"
  	         << "\n        <xs:element name=\"numero\" type=\"xs:integer\" />"
  	         << "\n        <xs:element name=\"coordonnees\" >"
  	         << "\n            <xs:simpleType>"
  	         << "\n          	 <xs:restriction base=\"liste_de_reels\">"
  	         << "\n                <xs:minLength value=\"3\" />"
  	         << "\n                <xs:maxLength value=\"3\" />"
  	         << "\n              </xs:restriction>"  
  	         << "\n            </xs:simpleType>"
  	         << "\n        </xs:element>"
  	         << "\n    </xs:sequence>"
  	         << "\n</xs:complexType>";
 	    break;		
      }
     case XML_IO_POINT_INFO:
      {  // définition d'une liste de noeuds
   //      sort  << "\n                 <xs:element  name=\"les_noeuds\" type=\"noeud_maillage\" "
   //	           << "\n                             minOccurs=\"1\" maxOccurs=\"unbounded\" />";
         break;		
      }
    };
 };






