// 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 "MvtSolide.h"
#include "TypeQuelconqueParticulier.h"

// CONSTRUCTEURS :
// pour tous les constructeurs: map < string, int , std::less <string> >* lisNomMail,
// est un tableau associatif nom <=> numéro de maillage, qui est utilisé par 
// les maillages, mais mis à jour par chaque maillage.
// nom_maill : est facultatif, s'il est différent de ".", il est pris en compte comme nom de maillage
		
// Constructeur par defaut
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail,int nmail,int dim
                    ,const string& nom_maill):
   listeNomMail(lisNomMail),nomDuMaillage(),idmail(nmail),dimension(dim)
   ,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front(),indice()
   , list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element()
   ,ddl_representatifs_des_physiques(),types_de_problemes()
   , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
   ,detruire_les_noeuds_et_elements(true)

  {	if (nom_maill == ".")
     {// tout d'abord on donne un nom par défaut au maillage
      nomDuMaillage = "pas_de_nom";  
      while  (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
      { // on cherche un nom quelconque qui n'est pas déjà utilisé
        nomDuMaillage += '_';      
      };
     }
    else // le paramètre de nom de maillage est valide
     { nomDuMaillage = nom_maill;
     };
    // maintenant on associe le nom au numéro dans la map
    listeNomMail[nomDuMaillage]=idmail;
  };

// Constructeur fonction d'une dimension, du nombre de noeuds
//  du nombre d'elements, et d'un numero d'identification (le nb de maillage)
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail
                    ,int dim,int n_noeud,int n_elt,int nmail,const string& nom_maill):
// Constructeur utile quand la dimension, le nombre de noeuds
// et le nombre d'elements du maillage sont connus
   listeNomMail(lisNomMail),tab_noeud(n_noeud),tab_element(n_elt),listFrontiere(),tab_noeud_front()
   ,indice(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element()
   ,ddl_representatifs_des_physiques(),types_de_problemes()
   , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
   ,detruire_les_noeuds_et_elements(true)

{if (nmail <=0)
	 {	cout << "\nErreur : numero de maillage invalide !\n";
		  cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n";
		  Sortie(1);
	 };
 idmail = nmail;
 // traitement du nom de maillage
 if (nom_maill ==".")
   {// on donne un nom par défaut au maillage
    nomDuMaillage = "pas_de_nom";  
    while  (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
    { // on cherche un nom quelconque qui n'est pas déjà utilisé
      nomDuMaillage += '_';      
    };
   }
 else // le paramètre de nom de maillage est valide
   { nomDuMaillage = nom_maill;
   };
 // maintenant on associe le nom au numéro dans la map
 listeNomMail[nomDuMaillage]=idmail;
 
 if ( (dim<1) || (dim>3) )
	 {	cout << "\nErreur : dimension invalide !\n";
		  cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n";
		  Sortie(1);
	 };
	if ( n_noeud<=0 )
	 {	cout << "\nErreur : nombre de noeuds non valide !\n";
		  cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n";
		  Sortie(1);
	 };
	if ( n_elt<=0 )
	 {	cout << "\nErreur : nombre d'elements invalide !\n";
		  cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n";
		  Sortie(1);
	 };
	dimension=dim;
};
		
		
// Constructeur fonction de la plupart des informations (qui peuvent être vide
// mais doivent être cohérentes)
// *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments,
// ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail
		          ,int dim,list <Noeud* >& li_noeud, list <Element* > li_element
		          ,int nmail,const string& nom_maill ):
   listeNomMail(lisNomMail),tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front()
   ,indice(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element()
   ,ddl_representatifs_des_physiques(),types_de_problemes()
   , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
   ,detruire_les_noeuds_et_elements(true)

{  if (ParaGlob::NiveauImpression() >= 5)
        cout << " \n creation du maillage: " << nom_maill << endl;
   if (nmail <=0)
	   {	cout << "\nErreur2 : numero de maillage invalide !\n";
		    cout << "MAILLAGE::MAILLAGE( ) \n";
		    Sortie(1);
	   };
   // si le numéro de maillage est déjà utilisé, on signale que la place est prise
   for (std::map< string, int , std::less <string> >::iterator it=listeNomMail.begin();
        it!=listeNomMail.end(); ++it)
    { if ((it->second) == nmail)
       { cout << "\n *** erreur: le numero de maillage "<<nmail
              << " est deja utilise pour le maillage " << (it->first)
              << "\n constructeur: Maillage::Maillage (..."<< flush;
         Sortie(1);
       };
    };
   // sinon c'est ok
   idmail = nmail;
   // traitement du nom de maillage
   if (nom_maill ==".")
     {// on donne un nom par défaut au maillage
      nomDuMaillage = "pas_de_nom";  
      while  (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
      { // on cherche un nom quelconque qui n'est pas déjà utilisé
        nomDuMaillage += '_';      
      };
     }
   else // le paramètre de nom de maillage est valide
     { nomDuMaillage = nom_maill;
     };
   // maintenant on associe le nom au numéro dans la map
   listeNomMail[nomDuMaillage]=idmail;
   
   if ( (dim<1) || (dim>3) )
	   {	cout << "\nErreur2 : dimension invalide !\n";
		    cout << "MAILLAGE::MAILLAGE(... \n";
		    Sortie(1);
	   };
   dimension=dim;
   // récupération des noeuds
   int nbN = li_noeud.size();
   list <Noeud* >::iterator il,ilfin=li_noeud.end();
   Change_nb_noeud(nbN);
//   tab_noeud.Change_taille(nbN,NULL);
   // on vérifie que la numérotation est correcte pour les noeuds
   // c'est-à-dire que tous les numéros peuvent être rangés à suivre 
   bool numerotation_correcte = true;   
   for  (il=li_noeud.begin();il!=ilfin;il++)
     {int nb = (*il)->Num_noeud();
      if (nb<1 || nb > nbN)
     	{numerotation_correcte=false;
         break;
     	};
     };
   if (numerotation_correcte)  	
    {// on peut y aller sans vérif
     for  (il=li_noeud.begin();il!=ilfin;il++)
       tab_noeud((*il)->Num_noeud()) = *il;
    }
   else
    // on est obligé de changer la numérotation des noeuds
    {int nb=1;
     for  (il=li_noeud.begin();il!=ilfin;il++,nb++)
       {tab_noeud(nb) = *il;int nbinit=(*il)->Num_noeud();
        (*il)->Change_num_noeud(nb);
        if (ParaGlob::NiveauImpression() > 0)
          {cout << "\n warning : le numero initial du noeud " << nbinit << " est remplace par "
           		<< " le numero d'ordre attribue automatiquement par herezh " << nb
           		<< "\n seul ce dernier sera utilise par la suite ! " << endl;
           if (ParaGlob::NiveauImpression() > 5)
             cout << "\n  Maillage::Maillage (map < string, int ,.... " << endl;		
          };
       };
    };
   // récupération des éléments
   int nbE = li_element.size();
   list <Element* >::iterator ile,ilefin=li_element.end();
   Change_nb_element(nbE);
   // on vérifie que la numérotation est correcte pour les éléments (comme pour les noeuds)
   // c'est-à-dire que tous les numéros peuvent être rangés à suivre 
   numerotation_correcte = true;   
   for (ile=li_element.begin();ile!=ilefin;ile++)
     {int nb = (*ile)->Num_elt();
      if (nb<1 || nb > nbE)
     	{numerotation_correcte=false;
         break;
     	};
     };
   if (numerotation_correcte)  	
    {// on peut y aller sans vérif
     for (ile=li_element.begin();ile!=ilefin;ile++)
       tab_element((*ile)->Num_elt()) = *ile;
    }
   else
    // on est obligé de changer la numérotation des éléments
    {int nb=1;
     for (ile=li_element.begin();ile!=ilefin;ile++,nb++)
       {tab_element(nb) = *ile;int nbinit=(*ile)->Num_elt();
        (*ile)->Change_num_elt(nb);
        if (ParaGlob::NiveauImpression() > 0)
          {cout << "\n warning : le numero initial de l'element " << nbinit << " est remplace par "
           		<< " le numero d'ordre attribue automatiquement par herezh " << nb
           		<< "\n seul ce dernier sera utilise par la suite ! " << endl;
           if (ParaGlob::NiveauImpression() > 5)
             cout << "\n  Maillage::Maillage (map < string, int ,.... " << endl;		
          };
       };
    };
   // on modifie le numéro de maillage pour les noeuds et éléments
   int NBN_P1 = tab_noeud.Taille()+1;
   for (int nn=1;nn < NBN_P1;nn++)
     tab_noeud(nn)->Change_num_Mail(idmail);
   int NBE_P1 = tab_element.Taille()+1;
   for (int ne=1;ne < NBE_P1;ne++)
     tab_element(ne)->Change_num_maillage(idmail);
     
   if (ParaGlob::NiveauImpression() >= 5)
        cout << " \n fin creation du maillage: " << nom_maill << endl;
};

// Constructeur de copie, cependant ici il n'y a pas de création de noeud ni d'élément
// c'est seulement une création de nouveaux conteneurs de pointeurs 
// d'autre part le numéro de maillage et le nom de maillage n'est pas valide, il faut
// ensuite les définir
Maillage::Maillage (const Maillage& mail):
   listeNomMail(mail.listeNomMail),idmail(mail.idmail),nomDuMaillage(mail.nomDuMaillage),dimension(mail.dimension)
   ,tab_noeud(mail.tab_noeud),tab_element(mail.tab_element)
   ,listFrontiere(mail.listFrontiere),tab_noeud_front(mail.tab_noeud_front)
   ,indice(),list_refIn(),list_refOut(),lesRefin(NULL)
   ,mitoyen_de_chaque_element(mail.mitoyen_de_chaque_element)
   ,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques)
   ,types_de_problemes(mail.types_de_problemes)
   , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
   ,detruire_les_noeuds_et_elements(true)

  {	// tout d'abord on donne un nom par défaut au maillage
    nomDuMaillage = "pas_de_nom";  
    while  (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
      { // on cherche un nom quelconque qui n'est pas déjà utilisé
        nomDuMaillage += '_';      
      };
    // maintenant on associe le nom au numéro dans la map
    listeNomMail[nomDuMaillage]=idmail;
  };
		
// Constructeur de copie, avec création de nouveaux noeuds et éléments identiques à ceux passées
// en argument, nmail: donne le numéro du nouveau maillage créée, qui est donc a priori différent
// de celui de mail, idem pour le nom du maillage
// les frontières ne sont pas transmises ni calculées ! ni les normales,
// ni les infos concernant les intégrales (qui sont propres aux maillages existants)
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail
                    ,int nmail, const string& nomDu,const Maillage& mail):
   listeNomMail(lisNomMail),idmail(nmail),nomDuMaillage(nomDu),dimension(mail.dimension)
   ,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front()
   ,indice(),list_refIn(),list_refOut(),lesRefin(NULL)
   ,mitoyen_de_chaque_element()
   ,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques)
   ,types_de_problemes(mail.types_de_problemes)
   , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
   ,detruire_les_noeuds_et_elements(true)
{ // on vérifie que le nom de maillage fourni n'existe pas
  if (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
   { cout << "\n erreur, le nom de maillage demande existe deja : " << nomDuMaillage
          << "\n Maillage::Maillage (.....";
     Sortie(1);
   }; 
  // on vérifie que le numéro de maillage proposé est valide        
  if (idmail <=0)
	  {	cout << "\nErreur : numero de maillage invalide ! = "<< idmail <<"\n";
		   cout << "MAILLAGE::MAILLAGE(.... \n";
		   Sortie(1);
	  };
  // maintenant on associe le nom au numéro dans la map
  listeNomMail[nomDuMaillage]=idmail;
  // on s'occupe tout d'abord des noeuds
  int nbn = mail.tab_noeud.Taille();
  Change_nb_noeud(nbn);
  for (int ino=1;ino<= nbn;ino++)
    { tab_noeud(ino) = new Noeud(*(mail.tab_noeud(ino)));
      tab_noeud(ino)->Change_num_Mail(nmail);
     };
  // maintenant les éléments
  int nbe = mail.tab_element.Taille();
  Change_nb_element(nbe);
  for (int ie=1;ie<=nbe;ie++)
    { tab_element(ie) = mail.tab_element(ie)->Nevez_copie();
//debug
//tab_element(ie)->Affiche(1); cout << endl;
//fin debug
      // on réaffecte les noeuds du maillage
		    Tableau<Noeud *>& ttab = tab_element(ie)->Tab_noeud();  
      int ttabtaille=ttab.Taille();
      for (int ine=1;ine<=ttabtaille;ine++)
        ttab(ine)=tab_noeud(ttab(ine)->Num_noeud());
      // on change le numéro de maillage
      tab_element(ie)->Change_num_maillage(idmail); 
    };
  // dans le cas où mail.mitoyen_de_chaque_element n'est pas vide,
  // on construit le nouveau
  if (mail.mitoyen_de_chaque_element.Taille() != 0)
     Calcul_tous_les_front_et_leurs_mitoyens();    
};

Maillage::~Maillage()
// Destructeur
{  if ( detruire_les_noeuds_et_elements) // cas normal
    { for (int i=1;i<= tab_noeud.Taille();i++)
        delete tab_noeud(i);
      for (int i=1;i<= tab_element.Taille();i++)
        delete tab_element(i);
     };
   // pas de destruction de tab_noeud_front car ce sont des noeuds de tab_noeud, ils sont déjà détruit
 };


void   // lecture d'un maillage et def des references s'y rapportant
Maillage::LectureMaillage(UtilLecture * entreePrinc,LesReferences& lesRef)
{  if (ParaGlob::NiveauImpression() >= 5) cout << " debut de lecture de maillage "  << endl;
   if (ParaGlob::NiveauImpression() >= 6) cout << " lecture du nom de maillage "  << endl;
   // cas où il y a un nom de maillage
   if (strstr(entreePrinc->tablcar,"nom_maillage")!=NULL)
     {
//       // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant
//       listeNomMail.erase(listeNomMail.find(nomDuMaillage));
// modif le 14 avril 2015
       // non c'est une mauvaise idée, il faut au contraire arrêter le programme et dire qu'il y a
       // deux fois le même nom, par contre si le nom de maillage c'est "pas_de_nom" il faut le supprimer
       if ((nomDuMaillage == "pas_de_nom") && (listeNomMail.find(nomDuMaillage) != listeNomMail.end()))
          listeNomMail.erase(listeNomMail.find(nomDuMaillage));
      
       string toto;
       *(entreePrinc->entree) >> toto >> nomDuMaillage;

       if (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
         {cout << "\n erreur *** plusieurs maillages ont le meme nom : "<< nomDuMaillage
               << " \n revoir les noms de maillage !! " << endl;
          Sortie(1);
         };
       // maintenant on associe le nom au numéro dans la map
       listeNomMail[nomDuMaillage]=idmail;
       // ensuite lecture de l'entête des noeuds
       entreePrinc->NouvelleDonnee();
       if (strstr(entreePrinc->tablcar,"noeuds")==NULL)
         { cout << " *** erreur dans la lecture des noeuds " 
                << " \n LectureMaillage(...  " << endl;
           entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         };
      }
   else 
   // on définit un nom apriori uniquement dans le cas d'un seul maillage
   // sinon c'est une erreur
       { if (idmail ==1)
           { // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant
             listeNomMail.erase(listeNomMail.find(nomDuMaillage));
             nomDuMaillage  = "premier_maillage";
             // maintenant on associe le nom au numéro dans la map
             listeNomMail[nomDuMaillage]=idmail;
            } 
         else
           { cout << "\n Erreur dans la lecture du maillage " << idmail <<" ****** ";
             cout << "\n il n'y a pas de nom de maillage alors que c'est obligatoire !! " 
                  << " \n LectureMaillage(...  " << endl;
             entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie (1);
           };
       };

   //------------- lecture des noeuds -------------
    // lecture du nombre de noeud
   if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des noeuds " << endl;   
   entreePrinc->NouvelleDonnee();
   if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre de noeud " << endl ; 
   int nbNoeud; // nombre de noeud
   *(entreePrinc->entree) >> nbNoeud; // lecture dans le flot memoire 
   if (ParaGlob::NiveauImpression() >= 8) cout << nbNoeud << endl ; 
   Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud
   #ifdef ETUDIANT_LIMITATION
     if (nbNoeud > nb_maxi_noeud)
       { cout << "\n nombre maxi de noeud autorisé atteind " << nb_maxi_noeud;
         Sortie(1);
       };
   #endif       
   // lecture des noeuds
   Noeud * ptr; 
   for (int i=1; i<= nbNoeud; i++)
     { entreePrinc->NouvelleDonnee();
       ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage
       if (ParaGlob::NiveauImpression() == 10) cout << "n:" << i << " " << flush ; 
       // lecture du noeud
       ptr->Lecture(entreePrinc);
       Affectation_noeud(*ptr);
     };
   // -------------- lecture des references se rapportant aux noeuds ---------
   entreePrinc->NouvelleDonnee();
   if (strstr(entreePrinc->tablcar,"elements")==NULL) 
     // cas où les références sont mises aprés les noeuds, dans ce cas c'est
     // des références de noeud
     { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references de noeuds " << endl;   
       lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds
       lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
       lesRef.Lecture(*entreePrinc);
      };

   // ------------ lecture des elements -----------
   // lecture du nombre d'element
   int nbElement=0; // nombre d'element null par défaut
   if (strstr(entreePrinc->tablcar,"elements")!=NULL) // cas avec element
      { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des elements du maillage " << endl ;   
        entreePrinc->NouvelleDonnee();
        if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre d'element " << endl ; 
        *(entreePrinc->entree) >> nbElement;
        if (ParaGlob::NiveauImpression() >= 8) cout << nbElement << endl ; 
        #ifdef ETUDIANT_LIMITATION
         if (nbElement > nb_maxi_element)
           { cout << "\n nombre maxi d'element autorise atteind " << nb_maxi_element;
             Sortie(1);
            };
        #endif       
        // dimensionnement dynamique du tableau d'elements 
        Change_nb_element(nbElement);
        // Lecture des elements
        Element * ptr;
        for (int i=1; i<= nbElement; i++)
         { // lecture geometrie et interpolation
           entreePrinc->NouvelleDonnee();
           if (ParaGlob::NiveauImpression() == 10) cout << "e:" << i << " " << flush ; 
           // def des énumérations de travail
           int num_elt = i; // numéro interne de l'élément
           int num_elt_lue; // numéro lue
           Enum_geom id_geom; Enum_interpol id_interpol;EnumElemTypeProblem  id_typeProb;
           // cas d'info annexe
           string str_precision(""); // stockage info annexe de choix, initié à rien par défaut
           // lectures des infos pour le choix d'un élément
           Lecture_info_1element(entreePrinc,num_elt_lue,id_geom,id_interpol,id_typeProb,str_precision);
           if (num_elt_lue != num_elt)
           	{ if (ParaGlob::NiveauImpression() > 0)
           		{cout << "\n warning : le numero de l'element lue  " << num_elt_lue << " est different du numero "
           		      << " d'ordre attribue automatiquement par herezh " << num_elt
           		      << "\n seul ce dernier sera utilise pour les resultats ! " << endl;
           		};
           	};
           // ======== choix de l'element =====================================
           // et affectation du pointeur d'element en fonction de id_geom et id_interpol
           // le numero d'element : num_elt, est affecte a l'element pointe par ptr
           ptr = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision);
           if (ptr == NULL)
             { // l'operation a echouee
               cout << "\n Erreur dans le choix d'element ****** ";
               cout << "\n l\'element : " << Nom_interpol(id_interpol) 
                    << " " << Nom_geom(id_geom)
                    << " n\'est pas present dans le programme ! " << endl;
               entreePrinc->MessageBuffer("** lecture d'un element **");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie (1);
              };
           // lecture des infos particulieres a l'element
           Tableau<Noeud*> * pt = & tab_noeud;
           ptr->LectureDonneesParticulieres(entreePrinc,pt);
           Affectation_element(*ptr);
           // si c'est le premier élément du premier maillage on regarde s'il s'agit 
           // d'un élément axisymétrique et on adapte l'espace de travail en conséquence
           if ((i==1) && (idmail==1)) 
           	{ if (TestEnum_geom_axisymetrique(id_geom))
           		    ParaGlob::Change_en_AxiSymetrie();
           	}
           else
            {// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent
             if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie()))
             	{cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail 
             	      << " nom= " <<  nomDuMaillage;
             	 if (ParaGlob::AxiSymetrie())     
             	 	cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)"
             	 	      << " et l'element lu est axisymetrique !! ";      
             	 else
             	 	cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)"
             	 	      << " et l'element lu n'est pas axisymetrique !! ";      
                 cout << endl;
                 Sortie (1);             		
             	};
            };	
         }
       }              
     else  
       { if (ParaGlob::NiveauImpression() >= 6)
            cout << " cas de la lecture d'un maillage SANS elements " << endl; // cas sans element
       };
  
  // -------------- lecture des references se rapportant aux elements ---------
  // ou aux arête ou aux faces et meme eventuellement à des noeuds
  if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references apres les elements " << endl ; 
  entreePrinc->NouvelleDonnee();
  lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
  lesRef.Indic("rien_actuellement"); // indic que les prochaines references seront 
       // a déterminer en fonction du nom de la référence
  lesRef.Lecture(*entreePrinc);
  // -------------- ajout de références globales ---------------------
  // ----  création de la référence de tous les éléments si elle n'existe pas déjà
  string etout("E_tout");
  if (!lesRef.Existe(etout,idmail) && (nbElement != 0))
    { // 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 la référence de tous les noeuds dans le cas où elle n'existe pas
  string ntout("N_tout");
  if (!lesRef.Existe(ntout,idmail))
    { // 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
    };
  if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture de maillage "  << endl;      
  // ----- on s'occupe maintenant de définir les types de pb gérés ------
  Mise_a_jour_type_pb_type_associe_ddl();
};
     
