// FICHIER : Maillage.cp
// CLASSE : Maillage

// 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 "Maillage.h"
# include <iostream>
using namespace std;  //introduces namespace std
#include <stdlib.h>
#include "Sortie.h"
#include <stdio.h>
#include <vector>
#include "List_io.h"
#include "CharUtil.h"
#ifndef SYSTEM_MAC_OS_X_unix
  #include "Frontier.h"
#endif
#include "ConstMath.h"
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "Util.h"
#include "MvtSolide.h"

   
// --------- utilitaires de manipulation de maillage
        // test pour savoir si le maillage contiend des éléments à interpolation linéaire
bool Maillage::Contient_lineaire()
  { // on balaie les éléments
    int taille_elem = tab_element.Taille();
    for (int i=1; i<=taille_elem;i++)
      {  Enum_interpol eninter = tab_element(i)->Id_interpolation();
			// LINEAIRE indique que l'on a une interpolation linéaire
         if (eninter == LINEAIRE) return true;
       }
    // sinon pas d'élément incomplet quadratique
    return false;
   };
bool Maillage::Contient_quadratique_incomplet()
  { // on balaie les éléments
    int taille_elem = tab_element.Taille();
    for (int i=1; i<=taille_elem;i++)
      {  Enum_interpol eninter = tab_element(i)->Id_interpolation();
         // QUADRATIQUE indique que l'on a une interpolation quadratique incomplète
         // alors que QUADRACOMPL indique que c'est quadratique complet
         if (eninter == QUADRATIQUE) return true;
       }
    // sinon pas d'élément incomplet quadratique
    return false;
   };
   
// transformation des éléments linéaires du maillage en quadratiques.
// les éléments linéaires  sont  supprimés, 
// Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! 
// il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage
void Maillage::Transfo_lin_quadraIncomp(LesReferences &lesRef)      
  {list <Element *> nv_remplace;
   list <Maillage::PosiEtNoeud> li_nv_noeud;
   list <DeuxEntiers> li_bornes;
   // 1) on balaie les éléments
   int nbnt=tab_noeud.Taille(); // le nombre de noeud total (évolue pendant la transformation) 
   // nbnt permet à Construct_from_imcomplet de donner des numéros de noeud licite, en particulier
   // permet d'éviter que deux noeuds aient le même numéro
   int taille_elem = tab_element.Taille();
   for (int i=1; i<=taille_elem;i++)
      {  Enum_interpol eninter = tab_element(i)->Id_interpolation();
         // LINEAIRE indique que l'on a une interpolation linéaire
         if (eninter == LINEAIRE)
          {// 2) on a trouvé un linéaire
           // on crée un quadratique incomplet de même type
           Element * elem =  tab_element(i); // pour simplifier
           Element::Signature signa = elem->Signature_element();
           // on change l'interpolation
           signa.id_interpol=QUADRATIQUE;
           // on crée le nouvel élément quadratique avec le même numéro que le linéaire (car il le remplacera
           // par la suite)
           Element* elem2= Element::Choix_element(elem->Num_maillage(),elem->Num_elt(),signa);
           if (elem2 == NULL)
            { cout << "\n erreur de creation d'un element quadratique incomplet a partir d'un lineaire"
                   << "\n signature du lineaire: interpolation " << Nom_interpol(signa.id_interpol)
                   << " geometrie: " << Nom_geom(signa.id_geom) << " problem: " << NomElemTypeProblem(signa.id_problem)
                   << " infos_annexes: " << signa.infos_annexes
                   << "\n Maillage::Transfo_lin_quadraIncomp(...";
               Sortie(1);                
             }
            // 3) on demande à l'élément de définir ses noeuds, d'une part à partir des noeuds
            //    déjà existants de l'élément linéaire, et d'autre part à partir de nouveaux noeuds
            //    construit à partir de l'interpolation initiale linéaire.
            //    on fournit également le premier numéro -1 du nouveau noeud
            list <DeuxEntiers> li_bo; // les bornes pour la renumérotation
            list <Noeud *> l_nv_noe = elem2->Construct_from_lineaire(*elem,li_bo,nbnt);
            nbnt += l_nv_noe.size();
            // 4) on ajoute les nouveaux noeuds
            list <Noeud *>::iterator lni,lnifin=l_nv_noe.end();
            for (lni=l_nv_noe.begin();lni!=lnifin;lni++)
               {li_nv_noeud.push_back(Maillage::PosiEtNoeud(*lni,elem2));
                }
            list <DeuxEntiers>::iterator pni,pnifin=li_bo.end();
            for (pni=li_bo.begin();pni!=pnifin;pni++)
               {li_bornes.push_back(*pni);
                }
            // 5) on enregistre l'élément linéaire et on le remplace par le quadratique dans 
            // la liste d'élément
            nv_remplace.push_back(elem);
            tab_element(i) = elem2;           
           }
        }   
           
   // 6) on supprime les doublons dans la liste des noeuds en réaffectant les bons pointeurs dans les éléments
//   li_nv_noeud.sort(); // ordonne la liste
   // suppression des doublons et réaffectation des pointeurs de noeuds supprimés dans les éléments
   if (li_nv_noeud.size() != 1)
    {list <Maillage::PosiEtNoeud>::iterator lili,lilifin = li_nv_noeud.end();
     list <Maillage::PosiEtNoeud>::iterator lila = li_nv_noeud.begin();lili=lila; lili++;
     list <DeuxEntiers>::iterator pili,pilifin = li_bornes.end();
     list <DeuxEntiers>::iterator pila = li_bornes.begin();pili=pila; pili++;
     do
      { if (*lila == *lili)
         { //cas de deux noeuds identiques, on réaffecte le pointeur de noeud dans l'élément
           (*lila).el->Reaffectation_pointeur_noeud((*lila).noe,(*lili).noe);
           // on supprime le noeud doublon
           delete (*lila).noe;
           // on supprime les éléments de la liste
           li_nv_noeud.erase(lila); li_bornes.erase(pila);
          }
        lila = lili; lili++; 
        pila = pili; pili++;
       } while (lili!= lilifin);
     } 
   // 7) insertion des nouveaux noeuds dans le tableau définitif  et renumérotation
    // a) on commence par définir une liste de noeud, équivalente au tableau tab_noeud
   List_io <Noeud *> li_no;
   int nbn = tab_noeud.Taille();
   // petite vérif: il faut que le maillage contienne au moins un noeud
   #ifdef MISE_AU_POINT
   if (nbn == 0)
     { cout << "\n erreur le maillage contiend 0 noeud en propre, ce qui est insufisent pour la routine"
            << "\n list <Element *> Maillage::Transfo_quadraIncomp_quadraComp()";
       Sortie(1);
      }      
   #endif
   // b) on définit un tableau de  listes de pointeurs de noeud
   Tableau <List_io<Noeud*> > tab_ln(nbn);
   // c) on remplit chaque liste des noeuds qu'il faudrait ajouter pour avoir une bonne numérotation
   list <Maillage::PosiEtNoeud>::iterator lili,lilifin = li_nv_noeud.end();
   list <DeuxEntiers>::iterator pilifin = li_bornes.end();
   list <DeuxEntiers>::iterator pili = li_bornes.begin();
   for (lili=li_nv_noeud.begin();lili != lilifin; lili++,pili++)
    { // récup de la position moyenne  d'insertion et remplissage de la liste correspondante
  //    cout << "\n un= " << (*pili).un << "deux= " << (*pili).deux ;
      int bi=( (*pili).un + (*pili).deux ) / 2; // division entière
  //    cout << " bi= " << bi << endl;
      tab_ln(bi).push_back((*lili).noe);    
     }
   // d) on définit un nouveau tableau de noeud qui comprend les anciens et les nouveaux noeuds, ordonnées
   int nbn_nv = nbn+li_nv_noeud.size();
   Tableau<Noeud  *> tab_noe_nv(nbn_nv);
   // définition également d'un tableau d'indiçage inverse
   Tableau <int> indic(nbn);
   int ino=0;  
   for (int ivo=1;ivo<= nbn;ivo++)
     { // tout d'abord le noeud ancien
       ino++; tab_noe_nv(ino)=tab_noeud(ivo);
       indic(ivo)=ino;
       // puis éventuellement les noeuds à intercaler      
       List_io<Noeud*>& li_ln = tab_ln(ivo); // pour simplifier
       if (li_ln.size() != 0)
        { List_io<Noeud*>::iterator iln,iln_end=li_ln.end();
          for (iln=li_ln.begin(); iln != iln_end; iln++)
            { ino++; tab_noe_nv(ino)=*iln;};
         }    
      } 
   tab_noeud = tab_noe_nv; // remplacement du tableau du maillage   
   // e) on renumérote les différents noeuds 
   for (int j=1;j<= nbn_nv;j++) tab_noeud(j)->Change_num_noeud(j);
   // 7) modification des références sur les noeuds
   //  a) on passe en revue les références et on sélectionne les références relatives aux noeuds
   //     de l'ancien maillage
   const Reference* ref1 = lesRef.Init_et_Premiere();
   do { if((ref1->Nbmaille() == idmail) && (ref1->Indic() == 1))
             // on a trouvé une référence de noeud à considérer
             { ReferenceNE * refNE = ( ReferenceNE *) ref1; // pour simplifier
               int nb_num=refNE->Taille();
               for (int it= 1;it<=nb_num;it++) 
                  refNE->Change_num_dans_ref(it,indic(refNE->Numero(it)));
              }
          ref1 =  lesRef.Reference_suivante();  // la référence suivante  
       } while (ref1 != NULL);
        
    cout << "\n *** attention les references generes ici ne sont pas bonnes !! , seul le maillage est "
         << " actuellement correcte ";    

   // 8) suppression des éléments linéaires qui n'ont plus lieu d'être
   list <Element *>::iterator lele,lelefin=nv_remplace.end();
   for (lele=nv_remplace.begin();lele!=lelefin;lele++)
     delete (*lele);
   // 9)  rien à faire sur les références d'élément, ou de face d'élément ou d'arrête d'élément
   //     car d'une part les nouveaux éléments ont le même numéro que les anciens, et d'autre part
   //     le fait de passer en élément complet ne modifie pas les arrêtes ou faces
   }; 
       
