// FICHIER : Maillage.h
// 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/>.

/************************************************************************
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:    def de la classe Maillage,                               *
 *         Une instance de la classe Maillage est identifiee a partir   *
 *         de la dimension, des tableaux des noeuds et des elements.    *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/


#ifndef MAILLAGE_H
#define MAILLAGE_H


#include <iostream>
#include <map>


#include "Noeud.h"
#include "Element.h"
#include "Tableau_T.h"
#include "UtilLecture.h"
#include "Enum_geom.h"
#include "Enum_interpol.h"
#include "LesReferences.h"
#include "Front.h"
#include "LaList.h"
#include "Nb_assemb.h"
#include "Ddl_enum_etendu.h"
#include "Droite.h"
#include "Plan.h"
#include "Sphere.h"
#include "Cylindre.h"
#include "Cercle.h"
#include "Condilineaire.h"
#include "DiversStockage.h"


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

//------------------------------------------------------------------
//!      Maillage:  un maillage particulier
//------------------------------------------------------------------
/// \author    Gérard Rio
/// \version   1.0
/// \date       23/01/97

class Maillage
{   
	public :
  friend class LesMaillages;
	
		// 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_maillage : est facultatif, s'il est différent de ".", il est pris en compte 
		
		// Constructeur par defaut
		Maillage (map < string, int , std::less <string> > & lisNomMail,int nmail=1,int dim=3
		          ,const string& nom_maillage = ".");
		
		// Constructeur fonction d'une dimension, du nombre de noeuds
		//  du nombre d'elements, et d'un numero d'identification (le nb de maillage)
		Maillage (map < string, int , std::less <string> > & lisNomMail
		          ,int dim,int n_noeud,int n_elt,int nmail
		          ,const string& nom_maillage = ".");
		
		// 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 (map < string, int , std::less <string> > & lisNomMail
		          ,int dim,list <Noeud* >& li_noeud, list <Element* > li_element
		          ,int nmail
		          ,const string& nom_maillage = ".");
		
		// 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 
		// cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut
		// ensuite les définir
		Maillage (const Maillage& mail);
		
		// 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 !
		Maillage (map < string, int , std::less <string> > & lisNomMail
		          ,int nmail, const string& nomDuMaillage, const Maillage& mail);
		
		// DESTRUCTEUR :		
		~Maillage ();
		
		
		// METHODES :
		
		// lecture de maillages au travers des outils de la classe 
		// UtilLecture et def des references s'y rapportant
		void LectureMaillage(UtilLecture * entreePrinc,LesReferences& lesRef);
  // lecture et application des opérations d'affinages sur le maillage: ex:déplacement solide
  void LectureEtApplicationAffinage(UtilLecture * entreePrinc,LesReferences& lesRef);
  
	 // ajout d'une liste de noeud à un maillage
  // si le numéro de maillage associé au noeud est nul, il est remplacé par celui du maillage
  // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a
  // création d'un nouveau noeud identique, avec le numéro this
  // ajout éventuel d'une liste de référence de noeuds, si celle-ci est non-nulle
  // il y a création de nouvelles ref correspondantes au numéro de maillage de this
  // et ces références sont rajoutées à lesRef
	 void Ajout_de_Noeuds(const list <Noeud *> & taN,list <const Reference*>* lref=NULL,LesReferences* lesRef=NULL );
	 // ajout d'une liste d'éléments et de noeud à un maillage
  // si le numéro de maillage associé à l'élément ou noeud est nul, il est remplacé par celui du maillage
  // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a
  // création d'un nouvel item  identique, avec le numéro this
  // ajout éventuel d'une liste de références associées , si celle-ci est non-nulle
  // il y a création de nouvelles ref correspondantes au numéro de maillage de this
  // et ces références sont rajoutées à lesRef
  // les noeuds qui sont associés aux éléments de taE, doivent faire partie : soit de taN, soit du maillage this
	 void Ajout_elements_et_noeuds(const list <Noeud *> & taN, const list <Element *> & taE,list <const Reference*>* lref,LesReferences* lesRef );
    
		// affichage et definition interactive des commandes
  // cas = 1: interactif complet
  // cas = 2: entrée uniquement de noms de fichier
		void Info_commande_Maillages(UtilLecture * entreePrinc,LesReferences& lesRef, int cas);
		
		// Affiche les donnees du maillage
		void Affiche () const ;
		
		// Affiche les donnees du maillage dans un fichier
		// dont le nom est construit à partir du nom du maillage
		// au format  ".her" et ".lis"
		void Affiche_dans_her_lis(LesReferences &lesRef,Enum_dure temps);
 
  //modification du maillage pour le restreindre aux seuls éléments de la référence passée en paramètre
  // toutes les infos relatives à des éléments supprimés, sont également supprimés
  void Restreint_sous_maillage(LesReferences* lesRef, string nom_ref);
 
		// Surcharge de l'operateur = : realise l'egalite de deux maillages
		// cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut
		// ensuite les définir
		Maillage& operator= (Maillage& mail);
		
		inline int Dimension () const
		// Retourne la dimension 
		{	return dimension;	};
 
  // ramène la liste des problèmes physiques gérés par les éléments du maillage
  inline const Tableau <Enum_ddl >& Ddl_representatifs_des_physiques()const
     {return ddl_representatifs_des_physiques;};

  // ramene la liste des degrés de liberté inconnus, associés aux pb
  // physiques gérés par les éléments qui existent dans le maillage
  // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i
  // Si éléments thermiques -> ddl de température
  // Si éléments méca + éléments thermiques -> ddl Xi et température
  // etc. en fonction des éléments qui existent dans le maillage
  inline const Tableau <EnumElemTypeProblem >& Types_de_problemes() const
     {return types_de_problemes;};
		
		inline int Nombre_noeud_elt(int i) const 
		// Retourne le nombre de noeuds lies au ieme element
		{	return tab_element(i)->Nombre_noeud();	};
				
		inline int Nombre_noeud() const 
		// Retourne le nombre de noeuds du maillage
		{	return tab_noeud.Taille();	};
		
		inline int Nombre_element() const 
		// Retourne le nombre d'elements du maillage
		{	return tab_element.Taille();	};
		
		inline Tableau<Noeud *>& Tab_noeud()
		// Retourne le tableau des noeuds
		{	return tab_noeud;	};
		
		inline Tableau<Element *>& Tab_element()
		// Retourne le tableau des elements
		{	return tab_element;	};	
		
		inline Noeud& Noeud_mail(int i)
		// Retourne le ieme noeud Noeud du tableau tab_noeud
		{	return *tab_noeud(i);	}; 
		
		inline Element& Element_mail(int i)
		// Retourne le ieme element Element du tableau tab_element
		{	return *tab_element(i);	};
		// idem mais en version constant
		inline const Element& Element_mail_const(int i)
		{	return *tab_element(i);	};
		
		// test si toutes les informations des maillages sont completes
		// = true -> complet
		// = false -> incomplet
		bool Complet();
	    
		// ramene la demi largeur de bande en ddl et la largeur de bande
		void Largeur_Bande(int& demi, int& total,const Nb_assemb& nb_casAssemb);

  // 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 Tous_Xi_fixes(const Nb_assemb& casAss) const;
 
  // 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 InitNormaleAuxNoeuds();
  // mise à jour -> mise à jour des normales à t
  void MiseAjourNormaleAuxNoeuds();
  // 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 MiseAjourNormaleAuxNoeuds_de_tdt_vers_T();

		// creation des elements frontiere
		void CreeElemFront();

		// ramene un pointeur sur la liste des elements frontieres
		inline LaLIST <Front>* ListFront() { return &listFrontiere;};
		// ramene le tableau des noeuds de la frontière
		Tableau<Noeud *>& Tab_noeud_front() {return tab_noeud_front;	};
        
  // ramene le nom du maillage
  string NomDuMaillage() {return nomDuMaillage;};
  
  // change le nom et le numéro du maillage
  void ChangeNomNumeroMaillage(const string & nom,int num);
  
  // ramène le numéro du noeud le plus proche du point donné à t=0, 
  int Noeud_le_plus_proche_0(const Coordonnee& M);
  // idem à t
  int Noeud_le_plus_proche_t(const Coordonnee& M);
  // idem à tdt
  int Noeud_le_plus_proche_tdt(const Coordonnee& M);
  
  // ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage
  double Max_var_dep_t_a_tdt() const;
	 
	 // ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments 
	 double Min_dist2Noeud_des_elements(Enum_dure temps) const;
	
	 // transfert de grandeurs des points d'intégration aux noeuds 
	 //    1- en entrée les type de ddl internes que l'on veut transférer
	 //       idem pour les type évoluées et les types particuliers
	 //    2- en entrée: cas qui indique la méthode de transfert à utiliser
  //                  =1 : les valeurs aux noeuds sont obtenue par moyennage des valeurs des pts d'integ les plus près
  //                       des éléments qui entourent le noeud
	 // on décompose le processus en trois étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois
	 // le même transfert 

  // A) première étape def des conteneurs et c'est tout, la méthode peut donc être utilisée
  //    pour autre chose. tabQ: permet d'avoir plusieurs listes de TypeQuelconque
  // en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur
  //   est nulle on n'en tient pas compte
	 void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu
                             ,const Tableau <List_io < TypeQuelconque > * >& tabQ);
  // B) initialisation des updates sur les noeuds
  void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu
	                      ,const Tableau <List_io < TypeQuelconque > * >& tabQ,int cas);
	                               
  // C) exécution du transfert
		// transfert incrémental (pour un élément et tous les pt d'integ):
		// transfert de ddl de tous les pt d'integ aux noeuds d'un éléments (on ajoute aux noeuds, on ne remplace pas)
		// les ddl doivent déjà exister aux noeuds sinon erreur
		// il doit s'agir du même type de répartition de pt d'integ pour toutes les grandeurs
	 void TransfertPtIntegAuNoeud(Element& ele,const List_io < Ddl_enum_etendu >& lietendu
                                 ,const Tableau <Tableau <double> > & tab_val,int cas)
	 	{ele.TransfertAjoutAuNoeuds(lietendu,tab_val,cas);};
	 // idem pour des grandeurs quelconques, transfert de "tous" les points d'intégration en même temps 
	 // ceci pour optimiser, les informations sont ici contenues dans les types quelconques                        
	 // liQ_travail: est une liste de travail qui sera utilisée dans le transfert                        
  // - transfert de type quelconque des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds, 
  // - on ne remplace pas). Les types quelconques doivent déjà exister.
  // - un tableau tab_liQ  correspondent aux grandeurs quelconque pour tous les pt integ. tab_liQ(i) est associé au pt d'integ i
  // - Toutes les listes sont identiques au niveau des descripteurs (types...) ce sont uniquement les valeurs numériques
  // - c-a-dire les valeurs associées à TypeQuelconque::Grandeur qui sont différentes (elles sont associées à chaque pt d'integ)
  // - liQ_travail: est une liste de travail qui sera utilisée dans le transfert                        
	 void TransfertPtIntegAuNoeud(Element& ele,const Tableau <List_io < TypeQuelconque > >& tab_liQ
	                            ,List_io < TypeQuelconque > & liQ_travail,int cas)
	 	{ele.TransfertAjoutAuNoeuds(tab_liQ,liQ_travail,cas);};
	 // D) dernière étape: (par exemple calcul des moyennes en chaque noeuds)
	 // les résultats sont stockés aux noeuds
	 void FinTransfertPtIntegAuNoeud(const List_io < Ddl_enum_etendu >& lienu
	                                ,const Tableau <List_io < TypeQuelconque > * >& tabQ,int cas);

	 // ..... cumul et moyenne de grandeurs venant des éléments vers les noeuds (exemple la pression appliquée) .....
	 // on décompose le processus en 4 étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois
	 // la même opération (typiquement à chaque incrément)
  // on peut utiliser:
  //  A)  AjoutConteneurAuNoeud : pour ajouter des conteneurs ad hoc aux noeuds
  //  B)  InitUpdateAuNoeud: avant le cumul, initialise les conteneurs
  //  C)  Accumul_aux_noeuds : balaie les éléments avec cumul aux noeuds
  //  D)  MoyenneCompteurAuNoeud : effectue les moyennes aux noeuds

  // accumulation aux noeuds de grandeurs venant des éléments vers leurs noeuds (exemple la pression appliquée)
	 // autres que celles aux pti classiques, mais directements disponibles
  // le contenu du conteneur stockées dans liQ est utilisé en variable intermédiaire
  void Accumul_aux_noeuds(const List_io < Ddl_enum_etendu >& lietendu
                          ,List_io < TypeQuelconque > & liQ,int cas)
	 	  {int NBE=tab_element.Taille();
      for (int i=1;i<=NBE;i++)
        tab_element(i)->Accumul_aux_noeuds(lietendu,liQ,cas);
     };
 
    // fonctions utilitaires du même genre
 
    // ajout sur le maillage d'un conteneur particulier quelconque
  void AjoutConteneurAuNoeud(TypeQuelconque& tQ);
    // ajout sur le maillage d'un ou plusieur ddl_enum_etendu comme conteneur
	 void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu);
    //  initialisation des updates de ddl_étendu uniquement sur les noeuds: on met à 0 les ddl_etendu correspondant, 
    //  les compteurs, comptant le nombre de fois où les noeuds sont modifiés, sont mis à 0
  void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu);
	 // idem pour un seul ddl_etendu	 
  void InitUpdateAuNoeud(const Ddl_enum_etendu & enu);
	 // moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié)	 
  void MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu);	 
 
  // initialisation des coordonnées à t et tdt aux mêmes valeurs qu'à 0
  // utile quand on veut utiliser les métriques pour un pb non couplés
  void Init_Xi_t_et_tdt_de_0();
 
  // def d'un conteneur pour deux numéros: elem et pti
  class NBelemEtptInteg 
       {public: int nbElem; int nbPtInteg;
         // surcharge de l'operator de lecture
         friend  istream & operator >> (istream & ent, NBelemEtptInteg & de) 
                      { ent >> de.nbElem >> de.nbPtInteg; return ent;};
         // surcharge de l'operator d'ecriture
         friend  ostream & operator << (ostream & sort , const NBelemEtptInteg & de) 
                            { sort << de.nbElem <<" " << de.nbPtInteg << " "; return sort;};
									bool operator < (const NBelemEtptInteg& c) const; bool operator > (const NBelemEtptInteg& c) const;
									bool operator == (const NBelemEtptInteg& c) const {return ((nbElem==c.nbElem)&&(nbPtInteg==c.nbPtInteg));};
									bool operator != (const NBelemEtptInteg& c) const {return !((nbElem==c.nbElem)&&(nbPtInteg==c.nbPtInteg));};
       };
       
  // def d'un conteneur pour 3 numéros: elem, num face ou arete, et pti
  class NBelemFAEtptInteg
       {public: int nbElem; int nbFA; int nbPtInteg;
         // surcharge de l'operator de lecture
         friend  istream & operator >> (istream & ent, NBelemFAEtptInteg & de)
           { ent >> de.nbElem >> de.nbFA >> de.nbPtInteg; return ent;};
         // surcharge de l'operator d'ecriture
         friend  ostream & operator << (ostream & sort , const NBelemFAEtptInteg & de)
           { sort << de.nbElem <<" "<< de.nbFA <<" " << de.nbPtInteg << " "; return sort;};
         bool operator < (const NBelemFAEtptInteg& c) const; bool operator > (const NBelemFAEtptInteg& c) const;
         bool operator == (const NBelemFAEtptInteg& c) const {return ((nbElem==c.nbElem)&&(nbFA==c.nbFA)&&(nbPtInteg==c.nbPtInteg));};
         bool operator != (const NBelemFAEtptInteg& c) const {return !((nbElem==c.nbElem)&&(nbFA==c.nbFA)&&(nbPtInteg==c.nbPtInteg));};
       };

  // 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
  NBelemEtptInteg Element_le_plus_proche
                 (Enum_dure enu_temps,const List_io <Ddl_enum_etendu>& list_enu,const Coordonnee& M);

  // 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* Centre_de_Gravite_Element_le_plus_proche(Enum_dure enu_temps,const Coordonnee& M);
			
  // ramène pour chaque noeud, la liste des éléments qui contiennent le noeud
  // si le tableau n'existe pas, il est construit, sinon uniquement un retour
  // et la miss à jour est uniquement faite lors de la création des frontières
  const Tableau <List_io < Element* > >& Indice()
		    {if (indice.Taille() == 0) Calcul_indice();
		     return indice; };					
  
	 //----- lecture écriture dans base info -----
	 // cas donne le niveau de la récupération
    // = 1 : on récupère tout
    // = 2 : on récupère uniquement les données variables (supposées comme telles)
	 void Lecture_base_info(ifstream& ent,const int cas);
    // cas donne le niveau de sauvegarde
    // = 1 : on sauvegarde tout
    // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
	 void Ecriture_base_info(ofstream& sort,const int cas);
    // sortie du schemaXML: en fonction de enu 
  static void SchemaXML_Maillages(ofstream& sort,const Enum_IO_XML enu) ;
	   
  // ------ 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>  Taille_boiteMail();

  // --------- utilitaires de manipulation de maillage
  // test pour savoir si le maillage contiend des éléments à interpolation linéaire
  bool Contient_lineaire();
  // test pour savoir si le maillage contiend des éléments à interpolation quadratique incomplète
  bool Contient_quadratique_incomplet();
  // transformation des éléments linéaires du maillage en quadratiques.
  // les éléments linéaires  sont  supprimés, 
  // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! 
  // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage
  void Transfo_lin_quadraIncomp(LesReferences &lesRef);      
  // transformation des éléments quadratiques incomplet du maillage en quadratiques complets.
  // les éléments incomplets  sont  supprimée, 
  // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! 
  // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage
  void Transfo_quadraIncomp_quadraComp(LesReferences &lesRef);      
  // relocalisation des points milieux des arrêtes des éléments quadratiques
  void RelocPtMilieuMailleQuadra();
  // définition interactive de listes de références
  void CreationInteractiveListesRef(LesReferences* lesRef);   
  // modification de l'orientation d'éléments
  void Modif_orientation_element(int cas_orientation,LesReferences* lesRef);
  // Lecture et Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe
  void LectureEtCollapse_element_superpose(UtilLecture * entreePrinc,LesReferences* lesRef);
  // Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe
  void Collapse_element_superpose(LesReferences* lesRef);
  // Lecture et collapse de noeuds très proche: appartenant à des éléments différents
  void LectureEtCollapse_noeuds_proches(UtilLecture * entreePrinc, LesReferences* lesRef);
  // collapse de noeuds très proche: appartenant à des éléments différents
  // rayon : donne la distance maxi entre les noeuds qui doivent être collapsé
  void Collapse_noeuds_proches(double rayon, LesReferences* lesRef);
  // Lecture et suppression  d'elements à 2 noeuds, de distances très proches
  void LectureEtSup_Elem_noeudsConfondu(UtilLecture * entreePrinc, LesReferences* lesRef);
  // suppression  d'elements à 2 noeuds, de distances très proches
  // rayon : donne la distance maxi entre les noeuds
  void Sup_Elem_noeudsConfondu(double rayon, LesReferences* lesRef);
  // création d'éléments SFE en fonction d'éléments classiques
  void CreationMaillageSFE();
  // test pour savoir si le maillage est ok pour être transformée en sfe
  bool OKPourTransSfe();
  //  lecture et suppression éventuelle des noeuds, non référencés par les éléments et les références 
  void LectureEtSuppressionNoeudNonReferencer(UtilLecture * entreePrinc,LesReferences& lesRef);
  // uniquement suppression éventuelle des noeuds, non référencés par les éléments et les références
  void SuppressionNoeudNonReferencer(LesReferences& lesRef);
  //  Affichage des noeuds, non référencés par les éléments
  void AffichageNoeudNonReferencer();
 
  //  lecture et création éventuelle d'une ref sur les noeuds, non référencés par les éléments
  void LectureEtCreationRefNoeudNonReferencer(UtilLecture * entreePrinc,LesReferences& lesRef);
  // création éventuelle d'une référence sur les noeuds, non référencés par les éléments
  void CreationRefNoeudNonReferencer(LesReferences& lesRef);
 		// 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
  void VerifReference(LesReferences& lesRef);
  // lecture et renumérotation éventuelle des noeuds
  void LectureEtRenumerotation(UtilLecture * entreePrinc,LesReferences& lesRef);
  // renumérotation des noeuds du maillage, en fonction  de conditions linéaires éventuelles
  // ramène false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure), vrai sinon
  bool Renumerotation(LesReferences& lesRef,const Tableau <Tableau <Condilineaire> >& condCLL);
  // création automatique des références globales de frontière si demandé dans le .info
  void CreationRefFrontiere(UtilLecture * entreePrinc,LesReferences& lesRef);
  // demande de création automatique des références globales de frontière 
  void CreationRefFrontiere(LesReferences& lesRef);
  // force la mise à une valeur d'un ddl (ou de la liste de ddl fonction de la dimention) particulier, quelques soit son activité
  // si fonction_de_la_dimension = true : c'est toute les ddl fct de la dimension qui sont mis à la valeur
  void Force_Ddl_aux_noeuds_a_une_valeur(Enum_ddl enu, const double& val,Enum_dure temps, bool fonction_de_la_dimension);
  // mise à zéro de dd_enum_etendu aux noeuds : force la mise à une valeur à 0
  void Force_Ddl_etendu_aux_noeuds_a_zero(const Tableau<Ddl_enum_etendu>&  tab_enu);
 
       
	protected :
      int idmail ; // numero de maillage
      string nomDuMaillage;
      // liste communes de tous les noms de maillages associée à un numéro 
      // sous forme d'un arbre pour faciliter la recherche
      // cette liste n'est modifiée que par chaque maillage
      map < string, int , std::less <string> >& listeNomMail;
      int dimension; // dimension du maillage
      Tableau<Noeud  *> tab_noeud; // tableau des noeuds du maillage
      Tableau<Element *> tab_element; // tableau des elements du maillage
      // list des elements frontieres du maillage, c-a-d des frontières uniques
      LaLIST <Front> listFrontiere; 
      // tableau des noeuds des éléments frontières
      Tableau <Noeud *> tab_noeud_front;
      // tableau utilitaire:
      // indice(i) contient la liste des éléments qui contiennent le noeud i
      Tableau <List_io < Element*> > indice;
      // pour chaque élément "i" , mitoyen_de_chaque_element(i)(j) contient l'élément Front
      // qui décrit la frontière "j" de l'élément et dedans, les éléments mitoyens de cette frontière
      // appartenant à d'autres éléments (ce tableau est construit par la méthode : Mitoyen())
      Tableau < Tableau <Front> > mitoyen_de_chaque_element;
 
      // définie la liste des types de degrés de liberté inconnus, qui vont être calculés par la résolution des problèmes
      // physiques gérés par les éléments qui existent dans le maillages
      // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i
      // Si éléments thermiques -> ddl de température
      // Si éléments méca + éléments thermiques -> ddl Xi et température
      // etc. en fonction des éléments qui existent dans les maillages
      // (généré à la lecture du maillage, ce qui permet d'optimiser la consultation par la suite)
      Tableau <Enum_ddl >  ddl_representatifs_des_physiques;
      // idem au niveau des types de problèmes gérés par les éléments
      Tableau <EnumElemTypeProblem > types_de_problemes;
  
      //indicateur uniquement utilisé pour la destruction, par défaut est toujours vrai
      // via la méthode Preparation_destruction_avec_conservation_noeuds_elements(), on peut le modifier
      bool detruire_les_noeuds_et_elements;
      
//  -- variables internes utilisées par Orientation_elements_mitoyens_recursif
      // tab_sens_element(i) : = 1 au début, puis vaut -1 si le sens de l'élément i à été changé
      Tableau <double> tab_sens_element; // pendant les différents appels de Orientation_elements_mitoyens_recursif
      // - on définit un tableau d'indicateur, permettant de savoir si un élément a été traité ou pas
      // une fois qu'un élément a été traité: a) on ne permet plus son changement de sens
      // b) de plus dans le cas d'une suite d'appels récursif, il n'est plus retenue pour les nouvelles listes
      Tableau <bool> ind_elem; // def et init à 0, c-à-d non traité
      
//  -- fin variables internes utilisées par Orientation_elements_mitoyens_recursif
  
    // METHODES PROTEGEES :
    
      // cas particulier de destruction, sans suppression des noeuds et éléments
      // l'utilisation de la méthode suivante, permet ensuite de supprimer le maillage
      // tout en évitant la destruction des noeuds internes et éléments internes
      // à utiliser avec précaution, intéressant si l'on veut créer un nouveau maillage
      // avec les noeuds et éléments de ce maillage
      void Preparation_destruction_avec_conservation_noeuds_elements()
        {  detruire_les_noeuds_et_elements = false; };
        
      // change le numéro de maillage
      void Change_numero_maillage(int new_num);

      // definition des elements mitoyens aux elements de frontiere
      // à la fin du programme tous les éléments mitoyens sont stocké dant les éléments
      // Front et non les éléments frontières qui eux sont supprimés
      void MitoyenFront();
      // création pour chaque noeud de la liste des éléments qui contiennent le noeud
      void Calcul_indice();
		
      // 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 Calcul_tous_les_front_et_leurs_mitoyens();

      // dans le cas où les éléments frontières sont des lignes, on les ordonnes 
      // de manière à former une ligne continue
      void OrdonancementDesLigne();
      // lectures des infos pour le choix d'un élément
      void Lecture_info_1element(UtilLecture * entreePrinc,int& num_elt,Enum_geom& id_geom
                       ,Enum_interpol& id_interpol,EnumElemTypeProblem&  id_typeProb
                       ,string& discriminant); 
      // lecture des mouvements solides si nécessaire
      void Lecture_des_mouvements_solides(UtilLecture * entreePrinc);                  
                       
      // une classe de travail qui sert pour pouvoir classer les noeuds par leur position géométrique initiale
      // deux élément sont identiques si leur position initiale sont identique
      // a >= b si : soit a.x >= b.x, ou a.x==b.x et a.y >= b.y, ou a.x==b.x et a.y == b.y et a.z >= b.z
      class PosiEtNoeud
         { public: 
            Noeud * noe; // le noeud
            Element * el; // l'élément auquel il est rattaché
            // -------- constructeur ------------
            PosiEtNoeud() : noe(NULL),el(NULL) {}; // constructeur par défaut
            PosiEtNoeud(Noeud * no,Element * e) : noe(no),el(e) {}; // constructeur normal
            PosiEtNoeud(const PosiEtNoeud& po) : noe(po.noe),el(po.el) {}; // constructeur de copie
            //------ surcharges qui ne travaillent que sur la position  --------
            PosiEtNoeud& operator= (const PosiEtNoeud& po); // affectation 
            bool operator == (const PosiEtNoeud& po) const ; // test d'égalité
            bool operator != (const PosiEtNoeud& po) const ; // test d'inégalité
            bool operator < (const PosiEtNoeud& po)  const ; // relation d'ordre
            bool operator <= (const PosiEtNoeud& po)  const ; // relation d'ordre
            bool operator > (const PosiEtNoeud& po)  const ; // relation d'ordre
            bool operator >= (const PosiEtNoeud& po)  const ; // relation d'ordre            
          };  
		
      // fonctions simples ayant pour but de bien repérer des opérations dangereuses
      
      // 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 Affectation_noeud (Noeud& noeud);      
		
      // 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 Affectation_element (Element& element);   
		
      // 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 Change_nb_noeud (int nouveau_nb);    
		
      // 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 Change_nb_element (int nouveau_nb);

      // ** pour l'instant ne fonctionne que pour les éléments surfaces
	 // orientation automatique des éléments mitoyens, à l'élément num_elem, et ensuite
	 // récursivement à tous les éléments mitoyens des mitoyens jusqu'à ce que la chaine s'arrête
	 // L'ensemble des éléments est alors groupé dans une référence qui est construit à partir du numéro num_elem
	 // et qui est ajouté aux refs déjà existantes
	 // ensuite, le programme passe en revue les éléments restants, et regarde s'ils font parti
	 // d'un ensemble homogène orienté, si non, ramène la liste des éléments hors ensemble orienté
	 // *** ne concerne que les éléments surfaces, les autres sont ignorés
	 // ind_elem(i) : (tableau interne) indique si l'élément i a été traité (=true) ou non (=false)
	 // ind_elem: est pris en compte puis mis à jour par le programme, c-a-d que les nouveaux éléments orienté
	 //           passe de false à true, par contre tous les éléments déjà à true, ne sont pas pris en compte dans le traitement
  // angle_maxi : angle maximum entre deux éléments, au dessus duquel on considère qu'il y a une rupture de la mitoyenneté
  // nom_ref : s'il est différent de "_", donne le nom de base voulu à la série de référence qui va être construite
  // inverse : indique si l'on souhaite partir d'une orientation inverse de celle existante avant application de l'algo
  //           ceci pour l'élément de départ: au premier appel, l'opération est toujours possible, ensuite cela dépend
  //           si l'élément trouvé a déjà été traité ou pas
  // recursiv : indique si l'on se situe dans une suite récursive d'appel de la méthode
  //            si oui, seule les éléments non déjà pris en compte dans les appels précédents, sont examiné
  //            c'est ind_elem qui permet de s'en assurer
  //            si non: cas par exemple d'un angle_maxi qui change, on réexamine tous les éléments, cependant
  //            la ré_orientation éventuelle n'est faite qu'une seule fois (toujours via ind_elem)
  list <int>  Orientation_elements_mitoyens_recursif(bool recursif,string& nom_ref,int num_elem
                                                        , LesReferences& lesRef,double& angle_maxi,bool inverse);
  // méthode pour initialiser les différents tableaux utilisés par Orientation_elements_mitoyens_recursif
  void Init_Orientation_elements_mitoyens_recursif();
 
  // méthode pour orienter des éléments en fonction d'un rayon: AG, A étant un point donné, G étant le centre de
  // gravité d'une facette
  // A : coordonnée d'un point, si indic_G(i) est true, alors A(i) est remplacé par la coordonnée G(i) du centre
  //     de gravité de la facette
  // zone_a_traiter: le nom de la référence des éléments a traiter
  // inverse : si true, l'orientation des normales des facettes est identique à celles de AG, sinon c'est l'inverse
 
  void Orientation_via_rayon(const Tableau <bool> & indic_G,const  Coordonnee & A
                             ,const  string& zone_a_traiter, LesReferences& lesRef, bool inverse);
 
  // ------- pour la définition interactive de liste de ref -------------
  // def d'un conteneur pour deux numéros: nb element nb face
  class NBelemEtFace {public: int nbElem; int nbFace;
									bool operator < (const NBelemEtFace& c) const; bool operator > (const NBelemEtFace& c) const;
									bool operator == (const NBelemEtFace& c) const {return ((nbElem==c.nbElem)&&(nbFace==c.nbFace));};
									bool operator != (const NBelemEtFace& c) const {return !((nbElem==c.nbElem)&&(nbFace==c.nbFace));};
									};
	 // def d'un conteneur pour deux numéros: nb element nb arête
	 class NBelemEtArete {public: int nbElem; int nbArete; 
        bool operator < (const NBelemEtArete& c) const; bool operator > (const NBelemEtArete& c) const;
							 bool operator == (const NBelemEtArete& c) const {return ((nbElem==c.nbElem)&&(nbArete==c.nbArete));};
							 bool operator != (const NBelemEtArete& c) const {return !((nbElem==c.nbElem)&&(nbArete==c.nbArete));};
        };
	
     // calcul des listes de références en fonction de la demande:
	 // list_nomReference: contient les types de refs que l'on veut
	 // list_methode:  contient la ou les méthodes que l'on veut utiliser 
	 //  cas 1D 
	 void  CalculListRef_1D(list<string>& list_nomReference,LesReferences* lesRef,list<string>& list_methode
	                      ,const Enum_ddl & enu_ddl); 
	 //  cas 2D
	 void CalculListRef_2D(list<string>& list_nomReference,LesReferences* lesRef,list<string>& list_methode
	                    ,const Enum_ddl & enu_ddl);  
	 //  cas 3D
	 void CalculListRef_3D(list<string>& list_nomReference,LesReferences* lesRef,list<string>& list_methode
	                    ,const Enum_ddl & enu_ddl); 
     // les méthodes de bases
	 // fonction générique pour des condition PresDe
	 void PresDe(const list<string>& list_nomReference, list <Noeud *>& list_noeud_restant
                 ,list <Element *>& list_element_restant,const Enum_ddl& enu_ddl
                 ,list <NBelemEtptInteg>& list_elemPtin_restant,bool& premLpti
                 ,list <NBelemEtFace>& list_elemFace_restant,bool& premLface
                 ,list <NBelemEtArete>& list_elemArrete_restant,bool& premLarrete); 
	 // fonction générique pour des condition "tout dedans"
	 void ToutDedans(const list<string>& list_nomReference, list <Noeud *>& list_noeud_restant
                  ,list <Element *>& list_element_restant,const Enum_ddl& enu_ddl
                  ,list <NBelemEtptInteg>& list_elemPtin_restant,bool& premLpti
                  ,list <NBelemEtFace>& list_elemFace_restant,bool& premLface
                  ,list <NBelemEtArete>& list_elemArrete_restant,bool& premLarrete); 
  // constitution des références
  void EnregRef(const list<string>& list_nomReference,list <Noeud *>& list_noeud_restant
                ,list <NBelemEtptInteg>& list_elemPtin_restant,list <Element *>& list_element_restant
                ,list <NBelemEtFace>& list_elemFace_restant,list <NBelemEtArete>& list_elemArrete_restant
                  ,LesReferences* lesRef);
  //  définition des fonctions conditions
  // def de data internes qui servent pour les fonctions init et exe: dimensionnées dans init, utilisé dans exe
  // donc: init et exe doivent être utilisé absolument à suivre
  Tableau <Coordonnee> t_poi; 
  Tableau <Droite>  t_droit; 
  Tableau <double>  t_para; 
  Tableau <Plan>  t_plan; 
  Tableau <Sphere>  t_sphere; 
  Tableau <Cylindre>  t_cylindre; 
  Tableau <Cercle>  t_cercle; 
	 // cas de croisement avec des références existantes: def de variables de passage pour InRef et OutRef
	 // les pointeurs qui suivent ne servent pas à créer des refs, mais uniquement a récupérer les adresses
	 list <const Reference*> list_refIn;
  list <const Reference*> list_refOut; 
	 LesReferences* lesRefin; // variable utilisée uniquement pour le passage d'info à 
					    // ,InitInRef(), ExeInRef (), InitOutRef(), ExeOutRef()
  
  // tout d'abord les pointeurs de fonctions en cours
  //  - pour les conditions Presde
  // acquisition interactive des paramètres de la condition
  void (Maillage::*initConditionPresDe) (double& dist); 
  // exécution de la condition : ramène true si ok, false sinon
  bool (Maillage::*ExeConditionPresDe) (const double& dist,const Coordonnee& M)const;  
  //  - pour les condition ToutDedans
  // acquisition interactive des paramètres de la condition
  void (Maillage::*initConditionToutDedans) (); 
  // exécution de la condition : ramène true si ok, false sinon
  bool (Maillage::*ExeConditionToutDedans) (const Tableau <Coordonnee> & tab_M)const;
                                        
   
  // recherche près d'un point
  // def interactive du point et de la distance
  void InitPresPoint(double& dist);
  // exécution de la condition
  bool ExePresPoint(const double& dist,const Coordonnee& M) const;
  
  // recherche d'un coté d'un point (en 1D) 
  void InitCotePoint();
  // ramène true si tous les points sont du même coté que t_poi(1) 
  bool ExeCotePoint(const Tableau <Coordonnee> & t_M)const;

  // recherche entre deux points (1D) 
  void InitEntrePoint();
  // ramène true si tous les points sont entre t_poi(1) et t_poi(2)
  bool ExeEntrePoint(const Tableau <Coordonnee> & t_M)const;

  // recherche entre deux points (1D) _avec_distance
  void InitEntrePoint_avec_distance();
  // ramène true si tous les points sont entre t_poi(1) et t_poi(2)
  bool ExeEntrePoint_avec_distance(const Tableau <Coordonnee> & t_M)const;

  // recherche près d'une ligne
  void InitPresLigne(double& dist);
  bool ExePresLigne(const double& dist,const Coordonnee& M)const;
  
  // dans le cas particulier d'une ligne, on peut ordonner certaines listes résultantes / à la lignes
  // il s'agit des noeuds et des pt d'integ: on les ordonnes par rapport à leurs projections sur la lignes
  void InitOrdonneLigne();
  void OrdonneLigne(list <Noeud *>& list_noeud_restant,list <NBelemEtptInteg>& list_elemPtin_restant
                      ,const Enum_ddl& enu_ddl);
    
		// recherche près d'un cercle
  void InitPresCercle(double& dist);
  bool ExePresCercle(const double& dist,const Coordonnee& M)const;
  
  // recherche près d'un plan
  void InitPresPlan(double& dist);
  bool ExePresPlan(const double& dist,const Coordonnee& M)const;
  
  // recherche près d'un cylindre
  void InitPresCylindre(double& dist);
  bool ExePresCylindre(const double& dist,const Coordonnee& M)const;
  
  // recherche près d'une sphere 
  void InitPresSphere(double& dist);
  bool ExePresSphere(const double& dist,const Coordonnee& M)const;
  
  // recherche d'un coté d'un plan 
  void InitCotePlan();
  // ramène true si tous les points sont du même coté que t_poi(1) du plan
  bool ExeCotePlan(const Tableau <Coordonnee> & t_M)const;

  // condition entre plans // 
  void InitEntrePlan();
  // ramène true si tous les points sont entre les deux plans
  bool ExeEntrePlan(const Tableau <Coordonnee> & t_M)const;

  // condition entre plans _avec_distance //
  void InitEntrePlan_avec_distance();
  // ramène true si tous les points sont entre les deux plans
  bool ExeEntrePlan_avec_distance(const Tableau <Coordonnee> & t_M)const;

  // condition dans ou dehors un cylindre 
  void InitDansCylindre();
  // ramène true si tous les points sont dans le cylindre
  bool ExeDansCylindre(const Tableau <Coordonnee> & t_M)const;
  // ramène true si tous les points sont à l'extérieur du cylindre
  bool ExeOutCylindre(const Tableau <Coordonnee> & t_M)const;
  
  // condition entre deux cylindre
  void InitEntreCylindre();
  // ramène true si tous les points sont entre les deux cylindres
  bool ExeEntreCylindre(const Tableau <Coordonnee> & t_M)const;

  // condition dans ou dehors d'une sphére 
  void InitDansSphere();
  // ramène true si tous les points sont dans la sphère
  bool ExeDansSphere(const Tableau <Coordonnee> & t_M)const;
  // ramène true si tous les points sont à l'extérieur de la sphère
  bool ExeOutSpheres(const Tableau <Coordonnee> & t_M)const;
  
  // condition entre deux spheres concentriques
  void InitEntreSpheres();
  // ramène true si tous les points sont entre les deux  sphères
  bool ExeEntreSpheres(const Tableau <Coordonnee> & t_M)const;

  // condition du même coté d'une droite (en 2D seulement)
  void InitCoteDroite();
  // ramène true si tous les points sont du même coté que t_poi(1) de la droite (en 2D uniquement)
  bool ExeCoteDroite(const Tableau <Coordonnee> & t_M)const;
  
  // condition entre 2 droites (en 2D seulement)
  void InitEntreDroite();
  // ramène true si tous les points sont entre les 2 droites (en 2D uniquement)
  bool ExeEntreDroite(const Tableau <Coordonnee> & t_M)const;
 
  // condition entre 2 droites (en 2D seulement) _avec_distance
  void InitEntreDroite_avec_distance();
  // ramène true si tous les points sont entre les 2 droites (en 2D uniquement)
  bool ExeEntreDroite_avec_distance(const Tableau <Coordonnee> & t_M)const;

  // condition dans ou dehors un cercle (en 2D seulement) 
  void InitDansCercle();
  // ramène true si tous les points sont dans le cercle
  bool ExeDansCercle(const Tableau <Coordonnee> & t_M)const;
  // ramène true si tous les points sont à l'extérieur du cercle
  bool ExeOutCercle(const Tableau <Coordonnee> & t_M)const;
  
  // condition entre cercles concentriques (en 2D seulement)
  void InitEntreCercles();
  // ramène true si tous les points sont entre les deux  cercles concentriques
  bool ExeEntreCercles (const Tableau <Coordonnee> & t_M)const;

  // acquisition d'un plan
  Plan Acquisition_interactive_plan();
 
  // acquisition d'un point
  Coordonnee Acquisition_interactive_point();
 
  // acquisition d'une droite
  Droite Acquisition_interactive_droite();
 
  // acquisition d'un vecteur=direction
  Coordonnee Acquisition_interactive_vecteur();

  // condition d'appartenance  à une référence existante
  void InitInRef();
  // condition d'exclusion à une référence existante 
  void InitOutRef();
	 // ---- mise en place de la condition d'appartenance ou d'exclusion à des références existantes
  // contrairement aux autres conditions, cette condition est prise en compte au moment de la création finale
  // de la référence dans la méthode : EnregRef, via les méthodes du 2)
		// 1) une fonction qui ne fait rien, mais est là pour que le tout fonctionne normalement
		bool Exe_In_out_avecRefExistantes(const Tableau <Coordonnee> & t_M)const; // ne fait rien
		// 2) fonctions qui réellement font quelque chose: utilisées dans la méthode EnregRef
		void Exe_In_out_avecRefExistantes_N(list <Noeud *>& list_noeud_restant);
		void Exe_In_out_avecRefExistantes_E(list <Element *>& list_element_restant);
		void Exe_In_out_avecRefExistantes_G(list <NBelemEtptInteg>& list_elemPtin_restant);
		void Exe_In_out_avecRefExistantes_F(list <NBelemEtFace>& list_elemFace_restant);
		void Exe_In_out_avecRefExistantes_A(list <NBelemEtArete>& list_elemArrete_restant);
//		    void InterOuDiff_avecRefExistantes(const Tableau <Coordonnee> & t_M)const;

  //-------------------- méthodes particulières pour l'optimisation de largeur de bande ------------------------
  
  // une classe intermédiaire pour pouvoir classer les noeuds en fonction du degré
  class Noeud_degre
      	{ public: Noeud* noe; int degre;
      	  Noeud_degre (): noe(NULL), degre(0) {};
      	  Noeud_degre (Noeud* no,int deg): noe(no),degre(deg) {};
      	  Noeud_degre (const Noeud_degre& no ): noe(no.noe), degre(no.degre) {};
      	  ~Noeud_degre() {};
            bool operator > (const Noeud_degre& a) const { return (this->degre > a.degre);};
            bool operator >= (const Noeud_degre& a) const { return (this->degre >= a.degre);};
            bool operator < (const Noeud_degre& a) const { return (this->degre < a.degre);};
            bool operator <= (const Noeud_degre& a) const { return (this->degre <= a.degre);};
            Noeud_degre& operator= (const Noeud_degre& de) { degre = de.degre; noe = de.noe; return (*this);};
      	};

  // méthode static: c-a-d  indépendante des données du maillage (elle est générale)
  // calcul du point de départ, en fonction  de conditions linéaires éventuelles
  // il y a également calcul des voisins et de la descendance du noeud de retour
  // s'il y a un pb, calcul_ok en retour est false
 static Noeud*  Point_de_depart(const Tableau<Element *>& tab_elem
                          ,const Tableau<Noeud  *>& tab_noe
                          ,const Tableau <Tableau <Noeud*> *> tt_noeud_front
                          ,Tableau < LaLIST_io <Noeud* > >& t_voisin
                          , list < list < Noeud_degre  > > & lis_descent
                          ,const Tableau <Tableau <Condilineaire> >& condCLL,bool& calcul_ok);
  
  // méthode static: c-a-d  indépendante des données du maillage (elle est générale)
  // calcul des voisins de tous les  noeuds du maillage en fonction des éléments et de conditions
  // linéaires éventuelles, 
  // en entrée/sortie t_voisin
  // restriction: il faut que tab_noe contienne tous les noeuds référencés dans tab_elem et tt_t_condCLL
  // s'il y a un pb, calcul_ok en retour est false
  static Tableau < LaLIST_io <Noeud* > >& Voisins(const Tableau<Element *>& tab_elem
                                           ,const Tableau<Noeud  *>& tab_noe
                                           ,Tableau < LaLIST_io <Noeud* > >& t_voisin
                                         ,const Tableau <Tableau <Condilineaire> >& t_t_condCLL,bool& calcul_ok);

  // méthode static: c-a-d  indépendante des données du maillage (elle est générale)
  // calcul de la descendance d'un noeud noeu,
  // on considère que les voisins sont dèjà correctement définis
  // en entrée la liste qui est modifiée en interne et retournée en sortie
  // le premier élément de la liste c'est la dernière descendance
  // s'il y a un pb, calcul_ok en retour est false
  static list < list < Noeud_degre  > > & Descendance (const int& taille_tabnoeud
                                            ,Noeud * noeu, Tableau < LaLIST_io <Noeud* > >& t_voisin
                                            , list < list < Noeud_degre  > > & lient,bool& calcul_ok);
  // méthode static: c-a-d  indépendante des données du maillage (elle est générale)
  // algorithme de Cuthill Mac Kee directe
  // noeu : le noeud de départ
  // lis_descent : les descendants de noeu, qui va être modifié dans le processus
  // ramène une nouvelle numérotation (mais les numéros internes des noeuds ne sont pas changé
  static Tableau <Noeud* > Cuthill_Mac_Kee(const int& taille_tabnoeud,Noeud * noeu
                                    ,Tableau < LaLIST_io <Noeud* > >& t_voisin
                                    , list < list < Noeud_degre  > >&  lis_descent);
  // méthode static: c-a-d  indépendante des données du maillage (elle est générale)
  // calcul de la largeur de bande en noeuds 
  static int LargeurBandeEnNoeuds(const Tableau<Element *>& tab_elem); 

  // on s'occupe de mettre à jour les types de pb et les ddl types associés
  void Mise_a_jour_type_pb_type_associe_ddl();
 
                                 
};
/// @}  // end of group

#endif  