// lecture et application des opérations d'affinages sur le maillage: ex:déplacement solide
void Maillage::LectureEtApplicationAffinage(UtilLecture * entreePrinc,LesReferences& lesRef)
{
  if (ParaGlob::NiveauImpression() >= 5) cout << " lecture affinage maillage "  << endl;

  while (    (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL)
          || (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL)
          || (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL)
          || (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL)
          || (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL)
          || (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL)
          || (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL)
          || (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL)
        )
      {
         // -------------- lecture éventuelle et application de mouvements rigides ------------------ 
         Lecture_des_mouvements_solides(entreePrinc);
  
         // --------------- suppression éventuelle des noeuds, non référencés par les éléments ------
         LectureEtSuppressionNoeudNonReferencer(entreePrinc,lesRef);

         // --------------- création éventuelle d'une référence sur les noeuds, non référencés par les éléments ------
         LectureEtCreationRefNoeudNonReferencer(entreePrinc,lesRef);
 
         // --------------- éventuellement collapse de noeuds proches ------------------------
         LectureEtCollapse_noeuds_proches(entreePrinc,&lesRef);
 
         // --------------- éventuellement collapse d'éléments supperposés -------------------
         LectureEtCollapse_element_superpose(entreePrinc,&lesRef);
       
         // -------------- éventuellement suppression  d'elements à 2 noeuds, de distances très proches
         LectureEtSup_Elem_noeudsConfondu(entreePrinc,&lesRef);
       
         //---------------- création automatique des références globales de frontière si demandé ----------
         CreationRefFrontiere(entreePrinc,lesRef);

//----- debug
//{  // on écrit la connection de l'élément 55
//  Element* el = tab_element(55);
//  const Tableau<Noeud *>& tabi = el->Tab_noeud_const();
//  cout << "\n *** connection de l'element 55: avant renumerotation ";
//  for (int i=1;i<=tabi.Taille();i++) cout << " "<<tabi(i)->Num_noeud();
//  cout << " Maillage::LectureMaillage () " << endl;
//}
//---fin debug
         // --------------- renumérotation éventuelle des noeuds ------------------------------------
         LectureEtRenumerotation(entreePrinc,lesRef);
////----- debug
//{  // on écrit la connection de l'élément 55
//  Element* el = tab_element(55);
//  const Tableau<Noeud *>& tabi = el->Tab_noeud_const();
//  cout << "\n *** connection de l'element 55: après renumerotation ";
//  for (int i=1;i<=tabi.Taille();i++) cout << " "<<tabi(i)->Num_noeud();
//  cout << " Maillage::LectureMaillage () " << endl;
//  Sortie(1);
//}
////---fin debug
      };
  
  // ----------------- vérification que toutes les références de noeuds, d'éléments, d'arêtes et de faces sont valides
  //                c-a-d se réfèrent à des éléments existants
  VerifReference(lesRef);
     
  if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture affinage maillage "  << endl;      
};
    