// transformation des éléments quadratiques incomplet du maillage en quadratiques complets.
// les éléments incomplets sont supprimée, 
// Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! 
// il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage
 void Maillage::Transfo_quadraIncomp_quadraComp(LesReferences &lesRef)
  {list <Element *> nv_remplace;
   list <Maillage::PosiEtNoeud> li_nv_noeud;
   list <DeuxEntiers> li_bornes;
   // 1) on balaie les éléments
   int nbnt=tab_noeud.Taille(); // le nombre de noeud total (évolue pendant la transformation) 
   // nbnt permet à Construct_from_imcomplet de donner des numéros de noeud licite, en particulier
   // permet d'éviter que deux noeuds aient le même numéro
   int taille_elem = tab_element.Taille();
   for (int i=1; i<=taille_elem;i++)
      {  Enum_interpol eninter = tab_element(i)->Id_interpolation();
         // QUADRATIQUE indique que l'on a une interpolation quadratique incomplète
         // alors que QUADRACOMPL indique que c'est quadratique complet
         if (eninter == QUADRATIQUE)
          {// 2) on a trouvé un quadratique incomplet
           // on crée un quadratique complet de même type
           Element * elem =  tab_element(i); // pour simplifier
           Element::Signature signa = elem->Signature_element();
           // on change l'interpolation
           signa.id_interpol=QUADRACOMPL;
           // on crée le nouvel élément complet avec le même numéro que l'incomplet (car il le remplacera
           // par la suite)
           Element* elem2= Element::Choix_element(elem->Num_maillage(),elem->Num_elt(),signa);
           if (elem2 == NULL)
            { cout << "\n erreur de creation d'un element quadratique complet a partir d'un incomplet"
                   << "\n signature du quadratique incomplet: interpolation " << Nom_interpol(signa.id_interpol)
                   << " geometrie: " << Nom_geom(signa.id_geom) << " problem: " << NomElemTypeProblem(signa.id_problem)
                   << " infos_annexes: " << signa.infos_annexes
                   << "\n Maillage::Transfo_quadraIncomp_quadraComp(...";
               Sortie(1);                
             }
            // 3) on demande à l'élément de définir ses noeuds, d'une part à partir des noeuds
            //    déjà existants de l'élément incomplet, et d'autre part à partir de nouveaux noeuds
            //    construit à partir de l'interpolation initiale incomplète.
            //    on fournit également le premier numéro -1 du nouveau noeud
            list <DeuxEntiers> li_bo; // les bornes pour la renumérotation
            list <Noeud *> l_nv_noe = elem2->Construct_from_imcomplet(*elem,li_bo,nbnt);
            nbnt += l_nv_noe.size();
            // 4) on ajoute les nouveaux noeuds
            list <Noeud *>::iterator lni,lnifin=l_nv_noe.end();
            for (lni=l_nv_noe.begin();lni!=lnifin;lni++)
               {li_nv_noeud.push_back(Maillage::PosiEtNoeud(*lni,elem2));
                }
            list <DeuxEntiers>::iterator pni,pnifin=li_bo.end();
            for (pni=li_bo.begin();pni!=pnifin;pni++)
               {li_bornes.push_back(*pni);
                }
            // 5) on enregistre l'élément incomplet et on le remplace par le complet dans 
            // la liste d'élément
            nv_remplace.push_back(elem);
            tab_element(i) = elem2;           
           }
        }   
           
   // 6) on supprime les doublons dans la liste des noeuds en réaffectant les bons pointeurs dans les éléments
// non car cela ne sert à rien et il faudrait également traiter li_bornes   li_nv_noeud.sort(); // ordonne la liste
   // suppression des doublons et réaffectation des pointeurs de noeuds supprimés dans les éléments
   if (li_nv_noeud.size() != 1)
    {list <Maillage::PosiEtNoeud>::iterator lili,lilifin = li_nv_noeud.end();
     list <Maillage::PosiEtNoeud>::iterator lila = li_nv_noeud.begin();lili=lila; lili++;
     list <DeuxEntiers>::iterator pili,pilifin = li_bornes.end();
     list <DeuxEntiers>::iterator pila = li_bornes.begin();pili=pila; pili++;
     do
      { if (*lila == *lili)
         { //cas de deux noeuds identiques, on réaffecte le pointeur de noeud dans l'élément
           (*lila).el->Reaffectation_pointeur_noeud((*lila).noe,(*lili).noe);
           // on supprime le noeud doublon
           delete (*lila).noe;
           // on supprime les éléments de la liste
           li_nv_noeud.erase(lila); li_bornes.erase(pila);
          }
        lila = lili; lili++; 
        pila = pili; pili++;
       } while (lili!= li_nv_noeud.end());
     };
////------ debug
//{
//cout << "\n debug: Maillage::Transfo_quadraIncomp_quadraComp ";
//list <DeuxEntiers>::iterator pili = li_bornes.begin();
//int i=1;
//for (pili;pili != li_bornes.end();pili++,i++)
//  cout << "\n borne "<< i <<": " << *pili;
//cout << endl;
//};
////----- fin debug

   
   
   // 7) insertion des nouveaux noeuds dans le tableau définitif  et renumérotation
   // a) on commence par définir une liste de noeud, équivalente au tableau tab_noeud
   List_io <Noeud *> li_no;
   int nbn = tab_noeud.Taille();
   // petite vérif: il faut que le maillage contienne au moins un noeud
   #ifdef MISE_AU_POINT
   if (nbn == 0)
     { cout << "\n erreur le maillage contiend 0 noeud en propre, ce qui est insufisent pour la routine"
            << "\n list <Element *> Maillage::Transfo_quadraIncomp_quadraComp()";
       Sortie(1);
      }      
   #endif
   // b) on définit un tableau de  listes de pointeurs de noeud
   Tableau <List_io<Noeud*> > tab_ln(nbn);
   // c) on remplit chaque liste des noeuds qu'il faudrait ajouter pour avoir une bonne numérotation
   list <Maillage::PosiEtNoeud>::iterator lili,lilifin = li_nv_noeud.end();
   list <DeuxEntiers>::iterator pilifin = li_bornes.end();
   list <DeuxEntiers>::iterator pili = li_bornes.begin();
   for (lili=li_nv_noeud.begin();lili != lilifin; lili++,pili++)
    { // récup de la position moyenne  d'insertion et remplissage de la liste correspondante
      int bi=( (*pili).un + (*pili).deux ) / 2; // division entière
////------ debug
//{
//cout << "\n debug: Maillage::Transfo_quadraIncomp_quadraComp ";
//  cout << "\n bornes : " << *pili << endl;
//};
////----- fin debug
      tab_ln(bi).push_back((*lili).noe);
    };
   // d) on définit un nouveau tableau de noeud qui comprend les anciens et les nouveaux noeuds, ordonnées
   int nbn_nv = nbn+li_nv_noeud.size();
   Tableau<Noeud  *> tab_noe_nv(nbn_nv);
   // définition également d'un tableau d'indiçage inverse
   Tableau <int> indic(nbn);
   int ino=0;  
   for (int ivo=1;ivo<= nbn;ivo++)
     { // tout d'abord le noeud ancien
       ino++; tab_noe_nv(ino)=tab_noeud(ivo);
       indic(ivo)=ino;
       // puis éventuellement les noeuds à intercaler      
       List_io<Noeud*>& li_ln = tab_ln(ivo); // pour simplifier
       if (li_ln.size() != 0)
        { List_io<Noeud*>::iterator iln,iln_end=li_ln.end();
          for (iln=li_ln.begin(); iln != iln_end; iln++)
            { ino++; tab_noe_nv(ino)=*iln;};
         }    
      } 
   tab_noeud = tab_noe_nv; // remplacement du tableau du maillage   
   // e) on renumérote les différents noeuds 
   for (int j=1;j<= nbn_nv;j++) tab_noeud(j)->Change_num_noeud(j);
   // 7) modification des références sur les noeuds
   //  a) on passe en revue les références et on sélectionne les références relatives aux noeuds
   //     de l'ancien maillage
   const Reference* ref1 = lesRef.Init_et_Premiere();
     do { if((ref1->Nbmaille() == idmail) && (ref1->Indic() == 1))
             // on a trouvé une référence de noeud à considérer
             { ReferenceNE * refNE = ( ReferenceNE *) ref1; // pour simplifier
               int nb_num=refNE->Taille();
               for (int it= 1;it<=nb_num;it++) 
                  refNE->Change_num_dans_ref(it,indic(refNE->Numero(it)));
              }
          ref1 =  lesRef.Reference_suivante();  // la référence suivante  
        } while (ref1 != NULL);

   // 8) suppression des élément incomplet qui n'ont plus lieu d'être
   list <Element *>::iterator lele,lelefin=nv_remplace.end();
   for (lele=nv_remplace.begin();lele!=lelefin;lele++)
     delete (*lele);
   // 9)  rien à faire sur les références d'élément, ou de face d'élément ou d'arrête d'élément
   //     car d'une part les nouveaux éléments ont le même numéro que les anciens, et d'autre part
   //     le fait de passer en élément complet ne modifie pas les arrêtes ou faces
   };     
		
// Affiche les donnees du maillage dans un fichier
// dont le nom est construit à partir du nom du maillage
// au format  ".her" et ".lis"
void Maillage::Affiche_dans_her_lis(LesReferences &lesRef,Enum_dure temps)
 { 
   //------------- écriture du .her  -------------
   // ouverture du fichier pour les noeuds
    char nomm[132];
    char*fileName  = nomm;
    strcpy(fileName, nomDuMaillage.c_str());
    ofstream * sur_sort = new ofstream (strcat(fileName,".her"));
    ofstream & sort = * sur_sort;
    if(!(sort.is_open()))
      //  le fichier ne peut être ouvert, message d'erreur
     {  cout << "\n erreur en ouverture pour l'ecriture du fichier  " << fileName << "\n"
             << " Maillage::Affiche_dans_her_lis(.... " << endl;
        Sortie(1);
      };
    // écriture de l'entete  
    sort << "\n ###########################################################################"
         << "\n # ecriture automatique d'un maillage au format .her, par Herezh++         #"
         << "\n ###########################################################################"
         << "\n # version: " <<  ParaGlob::NbVersion() << "\n \n \n ";
    // écriture du nom du maillage    
    sort << "\n nom_maillage " << nomDuMaillage << "    #  nom du maillage"
        << "\n"
        << "\n           noeuds ------------ # definition des noeuds";
    int dimen = ParaGlob::Dimension();
    // l'entete des noeuds
    int nbn = tab_noeud.Taille();
    sort << "\n            "<< nbn << "  NOEUDS         # definition du nombre de noeuds"
         << "\n \n" 
         << "\n#---------------------------------------------------------------"
         << "\n#|NO DU|        X         |        Y         |          Z      |"
         << "\n#|NOEUD|                  |                  |                 |"
         << "\n#---------------------------------------------------------------"
         << "\n";
    // écriture des noeuds
    double sero = 0.;
    for (int ine=1;ine<=nbn; ine++)
     { sort  << "\n" << setw (6) << ine <<" ";
       Coordonnee co;
       	switch (temps)
          {
           case TEMPS_0 : co=tab_noeud(ine)->Coord0(); break;
           // si les noeuds n'ont pas bougés on sort les coordonnées à 0
           case TEMPS_t :
             { if (tab_noeud(ine)->ExisteCoord1())
                 { co=tab_noeud(ine)->Coord1(); }
               else co=tab_noeud(ine)->Coord0();
               break;
             }
           case TEMPS_tdt :
             { if (tab_noeud(ine)->ExisteCoord2())
                 { co=tab_noeud(ine)->Coord2(); }
               else co=tab_noeud(ine)->Coord0();
               break;
             }
           default :
            cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
            cout << "Maillage::Affiche_dans_her_lis(.. \n";
            Sortie(1);
          };
       #ifndef ENLINUX_STREAM
        sort.setf(ios_base::scientific);
       #else  
        sort.setf(ios::scientific); 
       #endif
       for (int j=1;j<=3;j++)
         if (j<=dimen)
            sort  << setw (18) << setprecision(ParaGlob::NbdigdoCA()) <<co(j) << " ";
         else   
            sort  << setw (18) << setprecision(ParaGlob::NbdigdoCA()) <<  sero << " ";
       }
    sort <<  "\n \n";  
    // entête des éléments  
    int nbe=tab_element.Taille();
    sort << "\n       elements ---------- \n"
         << "\n    " << nbe << "  ELEMENTS     # definition du nombre d'elements"
         << "\n #----------------------------------------------------------------------"
         << "\n #| NO  |                           |                                  |"
         << "\n #|ELTS |     type element          |       Noeuds                     |"
         << "\n #----------------------------------------------------------------------"
         << "\n";
    // écriture des éléments
    for (int ie=1;ie<=nbe;ie++)
      { sort  << "\n" << setw (6) << ie <<" ";
        Element::Signature sign = tab_element(ie)->Signature_element();
        sort << Nom_geom(sign.id_geom) << " " << Nom_interpol(sign.id_interpol) 
             << " " << sign.infos_annexes << "  ";
        Tableau<Noeud *>& tab_n = tab_element(ie)->Tab_noeud();
        int taille_tab_n = tab_n.Taille();
        for (int ite=1;ite<=taille_tab_n;ite++)
          sort << tab_n(ite)->Num_noeud() << " ";
       }
    // quelques lignes blanches à la fin du fichier
    sort << "\n \n \n";
    // fermeture du fichier
    delete sur_sort;
    
   //------------- écriture du .lis  -------------
		
   // Affiche les donnees des références pour le maillage imail dans un fichier
   // dont le nom est construit à partir du nom du maillage au format   ".lis"
   lesRef.Affiche_dans_lis(nomDuMaillage,idmail);
    
  };
		
 
//modification du maillage pour le restreindre aux seuls éléments de la référence passée en paramètre
// toutes les infos relatives à des éléments supprimés, sont également supprimés
void Maillage::Restreint_sous_maillage(LesReferences* lesRef, string nom_ref)
 { // on définit un tableau d'indicateur donnant les éléments non référencés
   Tableau <bool> tab_el_non_referencer(tab_element.Taille(),true); // par défaut on ne conserve pas
   // on définit un tableau d'indicateur donnant les noeuds non référencés
   Tableau <bool> tab_noe_non_referencer(tab_noeud.Taille(),true);
   // récup de la référence des éléments
   const ReferenceNE & ref =((ReferenceNE &) lesRef->Trouve(nom_ref,idmail));
   if (ref.Indic() != 2)
    {cout << "\n *** erreur: la reference "<<nom_ref<<" n'est pas une ref d'element "
          << " on ne peut pas continuer ";
     if (ParaGlob::NiveauImpression() > 2)
       cout << "\n Maillage::Restreint_sous_maillage(... ";
     Sortie(1);
    };
   // récup du tableau d'éléments de la référence
   const Tableau<int>& tab_E_ref = ref.Tab_num();
   // on marque les éléments à conserver ainsi que les noeuds
   // qui appartiennent à des éléments à conserver
   int nb_el = tab_E_ref.Taille();
   for (int i=1;i<=nb_el;i++)
     {tab_el_non_referencer(tab_E_ref(i)) = false;
      Element * el =  tab_element(tab_E_ref(i));
      const Tableau<Noeud *>& tab_noeu = el->Tab_noeud_const();
      int nb_noe = tab_noeu.Taille();
      for (int noe = 1;noe <= nb_noe; noe++)
        tab_noe_non_referencer(tab_noeu(noe)->Num_noeud())=false;
     };
   // suppression des éléments non référencés
   int NBE=tab_element.Taille();
   for (int i=1;i<=NBE;i++)
    if (tab_el_non_referencer(i))
      delete tab_element(i);
   // suppression des noeuds non référencés
   int NBN = tab_noeud.Taille();
   int nb_noeud_final = 0; // init
   for (int i=1;i<= NBN;i++)
    if (tab_noe_non_referencer(i))
         {delete tab_noeud(i);}
    else {nb_noeud_final++;}; // sinon on compte
  
   // on redimentionne et réafecte le tableau de noeuds
   Tableau<Noeud *> tab_old_noe = tab_noeud; // sauvegarde de l'ancien tableau
   // nv_tab est tel que : nv_tab_noe(i) est le nouveau numéro qui avait auparavant le numéro "i"
   Tableau <int > nv_tab_noe(NBN);
   tab_noeud.Change_taille(nb_noeud_final);
   int indice_noeu=1; // pour parcourir le tableau final de noeud
   for (int i=1;i<=NBN;i++)
    if (!tab_noe_non_referencer(i))
      {tab_noeud(indice_noeu) = tab_old_noe(i);
       nv_tab_noe(i)=indice_noeu;
       tab_noeud(indice_noeu)->Change_num_noeud(indice_noeu);
       indice_noeu++;
      };
  
  
   // on redimentionne et réafecte le tableau d'élément
   Tableau<Element *> tab_old_El = tab_element; // sauvegarde de l'ancien tableau
   // nv_tab est tel que : nv_tab_ele(i) est le nouveau numéro qui avait auparavant le numéro "i"
   Tableau <int > nv_tab_ele(NBE);
   tab_element.Change_taille(nb_el);
   int indice_ele=1; // pour parcourir le tableau final d'élément
   for (int i=1;i<=NBE;i++)
    if (!tab_el_non_referencer(i))
      {tab_element(indice_ele) = tab_old_El(i);
       nv_tab_ele(i)=indice_ele;
       tab_element(indice_ele)->Change_num_elt(indice_ele);
       indice_ele++;
      };
  
   // on s'occupe maintenant des références
   lesRef->Mise_a_jour_ref_element(nv_tab_ele,idmail,tab_el_non_referencer);
   lesRef->Mise_a_jour_ref_noeud(nv_tab_noe,idmail,tab_noe_non_referencer);
   // toilettage final
   listFrontiere.clear();tab_noeud_front.Change_taille(0);indice.Change_taille(0);
   mitoyen_de_chaque_element.Change_taille(0);
 };


// relocalisation des points milieux des arrêtes des éléments quadratiques
void Maillage::RelocPtMilieuMailleQuadra()
  { // on passe en revue les différents éléments pour voir s'il ont une arrête quadratique
    int nbe = tab_element.Taille(); 
    for (int ne=1;ne<=nbe;ne++)
     { // récup de l'élément géométrique
       const ElemGeomC0& elgeom = tab_element(ne)->ElementGeometrique_const();
       // récup du nombre de segment
       int nbse= elgeom.NbSe();
       // on boucle sur les segments pour voir s'il y a un quadratique
       for (int iseg=1;iseg<=nbse;iseg++)
         { ElemGeomC0 const & elseg = elgeom.ElemSeg(iseg);
           if (elseg.TypeInterpolation() == QUADRACOMPL)
            { // récup de la connection des noeuds des arêtes par rapport a ceux de l'element
              Tableau<Tableau<int> > const & nonStout = elgeom.NonS();
              Tableau <int> const & nonS = nonStout(iseg);
              Tableau<Noeud *>& t_noeud = tab_element(ne)->Tab_noeud(); 
              Noeud & N1=*t_noeud(nonS(1));Noeud & N2=*t_noeud(nonS(2));Noeud & N3=*t_noeud(nonS(3)); 
              // ------------- étape de modification du noeud milieu -----------------------
              Coordonnee M01= N1.Coord0();Coordonnee M02= N2.Coord0();Coordonnee M03= N3.Coord0(); 
              Coordonnee M1M3=(M03-M01);Coordonnee M1M2=(M02-M01);Coordonnee M2M3=(M03-M02); 
              double d12=M1M2.Norme();double d13=M1M3.Norme();double d23=M2M3.Norme(); 
              if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit))
                { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant 0"
                       << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment"
                       << "\n Maillage::RelocPtMilieuMailleQuadra()";
                  N1.Affiche(); N2.Affiche(); N3.Affiche();
                  break;
                  }     
              Coordonnee U=M1M3/d13; 
              // le vecteur normal à U             
              int dim = ParaGlob::Dimension(); Coordonnee V(dim); 
              double sinusangle;
              switch (dim)
               { case 1: // ici il suffit de prendre le point milieu
                  { sinusangle=0.; break;}
                 case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;}
                 case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2);
                           if (sinusangle > ConstMath::unpeupetit)
                            { W.Normer(); V = Util::ProdVec_coor(W,U);}
                           break;
                           } 
                };
              // on vérifie que les 3 points ne sont pas naturellement alignés
              if (sinusangle > ConstMath::unpeupetit)
               // cas où l'on peut considérer une base locale
               {
                 double N1H = M1M2*U; double HN2 = M1M2*V;
                 double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H));
                 Coordonnee P = M01 + p1 * U + p2 * V;;
                 N2.Change_coord0(P); break;
                }
              else 
               // cas où les 3 points sont originalement alignés   
               { Coordonnee milieu = (M01+M03)/2.;
                 N2.Change_coord0(milieu); break;
                }
              // +++++++  si les coordonnées à t existent, même traitement
              if (N1.ExisteCoord1())
               { M01= N1.Coord1();M02= N2.Coord1();M03= N3.Coord1(); 
                 M1M3=(M03-M01); M1M2=(M02-M01); M2M3=(M03-M02); 
                 d12=M1M2.Norme(); d13=M1M3.Norme(); d23=M2M3.Norme(); 
                 if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit))
                  { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant t"
                         << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment"
                         << "\n Maillage::RelocPtMilieuMailleQuadra()";
                    N1.Affiche(); N2.Affiche(); N3.Affiche();
                    break;
                    }     
                 U=M1M3/d13; 
                 // le vecteur normal à U             
                 switch (dim)
                  { case 1: // ici il suffit de prendre le point milieu
                     { sinusangle=0.; break;}
                    case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;}
                    case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2);
                              if (sinusangle > ConstMath::unpeupetit)
                               { W.Normer(); V = Util::ProdVec_coor(W,U);}
                              break;
                           } 
                   };
                 // on vérifie que les 3 points ne sont pas naturellement alignés
                 if (sinusangle > ConstMath::unpeupetit)
                  // cas où l'on peut considérer une base locale
                  {
                    double N1H = M1M2*U; double HN2 = M1M2*V;
                    double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H));
                    Coordonnee P = M01 + p1 * U + p2 * V;;
                    N2.Change_coord1(P); break;
                   }
                 else 
                  // cas où les 3 points sont originalement alignés   
                  { Coordonnee milieu = (M01+M03)/2.;
                    N2.Change_coord1(milieu); break;
                   }
                 }  
              // +++++ si les coordonnées à t existent, même traitement
              if (N1.ExisteCoord2())
               { M01= N1.Coord2();M02= N2.Coord2();M03= N3.Coord2(); 
                 M1M3=(M03-M01); M1M2=(M02-M01); M2M3=(M03-M02); 
                 d12=M1M2.Norme(); d13=M1M3.Norme(); d23=M2M3.Norme(); 
                 if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit))
                  { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant tdt"
                         << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment"
                         << "\n Maillage::RelocPtMilieuMailleQuadra()";
                    N1.Affiche(); N2.Affiche(); N3.Affiche();
                    break;
                    }     
                 U=M1M3/d13; 
                 // le vecteur normal à U             
                 switch (dim)
                  { case 1: // ici il suffit de prendre le point milieu
                     { sinusangle=0.; break;}
                    case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;}
                    case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2);
                              if (sinusangle > ConstMath::unpeupetit)
                               { W.Normer(); V = Util::ProdVec_coor(W,U);}
                              break;
                           } 
                   };
                 // on vérifie que les 3 points ne sont pas naturellement alignés
                 if (sinusangle > ConstMath::unpeupetit)
                  // cas où l'on peut considérer une base locale
                  {
                    double N1H = M1M2*U; double HN2 = M1M2*V;
                    double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H));
                    Coordonnee P = M01 + p1 * U + p2 * V;;
                    N2.Change_coord2(P); break;
                   }
                 else 
                  // cas où les 3 points sont originalement alignés   
                  { Coordonnee milieu = (M01+M03)/2.;
                    N2.Change_coord2(milieu); break;
                   }
                }
              // ------------- fin de l'étape de modification du noeud milieu - --------------
             }
          }
      }
   };