// affichage et definition interactive des commandes 
// cas = 1: interactif complet
// cas = 2: entrée uniquement de noms de fichier
// cas = 3: entrée uniquement de l'affinage
void Maillage::Info_commande_Maillages(UtilLecture * entreePrinc,LesReferences& lesRef, int cas)
{  ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier
	  string rep="o";
   if (cas == 2)
	   { cout << "\n# voulez-vous inclure un fichier ou continuer sur un exemple (rep o  ou ? ou f) ? ";
	     rep = lect_return_defaut(false,"f");
    };
  
	  if (((rep == "o") || (rep == "O") ||(rep == "0")) && (cas != 3))
	  { cout << "\n non du fichier .her (sans l'extension .her) a inclure ? ";
     rep = lect_chaine();
     sort << "\n\n # -- def maillage ";
		   sort << "\n < " << (rep+".her") ;
     cout << "\n un fichier .lis a inclure ? (o ou n (defaut)) ";
     rep = lect_return_defaut(false,"n");
     if (rep == "o")
      { cout << "\n non du fichier .lis (sans l'extension .lis) a inclure ? ";
        rep = lect_chaine();
		      sort << "\n < " << (rep+".lis") ;
      };
	  }
	  else if ((rep == "?") && (cas != 3))
	  { // sinon on continue sur un exemple de maillage
      sort << "\n # -- defintion du nom du maillage (facultatif pour le premier maillage "
        << "\n # -- qui s'appel par defaut : premier_maillage)"
        << "\n"
        << "\n nom_maillage plaque_troue     # exemple de nom de maillage"
        << "\n           noeuds ------------ # definition des noeuds";

      //------------- definition des noeuds -------------
      int dimen = ParaGlob::Dimension();
      #ifdef SYSTEM_MAC_OS_CARBON
		    int nbNoeud = pow(3,dimen); // nombre de noeud de l'exemple
      #else  
      int nbNoeud = ((int)pow((float)3,(int)dimen)); // nombre de noeud de l'exemple
      #endif  

      sort << "\n            "<< nbNoeud << "  NOEUDS         # definition du nombre de noeud"
           << "\n \n" 
           << "\n#---------------------------------------------------------------"
           << "\n#|NO DU|        X         |        Y         |          Z      |"
           << "\n#|NOEUD|                  |                  |                 |"
           << "\n#---------------------------------------------------------------";
        
      Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud
      // définition d'une grille  générique de noeuds qui permettra de définir les éléments générique
      Tableau <Coordonnee*> tab_coo(nbNoeud);
      switch (dimen)
      { case 1:
         { for (int i=1;i<=3;i++) tab_coo(i) = new Coordonnee((double) i); break;}
        case 2:
         { int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++,l++)
           tab_coo(l) = new Coordonnee((double) i,(double) j); break;}  
		      case 3:
         { int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++) for (int k=1;k<=3;k++,l++)
           tab_coo(l) = new Coordonnee((double) i,(double) j,(double) k); break;} 
       };       
      // def des noeuds
      Noeud * ptr; 
      for (int i=1; i<= nbNoeud; i++)
      { ptr = new Noeud(i,dimension,1); // et attribution du numero de maillage
        // def du noeud
        ptr->Info_commande_Noeud(entreePrinc,*tab_coo(i),i);
        Affectation_noeud(*ptr);
      };
     
      // -------------- def d'exemples de references se rapportant aux noeuds ---------
      sort << "\n#     --- reference de noeuds ce trouvant apres la definition des noeuds ---"
           << "\n#    ( il est possible aussi de definir des references de noeud apres "
           << "\n#      la definition des elements)  "
           << "\n#   NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres \n"; 
      lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds
      lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
      lesRef.Info_commande_lesRef(nbNoeud,0,entreePrinc,1); // def d'exemple des divers refs de noeuds

      // ------------ def d'exemple d'elements -----------
   
      int nbElement = 0; // nombre d'element 
      bool choix_valide=false;  
      // affichage des types d'élément actuellement disponible selon la dimension
      // creation d'un tableau d'éléments
      Tableau <Element *> tab_el = Element::Info_commande_Element(entreePrinc);
      int nbele = tab_el.Taille(); 
      Tableau <bool> chooi(nbele,false); // tableau de travail
      cout << "\n Donner le type d'element que vous souhaitez utiliser: ?  ";
      string rep;int num;
      while (!choix_valide)
      {
       try 
       { // affichage des éléments possibles
        // on balaie le tableau des elements enregistre
        int undeux=0;
        cout << "\n (0) fin \n";
        for (int i=1;i<=nbele;i++)
         { cout << " (" << i << ") " << tab_el(i)->Geometrie() <<" "<< tab_el(i)->Interpolation()
                <<"  ";
           undeux++;
           if (undeux==2) {cout << "\n";undeux=0;}
          };
        rep = lect_return_defaut(false,"0");
        if (rep == "fin_prog") Sortie(1);
        num = ChangeEntier(rep);  
        choix_valide=false;  
        if (num == 0) 
         { choix_valide=true;}
        else // sinon
         { if ((num > 0)&&(num<=nbele)) 
            {if (chooi(num))
               cout << "\n type d'element deja choisit, recommencer";
             else    
              chooi(num) = true;
            }
           else { cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, "
                       << "\n redonnez une bonne valeur"
                       << "\n ou taper fin_prog pour arreter le programme"; 
                }
          }      
        }    
       catch (ErrSortieFinale)
            // cas d'une direction voulue vers la sortie
            // on relance l'interuption pour le niveau supérieur
          { ErrSortieFinale toto;
            throw (toto);
          }
       catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
       {   cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, "
                    << "\n redonnez une bonne valeur"
                      << "\n ou taper fin_prog pour arreter le programme"; 
			  choix_valide=false;
        }
       } //-- fin du while 
      // on definit le maillage d'essai
      // 1- def du nombre d'élément
      int ielmax=0;
      for (int ie=1;ie<=nbele;ie++)
      if (chooi(ie)) ielmax++;
      Change_nb_element(ielmax);
      // 2- remplissage du tableau d'élément
      int iel=1;  
      for (int ie=1;ie<=nbele;ie++)
        if (chooi(ie)) 
         {tab_element(iel)=tab_el(ie); 
          tab_element(iel)->Change_num_elt(iel);
          tab_el(ie)=NULL;
          iel++;
          }
      //  on affiche les éléments
      sort << "\n # les elements \n"
            << "\n elements ----------";
      sort << "\n    " << ielmax << "  ELEMENTS";

      sort << "\n #----------------------------------------------------------------------";
      sort << "\n #| NO  |                           |                                  |";
      sort << "\n #|ELTS |     type element          |       Noeuds                     |";
      sort << "\n #----------------------------------------------------------------------";
      string ord= "commande";
      Tableau<Noeud*> * pt = & tab_noeud;
      for (int i=1;i<=ielmax;i++)
        tab_element(i)->Info_com_Element(entreePrinc,ord,pt);
      sort << "\n \n" ;  

      // -------------- def des references se rapportant aux elements ---------
      // ou aux arête ou aux faces et meme eventuellement à des noeuds
      sort << "\n#     --- reference  ce trouvant apres la definition des elements ---"
           << "\n#   NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres "
           << "\n#   une reference d'element commence par E suivi d'une chaine de caracteres "
           << "\n#   une reference de face commence par F et une reference d'arrete commence par A  \n"; 
        
      lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
      lesRef.Info_commande_lesRef(nbNoeud,ielmax,entreePrinc,2); // def d'exemple des divers refs de noeuds
  
      // effacement des éléments qui ne servent plus
      for (int i=1;i<=ielmax;i++)
        if (tab_el(i) != NULL) delete tab_el(i);
	}; // fin de l'exemple de maillage	   
     
   // ---------- définition des affinages éventuelles ---------- 
// while (    (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL)
//          || (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL)
//          || (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL)
//          || (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL)
//          || (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL)
//          || (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL)
//          || (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL)
//          || (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL)
   //On va proposer un menu
   while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
      {
       try 
        { 
        cout 
           << "\n (0 ou f defaut)  (fin)               "
           << "\n (1)  mouvement solide     "
           << "\n (2)  suppression des noeuds non reference "              
           << "\n (3)  collapse de noeuds proches "
           << "\n (4)  collapse d'elements superposes "
           << "\n (5)  creation de references frontieres " 
           << "\n (6)  renumerotation "
           << "\n (7)  creation d'une ref sur les noeuds non references "
           << "\n (8)  suppression des petits elements a 2 ou 3 noeuds 2D "
           << "\n (9 ou ? ) informations  "
           << "\n  ";
        rep = lect_return_defaut(false,"f");
        if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
          break;
        int num = ChangeEntier(rep);
        if (Minuscules(rep) == "?")
          num = 9;
        bool choix_valide=false;
        if ((num >= 0)&&(num<=9))
             { choix_valide=true; }
        else { cout << "\n Erreur on attendait un entier entre 0 et 9 !!, "
                    << "\n redonnez une bonne valeur"
                    << "\n ou taper f ou 0 pour arreter le programme"; 
               choix_valide=false;
             }
        switch (num)
         { case 0:  // sortie
             { break;} // normalement cela a déjà été filtré avant
           case 1:  // mouvement solide
             { MvtSolide mvt; // un mouvement par défaut
               sort << "\n\n def_mouvement_solide_initiaux_ \n";
               mvt.Info_commande_MvtSolide(sort);
               break;}
           case 2:  // suppression des noeuds non reference
             { sort << "\n suppression_noeud_non_references_ ";
               break;}
           case 3:  // collapse de noeuds proches
             { sort << "\n fusion_noeuds_proches_ ";
               cout << "\n donner la distance en dessous de laquelle on fusionne (un reel) ? ";
               double rayon=0.;
               rayon = lect_double(); cout << " valeur lue "<< rayon;
               sort << rayon << " ";
               break;}
           case 4:  // collapse d'elements superposes
             { sort << "\n fusion_elements_superposes_ ";
               break;}
           case 5:  // creation de references frontieres
             { sort << "\n def_auto_ref_frontiere_ ";
               break;}
           case 6:  // creation de references frontieres
             { sort << "\n renumerotation_des_noeuds_ ";
               break;}
           case 7:  // creation d'une ref sur les noeuds non reference
             { sort << "\n creation_ref_noeud_non_references_ ";
               break;}
           case 8:  // suppression des petits elements a 2 ou 3 noeuds 2D
             { sort << "\n suppression_elements_2noeuds_tres_proches_ ";
               cout << "\n donner la distance entre deux noeuds de l'element en dessous de laquelle on supprime (un reel) ? ";
               double rayon=0.;
               rayon = lect_double(); cout << " valeur lue "<< rayon;
               sort << rayon << " ";
               break;}
           case 9:  // informations
             { cout << "\n en dehors de la signification intuitive des differents ordres"
                    << " pour des informations plus precise il est preferable de se rapporter a la documentation "
                    << " d'Herezh++, car c'est differents ordres recouvrent des procedures difficiles a "
                    << " decrire en quelques lignes. ";
               break;}
           default:
             cout << "\n le cas "<<rep<<" n'est pas encore traite !!, mais cela devrait ce faire sans tarder ";
          };
        }    
       catch (ErrSortieFinale)
            // cas d'une direction voulue vers la sortie
            // on relance l'interuption pour le niveau supérieur
          { ErrSortieFinale toto;
            throw (toto);
          }
       catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
        {  cout << "\n Erreur on attendait un des mots clés proposés !!, "
                << "\n redonnez une bonne valeur"
                << "\n ou taper f ou 0 pour sortir "; 
        };
      }; //-- fin du while
          
};
		

// Affiche l'ensemble des donnees du maillage
void Maillage::Affiche () const
{cout << "\n\t\t*** DONNEES DU MAILLAGE ***\n\n";
	cout << "\n nom du maillage : " << nomDuMaillage << " , ";
	cout << "Dimension : " << dimension << "\n";
 // les types de problèmes associés
// {list <EnumElemTypeProblem>::const_iterator il,ilfin=types_de_problemes.end();
//  cout <<"\n types_de_problemes: " << types_de_problemes.size() ;
//  for (il=types_de_problemes.begin();il != ilfin;il++)
//     NomElemTypeProblem(*il);
// };
 {int tail = types_de_problemes.Taille();
  cout <<"\n types_de_problemes: " << tail ;
  for (int i=1;i<=tail;i++)
    cout << " "<< NomElemTypeProblem(types_de_problemes(i));
 };

// // les ddl associés
// {list <Enum_ddl>::const_iterator il,ilfin=ddl_representatifs_des_physiques.end();
//  cout <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size();
//  for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++)
//     Nom_ddl(*il);
// };
 {int tail = ddl_representatifs_des_physiques.Taille();
  cout <<"\n type_de_ddl_associes: " << tail;
  for (int i=1;i<=tail;i++)
    cout << " "<< Nom_ddl(ddl_representatifs_des_physiques(i));
 };
 
 //	cout << "Nombre de degres de liberte : " << Nombre_ddl() << "\n";
	cout << "Nombre de noeuds : " << Nombre_noeud() << "\n";
	cout << "Nombre d'elements : " << Nombre_element() << "\n\n";
	for (int i=1;i<=Nombre_noeud();i++)
	// boucle sur les noeuds
	{
		cout << "\nNoeud " << i << " :\n";
		tab_noeud(i)->Affiche();
	};
	cout << "\n";
	for (int i=1;i<=Nombre_element();i++) 
	// boucle sur les elements
	{
		cout << "\nElement " << i << " :\n"; 
		tab_element(i)->Affiche(ParaGlob::NiveauImpression());
	};
	cout << "\n"; 
	// renseignement concernant les frontières
 int nbmaxiElement = (int) listFrontiere.size();
 cout << "nombre d'element frontiere : " << nbmaxiElement;
 cout << "liste : \n";
 LaLIST <Front>::const_iterator ip;int ne;
 for (ne=1,ip = listFrontiere.begin();ip != listFrontiere.end(); ip++,ne++)
     { // écriture de l'élément courant
       cout << ne << "  " ;  // le numéro
       const ElemGeomC0 & geom = (*ip).Eleme()->ElementGeometrique();
       cout << Nom_geom(geom.TypeGeometrie()) << "  " ; // la géométrie
       cout << Nom_interpol(geom.TypeInterpolation()) << "  " ; // l'interpolation
       // les noeuds
       Tableau <Noeud *> tabnoeud = (*ip).Eleme()->TabNoeud();
       int taille = tabnoeud.Taille();
       for (int ine = 1; ine<=taille; ine++)
         cout << tabnoeud(ine)->Num_noeud() << " ";
       cout << "\n";
     };
	// la liste des noeuds de la frontières, on ne sort que les numéros
	cout << " \n liste des numeros de noeud de la frontiere"; 
	int taal = tab_noeud_front.Taille();
	for (int i=1;i<= taal;i++)
	  cout << tab_noeud_front(i)->Num_noeud() << " ";
	cout << "\n";	
};

/*void
Maillage::Affiche (char* nom_fichier)
// Affiche les donnees du maillage dans le fichier nom_fichier
// au format du fichier d'entree ".her"
{
	FILE* fichier;
	// ouverture du fichier nom_fichier
	if ( (fichier=fopen(nom_fichier,"w"))==NULL )
	{
		cout << "ERREUR D'OUVERTURE DU FICHIER :"; 
		cout << nom_fichier << "\n";
		Sortie(1);
	};
	fprintf(fichier,"\n nom_maillage ",nomDuMaillage.c_str());
	fprintf(fichier,"\n\nnoeuds --------\n\n");
	fprintf(fichier,"\t\t%d NOEUDS\n\n",Nombre_noeud());
	// affichage des noeuds :
	switch (dimension)
	{
		case 1 : // cas unidimensionnel
			for (int i=1;i<=Nombre_noeud();i++)
			{
				fprintf(fichier,"\t%d\t%lf\n",Noeud_mail(i).Num_noeud(),
											Noeud_mail(i).Coord0()(1));
			};
			break;
		case 2 : // cas bidimensionnel
			for (int i=1;i<=Nombre_noeud();i++)
			{
				fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud());
				fprintf(fichier,"%lf\t%lf\n",Noeud_mail(i).Coord0()(1),
											Noeud_mail(i).Coord0()(2));
			};
			break;
		case 3 : // cas tridimensionnel
			for (int i=1;i<=Nombre_noeud();i++)
			{
				fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud());
				fprintf(fichier,"%lf\t%lf\t%lf\n",Noeud_mail(i).Coord0()(1),
						Noeud_mail(i).Coord0()(2),Noeud_mail(i).Coord0()(3));
			};
			break;
		default :
			cout << "Erreur de dimension\n";
			cout << "MAILLAGE::AFFICHE(char* ) \n";
			Sortie(1);
	};
	fprintf(fichier,"\n\nelements --------\n\n");
	fprintf(fichier,"\t\t%d ELEMENTS\n\n",Nombre_element());
	// affichage des elements
	for (int i=1;i<=Nombre_element();i++)
	{
		fprintf(fichier,"\t%d\t",Element_mail(i).Num_elt());
		fprintf(fichier,"%s\t%s\t\t",Element_mail(i).Geometrie(),
								Element_mail(i).Interpolation());
		for (int j=1;j<=Element_mail(i).Nombre_noeud();j++)
			fprintf(fichier,"%d\t",Element_mail(i).Num_noeud(j));
		fprintf(fichier,"\n");
	};
	fprintf(fichier,"\n\n");
	
};
*/	

Maillage& 
Maillage::operator= (Maillage& mail)
// Surcharge de l'operateur = : realise l'egalite entre deux maillages
// cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut
// ensuite les définir
{   dimension=mail.dimension;
    //nomDuMaillage = mail.nomDuMaillage;
    tab_noeud=mail.tab_noeud;
    tab_element=mail.tab_element;
    listFrontiere=mail.listFrontiere;
    tab_noeud_front = mail.tab_noeud_front;
    ddl_representatifs_des_physiques = mail.ddl_representatifs_des_physiques;
    types_de_problemes = mail.types_de_problemes;
    return (*this);
};

// test si toutes les informations des maillages sont completes
// = true -> complet
// = false -> incomplet
bool Maillage::Complet()
  { bool res = true;
    int tab_noeudTaille = tab_noeud.Taille();
    for ( int i=1; i<= tab_noeudTaille;i++)
      { // res = res && tab_noeud(i)->TestComplet();
        if(!(tab_noeud(i)->TestComplet()))
          { cout << " \n pb au niveau du test  du noeud " << tab_noeud(i)->Num_noeud();
            res = false;
          };
       };
    int tab_elemTaille = tab_element.Taille();  
    for ( int i=1; i<= tab_elemTaille;i++)
      {//res = res && tab_element(i)->TestComplet(); 
       if(!(tab_element(i)->TestComplet()))
         {cout << "\n pb au niveau du test de l'element " << tab_element(i)->Num_elt();
          res = false;
         };
      };
    // les parties frontières ne sont pas obligatoires        
    return res;
  };
	    
// ramene la demi largeur de bande en ddl et la largeur de bande
void Maillage::Largeur_Bande(int& demi, int& total,const Nb_assemb& casAss)
  {  demi = 0;
     int nb_ass = casAss.n;
     int tab_elemTaille = tab_element.Taille();  
     for (int ne=1;ne<=tab_elemTaille;ne++)
       {int tab_eleNbNoeud = tab_element(ne)->Nombre_noeud();
        for (int noe=1; noe<= tab_eleNbNoeud;noe++)
//  bug, voic remarque qui suit         for ( int no=noe+1; no<=tab_eleNbNoeud;no++)
           // l'idée est bonne de commencer à noe+1, mais en fait lorsque l'on a un seul noeud, cela conduit
			  // a avoir une largeur de bande nulle, donc il faut commencer à noe, et dans ce cas c'est ok
			  // mais pour les éléments avec plus d'un noeud, on a une boucle supp
           for ( int no=noe; no<=tab_eleNbNoeud;no++)
            { Noeud & nne = tab_element(ne)->Noeud_elt(noe);
              Noeud & nno = tab_element(ne)->Noeud_elt(no);
              int di;
              if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass))
                 di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass) 
                      + nne.NB_ddl_actif_casAssemb(nb_ass);
              else
                 di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass) 
                       + nno.NB_ddl_actif_casAssemb(nb_ass);   
              if ( di > demi)  demi = di;
            };
         };
     total = demi * 2 -1;
     demi = demi;  
  };

// test pour savoir si tous les coordonnées des noeuds d'un maillage sont imposé
// ramène 1 si tout est fixé, 0 sinon
int Maillage::Tous_Xi_fixes(const Nb_assemb& casAss) const
  {  int retour = 1;
     int nb_ass = casAss.n;
     // on va parcourir les noeuds
     int tab_noeud_taille= tab_noeud.Taille();
     int dim = ParaGlob::Dimension();
     switch(dim)
       {case 3:
          {for (int i=1;i<=tab_noeud_taille;i++)
            { Noeud& noe = *tab_noeud(i); // pour simplifier
              if (!( noe.Ddl_fixe(X3) && noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1)))
                {retour=0; break;};
            };
           break;
          }
        case 2:
          {for (int i=1;i<=tab_noeud_taille;i++)
            { Noeud& noe = *tab_noeud(i); // pour simplifier
              if (!( noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1)))
                {retour=0; break;};
            };
           break;
          }
        case 1:
          {for (int i=1;i<=tab_noeud_taille;i++)
            { Noeud& noe = *tab_noeud(i); // pour simplifier
              if (!( noe.Ddl_fixe(X1)))
                {retour=0; break;};
            };
           break;
          }
       };
//  --- idem mais plus long a priori car contient un switch
//     for (int i=1;i<=tab_noeud_taille;i++)
//       { Noeud& noe = *tab_noeud(i); // pour simplifier
//         switch(dim)
//          {case 3:  if (!(noe.Ddl_fixe(X3))) {retour=0; break;};
//           case 2:  if (!(noe.Ddl_fixe(X2))) {retour=0; break;};
//           case 1:  if (!(noe.Ddl_fixe(X1))) {retour=0; break;};
//          };
//         if (!retour) break;
//       };
     return retour;
  };

// création pour chaque noeud de la liste des éléments qui contiennent le noeud
void Maillage::Calcul_indice()
{   //  création du tableau indice : pour chaque noeud on regarde quel élément contiend ce noeud
/// les 3/ sont pour la version vector qui marche bien aussi     
///    vector <vector <Element*> > indice(tab_noeud.Taille());
    int tab_noeud_taille= tab_noeud.Taille();
    indice.Change_taille(tab_noeud_taille);
    // au cas où le tableau existait auparavant on initialise les éléments du tableau
    for (int i=1;i<= tab_noeud_taille;i++)
      indice(i).clear();
    // maintenant on passe en revue les éléments
    int tabelTaille = tab_element.Taille();
    // indice(i) contiend les numéros d'élément contenant le noeud i
    for (int i22 = 1; i22 <= tabelTaille; i22++)
       { Element * elem1 = tab_element(i22); // recup de l'element
         // récup de son tableau de noeud
         Tableau<Noeud *>& tabn = elem1->Tab_noeud();
         int tabntaille = tabn.Taille();
         for (int ij=1;ij<= tabntaille;ij++)
           {// on balaie ses noeuds  
///            indice[(tabn(ij)->Num_noeud())-1].push_back(elem1);
            indice((tabn(ij)->Num_noeud())).push_back(elem1);
           };
       };
	   // on supprime les doublons
	   for (int i=1;i<=tab_noeud_taille;i++)
	     { list<Element*>& intertab = indice(i); // pour allèger l'écriture
		      intertab.sort(); // on ordonne
			     intertab.unique(); // on supprime les doublons
/*//-- debug
//{cout << "\n noeud " << i << " taille indice(i) " << intertab.size() ;
// list<Element*>::iterator ina,infin;
// infin = intertab.end();
// for (ina = intertab.begin();ina!=infin;ina++)
//  {Element * elem2 = *ina; // recup de l'element
//	cout << " element " << elem2->Num_elt() << " ";
//	};
// cout << "\n";
// };
//-- debug
//{cout << "\n debug ** Maillage::Calcul_indice() ";
// int numnoeud = 104;
// list<Element*>& intertab = indice(numnoeud);
// list<Element*>::iterator ina,infin;
// infin = intertab.end();
// for (ina = intertab.begin();ina!=infin;ina++)
//  {Element * elem2 = *ina; // recup de l'element
//	  cout << " element-- " << elem2->Num_elt() << " ";
//  };
// cout << "\n"<<endl ;
//};
//--fin debug*/
			   }; 

};

// calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement
// a priori le calcul s'effectue par une moyenne des normales des éléments qui
// entourent le noeud.
// init -> calcul des normales à t=0
//         et ajout conteneur aux noeuds des normales à t = 0 et t
void Maillage::InitNormaleAuxNoeuds()
 { // on va parcourir les noeuds et on n'intervient que si le noeud
   // appartient à un élément 1D et/ou 2D
   int nbNoeud = tab_noeud.Taille();
   int borne_max_nbNoeud = nbNoeud+1;
   Coordonnee coor_inter; //  coordonnée de travail
   Coordonnee premiere_normale;// idem
   for (int ine =1; ine < borne_max_nbNoeud;ine++ )
     {// on regarde si le conteneur de la normale existe au noeud
      // et création éventuelle
      Noeud & noe = *tab_noeud(ine); // pour simplifier
      if (!noe.Existe_ici(NN_SURF_t0))
       { Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant
         TypeQuelconque typQ4(NN_SURF_t0,EPS11,grandCoordonnee);
         noe.AjoutUnTypeQuelconque(typQ4);
       };
      // on fait la même chose à t ce qui évitera de tester à la mise à jour
      if (!noe.Existe_ici(NN_SURF_t))
       { Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant
         TypeQuelconque typQ4(NN_SURF_t,EPS11,grandCoordonnee);
         noe.AjoutUnTypeQuelconque(typQ4);
       };
      // et on le récupère après création éventuelle
      TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t0);
      Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
      Coordonnee& normale = *gr.ConteneurCoordonnee();
      normale.Zero(); // init
      // calcul éventuel du tableau Indice
      this->Indice();

      List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud
      List_io < Element*>::iterator il,ilfin = li_elem.end();
      // on balaie les éléments
      int nb_normale=0; // le nombre de normales trouvées
      for (il = li_elem.begin(); il != ilfin; il++)
       {Element& elem = *(*il);
        Enum_type_geom enutygeom =  Type_geom_generique(elem.Id_geometrie());
//        if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
        if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
         {int cas = elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter);
          if (cas == 0)
           {cout << "\n *** erreur, le calcul de la normale n'est pas possible "
                 << " pour le noeud "<<tab_noeud(ine)->Num_noeud()
                 << " du maillage " << tab_noeud(ine)->Num_Mail()
                 << " par rapport  a l'element "<< elem.Num_elt()
                 << " du maillage " << elem.Num_maillage()
                 << "\n Maillage::MiseAjourNormaleAuxNoeuds() ";
            Sortie(1);
           }
          else if (cas == 2)
           {// le calcul n'est pas licite, mais ce n'est pas une erreur
            // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
           }
          else // sinon c'est ok
           {// on peut avoir des directions très proches mais de sens inverse ... ce qui va
            // conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire
            // s'il est négatif on utilise l'inverse de la normale
            // donc en définitif on gardera globalement la direction précédente
            if ((normale * coor_inter) > 0.)
              {normale += coor_inter;}
            else
              {normale -= coor_inter;};
            nb_normale++;
           };
         };
       };
      if (nb_normale != 0)
        {normale /= nb_normale;
         // enfin on normalise la normale
////------ debug
//if (normale.Norme() == 0.)
// {
//       for (il = li_elem.begin(); il != ilfin; il++)
//        {Element& elem = *(*il);
//         Enum_type_geom enutygeom =  Type_geom_generique(elem.Id_geometrie());
// //        if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
//         if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
//          {elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter);
//           if (coor_inter.Dimension() == 0)
//            {cout << "\n *** erreur, le calcul de la normale n'est pas possible "
//                  << " pour le noeud "<<tab_noeud(ine)->Num_noeud()
//                  << " du maillage " << tab_noeud(ine)->Num_Mail()
//                  << " par rapport  a l'element "<< elem.Num_elt()
//                  << " du maillage " << elem.Num_maillage()
//                  << "\n Maillage::MiseAjourNormaleAuxNoeuds() ";
//             Sortie(1);
//            }
//           else // sinon c'est ok
//            {normale += coor_inter;
//             nb_normale++;
//            };
//          };
//        };
//
// }
//
//// end debug
         normale.Normer();
         // ce qui fini la mise à jour de la normale au noeud
        };
     };
 };

// calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement
// a priori le calcul s'effectue par une moyenne des normales des éléments qui
// entourent le noeud.
// mise à jour -> mise à jour des normales à t

void Maillage::MiseAjourNormaleAuxNoeuds()
 { // on va parcourir les noeuds et on n'intervient que si le noeud
   // appartient à un élément 1D et/ou 2D
   int nbNoeud = tab_noeud.Taille();
   int borne_max_nbNoeud = nbNoeud+1;
   Coordonnee coor_inter; //  coordonnée de travail
   for (int ine =1; ine < borne_max_nbNoeud;ine++ )
     {Noeud & noe = *tab_noeud(ine); // pour simplifier
      // on récupère la normale au noeud
      TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t);
      Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
      Coordonnee& normale = *gr.ConteneurCoordonnee();
      normale.Zero(); // init
      // calcul éventuel du tableau Indice
      this->Indice();

      List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud
      List_io < Element*>::iterator il,ilfin = li_elem.end();
      // on balaie les éléments
      int nb_normale=0; // le nombre de normales trouvées
      for (il = li_elem.begin(); il != ilfin; il++)
       {Element& elem = *(*il);
        Enum_type_geom enutygeom =  Type_geom_generique(elem.Id_geometrie());
        //        if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
        if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
         {int cas = elem.CalculNormale_noeud(TEMPS_t,*tab_noeud(ine),coor_inter);
          if (cas == 0)
           {cout << "\n *** erreur, le calcul de la normale n'est pas possible "
                 << " pour le noeud "<<tab_noeud(ine)->Num_noeud()
                 << " du maillage " << tab_noeud(ine)->Num_Mail()
                 << " par rapport  a l'element "<< elem.Num_elt()
                 << " du maillage " << elem.Num_maillage()
                 << "\n Maillage::MiseAjourNormaleAuxNoeuds() ";
            Sortie(1);
           }
          else if (cas == 2)
           {// le calcul n'est pas licite, mais ce n'est pas une erreur
            // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
           }
          else // sinon c'est ok
           {normale += coor_inter;
            nb_normale++;
           };
         };
       };
      if (nb_normale != 0)
        {normale /= nb_normale;
         // enfin on normalise la normale
         normale.Normer();
        };
      // ce qui fini la mise à jour de la normale au noeud
     };
 };
 