// sortie du schemaXML: en fonction de enu  
void Maillage::SchemaXML_Maillages(ofstream& sort,const Enum_IO_XML enu)
 { switch (enu)  
    {case XML_TYPE_GLOBAUX:
 	  {// on définit des types pour un maillage 
        Noeud::SchemaXML_Noeud(sort,enu);
        // def du type maillage
        sort  << "\n           <xs:complexType name=\"Maillage\"   >"
  	          << "\n               <xs:annotation>"
  	          << "\n                 <xs:documentation> un nom de maillage,  des noeuds, des references de noeuds," 
  	          << "\n                                   des elements, des references d'elements "
  	          << "\n                </xs:documentation>"
  	          << "\n               </xs:annotation>"
  	          << "\n               <xs:sequence>"
  	          << "\n                 <xs:element name=\"nom_du_maillage\" type=\"xs:string\" />" 
  	          << "\n                 <xs:element  name=\"Noeud\" type=\"Noeud\" "
  	          << "\n                             minOccurs=\"1\" maxOccurs=\"unbounded\" />";



  	   /*       << "\n  <xs:complexType>"
  	          << "\n    <xs:element  name=\"****les_maillages:_nombre=\" type=\"xs:positiveInteger\" "
  	          << "\n              use=\"required\" minOccurs=\"1\" maxOccurs=\"unbounded\" />"
  	          << "\n    <xs:element  name=\"defMaillages\" type=\"Maillage\" use=\"required\" />" */
  	          
  	    sort  << "\n               </xs:sequence>"
  	          << "\n           </xs:complexType>";
 	    break;		
      }
     case XML_IO_POINT_INFO:
      {// cas de la définition d'un maillage
/*        sort  << "\n           <xs:element name=\"Maillages\"  minOccurs=\"1\" maxOccurs=\"unbounded\" >"
  	          << "\n             <xs:complexType>"
  	          << "\n               <xs:annotation>"
  	          << "\n                 <xs:documentation> un nom de maillage,  des noeuds, des references de noeuds," 
  	          << "\n                                   des elements, des references d'elements "
  	          << "\n                </xs:documentation>"
  	          << "\n               </xs:annotation>"
  	          << "\n               <xs:sequence>"
  	          << "\n                 <xs:element name=\"nom_du_maillage\" type=\"xs:string\" />" 
  	          << "\n                 <xs:element  name=\"les_noeuds\" type=\"Noeud\" "
  	          << "\n                             minOccurs=\"1\" maxOccurs=\"unbounded\" />"*/



  	   /*       << "\n  <xs:complexType>"
  	          << "\n    <xs:element  name=\"****les_maillages:_nombre=\" type=\"xs:positiveInteger\" "
  	          << "\n              use=\"required\" minOccurs=\"1\" maxOccurs=\"unbounded\" />"
  	          << "\n    <xs:element  name=\"defMaillages\" type=\"Maillage\" use=\"required\" />" */
  	          
 /* 	    sort  << "\n               </xs:sequence>"
  	          << "\n             </xs:complexType>"
              << "\n           </xs:element>";*/
     // def de Maillage
//     SchemaXML_Maillage(sort,niveau);
         break;		
      }
    };
 };

//---------------------- class de travail ---------------------------

// classe de travail qui sert pour pouvoir classer les noeuds par leur position géométrique initiale
// deux élément sont identiques si leur position initiale sont identique
// a >= b si : soit a.x >= b.x, ou a.x==b.x et a.y >= b.y, ou a.x==b.x et a.y == b.y et a.z >= b.z

Maillage::PosiEtNoeud& Maillage::PosiEtNoeud::operator= (const Maillage::PosiEtNoeud& po) // affectation 
  { noe=po.noe; return *this;};

bool Maillage::PosiEtNoeud::operator == (const Maillage::PosiEtNoeud& po)  const  // test d'égalité
  { if ((noe->Coord0()-po.noe->Coord0()).Norme() <= ConstMath::unpeupetit) return true; else return false; };

bool Maillage::PosiEtNoeud::operator != (const Maillage::PosiEtNoeud& po)  const  // test d'inégalité
  { if (noe->Coord0() != po.noe->Coord0()) return true; else return false; };

bool Maillage::PosiEtNoeud::operator < (const Maillage::PosiEtNoeud& po)  const  // relation d'ordre
  { Coordonnee co1=noe->Coord0(); Coordonnee co2=po.noe->Coord0(); 
    switch  (co1.Dimension())
     { case 1: return (co1(1) < co2(1));break;
       case 2: {if (co1(1) < co2(1)) return true; 
                else if (co1(1) == co2(1))
                  { return (co1(2) < co2(2));}
                else return false;
                break;}
       case 3: {if (co1(1) < co2(1)) return true; 
                else if (co1(1) == co2(1))
                  { if (co1(2) < co2(2)) return true; 
                    else if (co1(2) == co2(2))
                       { return (co1(3) < co2(3));}
                    else false;
                   }
                return false;
                break;
                }
       default:
         { cout << "\n erreur le cas différent de 1 2 3 n'est pas admissible ici= " << co1.Dimension()
                << "\n bool Maillage::PosiEtNoeud::operator < (co... ";
           Sortie(1);
          }              
       };
    Sortie(1); // ne doit jamais passer ici !!   
    return false;    
    };
                      
bool Maillage::PosiEtNoeud::operator <= (const Maillage::PosiEtNoeud& po)  const  // relation d'ordre
  { Coordonnee co1=noe->Coord0(); Coordonnee co2=po.noe->Coord0(); 
    switch  (co1.Dimension())
     { case 1: return (co1(1) <= co2(1));break;
       case 2: {if (co1(1) < co2(1)) return true; 
                else if (co1(1) == co2(1))
                  { return (co1(2) <= co2(2));}
                else return false;
                break;}
       case 3: {if (co1(1) < co2(1)) return true; 
                else if (co1(1) == co2(1))
                  { if (co1(2) < co2(2)) return true; 
                    else if (co1(2) == co2(2))
                       { return (co1(3) <= co2(3));}
                    else false;
                   }
                return false;
                break;
                }
       default:
         { cout << "\n erreur le cas différent de 1 2 3 n'est pas admissible ici= " << co1.Dimension()
                << "\n bool Maillage::PosiEtNoeud::operator <= (co... ";
           Sortie(1);
          }              
       };
    Sortie(1); // ne doit jamais passer ici !!   
    return false;    
    };                  
                 
bool Maillage::PosiEtNoeud::operator > (const Maillage::PosiEtNoeud& po)  const  // relation d'ordre
  { return !(*this <= po);};

bool Maillage::PosiEtNoeud::operator >= (const Maillage::PosiEtNoeud& po)  const  // relation d'ordre
  { return !(*this < po);};
               
// transfert de grandeurs des points d'intégration aux noeuds 
//    1- en entrée les type évolués et quelconques que l'on veut transférer
//    2- en entrée: cas qui indique la méthode de transfert à utiliser
//                  =1 : les valeurs aux noeuds sont obtenue par moyennage
//                       des valeurs des pts d'integ les plus près
//                       des éléments qui entourent le noeud
// on décompose le processus en 3 étapes pour éviter d'initialiser plusieurs
//                fois lorque l'on refait à chaque fois
// le même transfert

// A) première étape def des conteneurs et c'est tout, la méthode peut donc être utilisée
//    pour autre chose. tabQ: permet d'avoir plusieurs listes de TypeQuelconque
// en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur
//   est nulle on n'en tient pas compte
void Maillage::AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu
	                                    ,const Tableau <List_io < TypeQuelconque > * >& tabQ)
{ // on crée des tableaux pour optimiser le nombre d'appel aux fonctions d'ajout de grandeur aux noeuds
  // 1) cas des Ddl_enum_etendu
  Tableau <Ddl_enum_etendu > tab_ddlEnuEtendu(lienu.size());
  {List_io < Ddl_enum_etendu >::const_iterator ilienu,ilienufin = lienu.end();
   int indice = 1;
   for (ilienu = lienu.begin();ilienu != ilienufin; ilienu++,indice++)
       tab_ddlEnuEtendu(indice) = (*ilienu);
  };
  // 2) cas des grandeurs quelconques
  Tableau < TypeQuelconque > tabglobQ;
  int ttai = 0;
  if (tabQ(1) != NULL) ttai += tabQ(1)->size();
  if (tabQ(2) != NULL) ttai += tabQ(2)->size();
  tabglobQ.Change_taille(ttai);
  int indice = 1;
  if (tabQ(1) != NULL)
  {List_io < TypeQuelconque >::const_iterator itabQ,itabQfin = tabQ(1)->end();
   for (itabQ = tabQ(1)->begin();itabQ != itabQfin; itabQ++,indice++)
       {tabglobQ(indice).ChangeGrandeur(*itabQ); // on commence par changer la grandeur
        tabglobQ(indice) = (*itabQ); // et on affecte
       };
  };
  if (tabQ(2) != NULL)
  {List_io < TypeQuelconque >::const_iterator itabQ,itabQfin = tabQ(2)->end();
   for (itabQ = tabQ(2)->begin();itabQ != itabQfin; itabQ++,indice++)
       {tabglobQ(indice).ChangeGrandeur(*itabQ); // on commence par changer la grandeur
        tabglobQ(indice) = (*itabQ); // et on affecte
       };
  };
  
  int nbN=tab_noeud.Taille();
  // on met à jour les noeuds    
  for(int i=1;i<=nbN;i++)
   { // Pour les grandeurs ddl étendu on les ajoutes aux noeuds si ce n'est pas déjà fait
     tab_noeud(i)->AjoutTabDdl_etendu(tab_ddlEnuEtendu);
     // on ajoute également les différents types quelconques aux noeuds
     tab_noeud(i)->AjoutTabTypeQuelconque(tabglobQ);
     // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté
     tab_noeud(i)->Mise_non_update_Ddl_etendu();
     tab_noeud(i)->Mise_non_update_grandeurs_quelconques();
    };
};