// mise à jour -> mise à jour des normales à t
// mais ici, on calcule les normales à tdt, et on transfert à t
// cette méthode est utile si on veut utiliser des normales à t pour une valeur
// particulière (transitoire) de la géométrie à tdt
// cf: l'algo non dyna par exempel
void  Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T()
{ // on va parcourir les noeuds et on n'intervient que si le noeud
  // appartient à un élément 1D et/ou 2D
  int nbNoeud = tab_noeud.Taille();
  int borne_max_nbNoeud = nbNoeud+1;
  Coordonnee coor_inter; //  coordonnée de travail
  for (int ine =1; ine < borne_max_nbNoeud;ine++ )
    {Noeud & noe = *tab_noeud(ine); // pour simplifier
     // on récupère la normale au noeud
     TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t);
     Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
     Coordonnee& normale = *gr.ConteneurCoordonnee();
     normale.Zero(); // init
     // calcul éventuel du tableau Indice
     this->Indice();

     List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud
     List_io < Element*>::iterator il,ilfin = li_elem.end();
     // on balaie les éléments
     int nb_normale=0; // le nombre de normales trouvées
     for (il = li_elem.begin(); il != ilfin; il++)
      {Element& elem = *(*il);
       Enum_type_geom enutygeom =  Type_geom_generique(elem.Id_geometrie());
       //        if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
       if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
        {// ici contrairement à la méthode: MiseAjourNormaleAuxNoeuds
         // on demande à l'élément de calculer la normale avec la géométrie à tdt
         int cas = elem.CalculNormale_noeud(TEMPS_tdt,*tab_noeud(ine),coor_inter);
         if (cas == 0)
          {cout << "\n *** erreur, le calcul de la normale n'est pas possible "
                << " pour le noeud "<<tab_noeud(ine)->Num_noeud()
                << " du maillage " << tab_noeud(ine)->Num_Mail()
                << " par rapport  a l'element "<< elem.Num_elt()
                << " du maillage " << elem.Num_maillage()
                << "\n Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T() ";
           Sortie(1);
          }
         else if (cas == 2)
          {// le calcul n'est pas licite, mais ce n'est pas une erreur
           // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
          }
         else // sinon c'est ok
          {normale += coor_inter;
           nb_normale++;
          };
        };
      };
     if (nb_normale != 0)
       {normale /= nb_normale;
        // enfin on normalise la normale
        normale.Normer();
       };
     // ce qui fini la mise à jour de la normale au noeud
    };
};

// creation des elements frontiere
void Maillage::CreeElemFront()
{
  // 0- on supprime la liste existante
  listFrontiere.erase(listFrontiere.begin(),listFrontiere.end());
  // 1- tout d'abord on crée les éléments frontière dans chaque élément
  int tabelTaille = tab_element.Taille();
  // on boucle sur les elements 
  for (int i2 = 1; i2 <= tabelTaille; i2++)
        // création des éléments frontières (on force)
       tab_element(i2)->Frontiere(true);
  // 2- maintenant on va créé des tableaux permettant d'accélérer l'algorithme final
  // pour chaque noeud on regarde quel élément contiend ce noeud
	 Calcul_indice();
  int tab_noeud_taille= tab_noeud.Taille();
  // indice contiend les numéros d'élément succeptible d'avoir des frontières
  // communes
 
  // 3- maintenant on va de nouveau boucler sur les éléments en regardant
  // pour chaque frontière si elle est effectivement recevable c-a-d si
  // il n'y a pas deux frontières identiques     
  Front lili; // un element de référence de frontière courant
//    for (int i1 = 1; i1 <= tabelTaille-1; ++i1)
  for (int i1 = 1; i1 <= tabelTaille; i1++)
   {Element * elem1 = tab_element(i1); // recup de l'element
    const Tableau <ElFrontiere*>&  tab1 = elem1->Frontiere(); // et de ses frontières
    int tab1Taille = tab1.Taille();      // frontières
//-- debug
//cout << "\n elem1 " << elem1->Num_elt() << " ";
//--fin debug		
		// on boucle sur les frontière, qui doivent être repérée par un pointeur non nulle
    for (int j1=1;j1<= tab1Taille;j1++)
    // on essaie de voir si l'élément j1 est recevable, c-a-d pointeur non nulle
		// sinon cela veut dire que la frontière a été supprimer car en double
    {ElFrontiere * elfr = tab1(j1); // pour simplifier
     // on ne continu que si le pointeur est non nul
     if (elfr != NULL)
      {
        bool res = false; 
        // si deux éléments frontières sont identiques alors tous leurs noeuds
        // sont identiques. En particulier le premier noeud de *elfr est commum
        // avec tous les éléments succeptibles de contenir un élément frontière
        // identique. On va donc utiliser la liste indice qui contiend cette liste
        int numnoeud = (elfr->TabNoeud())(1)->Num_noeud();
///          vector<Element*>::iterator ina,infin;
///          vector<Element*>& intertab = indice[numnoeud-1]; // pour allèger l'écriture
        list<Element*>::iterator ina,infin;
        list<Element*>& intertab = indice(numnoeud); // pour allèger l'écriture
        infin = intertab.end();
        // on balaie les élément succeptibles d'avoir des frontières communes
        for (ina = intertab.begin();ina!=infin;ina++)
         {Element * elem2 = *ina; // recup de l'element

//-- debug
//cout << " intertab.size() = " << intertab.size();
//cout << ", elem2 " << elem2->Num_elt() << " ";
//--fin debug		
          // on ne fait la recherche que pour les éléments différents de elem1
		        bool res_ina = false; // init d'un indicateur interne à la boucle j2 qui suit, 
          if (elem2 != elem1)
            {
//------- debug
//cout << "\n debug ** Maillage::CreeElemFront() ";
//elem2->Affiche(); cout << endl;
//---- fin debug
            
              const Tableau <ElFrontiere*>&  tab2 = elem2->Frontiere(); // et des éléments
              int tab2Taille = tab2.Taille();      // frontières
              for (int j2=1;j2<= tab2Taille;++j2)
               { // dans le cas où l'élément frontière existe, c'est-à-dire
                 // qu'il n'a pas été supprimé par un précédent passage
                 // on le compare
                 ElFrontiere* tab2j2 = tab2(j2); // pour simplifier
                 if (tab2j2 != NULL)
                  {ElFrontiere* p = tab2j2->Oppose(); // variable transitoire
                   if ((*elfr) == (*p))
                    // on a trouve un element qui annule
                     { res = res_ina = true;// on met l'indicateur
                       // suppression de l'élément dans la liste 
                       elem2->SupprimeFront(tab2j2);
                     };
                   delete p; // suppression de l'element p transitoire
                   }
                    // si il y a eu suppression de l'élément frontière on sort de la boucle
                 if (res_ina)   break; // on sort de la boucle si pas élément de frontière
               };
              // si l'on a détecté une égalité on arrète également cette boucle 
              // après avoir supprimé l'élément frontière 
      //             non, car on pourrait avoir une frontière qui soit commune à plus de 2 éléments
      //             pour l'instant ce n'est pas le cas, mais par exemple des arrêtes pour les volumes ??
      //          if (res)  
      //           { elem1->SupprimeFront(elfr);
      //             elfr=NULL;
      //             break;
      //            }  
            };
         };
        // en sortie on sauvegarde uniquement si c'est un élément frontière
        if (!res)
              {// lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1;
					          int num_dans_le_type = elem1->Num_de_frontiere_dans_le_type(j1);
               listFrontiere.push_back(Front(*elfr,elem1,num_dans_le_type));
              }
        else // sinon la frontière est commune avec au moins une autre, on l'a supprime
           { elem1->SupprimeFront(elfr);
           };  
      }; // fin du test if (elfr != NULL)
    }; // fin de la boucle sur les frontières de elem1
   }// fin de la boucle externe des éléments
     
     
/* // cas du dernier élément, ses éléments frontières non nuls sont forcément bons
non finalement, cela semble poser des pb sur le dernier élément vu que l'on a mis une procédure d'accélération 
pour le calcul des frontières donc on met en stand by pour l'instant, si pas de pb qui apparaissent on supprime
  { Element * elem1 = tab_element(tabelTaille); // recup de l'element
    const Tableau <ElFrontiere*>&  tab1 = elem1->Frontiere(); // et des éléments
    int tab1Taille = tab1.Taille();      // frontières
    for (int j1=1;j1<= tab1Taille;++j1)
      // on essaie de voir si l'élément j1 est recevable
     { ElFrontiere * elfr = tab1(j1); // pour simplifier
       if (elfr != NULL)
         {//lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1;
          listFrontiere.push_back(Front(elfr,elem1));
          }
       }   
    } 
	 */
    
//Sortie(1);         
 // effacement du contenu du tableau indice
 indice.Libere (); 
 
 //// ---- debug -----
 // vérification que l'on a bien les frontières bien connectées
// cout << " \n debug: Maillage::CreeElemFront()";
//{ LaLIST <Front>::iterator iF;
//  LaLIST <Front>::iterator iFfin = listFrontiere.end();
//  cout << "\n liste des frontières: \n ";
//  for (iF = listFrontiere.begin();iF!=iFfin; iF++)
//    { Front* elfront = &(*iF);
//	   Enum_type_geom type_front; // va être modifier par Num_frontiere
//	   cout	 << " frontière: " << elfront->Num_frontiere() << " " << elfront->Eleme()->Type_geom_front()
//                 << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage "
//					  << elfront->PtEI()->Num_maillage() << " \n ";
//     };
//};
 
// // vérif particulière (a commenter !)
//{ LaLIST <Front>::iterator iF; 
//  LaLIST <Front>::iterator iFfin = listFrontiere.end();
//  int nbf = 1;
//  for (iF = listFrontiere.begin();iF!=iFfin; iF++)
//    { Front* fro = &(*iF);
//      ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière
//      // récup de son tableau de noeud
//      Tableau<Noeud *>& tabn = efem1->TabNoeud();
//      int tabntaille = tabn.Taille();
//	   if (fro->PtEI()->Id_geometrie() == HEXAEDRE)
//         {cout << "nbf= " << nbf << ",  ele= " << fro->PtEI()->Num_elt() << " : ";
//			 for (int ij=1;ij<= tabntaille;ij++)
//				// on balaie ses noeuds  
//				cout <<  tabn(ij)->Num_noeud() << " ";
//			 cout << endl ;
//			 nbf++;
//			 };
//     };
//
//} 
// 
 //// ---- fin debug -----
 
 
 
 
  
 // definition des elements mitoyens aux elements de frontiere
 MitoyenFront();
 // ==== définition du tableau des noeuds frontières =====
 // 1) on définit un tableau de numéro de noeuds qui sont utilisés
 Tableau <int> t_noe(tab_noeud_taille,0); // tous les éléments sont nul
 // 2) on balaie les éléments frontières
 LaLIST <Front>::iterator li,li_end=listFrontiere.end();
 for (li=listFrontiere.begin();li!=li_end;li++)
   { Tableau <Noeud *> & tt = (*li).Eleme()->TabNoeud();
     int tt_taille=tt.Taille();
     for (int i=1;i<=tt_taille;i++)
       (t_noe(tt(i)->Num_noeud()))++;   
   };
 // 3) on récupère le nombre de noeud frontière
 int nb_n_f=0;
 for (int ii=1;ii<= tab_noeud_taille;ii++)
   if (t_noe(ii)!=0) nb_n_f++;
 // 4) def du tableau final
 tab_noeud_front.Change_taille(nb_n_f);
 nb_n_f=0; // on se ressert du numéro
 for (int ii=1;ii<= tab_noeud_taille;ii++)
   {if (t_noe(ii)!=0) {nb_n_f++;tab_noeud_front(nb_n_f)=tab_noeud(ii);};};
 
 // dans le cas où les éléments frontières sont des lignes, on les ordonnes 
 // de manière à former une ligne continue
// OrdonancementDesLigne();
};
        
// change le nom et le numéro du maillage
void Maillage::ChangeNomNumeroMaillage(const string & nom,int num)
   { // on vérifie que le nom de maillage fourni n'existe pas 
     if (listeNomMail.find(nom) != listeNomMail.end())
      { cout << "\n erreur, le nom de maillage demande existe deja : " << nom
             << "\n Maillage::ChangeNomNumeroMaillage(.....";
        Sortie(1);
      };
     // on met à jour listeNomMail en supprimant le doublet nom <=> numéro existant
     listeNomMail.erase(listeNomMail.find(nomDuMaillage));
     nomDuMaillage = nom; // on enregistre le nouveau nom   
     // on vérifie que le numéro de maillage proposé est valide        
     if (num <=0)
	      {	cout << "\nErreur : numero de maillage invalide ! = "<< num <<"\n";
		       cout << "Maillage::ChangeNomNumeroMaillage(.... \n";
		       Sortie(1);
	      };
	    idmail=num; // on enregistre le nouveau numéro 
     // maintenant on peut associer le nom au numéro dans la map
     listeNomMail[nomDuMaillage]=idmail;
   };  
        
// ramène le numéro du noeud le plus proche du point donné à t=0 
int Maillage::Noeud_le_plus_proche_0(const Coordonnee& M)
 { // tout d'abord si le maillage n'a pas de noeud on ramène 0
   int tail_mail = tab_noeud.Taille();
   if (tail_mail == 0) return 0;
   // sinon initialisation de la recherche
   int num_rech = 1; // choix du premier noeud
   // distance avec le noeud
   double dist = (tab_noeud(1)->Coord0() - M).Norme();
   // on boucle sur les noeuds
   for (int i=2;i<=tail_mail;i++)
    { double dista = (tab_noeud(i)->Coord0() - M).Norme();
      if (dista <= dist)
       { dist = dista; num_rech = i;};
    };
   // retour
   return num_rech;
  };
// ramène le numéro du noeud le plus proche du point donné à t=t 
int Maillage::Noeud_le_plus_proche_t(const Coordonnee& M)
 { // tout d'abord si le maillage n'a pas de noeud on ramène 0
   int tail_mail = tab_noeud.Taille();
   if (tail_mail == 0) return 0;
   // sinon initialisation de la recherche
   int num_rech = 1; // choix du premier noeud
   // distance avec le noeud
   double dist = (tab_noeud(1)->Coord1() - M).Norme();
   // on boucle sur les noeuds
   for (int i=2;i<=tail_mail;i++)
    { double dista = (tab_noeud(i)->Coord1() - M).Norme();
      if (dista <= dist)
       { dist = dista; num_rech = i;};
    };
   // retour
   return num_rech;
  };
// ramène le numéro du noeud le plus proche du point donné à t=tdt 
int Maillage::Noeud_le_plus_proche_tdt(const Coordonnee& M)
 { // tout d'abord si le maillage n'a pas de noeud on ramène 0
   int tail_mail = tab_noeud.Taille();
   if (tail_mail == 0) return 0;
   // sinon initialisation de la recherche
   int num_rech = 1; // choix du premier noeud
   // distance avec le noeud
   double dist = (tab_noeud(1)->Coord2() - M).Norme();
   // on boucle sur les noeuds
   for (int i=2;i<=tail_mail;i++)
    { double dista = (tab_noeud(i)->Coord2() - M).Norme();
      if (dista <= dist)
       { dist = dista; num_rech = i;};
    };
   // retour
   return num_rech;
  };

        
// ramène le numéro de l'élément qui contiend un point donné et le numéro du point
// d'intégration le plus proche  pour les ddl de la liste, (ddl spécifique à l'élément c'est-a-dire
// hors des ddl des noeuds de l'éléments)
// si pas de numéro d'élément ramène un numéro d'élément nulle
// si les numéros de point d'intégration ne sont pas identique pour l'ensemble
// des ddl, pb !!, le numéro du pt integ de retour est alors négatif
// enu_temps: dit si les coordonnées du point M sont à 0 ou t ou tdt
Maillage::NBelemEtptInteg Maillage::Element_le_plus_proche
            (Enum_dure enu_temps,const List_io <Ddl_enum_etendu>& list_enu
            ,const Coordonnee& M)
 { Maillage::NBelemEtptInteg ret;
   // tout d'abord si le maillage n'a pas d'élément on ramène 0
   int tail_mail = tab_element.Taille();ret.nbElem=0;ret.nbPtInteg=0;
   if (tail_mail == 0) { return ret;}
   // sinon initialisation de la recherche
   // on boucle sur les éléments  pour trouver celui qui contiend M
   // M peut également être sur la surface de l'élément ce qui est ok également   
   for (int i=1;i<=tail_mail;i++)
    { bool trouve = false;
      switch (enu_temps)
       { case TEMPS_0 : if(tab_element(i)->Interne_0(M)) trouve = true; break;
         case TEMPS_t : if(tab_element(i)->Interne_t(M)) trouve = true; break;
         case TEMPS_tdt : if(tab_element(i)->Interne_tdt(M)) trouve = true; break;
        };
     if(trouve)
       {// on a trouvé un élément on recherche le point le plus près ou est exprimé la grandeur
        ret.nbElem = i;
        List_io <Ddl_enum_etendu>::const_iterator ii,iide= list_enu.begin();
        List_io <Ddl_enum_etendu>::const_iterator iifin= list_enu.end();
        ret.nbPtInteg = tab_element(i)->PointLePlusPres(enu_temps,(*iide).Enum(),M);
        // on vérifie que tous les ddl sont disponibles au pt d'integ
        for (ii = iide;ii != iifin; ii++)
          if (!(tab_element(i)->Existe_pt_integ (ret.nbPtInteg,(*ii).Enum())))
            { ret.nbPtInteg = -1; return ret;} 
        // retour normal
        return ret;
/* ancienne vérif, pas bonne        
        // on vérifie que tous les ddl sont de la même famille sinon erreur
        for (ii = iide;ii != iifin; ii++)
          if (!Meme_famille((*ii).Enum(),(*iide).Enum())) 
            { ret.nbPtInteg = -1; return ret;} 
        // retour normal
        return ret;
 */
        };
     };
   // retour dans le cas où l'on n'a pas trouvé d'élément 
   ret.nbElem = 0;
   ret.nbPtInteg = 0;   
   return ret;
  };


// ramène le numéro de l'élément dont le centre de gravité à t = enu_temps est le plus proche d'un point donné
// Le point peut être n'importe où, en particulier à l'extérieur de la matière
// si pb retour de null
const Element* Maillage::Centre_de_Gravite_Element_le_plus_proche(Enum_dure enu_temps,const Coordonnee& M)
{ Element * el_retour=NULL;
  double distance = ConstMath::tresgrand;
  int nbelem = tab_element.Taille();
  Coordonnee G(ParaGlob::Dimension());
  // on balaie les éléments
  for (int ine = 1; ine <= nbelem; ine++)
   {// on commence par calculer le centre de gravité
    G.Zero();
    Tableau <Noeud *> taN = tab_element(ine)->Tab_noeud();
    int nbn = taN.Taille();
    switch (enu_temps)
     { case TEMPS_0:
        for (int inn = 1;inn<=nbn;inn++)
         {Noeud* noe = taN(inn);
          G += noe->Coord0();
         };
        break;
       case TEMPS_t:
        for (int inn = 1;inn<=nbn;inn++)
         {Noeud* noe = taN(inn);
          G += noe->Coord1();
         };
        break;
       case TEMPS_tdt:
        for (int inn = 1;inn<=nbn;inn++)
         {Noeud* noe = taN(inn);
          G += noe->Coord2();
         };
        break;
     };
    G /= nbn;
    double new_distance = (M-G).Norme();
    if (new_distance < distance)
      {el_retour = tab_element(ine);
       distance = new_distance;
      };
   };

 // retour de l'élément
 return el_retour;
};

        
// ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage
double Maillage::Max_var_dep_t_a_tdt() const
  { int nbn = tab_noeud.Taille(); double ret=0.;
    for (int i=1;i<=nbn;i++) ret=MaX(tab_noeud(i)->Max_var_coor_t_a_tdt(),ret);
    return ret;  
  };
	  
// ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments 
double Maillage::Min_dist2Noeud_des_elements(Enum_dure temps) const
{ double retour=ConstMath::tresgrand; // init
  // on balaie les éléments
  int taille_elem = tab_element.Taille();
  for (int i=1; i<=taille_elem;i++)
    {  const Tableau<Noeud *>& tab_N_el = tab_element(i)->Tab_noeud();
			    int nbn_loc = tab_N_el.Taille();
			    switch (temps)
				    { case TEMPS_0 :
					      { for (int in = 1;in<=nbn_loc;in++)
					         {const Coordonnee& Ci = tab_N_el(in)->Coord0();
					          for (int jn = in+1;jn<=nbn_loc;jn++)
						          {const Coordonnee& Cj = tab_N_el(jn)->Coord0();
							          retour = MiN(retour,(Ci-Cj).Max_val_abs());
							         };
						        };	
					        break;
					      } 
				      case TEMPS_t :
					      { for (int in = 1;in<=nbn_loc;in++)
			           {const Coordonnee& Ci = tab_N_el(in)->Coord1();
			            for (int jn = in+1;jn<=nbn_loc;jn++)
						          {const Coordonnee& Cj = tab_N_el(jn)->Coord1();
							          retour = MiN(retour,(Ci-Cj).Max_val_abs());
							         };
						        };	
					        break;
					      } 
				      case TEMPS_tdt :
					      { for (int in = 1;in<=nbn_loc;in++)
			           {const Coordonnee& Ci = tab_N_el(in)->Coord2();
			            for (int jn = in+1;jn<=nbn_loc;jn++)
						          {const Coordonnee& Cj = tab_N_el(jn)->Coord2();
							          retour = MiN(retour,(Ci-Cj).Max_val_abs());
							         };
						        };	
					        break;
					      } 
				      default :
					       cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
					       cout << "Maillage::Min_dist2Noeud_des_elements(... \n";
					       Sortie(1);
			     };
		  };
  return retour;
};

//----- lecture écriture de base info -----
//   lecture base info
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void Maillage::Lecture_base_info(ifstream& entr,const int cas)
{switch (cas)
  { case 1 : // ------- on récupère tout -------------------------
    {// l'id et le nom du maillage et la dimension
     int dime; string toto; int idmail_n; string nomDuMaillage_n;
     entr >>  toto >> idmail_n >> nomDuMaillage_n >> toto >> dime ;
     // les types de problèmes associés
//     { types_de_problemes.clear(); int nb=0; // init
//       entr >> toto >> nb ; string type;
//       for (int i=1;i<=nb;i++)
//         {entr >> type;types_de_problemes.push_back(Id_nom_ElemTypeProblem(type));};
//     };
     { int nb=0; // init
       entr >> toto >> nb ; string type;
       types_de_problemes.Change_taille(nb);
       for (int i=1;i<=nb;i++)
         {entr >> type;types_de_problemes(i)=(Id_nom_ElemTypeProblem(type));};
     };
     // les ddl associés
//     { ddl_representatifs_des_physiques.clear(); int nb=0; // init
//       entr >> toto >> nb ; string ddl;
//       for (int i=1;i<=nb;i++)
//         {entr >> ddl;ddl_representatifs_des_physiques.push_back(Id_nom_ddl(ddl));};
//     };
     { int nb=0; // init
       entr >> toto >> nb ; string type;
       ddl_representatifs_des_physiques.Change_taille(nb);
       for (int i=1;i<=nb;i++)
         {entr >> type;ddl_representatifs_des_physiques(i)=(Id_nom_ddl(type));};
     };
     
     // si le nom de maillage lu est différent de celui existant, 
     // on supprime le doublet dans la map de gestion et on met à jour
     if (nomDuMaillage != nomDuMaillage_n)
       { listeNomMail.erase(listeNomMail.find(nomDuMaillage));
         nomDuMaillage = nomDuMaillage_n;
         listeNomMail[nomDuMaillage] = idmail_n;
         idmail = idmail_n;
        }
     else
      { // sinon on vérifie quand même que le numéro n'a pas changé
        if (idmail != idmail_n)
          { listeNomMail[nomDuMaillage] = idmail_n;
            idmail = idmail_n;
           };
      };          
     if (dime != dimension)
		    cout << "\nErreur : valeur de la dimension non coherente avec "
		         << " l'espace de travail!\n"
		         << "Maillage::Lecture_base_info(ofstream& sort,int cas)"
			        << endl;
     cout << " === lecture du maillage " << nomDuMaillage << " nb " << idmail << "\n" ;   
     //------------- lecture des noeuds -------------
     cout << " lecture des noeuds " ;   
     // le nombre de noeud
     int nbNoeud = tab_noeud.Taille();
     entr >> nbNoeud >> toto;
     // normalement ici on ne doit pas avoir déjà de noeud
     Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud
     // lecture des noeuds
     Noeud * ptr; 
     for (int i=1; i<= nbNoeud; i++)
      { ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage
        ptr->Lecture_base_info(entr,cas);
        Affectation_noeud(*ptr);
      };
     // ------------ les elements finis -----------
     cout << ", lecture des elements \n" ;
     entr >> toto;  
     // lecture du nombre d'element
     int nbElement;
     entr >> toto >> nbElement;
     // dimensionnement dynamique du tableau d'elements 
     Change_nb_element(nbElement);
     // Lecture des elements
     Element * pte;
     for (int i=1; i<= nbElement; i++)
       { // lecture geometrie et interpolation
         Enum_geom id_geom; Enum_interpol id_interpol;
         EnumElemTypeProblem  id_typeProb;string str_precision;
         int num_elt; // donnee dont on ne se sert pas
         entr >>  toto >> num_elt  >> id_geom >> id_interpol >> id_typeProb;
         // on regarde  le prochain caractère sans changer le flot
         /////int cr=entr.peek();
         //--- début du remplacement du peek
         char car = Picococar(entr); // = flot.peek();
         // on recupère l'entier correspondant au caractère
         int cr = int(car);
         //--- fin du remplacement du peek
         // on regarde s'il y a une chaine discriminante
         if (cr == int('_')) entr >> str_precision;
         // ======== choix de l'element =====================================
         // et affectation du pointeur d'element en fonction de id_geom et id_interpol
         // le numero d'element : num_elt, est affecte a l'element pointe par ptr
         pte = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision);
         if (pte == NULL)
             { // l'operation a echouee
               cout << "\n Erreur dans le choix d'element ****** ";
               cout << "\n l\'element : " << Nom_interpol(id_interpol) 
                    << " " << Nom_geom(id_geom)
                    << " n\'est pas present dans le programme ! " 
                    << "\n Maillage::Lecture_base_info(..." << endl;
               Sortie (1);
             };
         // lecture des infos particulieres a l'element
         Tableau<Noeud*> * pt = & tab_noeud;
         pte->Lecture_base_info(entr,pt,cas);
         Affectation_element(*pte);  
         // si c'est le premier élément du premier maillage on regarde s'il s'agit 
         // d'un élément axisymétrique et on adapte l'espace de travail en conséquence
         if ((i==1) && (idmail==1)) 
           	{ if (TestEnum_geom_axisymetrique(id_geom))
           		    ParaGlob::Change_en_AxiSymetrie();
           	}
         else
            {// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent
             if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie()))
             	{cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail 
             	      << " nom= " <<  nomDuMaillage;
             	 if (ParaGlob::AxiSymetrie())     
             	 	cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)"
             	 	      << " et l'element lu est axisymetrique !! ";      
             	 else
             	 	cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)"
             	 	      << " et l'element lu n'est pas axisymetrique !! ";      
                 cout << endl;
                 Sortie (1);             		
             	};
            };	
        }
     // ------------ les elements frontières -----------
     // il sont créé par ailleurs si il y en a besoin
	    break;
	   }
    case  2 : // ----------- lecture uniquement de se qui varie --------------------
    {// le nom du maillage pour vérification
//    cout << "\n debug **** Maillage::Lecture_base_info\n"
//         << "\n entr.rdstate() " << entr.rdstate() << flush;
//entr.clear();
     string inter,nomDuMail;
     entr >> inter >> nomDuMail ;
//string truc; entr >> truc;
//     cout << "\n debug **** Maillage::Lecture_base_info\n"
//          << " inter=" << inter << " nomDuMaillage= " << nomDuMail
//          << " titi= "<< titi << " titi1= "<< titi1
//          << "\n entr.rdstate() " << entr.rdstate() << flush;

     if (nomDuMail != nomDuMaillage)
		    { cout << "\nErreur : le nom du maillage lu (" << nomDuMail << ") n'est pas identique avec celui en cours ("
		           << nomDuMaillage << ") !! "
		           << "\n Maillage::Lecture_base_info(ofstream& sort,int cas)"
			          << endl;
		      Sortie (1);
		    };
     //------------- les noeuds -------------
     // le tableau doit être déjà dimensionné
     int nbNoeud = tab_noeud.Taille();
     for (int i=1; i<=nbNoeud;i++)
       tab_noeud(i)->Lecture_base_info(entr,cas);
     // ------------ les elements finis -----------
     int nbElement = tab_element.Taille();
     Tableau<Noeud*> * pt = & tab_noeud;
     int nb;string toto;
     for (int j=1;j<=nbElement;j++)
       {entr >> toto >> nb; // le numéro de l'élément
        tab_element(j)->Lecture_base_info(entr,pt,cas);
       };
     // ------------ les elements frontières -----------
     // il sont créé par ailleurs si il y en a besoin
	    break;
    }
    default :
	    { cout << "\nErreur : valeur incorrecte du type de lecture !\n";
	      cout << "Maillage::Lecture_base_info(ofstream& sort,int cas)"
			         << " cas= " << cas << endl;
	      Sortie(1);
	    };
  };
};
        