// B) initialisation des updates sur les noeuds
void Maillage::InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienetendu
	                             ,const Tableau <List_io < TypeQuelconque > * >& tabQ, int )
 {int nbN=tab_noeud.Taille();
  List_io <Ddl_enum_etendu>::const_iterator iliet,ilietfin  = lienetendu.end(); 
  List_io <TypeQuelconque>::const_iterator iliGQ,iliGQfin;
  // on met à jour tous les noeuds    
  for(int inoeud=1;inoeud<=nbN;inoeud++)
    {for (iliet = lienetendu.begin();iliet != ilietfin; iliet++)       
        {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); 
         // on initialise la grandeur pointée: 
         dd.Valeur()=0.;
         // mise à 0 du nombre d'appel
         tab_noeud(inoeud)->Mise_non_update_Ddl_etendu(*iliet);
        };
     for (int iQu=1;iQu<=tabQ.Taille();iQu++) 
          {if (tabQ(iQu) != NULL)
            {iliGQfin = tabQ(iQu)->end(); 	
             for (iliGQ = tabQ(iQu)->begin();iliGQ != iliGQfin; iliGQ++)       
              {TypeQuelconque& tq = tab_noeud(inoeud)->ModifGrandeur_quelconque((*iliGQ).EnuTypeQuelconque());
               TypeQuelconque::Grandeur & grandeur = *(tq.Grandeur_pointee());
               // on initialise la grandeur pointée: 
               grandeur *= 0.;
               // mise à 0 du nombre d'appel
               tab_noeud(inoeud)->Mise_non_update_grandeurs_quelconques((*iliGQ).EnuTypeQuelconque());
              };
            }
          };
    };		
 };

// D) dernière étape: (par exemple calcul des moyennes en chaque noeuds)
void Maillage::FinTransfertPtIntegAuNoeud
           (const List_io < Ddl_enum_etendu >& lienetendu,const Tableau <List_io < TypeQuelconque > * >& tabQ,int cas)
{switch(cas)
  { case 1: // cas du transfert par moyennage
	 { int nbN=tab_noeud.Taille();
	   List_io <Ddl_enum_etendu>::const_iterator iliet,ilietfin  = lienetendu.end();
	   List_io <TypeQuelconque>::const_iterator iliGQ,iliGQfin;
	   // on passe en revue les grandeurs aux noeuds, et on les moyennes
	   for(int inoeud=1;inoeud<=nbN;inoeud++)
        { // .. pour les ddl étendus ..
          for (iliet = lienetendu.begin();iliet != ilietfin; iliet++)
              {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); 
               // on modifie la grandeur pointée: -1 car ici on vient d'appeler
               //  ModifDdl_etendu qui comptabilise un appel de +
  //             dd.Valeur()/=(tab_noeud(inoeud)->DdlEtendue_update(*iliet)-1);
               int nbappel = MaX((tab_noeud(inoeud)->DdlEtendue_update(*iliet)-1),1);
               dd.Valeur()/=nbappel;
              };
          // .. pour les grandeurs quelconques ..
          for (int iQu=1;iQu<=tabQ.Taille();iQu++) 
          {if (tabQ(iQu) != NULL)
            {iliGQfin = tabQ(iQu)->end(); 	
             for (iliGQ = tabQ(iQu)->begin();iliGQ != iliGQfin; iliGQ++)       
              {TypeQuelconque_enum_etendu enuQ = (*iliGQ).EnuTypeQuelconque();
               TypeQuelconque& tq = tab_noeud(inoeud)->ModifGrandeur_quelconque(enuQ);
               TypeQuelconque::Grandeur & grandeur = *(tq.Grandeur_pointee());
               // on modifie les grandeurs pointées: -1 car ici on vient d'appeler
               //  ModifGrandeur_quelconque qui comptabilise un appel de +
               grandeur /= MaX((tab_noeud(inoeud)->Grandeur_quelconque_update(enuQ)-1),1);
//--- debug
//if (iliGQ == tabQ(iQu)->begin())
//    cout << " noeud " << inoeud << " grandeur " << grandeur << endl;
//--- fin debug               
              };
            }
          };
        };
       break;
	 }
	default :
	 cout << "\n *** cas non implante, cas = " << cas 
	      << "\n  FinTransfertPtIntegAuNoeud(... ";
	 Sortie(1);
  };
		
};

// fonctions utilitaires du même genre

// ajout sur le maillage d'un conteneur particulier quelconque
void Maillage::AjoutConteneurAuNoeud(TypeQuelconque& tQ)
{ int nbN=tab_noeud.Taille();
  // on met à jour les noeuds
  for(int i=1;i<=nbN;i++)
   { // on ajoute le  type quelconque au noeud
     tab_noeud(i)->AjoutUnTypeQuelconque(tQ);
     // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté
     tab_noeud(i)->Mise_non_update_grandeurs_quelconques();
   };
};

// ajout sur le maillage d'un ou plusieur ddl_enum_etendu comme conteneur
void Maillage::AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu)
{ // on crée des tableaux pour optimiser le nombre d'appel aux fonctions d'ajout de grandeur aux noeuds
  // 1) cas des Ddl_enum_etendu
  Tableau <Ddl_enum_etendu > tab_ddlEnuEtendu(lienu.size());
  {List_io < Ddl_enum_etendu >::const_iterator ilienu,ilienufin = lienu.end();
   int indice = 1;
   for (ilienu = lienu.begin();ilienu != ilienufin; ilienu++,indice++)
       tab_ddlEnuEtendu(indice) = (*ilienu);
   };
  
  int nbN=tab_noeud.Taille();
  int nb_ienu = lienu.size();
  // on met à jour les noeuds    
  for(int i=1;i<=nbN;i++)
   { // Pour les grandeurs ddl étendu on les ajoutes aux noeuds si ce n'est pas déjà fait
     tab_noeud(i)->AjoutTabDdl_etendu(tab_ddlEnuEtendu);
     // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté
     for (int idee=1; idee <= nb_ienu; idee++)
         tab_noeud(i)->Mise_non_update_Ddl_etendu(tab_ddlEnuEtendu(idee));
    };
};

//  initialisation des updates de ddl_étendu uniquement sur les noeuds: on met à 0 les ddl_etendu correspondant, 
//  les compteurs, comptant le nombre de fois où les noeuds sont modifiés, sont mis à 0
void Maillage::InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienetendu)
 {int nbN=tab_noeud.Taille();
  List_io <Ddl_enum_etendu>::const_iterator iliet,ilietfin  = lienetendu.end(); 
  // on met à jour tous les noeuds    
  for(int inoeud=1;inoeud<=nbN;inoeud++)
    {for (iliet = lienetendu.begin();iliet != ilietfin; iliet++)       
        {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); 
         // on initialise la grandeur pointée: 
         dd.Valeur()=0.;
        };
     // on met à 0 le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté
     tab_noeud(inoeud)->Mise_non_update_Ddl_etendu();
    };		
 };

//  initialisation des updates d'un seul ddl_étendu uniquement sur les noeuds: on met à 0 le ddl_etendu correspondant, 
//  le compteur, comptant le nombre de fois où le noeud est modifié, est mis à 0
void Maillage::InitUpdateAuNoeud(const Ddl_enum_etendu & enetendu)
 {int nbN=tab_noeud.Taille();
  // on met à jour tous les noeuds    
  for(int inoeud=1;inoeud<=nbN;inoeud++)
    { // on initialise la grandeur pointée:
      (tab_noeud(inoeud)->ModifDdl_etendu(enetendu)).Valeur()=0.; 
      // on met à 0 le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté
      tab_noeud(inoeud)->Mise_non_update_Ddl_etendu();
    };		
 };

// moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié)	 
void Maillage::MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu)	 
{ int nbN=tab_noeud.Taille();
  // on passe en revue les grandeurs aux noeuds, et on les moyennes
  for(int inoeud=1;inoeud<=nbN;inoeud++)
    { Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(enu); 
      // on modifie la grandeur pointée: -1 car ici on vient d'appeler
      //  ModifDdl_etendu qui comptabilise un appel de +
      int nbappel = (tab_noeud(inoeud)->DdlEtendue_update(enu)-1);
      dd.Valeur()/=nbappel;
    };
};
 
// initialisation des coordonnées à t et tdt aux mêmes valeurs qu'à 0
// utile quand on veut utiliser les métriques pour un pb non couplés
void Maillage::Init_Xi_t_et_tdt_de_0()
{ int nbN=tab_noeud.Taille();
  // on passe en revue les grandeurs aux noeuds, et on les moyennes
  for(int inoeud=1;inoeud<=nbN;inoeud++)
    { Noeud & noe = *tab_noeud(inoeud);
      const Coordonnee& co1 = noe.Coord0();
      noe.Change_coord1(co1);
      noe.Change_coord2(co1);
    };
};