//   écriture base info   
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Maillage::Ecriture_base_info(ofstream& sort,const int cas)
{switch (cas)
  { case 1 : // ------- on sauvegarde tout -------------------------
    {// l'id et le nom du maillage et la dimension
     sort << "\n num= " << idmail <<"  "<< nomDuMaillage <<" " 
          << "dim= " << dimension;
     // les types de problèmes associés
//     {list <EnumElemTypeProblem>::iterator il,ilfin=types_de_problemes.end();
//      sort <<"\n types_de_problemes: " << types_de_problemes.size() ;
//      for (il=types_de_problemes.begin();il != ilfin;il++)
//         sort << NomElemTypeProblem(*il);
//     };
     {int tail = types_de_problemes.Taille();
      sort <<"\n types_de_problemes: " << tail ;
      for (int i=1;i<=tail;i++)
        sort << " "<< NomElemTypeProblem(types_de_problemes(i));
     };
     
     // les ddl associés
//     {list <Enum_ddl>::iterator il,ilfin=ddl_representatifs_des_physiques.end();
//      sort <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size();
//      for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++)
//         Nom_ddl(*il);
//     };
     {int tail = ddl_representatifs_des_physiques.Taille();
      sort <<"\n type_de_ddl_associes: " << tail;
      for (int i=1;i<=tail;i++)
        sort << " "<< Nom_ddl(ddl_representatifs_des_physiques(i));
     };
     
     sort <<"\n";
     //------------- les noeuds -------------
     // le nombre de noeud
     int nbNoeud = tab_noeud.Taille();
     sort << nbNoeud << " noeuds \n";
     // sorti des noeuds
     for (int i=1; i<=nbNoeud;i++)
       tab_noeud(i)->Ecriture_base_info(sort,cas);
     // ------------ les elements finis -----------
     sort << "\n --les_elements-- ";
     // le nombre d'élément
     int nbElement = tab_element.Taille();
     sort <<"\n nombre_d'element " << nbElement ;
     // écriture des éléments
     for (int j=1;j<=nbElement;j++)
      { // tout d'abord les données de différentiation
        // numéro geometrie et interpolation
         sort << "\n\n element: " << tab_element(j)->Num_elt() << " "
              << tab_element(j)->Id_geometrie() << " "
              << tab_element(j)->Interpolation() << " "
              << tab_element(j)->TypeProblem() << " "
              << tab_element(j)->Infos_annexe() << "\n";
         // puis les données de l'élément     
         tab_element(j)->Ecriture_base_info(sort,cas);
       };
     sort << "\n ";  
     // ------------ les elements frontières -----------
     // ne sont pas sauvegardé car reconstruit à la demande
	    break;
	    }
    case  2 : // ----------- sauvegarde uniquement de se qui varie --------------------
    {// le nom du maillage pour vérification en lecture
     sort << "\nnomDuMail= " <<  nomDuMaillage << "\n";
     //------------- les noeuds -------------
     int nbNoeud = tab_noeud.Taille();
     // sorti des noeuds
     for (int i=1; i<=nbNoeud;i++)
       tab_noeud(i)->Ecriture_base_info(sort,cas);
     // ------------ les elements finis -----------
     int nbElement = tab_element.Taille();
     for (int j=1;j<=nbElement;j++)
       {sort << "\n\n element_nb: " << tab_element(j)->Num_elt() << " ";
        tab_element(j)->Ecriture_base_info(sort,cas);
       };
     // ------------ les elements frontières -----------
     // ne sont pas sauvegardé car reconstruit à la demande
     
     break;
     }
    default :
	    { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
       cout << "Maillage::Ecriture_base_info(ofstream& sort,int cas)"
			         << " cas= " << cas << endl;
	      Sortie(1);
	    };
  };
};
	    
// ------ informations utiles par exemples pour la visualisation
        // retourne les dimensions minis et maxi suivant les axes du repère
        // absolu du maillage  (en faite le calcul est fondé
        // uniquement sur la position des noeuds du maillage
        // le premier vecteur contient les minimums
        // le deuxième vecteur contient les maximums     
Tableau <Vecteur>  Maillage::Taille_boiteMail()
  { // définition du tableau de retour
    Tableau <Vecteur> tabret(2);
    // cas particulier de maillage vide 
    int nbNoeud = tab_noeud.Taille();
    if (nbNoeud == 0)
      return tabret;
    // sinon le cas normal  
    tabret(1).Change_taille(dimension);
    tabret(2).Change_taille(dimension);
    // on balaie tous les coordonnées des noeuds pour déterminer les tailles
    // maxi et mini 
      // dans une première étape on regarde s'il existe les coordonnées à t=0
      // t et t+dt, ceci à partir du premier noeud qui sert de test
    // on cherche les extrémas  
    for (int i=1; i<=nbNoeud;i++)
      { Coordonnee a0=tab_noeud(i)->Coord0();
        for (int k=1;k<= dimension;k++)
            { if (tabret(1)(k) > a0(k))
                tabret(1)(k) = a0(k);
              if (tabret(2)(k) < a0(k))
                tabret(2)(k) = a0(k);
             }
        // dans le cas de coordonnées à t idem     
        if (tab_noeud(i)->ExisteCoord1())
         {Coordonnee aat=tab_noeud(i)->Coord1();
          for (int k=1;k<= dimension;k++)
            { if (tabret(1)(k) > aat(k))
                tabret(1)(k) = aat(k);
              if (tabret(2)(k) < aat(k))
                tabret(2)(k) = aat(k);
             }
           };  
        // dans le cas de coordonnées à t+dt idem     
        if (tab_noeud(i)->ExisteCoord2())
         {Coordonnee aatdt=tab_noeud(i)->Coord2();
          for (int k=1;k<= dimension;k++)
            { if (tabret(1)(k) > aatdt(k))
                tabret(1)(k) = aatdt(k);
              if (tabret(2)(k) < aatdt(k))
                tabret(2)(k) = aatdt(k);
             }
          };   
       }      
    
    return tabret;
   };
   
//==========================  fonction protegee =============================

// definition des elements mitoyens aux elements de frontiere
// à la fin du programme tous les éléments mitoyens sont stocké dant les éléments front
// la manip est de créer des éléments frontières aux éléments frontières existant
// ensuite deux éléments sont mitoyens s'il ont la même frontière
// à la fin du programme tous les frontières des éléments frontières sont supprimé
void Maillage::MitoyenFront()
{ // le tableau indice_NFr (indice des noeuds frontières) va permettre une recherche plus rapide
  //  on le construit:
  int tab_noeud_taille= tab_noeud.Taille();
  Tableau <List_io <Front*> > indice_NFr(tab_noeud_taille);
  // indice_NFr contiend les front succeptible d'avoir des frontières géométriques communes
  LaLIST <Front>::iterator iF; 
  LaLIST <Front>::iterator iFfin = listFrontiere.end();
  for (iF = listFrontiere.begin();iF!=iFfin; iF++)
    { Front* fro = &(*iF);
      ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière
      // récup de son tableau de noeud
      Tableau<Noeud *>& tabn = efem1->TabNoeud();
      int tabntaille = tabn.Taille();
      for (int ij=1;ij<= tabntaille;ij++)
          // on balaie ses noeuds  
           indice_NFr((tabn(ij)->Num_noeud())).push_back(fro);
     };
	 // on supprime les doublons
	 for (int i=1;i<=tab_noeud_taille;i++)
	     { List_io <Front*>& intertab = indice_NFr(i); // pour allèger l'écriture
		    intertab.sort(); // on ordonne
			 intertab.unique(); // on supprime les doublons
			}; 
     
//-- debug
//  cout << "\n maillage " << idmail << "\n";
//  for (int ii=1;ii<= tab_noeud.Taille();ii++) 
//  	{cout << "\n noeud " << ii << "\n";
//  	 list<Front*>::iterator ina,infin;
//     list<Front*>& intertab = indice_NFr(ii); // pour allèger l'écriture
//     infin = intertab.end();
//     for (ina = intertab.begin();ina!=infin;ina++)
//      {Front*  elem2 = (*ina); // recup de l'element
//       elem2->Affiche();
//      };
//  	};  
//  cout << endl;
// // Sortie(1);     
//--fin debug		
     
      
  // on determine les elements front mitoyens a chaque element frontiere, s'ils existent
  LaLIST <Front>::iterator iE,jE,iiE; 
  LaLIST <Front*>  inters; // stockage intermediaire 
  LaLIST <Front>::iterator iEfin = listFrontiere.end();   
  for ( iE = listFrontiere.begin(); iE !=iEfin; iE++)
     // pour chaque element on recherche d'autre element ayant des frontieres communes
     { // création d'élément frontières secondaires des frontières primaires
       Tableau <ElFrontiere*> tabi = (*iE).Eleme()->Frontiere(); // frontieres géométriques de iE
// pour le débug      cout << "\n on cherche un mitoyen a "; (*iE).Affiche();
       int tabitaille = tabi.Taille();
       for (int i=1;i<= tabitaille;i++)
        { ElFrontiere* elfr = tabi(i);
// pour le débug        cout << " frontiere : " << i ;
          // si deux éléments frontières sont identiques alors tous leurs noeuds
          // sont identiques. En particulier le premier noeud de *elfr est commum
          // avec tous les éléments succeptibles de contenir un élément frontière
          // identique. On va donc utiliser le vector indice_NFr qui contiend cette liste
          int numnoeud = (elfr->TabNoeud())(1)->Num_noeud();
          list<Front*>::iterator ina,infin;
          list<Front*>& intertab = indice_NFr(numnoeud); // pour allèger l'écriture
          infin = intertab.end();
          // on balaie les élément succeptibles d'avoir des frontières communes
          for (ina = intertab.begin();ina!=infin;ina++)
           {Front*  elem2 = (*ina); // recup de l'element frontière
            // on ne fait la recherche que pour les éléments différent de *iE
            if (*elem2!=*iE)
             {Tableau <ElFrontiere*> tabj = elem2->Eleme()->Frontiere(); // frontieres de ina
              int tabjtaille = tabj.Taille();
              for (int j=1;j<= tabjtaille;j++)
               { // ElFrontiere * tabjjOppose=(tabj(j)->Oppose()); // element transitoire
                 if ((*elfr) == *(tabj(j))) // ||
               //   (*(tabi(i)) == *tabjjOppose) )
                 // iE et ina ont une frontiere commune, sont donc mitoyen
                   { //Front pj = &(*(*ina));
                     inters.push_back(&(*elem2));
//-- debug
//{Tableau <Noeud *>& toto = elfr->TabNoeud(); cout << "\n premiere frontiere NB: "<< i << ":  ";
//for (int ii=1;ii<=toto.Taille();ii++) cout <<toto(ii)->Num_noeud() << " ";}
//{Tableau <Noeud *>& toto = (tabj(j))->TabNoeud(); cout << "\n frontiere mitoyenne NB: "<< j << ":  ";
//for (int ii=1;ii<=toto.Taille();ii++) cout <<toto(ii)->Num_noeud() << " "; }
//cout << "\n ";
//if ((j1==3)&&(j2==6))
// cout << "on y est ";
//--fin debug		
//  pour le débug
//                     cout << "\n on a trouve une frontiere commune ";
//                     elem2->Affiche();
//                     cout << " frontiere commune: noeuds: ";
//                     Tableau <Noeud *> tabno = (tabj(j))->TabNoeud();
//                     int nb = tabno.Taille();
//                     for (int ijk=1;ijk<=nb; ijk++) 
//                       cout << tabno(ijk)->Num_noeud() << " ";
//  fin pour le débug                     
                    };
              //   delete tabjjOppose; // suppression de l'element  transitoire
               };
             };
           };
        }; 
      // fin de la recherche concernant elfr
	   // on supprime les doublons
		inters.sort(); // on ordonne
		inters.unique(); // on supprime les doublons
      // creation d'un tableau a la place de la liste
      Tableau  <Front*>  tabb((int) inters.size());
      LaLIST <Front*>::iterator ip; int i2;
      LaLIST <Front*>::iterator ipfin=inters.end();
      LaLIST <Front*>::iterator ipdebut=inters.begin();
      for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++)
       tabb(i2) = &(*(*ip));
      // def des elements mitoyen     
      (*iE).DefMitoyen(tabb);
//  -- débug --- affichage
//if (inters.size() > 6)
//  {cout << "\n nb frontière > 6 ";
//   (*iE).Affiche();
//	cout << endl;
//	};
//  -- fin débug --- affichage
      // on vide la liste
      inters.erase(ipdebut,ipfin);
     };
//  -- débug --- affichage
//  for ( iE = listFrontiere.begin(); iE !=iEfin; iE++)
//      (*iE).Affiche(); 
//  -- fin débug --- affichage
  //effacement de tous les éléments frontières secondaires des éléments frontières
  // primaires
  LaLIST <Front>::iterator iEE; 
  for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++)
     (*iEE).Eleme()->EffaceFrontiere();
     
//  -- débug --- affichage
//  for ( iE = listFrontiere.begin(); iE !=iEfin; iE++)
//     { Tableau <Front*>& tabi = (*iE).TabMitoyen(); 
//       int tabitaille = tabi.Taille();
//       for (int i=1;i<= tabitaille;i++)
//        { Front* elfr = tabi(i);
//          cout << "\n"; 
//          elfr->Affiche();
//        }
//     };
////  -- fin débug --- affichage
//     
     
 };      
 
 // dans le cas où les éléments frontières sont des lignes, on les ordonnes 
 // de manière à former une ligne continue
 void Maillage::OrdonancementDesLigne()
  {// on définit une liste intermédiaire
   LaLIST <Front> interlist;
   // on commence par le premier élément de la liste et de proche en proche on 
   // rempli la liste    
  // on passe en revue les éléments frontières
//  LaLIST <Front>::iterator iEE; 
//  for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++)
 //    (*iEE).elem->EffaceFrontiere();
   };
	
// definition d'un stockage contenant tous les Front associés à toutes les frontières de tous les éléments
// puis définition des elements mitoyens à ces Front : deux éléments Front sont mitoyens
// s'ils correspondent à des Element différents, et si les frontières associées possèdent les mêmes noeuds 
// toutes ces informations sont stockées dans : mitoyen_de_chaque_element (cf. sa description)
void Maillage::Calcul_tous_les_front_et_leurs_mitoyens()
{   // on crée les éléments frontières dans chaque élément
    int tabelTaille = tab_element.Taille();
    mitoyen_de_chaque_element.Change_taille(tabelTaille); // dimensionnement    
    // on boucle sur les elements 
    for (int i2 = 1; i2 <= tabelTaille; i2++)
      { // création des éléments frontières
		      Element * elem1 = tab_element(i2);
		      elem1->Frontiere(true);
		      // puis on crée tous les éléments Front, qui sont alors stockés dans mitoyen_de_chaque_element(i2)
		      // par contre pour l'instant on n'a pas les mitoyens de calculés
        const Tableau <ElFrontiere*>&  tab1 = elem1->Frontiere(); // et de ses frontières
		      Tableau <Front> & tab_front =  mitoyen_de_chaque_element(i2); // pour simplifier
        int tab1Taille = tab1.Taille();      // nb de frontières
		      tab_front.Change_taille(tab1Taille); // dimensionne mitoyen_de_chaque_element(i2)
		      for (int j=1;j<=tab1Taille;j++)
		        tab_front(j) = Front(*tab1(j),elem1,j);
//cout << "\n les front";
//for (int j=1;j<=tab1Taille;j++)
//		    tab_front(j).Affiche();
		    };

    // on  crée des tableaux permettant d'accélérer l'algorithme final
    // pour chaque noeud on note quel élément contiend ce noeud
    // "indice" contiend les numéros d'élément succeptible d'avoir des frontières communes
	   Calcul_indice();
    // on va  boucler sur les éléments en regardant
    // pour chaque frontière si il y a d'autres frontières mitoyennes  c-a-d si
    // il y a d'autres frontières identiques 
    for (int i1 = 1; i1 <= tabelTaille; i1++)
     {Tableau <Front> & tab_front =  mitoyen_de_chaque_element(i1); // pour simplifier
      int tab1Taille = tab_front.Taille(); // nb de frontières (qui sont déjà stockées)
      for (int j1=1;j1<= tab1Taille;j1++) // on boucle sur les frontière de l'élément principale (nb=i1)
      // on essaie de voir si l'élément j1 est recevable
      {const ElFrontiere * elfr = tab_front(j1).Eleme_const(); // récup de la frontière
       // si deux éléments frontières sont identiques alors tous leurs noeuds
       // sont identiques. En particulier le premier noeud de *elfr est commum
       // avec tous les éléments succeptibles de contenir un élément frontière
       // identique. On va donc utiliser la liste indice qui contiend cette liste
       int numnoeud = (elfr->TabNoeud_const())(1)->Num_noeud();
       list<Element*>::iterator ina,infin;
       list<Element*>& intertab = indice(numnoeud); // pour allèger l'écriture
       infin = intertab.end();
       LaLIST <Front*>  inters; // stockage intermediaire 
       // on balaie les élément succeptibles d'avoir des frontières communes
       for (ina = intertab.begin();ina!=infin;ina++)
        {Element * elem2 = *ina; // recup de l'element
         // on ne fait la recherche que pour les éléments différents de elem1
			      int num_elem2 = elem2->Num_elt(); 
         if (num_elem2 != i1)
           {// récup des éléments front correspondant à elem2 
			         Tableau <Front>& tab_fro = mitoyen_de_chaque_element(num_elem2);
			         int tab_fro_taille = tab_fro.Taille();
				        for (int j2=1;j2<=tab_fro_taille;j2++)
				         { // on compare
				           if ((*tab_fro(j2).Eleme_const()) == (*elfr))
						          {// on récupère le Front de l'élément elem2, pour la frontière j2
						           Front* front_j2 = &tab_fro(j2);
						           inters.push_back(front_j2);
//--debug
//tab_front(j1).Affiche();
//front_j2->Affiche();
//--fin_debug						  
						          };
				         };
           };
		      };
     
	      // on supprime les doublons
		     inters.sort(); // on ordonne
       inters.unique(); // on supprime les doublons
       // creation d'un tableau a la place de la liste
       Tableau  <Front*>  tabb((int) inters.size());
       LaLIST <Front*>::iterator ip; int i2;
       LaLIST <Front*>::iterator ipfin=inters.end();
       LaLIST <Front*>::iterator ipdebut=inters.begin();
       for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++)
        tabb(i2) = &(*(*ip));
       // def des elements mitoyen, stocké dans mitoyen_de_chaque_element(i1)   
		     tab_front(j1).DefMitoyen(tabb);
     
      }; // fin de la boucle sur les frontières de elem1
     };// fin de la boucle externe des éléments
//--debug
//for (int i=1;i<=mitoyen_de_chaque_element.Taille();i++)
//   {cout <<"\n\n ****  element: "<<i<<" frontiere: ";
//	 Tableau <Front>& tab_f = mitoyen_de_chaque_element(i);
//	 for (int j=1;j<=tab_f.Taille();j++)
//	   tab_f(j).Affiche();
//	}	
//--fin debug	
    // effacement du contenu du tableau indice
    indice.Libere ();
      
};      
	
  
// lectures des infos pour le choix d'un élément
void Maillage::Lecture_info_1element(UtilLecture * entreePrinc,int& num_elt,Enum_geom& id_geom
                         ,Enum_interpol& id_interpol,EnumElemTypeProblem&  id_typeProb
                         ,string& str_precision)
 {  // mise en place des valeurs par défaut
    str_precision = "";
    id_typeProb = MECA_SOLIDE_DEFORMABLE; // type par défaut
    // lecture des champs qui doivent être toujours présents
    *(entreePrinc->entree) >>  num_elt >> id_geom >> id_interpol;
  
    // cas d'info annexe ou du type de problème
    // on regarde  le prochain caractère sans changer le flot
    /// int cr=(entreePrinc->entree)->peek(); ne marche pas !!!
    //--- début du remplacement du peek
    char car = Picococar(*(entreePrinc->entree)); // = flot.peek();
    // on recupère l'entier correspondant au caractère
    int cr = int(car);
    //--- fin du remplacement du peek
    // si c'est un chiffre c'est fini pour le choix de l'élément
    int zero = int('0'); int neuf = int('9');
//    if ((cr >= int('0'))&&(cr <= int('9'))) return;
    if ((cr >= zero)&&(cr <= neuf)) return;
    // maintenant on a deux cas, soit des infos annexes ou soit
    // la définition du type de pb suivi ou non d'infos annexes
    if (cr == int('_'))
       // cas où on a des infos annexes de choix
      { *(entreePrinc->entree) >> str_precision;
        // ensuite il ne doit y avoir que des numéros donc fin
        return;
      } 
    // ou on regarde s'il y a définition du type de problème
    // qui doit commencer par une lettre 
    else if ( ((cr >= int('a'))&&(cr<=int('z'))) ||
              ((cr >= int('A'))&&(cr<=int('Z'))) )
        {  *(entreePrinc->entree) >> id_typeProb; 
           // on regarde s'il y a des infos annexes après le type de problem   
           if (cr == int('_'))
             // cas où on a des infos annexes de choix
             { *(entreePrinc->entree) >> str_precision;
               // ensuite il ne doit y avoir que des numéros donc fin
               return;
              } 
        };
    // sinon c'est le cas qui ne doit pas arriver mais pour éviter des warnings
    return;  
  };             
               
// affectation d'un noeud au maillage c-a-d au tableau de pointeur de noeud, 
// a condition que la place ne soit pas déjà occupée sinon on change le numéro
// de noeud et on augmente le tableau 
void Maillage::Affectation_noeud(Noeud& noeud)      
  {	int nbn = noeud.Num_noeud();
    if (tab_noeud(nbn) == NULL)
      {tab_noeud(nbn)=&noeud;}
    else
      // on augmente la place
      {int tail_tab_noeud = tab_noeud.Taille()+1;
       tab_noeud.Change_taille(tail_tab_noeud);
       noeud.Change_num_noeud(tail_tab_noeud);
       tab_noeud(tail_tab_noeud)=&noeud;
       if (ParaGlob::NiveauImpression() > 0)
          {cout << "\n warning : le numero initial du noeud " << nbn << " est remplace par "
           		<< " le numero d'ordre attribue automatiquement par herezh " << tail_tab_noeud
           		<< "\n seul ce dernier sera utilise par la suite ! " << endl;
           if (ParaGlob::NiveauImpression() > 5)
             cout << "\n  Maillage::Affectation_noeud (Noeud& noeud) " << endl;		
          };
      };
  };
		
// affectation d'un element au maillage c-a-d au tableau de pointeur d'element, 
// a condition que la place ne soit pas déjà occupée sinon on change le numéro
// de l'élément et on augmente le tableau 
void Maillage::Affectation_element(Element& element)   
  { int nbe = element.Num_elt();
    if (tab_element(nbe) == NULL)
      {tab_element(nbe)=&element;}
    else
      // on augmente la place
      {int tail_tab_element = tab_element.Taille()+1;
       tab_element.Change_taille(tail_tab_element);
       element.Change_num_elt(tail_tab_element);
       tab_element(tail_tab_element)=&element;
       if (ParaGlob::NiveauImpression() > 0)
          {cout << "\n warning : le numero initial de l'element " << nbe << " est remplace par "
           		<< " le numero d'ordre attribue automatiquement par herezh " << tail_tab_element
           		<< "\n seul ce dernier sera utilise par la suite ! " << endl;
           if (ParaGlob::NiveauImpression() > 5)
             cout << "\n  Maillage::Affectation_element (Element& element) " << endl;		
          };
      };
    // on met à jour éventuellement les types de problèmes gérés
    EnumElemTypeProblem enu = element.Id_TypeProblem();
    if (!types_de_problemes.Contient(enu))
     {int tail = types_de_problemes.Taille();
      types_de_problemes.Change_taille(tail+1);
      types_de_problemes(tail+1) = enu;
      ddl_representatifs_des_physiques.Change_taille(tail+1);
      switch (enu)
          {case MECA_SOLIDE_DEFORMABLE :
            ddl_representatifs_des_physiques(tail+1)=X1;break;
           case THERMIQUE :
            ddl_representatifs_des_physiques(tail+1)=TEMP;break;
           default :
            cout << "\n***Erreur : pour l'instant le type de probleme: "<<NomElemTypeProblem(enu)
               << "n'est pas pris en compte !\n";
            cout << "\n Maillage::Affectation_element(... \n";
            Sortie(1);
          };

     };
//   
//   
//   
//    if (find(types_de_problemes.begin(),types_de_problemes.end(),enu) == types_de_problemes.end())
//       {
//         types_de_problemes.push_back(enu);
//         types_de_problemes.sort(); types_de_problemes.unique();
//         switch (enu)
//          {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(enu)
//               << "n'est pas pris en compte !\n";
//            cout << "\n Maillage::Affectation_element(... \n";
//            Sortie(1);
//          };
//       };
  };

// Modifie le nombre de noeuds du maillage (N.B.: Fait appel
// a la methode Change_taille de la classe Tableau<Noeud>)
// les éléments supplémentaires ont un pointeur mis à Null
void Maillage::Change_nb_noeud (int nouveau_nb)    
{ int vieille_taille = tab_noeud.Taille();	
  tab_noeud.Change_taille(nouveau_nb);	
  for (int i=vieille_taille+1;i<=nouveau_nb;i++)
   tab_noeud(i)=NULL;
};
		
// Modifie le nombre d'elements du maillage (N.B.: Fait appel
// a la methode Change_taille de la classe Tableau<Element>)
// les éléments supplémentaires ont un pointeur mis à Null
void Maillage::Change_nb_element (int nouveau_nb)   
{ int vieille_taille = tab_element.Taille();	
  tab_element.Change_taille(nouveau_nb);	
  for (int i=vieille_taille+1;i<=nouveau_nb;i++)
   tab_element(i)=NULL;
};
              
               
               
                                      
  
  
  
 