// lecture des mouvements solides si nécessaire
void Maillage::Lecture_des_mouvements_solides(UtilLecture * entreePrinc)
 { // on définit un mouvement solide (vide par défaut)
   MvtSolide mvtsolide;
   if (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL) // cas de mouvements initiaux initiaux
      { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ;   
        entreePrinc->NouvelleDonnee(); // on passe le mot clé
      };
   // lecture éventuelle des mouvements solides
   mvtsolide.Lecture_mouvements_solides(entreePrinc); 
   // traitement au cas où il y a eu lecture de mouvements non nul
   if (mvtsolide.ExisteMvtSolide())
   	{ if (ParaGlob::NiveauImpression() >= 6) 
          cout << " traitement des mouvements solides initiaux sur le maillage " << endl ;   
      // on passe le mot clé de fin de mouvement solides pour les lectures suivantes
      entreePrinc->NouvelleDonnee();
     
      // --- dans le cas où il y a des centres de rotation qui sont des positions de noeud, on renseigne
      // a) récupération des centres de rotation noeud, éventuellement
      const list <String_et_entier>& lis_centre_noeud = mvtsolide.Liste_ident_centreNoeud();
      if (lis_centre_noeud.size() != 0)
      { list <String_et_entier>::const_iterator ict,ictfin=lis_centre_noeud.end();
        list <Coordonnee> list_coor; // liste des coordonnées des noeuds centre de rotation
        for (ict = lis_centre_noeud.begin();ict!=ictfin;ict++)
         { // a priori ne concerne que le maillage en question
           if (((*ict).nom == "")|| ((*ict).nom == nomDuMaillage))
             // cas normal
             { int num_noeud = (*ict).n;
               if ((num_noeud < 0) || (num_noeud > tab_noeud.Taille()))
                 { cout << "\n *** erreur sur le numero de noeud de centre de rotation = "<< num_noeud
                        << " on ne peut pas appliquer la rotation " << endl;
                   if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ;
                 };
               list_coor.push_back(tab_noeud(num_noeud)->Coord0()); // on récupère les coordonnées initiales
             }
          else // cas où il s'agit d'un autre maillage, pour l'instant non pris en compte
            { cout << "\n *** erreur sur le numero de noeud concerne un autre maillage = "<< (*ict).nom
                        << " cette option n'est pas prise en compte  " << endl;
                   if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ;
                 };
         };
       // b)  maintenant on passe l'info au mouvement solide
       mvtsolide.RenseigneCentreNoeud(list_coor);
      };
      int nbnoeud = tab_noeud.Taille();
      Coordonnee point_inter;
      for (int ne=1;ne<=nbnoeud;ne++)
       { point_inter = tab_noeud(ne)->Coord0(); // récupération des coordonnées initiales
         mvtsolide.AppliqueMvtSolide(point_inter); // on applique le mouvement solide
         tab_noeud(ne)->Change_coord0(point_inter); // on met à jour les nouvelles coordonnées
       };
   	};
 };
 
// ajout d'une liste de noeud à un maillage
// si le numéro de maillage associé au noeud est nul, il est remplacé par celui du maillage
// si le numéro de maillage est déjà existant et est différent ce celui de this, il y a
// création d'un nouveau noeud identique, avec le numéro this
// ajout éventuel d'une liste de référence de noeuds, si celle-ci est non-nulle
// il y a création de nouvelles ref correspondantes au numéro de maillage de this
// et ces références sont rajoutées à lesRef
void Maillage::Ajout_de_Noeuds(const list <Noeud *> & lisN, list <const Reference*>* lref,LesReferences* lesRef )
{ // on change de taille du tableau de noeud et on ajoute les noeuds passés en paramètre
  int nbN = tab_noeud.Taille();
  int nb_lisN = lisN.size();
  tab_noeud.Change_taille(nbN+nb_lisN);
  list<Noeud*>::const_iterator il,ilfin=lisN.end();
  // on définit un tableau indiquant les nouveaux numéros indicés par les anciens
  // t_new_num(i) : = le numéro du nouveau noeud correspondant au noeud initial i
  int taille_maxi = 0;
  for(il=lisN.begin();il!=ilfin;il++) // un premier passage pour avoir la dimension maxi du tableau
    if ((*il)->Num_noeud() > taille_maxi)
       taille_maxi = (*il)->Num_noeud();
  Tableau<int> t_new_num(taille_maxi,0); // les données du tableau sont initialisées à 0  
  
  int i=1;
  for(il=lisN.begin();il!=ilfin;il++,i++)
    { int ancien_num = (*il)->Num_noeud();
      if (((*il)->Num_Mail() != 0) && ((*il)->Num_Mail() != idmail))
       { // on crée un nouveau noeud identique
         Noeud* new_noe = new Noeud(*(*il));
         // on change les numéros de noeud et de maillage
         new_noe->Change_num_noeud(i+nbN);
         new_noe->Change_num_Mail(idmail);
         // affectation
         tab_noeud(i+nbN) = new_noe;
       }
      else // sinon cela signifie que le noeud n'appartient pas pour l'instant à un maillage
       { // on change les numéros de noeud et de maillage
         (*il)->Change_num_noeud(i+nbN);
         (*il)->Change_num_Mail(idmail);
         // affectation
         tab_noeud(i+nbN) = (*il);
       };
      // on enregistre le nouveau num que si l'ancien est non nul
      if (ancien_num != 0)
           t_new_num(ancien_num) = i+nbN;
    };
  // cas de la présence d'une liste de référence éventuellement à ajouter
  if (lref != NULL)
   {
   #ifdef MISE_AU_POINT
     if (lesRef == NULL)
      { cout << "\n erreur le conteneur de reference n'est pas defini "
             << "\n Maillage::Ajout_de_Noeuds(... ";
        Sortie(1);
      };
   #endif
     // on va passer en revue la liste des références à ajouter
     list<const Reference*>::const_iterator im,imfin = lref->end();
     for (im=lref->begin();im!=imfin;im++)
       { if ((*im)->Indic() == 1)
         {const ReferenceNE & refN  = *((ReferenceNE *) (*im));
          // on va contruire une nouvelle référence ad hoc:
          string nouveau_nom = (refN.Nom());
          // on regarde s'il y a déjà une ref avec le même nom dans le maillage
          // si oui on change le nom de la ref à ajouter
          string ajout="";int num=0;
          while (lesRef->Existe((refN.Nom()+ajout),idmail))
                 {num++;ajout = "_"+ChangeEntierSTring(num);};
          if (ajout != "")
           { nouveau_nom += ajout;
             if (ParaGlob::NiveauImpression() > 0)
               cout << "\n >>> attention la reference "<<refN.Nom()<<" a ajouter au maillage "
                    << nomDuMaillage << " a un nouveau nom "<< (refN.Nom()+ajout);
           };
          Tableau<int> tt = refN.Tab_num(); // on récupère une copie du tableau de ref
          // on le met à jour / aux nouveaux numéros
          int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref
          for (int k=1;k<= tai; k++)
           {if (t_new_num(k) != 0)
              { kn++;
                tt(kn) = t_new_num(k); // cas où effectivement on a rajouté un noeud qui était déjà référencé
                 // dans l'ancienne référence
              }
            else
              {if (ParaGlob::NiveauImpression() > 0)
                cout << "\n le noeud "<<k<<" de la ref "<<refN.Nom()
                     <<" n'existe plus dans le nouveau maillage "<<nomDuMaillage;
              };
           };
          // on redimentionne le tableau au maxi d'élément
          tt.Change_taille(kn);
          // on crée la nouvelle référence si le tableau n'est pas nul
          if (tt.Taille() != 0)
             { ReferenceNE* newref = new ReferenceNE(tt,idmail,1,nouveau_nom);
               // ajout de la référence
               lesRef->Ajout_reference(newref);
             };
         };
       
       };
   };
};

// ajout d'une liste d'éléments et de noeud à un maillage
// si le numéro de maillage associé à l'élément ou noeud est nul, il est remplacé par celui du maillage
// si le numéro de maillage est déjà existant et est différent ce celui de this, il y a
// création d'un nouvel item  identique, avec le numéro this
// ajout éventuel d'une liste de références associées , si celle-ci est non-nulle
// il y a création de nouvelles ref correspondantes au numéro de maillage de this
// et ces références sont rajoutées à lesRef
// les noeuds qui sont associés aux éléments de lisE, doivent faire partie : soit de lisN, soit du maillage this
void Maillage::Ajout_elements_et_noeuds
   (const list <Noeud *> & lisN, const list <Element *> & lisE,list <const Reference*>* lref,LesReferences* lesRef )
{ // -- on commence par ajouter les noeuds en gardant une trace du type d'ajout

  // on change de taille du tableau de noeud et on ajoute les noeuds passés en paramètre
  int nbN = tab_noeud.Taille();
  int nb_lisN = lisN.size();
  tab_noeud.Change_taille(nbN+nb_lisN);
  list<Noeud*>::const_iterator il,ilfin=lisN.end();
  // on définit un tableau indiquant les nouveaux numéros indicés par les anciens
  // t_new_num(i) : = le numéro du nouveau noeud correspondant au noeud initial i
  int taille_maxi = 0;
  for(il=lisN.begin();il!=ilfin;il++) // un premier passage pour avoir la dimension maxi du tableau
    if ((*il)->Num_noeud() > taille_maxi)
       taille_maxi = (*il)->Num_noeud();
  Tableau<int> t_new_num(taille_maxi,0); // les données du tableau sont initialisées à 0  
  
  list<Noeud*> li_nevez_noeud; // la liste des nouvelles positions de noeuds
  int i=1;
  for(il=lisN.begin();il!=ilfin;il++,i++)
    { int ancien_num = (*il)->Num_noeud();
      if (((*il)->Num_Mail() != 0) && ((*il)->Num_Mail() != idmail))
       { // on crée un nouveau noeud identique
         Noeud* new_noe = new Noeud(*(*il));
         // on change les numéros de noeud et de maillage
         new_noe->Change_num_noeud(i+nbN);
         new_noe->Change_num_Mail(idmail);
         // affectation
         tab_noeud(i+nbN) = new_noe;
         li_nevez_noeud.push_back(new_noe);
       }
      else // sinon cela signifie que le noeud n'appartient pas pour l'instant à un maillage
       { // on change les numéros de noeud et de maillage
         (*il)->Change_num_noeud(i+nbN);
         (*il)->Change_num_Mail(idmail);
         // affectation
         tab_noeud(i+nbN) = (*il);
         li_nevez_noeud.push_back((*il));
       };
      // on enregistre le nouveau num que si l'ancien est non nul
      // sinon
      if (ancien_num != 0)
           t_new_num(ancien_num) = i+nbN;
    };

  // -- puis on s'occupe des éléments


  // on change de taille du tableau d'éléments et on ajoute les éléments passés en paramètre
  int nbE = tab_element.Taille();
  int nb_lisE = lisE.size();
  tab_element.Change_taille(nbE+nb_lisE);
  list<Element*>::const_iterator ie,iefin=lisE.end();
  // on définit un tableau indiquant les nouveaux numéros indicés par les anciens
  // t_new_num_elem(i) : = le numéro du nouvel élément correspondant à l'élément initial i
  taille_maxi = 0;
  for(ie=lisE.begin();ie!=iefin;ie++) // un premier passage pour avoir la dimension maxi du tableau
    if ((*ie)->Num_elt_const() > taille_maxi)
       taille_maxi = (*ie)->Num_elt_const();
  Tableau<int> t_new_num_elem(taille_maxi,0); // les données du tableau sont initialisées à 0  

  i=1;
  for(ie=lisE.begin();ie!=iefin;ie++,i++)
    { int num_elt = i+nbE; // numéro interne de l'élément
      int ancien_num = (*ie)->Num_elt_const();
      Element* new_elem = NULL; // sera affecté dans le if qui suit
      if (((*ie)->Num_maillage() != 0) && ((*ie)->Num_maillage() != idmail))
       { Element::Signature signa = (*ie)->Signature_element(); // récupération de la signature de l'élément
         // on crée un nouveau element identique
         new_elem = Element::Choix_element(idmail,num_elt,signa);
         if (new_elem == NULL)
           { // l'operation a echouee
             cout << "\n Erreur dans la creation d'un nouvel element ****** ";
             cout << "\n element : " << Nom_interpol(signa.id_interpol)
                  << " " << Nom_geom(signa.id_geom)
                  << "\n Maillage::Ajout_elements_et_noeuds(... " << endl;
             Sortie (1);
            };
         // on affecte les données internes
         (*new_elem) = (*(*ie));
         // il faut de nouveau définir les numéros de maillage et d'élément
         new_elem->Change_num_elt(num_elt);
         new_elem->Change_num_maillage(idmail);
       }
      else // sinon cela signifie que l'éléments n'appartient pas pour l'instant à un maillage
       { // on change les numéros d'élément et de maillage, et peut directement l'affecté
         (*ie)->Change_num_elt(num_elt);
         (*ie)->Change_num_maillage(idmail);
         new_elem = (*ie);
       };

      // maintenant on va s'occuper de la connexion
      Tableau<Noeud *>& t_n_elem = new_elem->Tab_noeud();
      int nbnoe = t_n_elem.Taille();
      for (int inoe = 1; inoe <= nbnoe; inoe++)
        {// on regarde si le noeud fait partie de la liste des noeuds en entrée
         // ou alors, qu'il utilise les noeuds existants
         bool fait_partie = false;
         list<Noeud*>::iterator it=li_nevez_noeud.begin();
         for(il=lisN.begin();il!=ilfin;il++,it++)
           if ((*il) == t_n_elem(inoe))
             { fait_partie = true; break;};
         // deux cas
         if (fait_partie)
           // on réaffecte
           {t_n_elem(inoe)=(*it);}
         else // sinon cela signifie que l'on utilise les noeuds existants
              // on vérifie qu'il s'agit bien de noeud existant
           { bool verif = false;
             for (int j=1;j<= nbN;j++) // on boucle jusqu'à nbN = le nombre initial de noeud
               if (tab_noeud(j) == t_n_elem(inoe))
                 {verif = true; break;};
             if (!verif)
              { cout << "\n erreur, la connexion de l'element a ajouter n'est pas recevable "
                     << " le noeud "<<t_n_elem(inoe)->Num_noeud()<< " de l'element "
                     << new_elem->Num_elt() << " n'existe pas dans le maillage initial "
                     << "\n Maillage::Ajout_elements_et_noeuds(... " << endl;
                Sortie (1);
              };              
           }
        };
      // arrivée ici c'est que tout est ok, on ajoute l'élément
      tab_element(nbE+i)=new_elem;
      // on enregistre le nouveau num que si l'ancien est non nul
      if (ancien_num != 0)
           t_new_num_elem(ancien_num) = nbE+i;
    };
 
 
  // cas de la présence d'une liste de référence éventuellement à ajouter
  if (lref != NULL)
   {
   #ifdef MISE_AU_POINT
     if (lesRef == NULL)
      { cout << "\n erreur le conteneur de reference n'est pas defini "
             << "\n Maillage::Ajout_de_Noeuds(... ";
        Sortie(1);
      };
   #endif
     // on va passer en revue la liste des références à ajouter
     list<const Reference*>::const_iterator im,imfin = lref->end();
     for (im=lref->begin();im!=imfin;im++)
       {int indic = (*im)->Indic(); // pour simplifier
        switch (indic)
         {case 1: // cas d'une ref de noeuds
           {const ReferenceNE & refN  = *((ReferenceNE *) (*im));
            // on va contruire une nouvelle référence ad hoc:
            string nouveau_nom = (refN.Nom());
            // on regarde s'il y a déjà une ref avec le même nom dans le maillage
            // si oui on change le nom de la ref à ajouter
            string ajout="";int num=0;
            while (lesRef->Existe((refN.Nom()+ajout),idmail))
                   {num++;ajout = "_"+ChangeEntierSTring(num);};
            if (ajout != "")
             { nouveau_nom += ajout;
               if (ParaGlob::NiveauImpression() > 0)
                 cout << "\n >>> attention la reference "<<refN.Nom()<<" a ajouter au maillage "
                      << nomDuMaillage << " a un nouveau nom "<< (refN.Nom()+ajout);
             };
            Tableau<int> tt = refN.Tab_num(); // on récupère une copie du tableau de ref
            Tableau<int> tt_new = tt; // le nouveau tableau
            // on le met à jour / aux nouveaux numéros
            int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref
            for (int k=1;k<= tai; k++)
             {if (t_new_num(tt(k)) != 0)
                { kn++;
                  tt_new(kn) = t_new_num(tt(k)); // cas où effectivement on a rajouté un noeud qui était déjà référencé
                   // dans l'ancienne référence
                }
              else
                {if (ParaGlob::NiveauImpression() > 0)
                  cout << "\n le noeud "<<tt(k)<<" de la ref "<<refN.Nom()
                       <<" n'existe plus dans le nouveau maillage "<<nomDuMaillage;
                };
             };
            // on redimentionne le tableau au maxi d'élément
            tt_new.Change_taille(kn);
            // on crée la nouvelle référence si le tableau n'est pas nul
            if (tt_new.Taille() != 0)
              {ReferenceNE* newref = new ReferenceNE(tt_new,idmail,indic,nouveau_nom);
               // ajout de la référence
               lesRef->Ajout_reference(newref);
              };
            break;
           }
          case 2: // cas d'une ref d'éléments
           {const ReferenceNE & refE  = *((ReferenceNE *) (*im));
            // on va contruire une nouvelle référence ad hoc:
            string nouveau_nom = (refE.Nom());
            // on regarde s'il y a déjà une ref avec le même nom dans le maillage
            // si oui on change le nom de la ref à ajouter
            string ajout="";int num=0;
            while (lesRef->Existe((refE.Nom()+ajout),idmail))
                   {num++;ajout = "_"+ChangeEntierSTring(num);};
            if (ajout != "")
             { nouveau_nom += ajout;
               if (ParaGlob::NiveauImpression() > 0)
                 cout << "\n >>> attention la reference "<<refE.Nom()<<" a ajouter au maillage "
                      << nomDuMaillage << " a un nouveau nom "<< (refE.Nom()+ajout);
             };
            Tableau<int> tt = refE.Tab_num(); // on récupère une copie du tableau de ref
            // on le met à jour / aux nouveaux numéros
            int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref
            Tableau<int> tt_new = tt; // le nouveau tableau
            for (int k=1;k<= tai; k++)
             {if (t_new_num_elem(tt(k)) != 0)
                { kn++;
                  tt_new(kn) = t_new_num_elem(tt(k)); // cas où effectivement on a rajouté un élément qui était déjà référencé
                   // dans l'ancienne référence
                }
              else
                {if (ParaGlob::NiveauImpression() > 0)
                  cout << "\n l'element "<<tt(k)<<" de la ref "<<refE.Nom()
                       <<" n'existe plus dans le nouveau maillage "<<nomDuMaillage;
                };
             };
            // on redimentionne le tableau au maxi d'élément
            tt_new.Change_taille(kn);
            // on crée la nouvelle référence si le tableau n'est pas nul
            if (tt_new.Taille() != 0)
              {ReferenceNE* newref = new ReferenceNE(tt_new,idmail,indic,nouveau_nom);
               // ajout de la référence
               lesRef->Ajout_reference(newref);
              };
            break;
           }
          case 3: case 4: case 5: case 6:// cas des autres refs: exemple surfaces
           {const ReferenceAF & refAF  = *((ReferenceAF *) (*im));
            // on va contruire une nouvelle référence ad hoc:
            string nouveau_nom = (refAF.Nom());
            // on regarde s'il y a déjà une ref avec le même nom dans le maillage
            // si oui on change le nom de la ref à ajouter
            string ajout="";int num=0;
            while (lesRef->Existe((refAF.Nom()+ajout),idmail))
                   {num++;ajout = "_"+ChangeEntierSTring(num);};
            if (ajout != "")
             { nouveau_nom += ajout;
               if (ParaGlob::NiveauImpression() > 0)
                 cout << "\n >>> attention la reference "<<refAF.Nom()<<" a ajouter au maillage "
                      << nomDuMaillage << " a un nouveau nom "<< (refAF.Nom()+ajout);
             };
            Tableau<int> te = refAF.Tab_Elem(); // on récupère une copie du tableau des éléments
            Tableau<int> te_new = te; // le nouveau tableau
            // apriori seules les numéros d'élément sont succeptible d'avoir changé, les numéros
            // locaux: surface, arête, noeuds relatifs à l'éléments, et pti restent inchangé
            // par contre ils peuvent être supprimés si le num d'élément est supprimé
            Tableau<int> tl = refAF.Tab_FA(); // on récupère une copie du tableau des num locaux
          
            // on  met à jour le tableau de d'éléments / aux nouveaux numéros
            int tai = te.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref
            for (int k=1;k<= tai; k++)
             {if (t_new_num_elem(te(k)) != 0)
                { kn++;
                  te_new(kn) = t_new_num_elem(te(k)); // cas où effectivement on a rajouté un élément qui était déjà référencé
                   // dans l'ancienne référence
                  tl(kn) = tl(k); // normalement k est > kn, donc cela revient à décaler
                  // en ne gardant que les termes viables
                }
              else
                {if (ParaGlob::NiveauImpression() > 0)
                  cout << "\n l'element "<<te(k)<<" de la ref "<<refAF.Nom()
                       <<" n'existe plus dans le nouveau maillage "<<nomDuMaillage;
                };
             };
            // on redimentionne le tableau au maxi d'élément
            te_new.Change_taille(kn);tl.Change_taille(kn);
            // on crée la nouvelle référence si le tableau n'est pas nul
            if (te_new.Taille() != 0)
              {ReferenceAF* newref = new ReferenceAF(te_new,tl,idmail,indic,nouveau_nom);
               // ajout de la référence
               lesRef->Ajout_reference(newref);
              };
            break;
           }
         };
       };
   };
  // -------------- ajout de références globales si elles n'existent pas ---------------------
  // ----  mise à jour de la référence de tous les éléments si elle n'existe pas déjà
  int nbElement = tab_element.Taille();
  string etout("E_tout");
  if (lesRef->Existe(etout,idmail))
       lesRef->SupprimeReference("E_tout",idmail); // on supprime la référence E_tout
  // on construit le tableau des numéros des éléments
  Tableau <int> tabE(nbElement); for (int i=1;i<=nbElement;i++) tabE(i)=i;          
  ReferenceNE*  retout = new ReferenceNE(tabE,idmail,2,etout);// construction de la référence
  lesRef->Ajout_reference(retout); // ajout de la ref, qui est maintenant géré par lesRef
  
  // ----   dans tous les cas on ajoute ou modifie la référence de tous les noeuds
  string ntout("N_tout");
  int nbNoeud = tab_noeud.Taille();
  if (lesRef->Existe(ntout,idmail))
     lesRef->SupprimeReference("N_tout",idmail); // on supprime la référence N_tout
  // on construit le tableau des numéros de noeuds
  Tableau <int> tabN(nbNoeud); for (int i=1;i<=nbNoeud;i++) tabN(i)=i;          
  ReferenceNE*  rtout = new ReferenceNE(tabN,idmail,1,ntout);// construction de la référence
  lesRef->Ajout_reference(rtout); // ajout de la ref, qui est maintenant géré par lesRef
//debug
//cout << "\n nbElement " << nbElement << ", nbNoeud "<< nbNoeud << endl;
// fin debug
 
 
};


// force la mise à une valeur d'un ddl (ou de la liste de ddl fonction de la dimention) particulier, quelques soit son activité
// si fonction_de_la_dimension = true : c'est toute les ddl fct de la dimension qui sont mis à la valeur
void Maillage::Force_Ddl_aux_noeuds_a_une_valeur(Enum_ddl enu, const double& val,Enum_dure temps, bool fonction_de_la_dimension)
{  
 int nbnoeud = tab_noeud.Taille();
 int dima = ParaGlob::Dimension();
	switch (temps) 
	 {case TEMPS_0:
		 { if (!(fonction_de_la_dimension) || !FoncDim(enu))
		    {for (int i=1;i<= nbnoeud;i++)
		      { Noeud& noe = *tab_noeud(i); // pour simplifier
			       if (noe.Existe_ici(enu)) // on intervient que si le ddl existe
			         noe.Change_val_0(enu,val);
				    };
			   }	 	  
     else 
		    {for (int i=1;i<= nbnoeud;i++)
		      { Noeud& noe = *tab_noeud(i); // pour simplifier
			       if (noe.Existe_ici(enu)) // on intervient que si le ddl existe
				       { switch (dima)
					         { case 3: noe.Change_val_0(Enum_ddl(enu+2),val);
					           case 2: noe.Change_val_0(Enum_ddl(enu+1),val);
					           case 1: noe.Change_val_0(Enum_ddl(enu),val);
						        };
					      };	 
				    };
			   };	 	  
		   break;
		 }
	  case TEMPS_t:
		 { if (!(fonction_de_la_dimension) || !FoncDim(enu))
		    {for (int i=1;i<= nbnoeud;i++)
		      { Noeud& noe = *tab_noeud(i); // pour simplifier
			       if (noe.Existe_ici(enu)) // on intervient que si le ddl existe
			         noe.Change_val_t(enu,val);
				    };
      }	 	  
     else 
		    {for (int i=1;i<= nbnoeud;i++)
		      { Noeud& noe = *tab_noeud(i); // pour simplifier
			       if (noe.Existe_ici(enu)) // on intervient que si le ddl existe
				       { switch (dima)
					        { case 3: noe.Change_val_t(Enum_ddl(enu+2),val);
					          case 2: noe.Change_val_t(Enum_ddl(enu+1),val);
					          case 1: noe.Change_val_t(Enum_ddl(enu),val);
						       };
					      };	 
				    };
			   };	 	  
		   break;
		 } 
	  case TEMPS_tdt:
		 { if (!(fonction_de_la_dimension) || !FoncDim(enu))
		    {for (int i=1;i<= nbnoeud;i++)
		      { Noeud& noe = *tab_noeud(i); // pour simplifier
			       if (noe.Existe_ici(enu)) // on intervient que si le ddl existe
			         noe.Change_val_tdt(enu,val);
				    };
			   }	 	  
     else
		    {for (int i=1;i<= nbnoeud;i++)
		      { Noeud& noe = *tab_noeud(i); // pour simplifier
			       if (noe.Existe_ici(enu)) // on intervient que si le ddl existe
				       { switch (dima)
					         { case 3: noe.Change_val_tdt(Enum_ddl(enu+2),val);
					           case 2: noe.Change_val_tdt(Enum_ddl(enu+1),val);
					           case 1: noe.Change_val_tdt(Enum_ddl(enu),val);
						        };
					      };	 
				    };
			   };
		   break;
		 }
	 };	

};


// mise à zéro de dd_enum_etendu aux noeuds : force la mise à une valeur à 0
void Maillage::Force_Ddl_etendu_aux_noeuds_a_zero(const Tableau<Ddl_enum_etendu>&  tab_enu)
{  
 int nbnoeud = tab_noeud.Taille();
 int nb_enu = tab_enu.Taille();
 for (int i=1;i<=nb_enu;i++)
	{const Ddl_enum_etendu& enu = tab_enu(i);
    for (int i=1;i<= nbnoeud;i++)
		      { Noeud& noe = *tab_noeud(i); // pour simplifier
			       if (noe.Existe_ici_ddlEtendu(enu)) // on intervient que si le ddl existe
			         noe.ModifDdl_etendu(enu).Valeur() = 0.;
				    };
	};	

};

	 
// on s'occupe de mettre à jour les types de pb et les ddl types associés
void Maillage::Mise_a_jour_type_pb_type_associe_ddl()
{ //types_de_problemes.clear();
  //ddl_representatifs_des_physiques.clear();
//  types_de_problemes.Libere();ddl_representatifs_des_physiques.Libere();
//  int nbElement = tab_element.Taille();
//string titi;
//cout << "\n nbElement "<<nbElement << " une valeur ? ";
//cin >> titi;
//  // on définit un tableau intermédiaire
//  int nombre_de_EnumElemTypeProblem = Nombre_de_EnumElemTypeProblem();
//cout << "\n nombre_de_EnumElemTypeProblem "<<nombre_de_EnumElemTypeProblem << " une valeur ? ";
//cin >> titi;
//  Tableau < int> types_de_problemes_actif(nombre_de_EnumElemTypeProblem,0);
//  types_de_problemes_actif(1)=1;
//cout << "\n taill "<<types_de_problemes_actif.Taille() << " une valeur ? ";
//cin >> titi;
//cout << "\n types_de_problemes_actif(1) "<<types_de_problemes_actif(1) << " une valeur ? ";
//cin >> titi;
// 
//  for (int i;i<=nbElement;i++)
//   {Element& ele = *tab_element(i);
//cout << "\n i"<<i <<"ele "<<ele.Num_elt() << " une valeur ? ";
//cin >> titi;
//ele.Affiche();
//cout << "\n i"<<i <<"ele "<<ele.Num_elt() << " une valeur ? ";
//cin >> titi;
//  EnumElemTypeProblem enu = ele.Id_TypeProblem();
//cout << "\n i"<<i <<"ele "<<ele.Num_elt() << " une valeur ? ";
//cin >> titi;
//int truc =enu;
//cout << "\n enu= "<<enu<<" truc "<< truc<< " une valeur ? ";
//cin >> titi;
//cout << "\n types_de_problemes_actif(1) "<<types_de_problemes_actif(1) << " une valeur ? ";
//cin >> titi;
//types_de_problemes_actif(1) = 1;
//cout << "\n types_de_problemes_actif(1) "<<types_de_problemes_actif(1) << " une valeur ? ";
//cin >> titi;
//types_de_problemes_actif(int(enu)) = 1;
//cout << "\n types_de_problemes_actif(1) "<<types_de_problemes_actif(1) << " une valeur ? ";
//cin >> titi;
// //   types_de_problemes_actif(truc) = 1; // on rend actif l'élément du tableau
//   };
//cout << "\n  une valeur ? ";
//cin >> titi;
//  // maintenant on regarde le nombre de pb actif
//  int nb_pb = 0; // init
//  for (int i=1;i<=nombre_de_EnumElemTypeProblem;i++)
//    if (types_de_problemes_actif(i)) nb_pb++;
//cout << "\n  une valeur ? ";
//cin >> titi;
//  // on redimentionne et on rempli
//  types_de_problemes.Change_taille(nb_pb);
//cout << "\n  une valeur ? ";
//cin >> titi;
//  nb_pb = 0; // init
//  for (int i=1;i<=nombre_de_EnumElemTypeProblem;i++)
//    if (types_de_problemes_actif(i))
//      {nb_pb++;types_de_problemes(nb_pb)=EnumElemTypeProblem(i);};
//cout << "\n  une valeur ? ";
//cin >> titi;
// 
//    
////cout << "\n enu"<<enu << " une valeur ? ";
////cin >> titi;
////    bool trouve = false;
////    list <EnumElemTypeProblem>::iterator il,ilfin=types_de_problemes.end();
////if (!types_de_problemes.empty())
////cout << "\n ilfin  il begin " << (*types_de_problemes.begin())<< " une valeur ? ";
////cin >> titi;
////    for (il=types_de_problemes.begin();il != ilfin; il++)
////     {cout << "\n "<<NomElemTypeProblem(*il) << " une valeur ? ";
////      cin >> titi;
////     
////      if ((*il)==enu) {trouve = true; break;};
////     };
////    if (find(types_de_problemes.begin(),types_de_problemes.end(),enu) == types_de_problemes.end())
////    if (!trouve)
////EnumElemTypeProblem tutu = MECA_SOLIDE_DEFORMABLE;
// //      { types_de_problemes.push_back(tutu);};
////    
////    int taill = types_de_problemes.Taille();
////    for (int j=1;j<=taill;j++)
////      if (types_de_problemes(j) == enu)
////       { types_de_problemes.Change_taille(taill+1);
////         types_de_problemes(taill+1)=enu;
////         break;
////       };
////   };
////  inter.sort(); inter.unique();
////  types_de_problemes = inter;
//  // on parcours les types de pb pour attribuer les types de ddl
////  list <EnumElemTypeProblem>::iterator il,ilfin=types_de_problemes.end();
////  for (il=types_de_problemes.begin();il != ilfin;il++)
//// 
////    { 	switch (types_de_problemes(j))
////       {case MECA_SOLIDE_DEFORMABLE :
////         ddl_representatifs_des_physiques.push_back(X1);break;
////        case THERMIQUE :
////         ddl_representatifs_des_physiques.push_back(TEMP);break;
////        default :
////         cout << "\n***Erreur : pour l'instant le type de probleme: "<<NomElemTypeProblem(*il)
////               << "n'est pas pris en compte !\n";
////         cout << "\n Maillage::LectureMaillage(... \n";
////         Sortie(1);
////       };
////   };
////  types_de_problemes.sort(); types_de_problemes.unique();
////  ddl_representatifs_des_physiques.sort(); ddl_representatifs_des_physiques.unique();
// 
// ddl_representatifs_des_physiques.Change_taille(nb_pb);
// for (int j=1;j<=nb_pb;j++)
//     { 	switch (types_de_problemes(j))
//       {case MECA_SOLIDE_DEFORMABLE :
//         ddl_representatifs_des_physiques(j)=X1;break;
//        case THERMIQUE :
//         ddl_representatifs_des_physiques(j)=TEMP;break;
//        default :
//         cout << "\n***Erreur : pour l'instant le type de probleme: "
//               <<NomElemTypeProblem(types_de_problemes(j))
//               << "n'est pas pris en compte !\n";
//         cout << "\n Maillage::LectureMaillage(... \n";
//         Sortie(1);
//       };
//   };

};

