// 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-2022 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:  definir le groupe de maillage                              *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef LESMAILLAGES_H
#define LESMAILLAGES_H

#include "Maillage.h"
#include "Tableau_T.h"
#include "UtilLecture.h"
#include "ParaGlob.h"
#include "LesReferences.h"
// #include "bool.h"
#include "DiversStockage.h"
#include "LesLoisDeComp.h"
#include "Front.h"
#include "Enum_dure.h"
#include "Nb_assemb.h"
#include "Basiques.h"
#include "Enum_dure.h"
#include "TypeQuelconque.h"
#include "Enum_IO_XML.h"
#ifdef UTILISATION_MPI
  #include <boost/mpi/environment.hpp>
  #include <boost/mpi/communicator.hpp>
  #include <boost/serialization/string.hpp>
  #include <boost/serialization/vector.hpp>
  #include <boost/mpi.hpp>
  namespace mpi = boost::mpi;
#endif

/** @defgroup Les_Maillages Les_Maillages
*
*     BUT:  definir le groupe de maillage                              *
*
* \author    Gérard Rio
* \version   1.0
* \date       23/01/97
* \brief       Définition du groupe de maillage
*
*/

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

//------------------------------------------------------------------
//!      LesMaillages:  l'ensemble des maillages
//------------------------------------------------------------------
/// \author    Gérard Rio
/// \version   1.0
/// \date       23/01/97

class LesMaillages
{
  public :
    // VARIABLES PUBLIQUES :
    
    // CONSTRUCTEURS : le pointeur sur UtilLecture permet d'avoir acces a la lecture
    //  le second pointe sur les variables globales
    // le troisieme pointe sur l' instance des references
    LesMaillages (UtilLecture * , ParaGlob *,LesReferences* lesRef); 
    // constructeur par défaut
    LesMaillages();   
	   // Constructeur de copie, 
	   LesMaillages(const LesMaillages& lesmail);
    // DESTRUCTEUR :
    ~LesMaillages();    
    // METHODES PUBLIQUES :
    // lecture des maillages et des references s'y rapportant
    void LectureLesMaillages(); 
    // création et ajout d'un nouveau maillage en fonction d'un nom et d'une liste 
    // d'éléments
    // *** 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éé
    // >> ramène le numéro du nouveau maillage
    int Creation_nouveau_maillage
           (list <Noeud*>& li_noeud,list <Element*>& list_elem,const string& nom_maillage);
    // suppression d'un maillage existant
    // par défaut, tous les noeuds et éléments du maillage sont supprimés
    // si sans_conservation_noeuds_elements est false: les noeuds et les éléments ne sont pas supprimés
    // mais ils ne sont plus référencés dans ce maillage !
    void Suppression_maillage( const string& nom_maillage,const bool sans_conservation_noeuds_elements = true);
	   // ajout d'un tableau de noeud à un maillage
	   void Ajout_de_Noeuds(const list <Noeud *> & taN, int numMail)
	    {tabMaillage(numMail)->Ajout_de_Noeuds(taN);};
    // -- ajout de noeuds, éléments et éventuellement de ref à un maillage
    // 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, int numMail )
       {tabMaillage(numMail)->Ajout_elements_et_noeuds(taN,taE,lref,lesRef);};

    // affichage et definition interactive des commandes 
    void Info_commande_lesMaillages();
      
    // Affiche les donnees du maillage
	   void Affiche () const ;
    // Affiche les donnees du maillage dans le fichier de nom nom_fichier
	   // au format du fichier ".her"
	   void Affiche (char* nom_fichier)  const ;
	
	   // test si toutes les informations des maillages sont completes
	   // = true -> complet
	   // = false -> incomplet
	   bool Complet();
	
	   // introduction des lois de comportement dans les elements qui le necessite
    //    des sections pour les biellettes etc c-a-d , completer les elements
    // avec les donnees qui ont ete acquises apres la lecture du maillage
    // def des tableaux de ddl dans les noeuds
    // def des pointeurs d'assemblage dans les noeuds
    void Completer(DiversStockage* divers,LesLoisDeComp* lesLois
                  ,LesFonctions_nD*  lesFonctionsnD);
 
    // mise à jour des repères d'anisotropie
    void Mise_a_jour_repere_anisotropie(DiversStockage* divers,LesFonctions_nD*  lesFonctionsnD);

    // ramene le nombre de maillage
    inline int NbMaillage() const 
       { return nbMaillageTotal;};
       
    // ramene le nombre d'element du maillage i
    inline int Nombre_element(int i) const 
       { return tabMaillage(i)->Nombre_element();};
        
    // ramene le nombre de noeud du maillage i
    inline int Nombre_noeud(int i) const 
       { return tabMaillage(i)->Nombre_noeud();};
         
    // ramene l'element j du maillage i 
    inline Element& Element_LesMaille(int i, int j) const
       {return tabMaillage(i)->Element_mail(j);};
    // idem mais en version constant   
    inline const Element& Element_LesMaille_const(int i, int j) const
       {return tabMaillage(i)->Element_mail_const(j);};       
    
    // ramene le noeud j du maillage i 
    inline Noeud& Noeud_LesMaille(int i, int j) const 
       {return tabMaillage(i)->Noeud_mail(j);};

	   // Retourne le tableau des noeuds du maillage i
	   inline Tableau<Noeud *>& Tab_noeud (int i)
		     {	return tabMaillage(i)->Tab_noeud();	};
    
    // Retourne le nom du maillage i
    string NomMaillage(int i) const {return tabMaillage(i)->NomDuMaillage();};
    // retourne le numéro du maillage de nom donné
    // ou 0 si le nom ne correspond pas à un maillage
    int NumMaillage(const string& nom) const 
       {map < string, int , std::less <string> >::const_iterator itmap = mapNomMail.find(nom);
       if (itmap!=mapNomMail.end()) {return (*itmap).second;}
          else                      {return 0;}; 
       };
       
    // suppression éventuelle des noeuds, non référencés par les éléments et les références
    // dans tous les maillages
    void SuppressionNoeudNonReferencer(LesReferences& lesRef)
		    { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->SuppressionNoeudNonReferencer(lesRef);};
    //  Affichage des noeuds, non référencés par les éléments
    void AffichageNoeudNonReferencer()
		    { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->AffichageNoeudNonReferencer();};
 
    // renumérotation des noeuds de tous les  maillagesen même temps, + prise en compte
    // des conditions linéaires qui existent entre les noeuds
    // ramène false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure), vrai sinon
    // si le pointeur d'assemblage est non nulle, cela veut dire que l'on veut également une mise à jour
    // globale des pointeurs d'assemblages (ce qui est différent de la méthode : MiseAJourPointeurAssemblage(
    //                                       qui agit maillage après maillage)
    // si le pointeur d'assemblage est non nulle et le drapeau: sans_changement_num_noeud = true
    // cela signifie que l'on désire uniquement une renumérotation de pointeur sans les noeuds
    // ramène dans tous les cas les nouvelles largeurs en ddl
    //  nouvelles_largeur_en_ddl.un = la largeur totale résultante
    //  nouvelles_largeur_en_ddl.deux = la demie largeur totale résultante
    //  nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis
    //                                   uniquement (sans les CLL)
    //
    bool Renumerotation(LesReferences& lesRef,const Tableau <Tableau <Condilineaire> >& condCLL
                        ,TroisEntiers&  nouvelles_largeur_en_ddl,const Nb_assemb* nb_casAssemb = NULL
                        ,bool sans_changement_num_noeud = false);
 
    // renumérotation des noeuds maillages par maillage,
    // === sans prise en compte de conditions linéaires ===
    // en sortie les maillages sont mis à jour si la nouvelle numérotation conduit à une largeur de bande
    // plus faible que la largeur initiale: en noeuds
    // 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);

    // création éventuelle d'une référence sur les noeuds, non référencés par les éléments
    // dans tous les maillages
    void CreationRefNoeudNonReferencer(LesReferences& lesRef)
		    { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->CreationRefNoeudNonReferencer(lesRef);};
 
    // ramène le numéro du noeud le plus proche du point donné pour t=0,
    // ceci pour le maillage i, par défaut i vaut 1
    inline int Noeud_le_plus_proche_0(const Coordonnee& M,int i = 1)
      { return  tabMaillage(i)->Noeud_le_plus_proche_0(M); };
    // idem à t  
    inline int Noeud_le_plus_proche_t(const Coordonnee& M,int i = 1)
      { return  tabMaillage(i)->Noeud_le_plus_proche_t(M); };
    // idem à tdt  
    inline int Noeud_le_plus_proche_tdt(const Coordonnee& M,int i = 1)
      { return  tabMaillage(i)->Noeud_le_plus_proche_tdt(M); };

    // 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)
    // ceci pour le maillage i, (par défaut i vaut 1)
    // 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
    // si pb ramène un numéro d'élément nulle
	   // enu_temps: dit si les coordonnées du point M sont à 0 ou t ou tdt
    inline Maillage::NBelemEtptInteg Element_le_plus_proche
        (Enum_dure enu_temps,const List_io <Ddl_enum_etendu>& list_enu,const Coordonnee& M,int i = 1)
             { return  tabMaillage(i)->Element_le_plus_proche(enu_temps,list_enu,M); };

    // ramène la liste des problèmes physiques gérés par les éléments de tous les maillages
    inline const list <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 tous les 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
    inline const list <EnumElemTypeProblem >& Types_de_problemes() const
       {return types_de_problemes;};
 

    // ramene le nombre total de ddl actifs du pb
    int NbTotalDdlActifs() const ;
    // idem mais pour un type de ddl donné, dans le cas de type
    // vectoriel on cumule les ddl de l'ensemble de la dimension
    int NbTotalDdlActifs(Enum_ddl enum_ddl) const;
    
    // ramene le nombre total de points d'intégration correspondant à un ddl donné
    int NbTotalPtInteg(Enum_ddl enum_ddl) const ;
    
    // ramene le nombre total de grandeurs génératrices, calculées aux points d'intégrations,
    //  correspondant à un ddl donné.
    int NbTotalGrandeursGeneratrices(Enum_ddl enu) const ;
		 
    //récupération d'une grandeur vectoriel de dimension, la dimension
    // de l'espace, défini au noeud et transféré dans un vecteur global
    // qui cumule de manière séquentielle toutes les grandeurs
    // en entrée : enum_ddl donne le type de la grandeur à récupérer
    // en fait de la première composante
    // duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt
    // enum_actif : le transfert s'effectue que si le ddl enum_actif est actif
    // ce qui permet la différentiation entre les différents ddl
    // vect : est le vecteur global de stockage qui normalement a été 
    // au préalable dimensionné avec NbTotalDdlActifs(Enum_ddl enum_ddl)
    // en retour : une référence sur vect
    Vecteur & Vect_loc_vers_glob(Enum_dure duree,Enum_ddl enum_actif
                                 ,Vecteur& vect,Enum_ddl enum_ddl,const Nb_assemb& nb_casAssemb);

    // fonction inverse de Vect_loc_vers_glob, il s'agit ici de passer
    // de la grandeur globale aux grandeurs locale
    void Vect_glob_vers_local(Enum_dure duree,Enum_ddl enum_actif
                             ,const Vecteur& vect,Enum_ddl enum_ddl,const Nb_assemb& nb_casAssemb) ;
 
 
    //récupération d'une grandeur vectoriel de dimension, la dimension
    // de l'espace, défini au noeud et transféré dans un vecteur global
    // qui cumule de manière séquentielle toutes les grandeurs
    // en entrée : tab_enum_ddl donne le tableau des type de la grandeur à récupérer
    // en fait de la première composante
    // duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt
    // tab_enum_actif : pour chaque élément tab_enum_ddl(i), le transfert s'effectue que si
    // le ddl tab_enum_actif(i) est actif
    // ce qui permet la différentiation entre les différents ddl
    // vect : est le vecteur global de stockage qui normalement a été 
    // au préalable dimensionné avec somme des NbTotalDdlActifs(Enum_ddl enum_ddl), avec enum_ddl
    // qui balaie l'ensemble des éléments de tab_enum_ddl
    // Important: pour chaque famille de ddl, les ddl sont classés de manière croissante, ce qui signifie
    //  que c'est l'ordre des pointeurs d'assemblage si et seulement si, ces ddl ont été rangés dans les noeuds
    //  au préalable 
    // en retour : une référence sur vect
    Vecteur & Vect_loc_vers_glob(Enum_dure duree,const Tableau <Enum_ddl>& tab_enum_actif
                                     ,Vecteur& vect,const Tableau <Enum_ddl>& tab_enum_ddl
                                     ,const Nb_assemb& nb_casAssemb);

    // fonction inverse de Vect_loc_vers_glob, il s'agit ici de passer
    // de la grandeur globale aux grandeurs locale
    void Vect_glob_vers_local(Enum_dure duree,const Tableau <Enum_ddl>& tab_enum_actif
                                    ,const Vecteur& vect,const Tableau <Enum_ddl>& tab_enum_ddl
                                    ,const Nb_assemb& nb_casAssemb) ;

    //récupération d'une grandeur scalaire 
    // défini au noeud et transféré dans un vecteur global
    // qui cumule de manière séquentielle toutes les grandeurs
    // en entrée : enum_ddl donne le type de la grandeur à récupérer
    // duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt
    // enum_actif : le transfert s'effectue que si le ddl enum_actif est actif
    // ce qui permet la différentiation entre les différents ddl
    // vect : est le vecteur global de stockage qui normalement a été 
    // au préalable dimensionné avec NbTotalDdlActifs(Enum_ddl enum_ddl)
    // en retour : une référence sur vect
    Vecteur & Scalaire_loc_vers_glob(Enum_dure duree,Enum_ddl enum_actif
                                       ,Vecteur& vect,Enum_ddl enum_ddl
                                       ,const Nb_assemb& nb_casAssemb);

    // fonction inverse de Scalaire_loc_vers_glob, il s'agit ici de passer
    // de la grandeur globale à la grandeur locale
    void Scalaire_glob_vers_local(Enum_dure duree,Enum_ddl enum_actif
                                    ,Vecteur& vect,Enum_ddl enum_ddl
                                    ,const Nb_assemb& nb_casAssemb);

    // deux fonctions idem que pour les ddl : mais pour un Ddl_etendu
    Vecteur & Scalaire_loc_vers_glob(Enum_ddl enum_actif,Vecteur& vect,const Ddl_enum_etendu& enum_ddl_etend
                                     ,const Nb_assemb& nb_casAssemb);
    void Scalaire_glob_vers_local(Enum_ddl enum_actif,Vecteur& vect,const Ddl_enum_etendu& enum_ddl_etend
                                     ,const Nb_assemb& nb_casAssemb);

    // deux fonctions idem que pour les ddl_etendu : mais pour une grandeur quelconque
    Vecteur & Quelconque_loc_vers_glob(Enum_ddl enum_actif,Vecteur& vect,const TypeQuelconque& type_generique
                                       ,const Nb_assemb& nb_casAssemb);
    void Quelconque_glob_vers_local(Enum_ddl enum_actif,Vecteur& vect,const TypeQuelconque& type_generique
                                       ,const Nb_assemb& nb_casAssemb);

	   // retourne la liste des types de ddl principaux actuellement utilisé
	   // aux noeuds pour chaque maillage, la liste est exhaustive
	   // elle contiend tous les types au moins une fois utilisée
	   // cela ne signifie pas que le ddl en question soit présent
	   // pour tous les noeud du maillage considéré
	   // - le tableau de retour est indicé par le numéro de maillage correspondant
	   // - il y a une liste par maillage
	   Tableau <List_io <Ddl_enum_etendu> > Les_type_de_ddl_par_noeud(bool absolue);
		
	   // retourne la liste des types de ddl étendu actuellement utilisé
	   // aux noeuds pour chaque maillage, la liste est exhaustive
	   // elle contiend tous les types au moins une fois utilisée
	   // cela ne signifie pas que le ddl en question soit présent
	   // pour tous les noeud du maillage considéré
	   // - le tableau de retour est indicé par le numéro de maillage correspondant
	   // - il y a une liste par maillage
	   Tableau <List_io <Ddl_enum_etendu> > Les_type_de_ddl_etendu_par_noeud(bool absolue);
		
	   // retourne la liste des types quelconque actuellement utilisé
	   // aux noeuds pour chaque maillage, la liste est exhaustive
	   // elle contiend tous les types au moins une fois utilisée
	   // cela ne signifie pas que le ddl en question soit présent
	   // pour tous les noeud du maillage considéré
	   // - le tableau de retour est indicé par le numéro de maillage correspondant
	   // - il y a une liste par maillage
    // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
	   Tableau <List_io <TypeQuelconque> > Les_type_de_TypeQuelconque_par_noeud(bool absolue);
 
    // initialisation par défaut de tous les conteneurs aux noeuds
    // de tous les maillages
    // contenant li_restreinte_TQ
    // ces conteneurs sont supposés déjà existés
    // typiquement si le conteneurs est un scalaire, on met 0
    void Init_par_defaut_conteneurs(List_io < TypeQuelconque >& li_restreinte_TQ);
    // idem pour une seule grandeur
    void Init_par_defaut_conteneurs(TypeQuelconque_enum_etendu enuTypeQuelconque);

    // intro de certains conteneurs internes en relation par exemple avec les demandes de visualisation
    // ou autre
    // exemple: si VECT_REAC_N qui est un type quelconque, a été choisit
    // il faut qu'il soit présent aux noeuds, alors qu'il est alimenter par les ddl pur ...
    // on introduit donc le type quelconque associé
    // NB: le conteneur passé en paramètre ne sert que pour localiser les grandeurs
    void Intro_Conteneurs_internes_noeud_relier_auto_autres_grandeur
                   ( const List_io < TypeQuelconque > & glob_noeud_evol_retenu);
 
    // idem mais ciblé en fonction d'un tableau indicé sur les maillages
    void Intro_Conteneurs_internes_noeud_relier_auto_autres_grandeur
                   ( const Tableau < List_io < TypeQuelconque > > & tab_noeud_evol_retenu);

	   // retourne la liste des types de ddl actuellement utilisé
	   // aux éléments pour chaque maillage, la liste est exhaustive
	   // elle contiend tous les types au moins une fois utilisée
	   // cela ne signifie pas que le ddl en question soit présent
	   // pour tous les éléments du maillage considéré
	   // - le tableau de retour est indicé par le numéro de maillage correspondant
	   // - il y a une liste par maillage
	   Tableau <List_io <Ddl_enum_etendu> > Les_type_de_ddl_par_element(bool absolue);
	   // idem pour les grandeurs évoluées interne actuellement utilisés
    // par les éléments, c'est-à-dire comme les ddl mais directement sous forme de vecteur, tenseurs ...
	   Tableau <List_io <TypeQuelconque> > Les_type_de_donnees_evolues_internes_par_element(bool absolue);
	   // idem pour les grandeurs particulières
	   Tableau <List_io <TypeQuelconque> > Les_type_de_donnees_particulieres_par_element(bool absolue);

    // retourne la liste des types de grandeur quelconque actuellement utilisé
    // aux faces élément pour chaque maillage, la liste est exhaustive
    // elle contiend tous les types au moins une fois utilisée
    // cela ne signifie pas que la grandeur en question soit présent
    // pour tous les éléments du maillage considéré
    // - le tableau de retour est indicé par le numéro de maillage correspondant
    // - il y a une liste par maillage
    Tableau <List_io <TypeQuelconque> > Les_type_de_donnees_evolues_internes_par_face_element(bool absolue);
    // idem pour les arêtes d'élément
    Tableau <List_io <TypeQuelconque> > Les_type_de_donnees_evolues_internes_par_arete_element(bool absolue);

    // Au niveau des noeuds: transfert des coordonnées de grandeurs vectorielles à des grandeurs évoluées
    // stockée sous forme de grandeurs TypeQuelconque
    //  exemple: les réactions qui sont naturellement stockée en composantes
    // le principe est que ce passage s'effectue si les conteneurs existent au niveau des noeuds
    void PassageInterneDansNoeud_composantes_vers_vectorielles();
	
	   // ..... transfert de grandeurs des points d'intégration aux noeuds .....
	   //    1- en entrée les type évoluées et les types particuliers que l'on veut transférer
	   //    2- en entrée: cas qui indique la méthode de transfert à utiliser
    //                  =1 : les valeurs aux noeuds sont obtenue par moyennage des valeurs des pts d'integ les plus près
    //                       des éléments qui entourent le noeud
	   // on décompose le processus en 4 étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois
	   // le même transfert
    // les méthodes: AjoutConteneurAuNoeud, InitUpdateAuNoeud, sont générales, peuvent être utilisés pour autres choses
 
 
    // 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(int num_maillage,const List_io < Ddl_enum_etendu >& lienu
	                                ,const Tableau <List_io < TypeQuelconque > * >& tabQ)
		        { tabMaillage(num_maillage)->AjoutConteneurAuNoeud(lienu,tabQ);};
    // fonctions utilitaires du même genre pour tous les maillages
    // ajout sur tous les maillages d'un ou plusieur ddl_enum_etendu comme conteneur
    // 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)
		   { for (int imail=1;imail<=nbMaillageTotal;imail++)
         tabMaillage(imail)->AjoutConteneurAuNoeud(lienu,tabQ);};

     // B) initialisation des updates sur les noeuds
     //    lorsque l'on a des listes différentes pour chaque maillage on peut directement utiliser la routine de Maillage
	   void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu
	                                , const Tableau <List_io < TypeQuelconque > * >& tabQ,int cas)
		        { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->InitUpdateAuNoeud(lienu,tabQ,cas);};
	   void InitUpdateAuNoeud(int numMail,const List_io < Ddl_enum_etendu >& lienu
	                                , const Tableau <List_io < TypeQuelconque > * >& tabQ,int cas)
		        { tabMaillage(numMail)->InitUpdateAuNoeud(lienu,tabQ,cas);};
    // C) exécution du transfert
		  // transfert de ddl des points d'intégrations (de tous) 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(int numMail,Element& ele,const List_io < Ddl_enum_etendu >& lietendu
                                     ,const Tableau <Tableau <double> > & tab_val,int cas)
		   { tabMaillage(numMail)->TransfertPtIntegAuNoeud(ele,lietendu,tab_val,cas);};
	   // idem pour des grandeurs quelconques 
	   // les informations sont ici contenues dans les types quelconques
	   // liQ_travail: est une liste de travail qui sera utilisée dans le transfert                        
	   void TransfertPtIntegAuNoeud(int numMail,Element& ele,const Tableau <List_io < TypeQuelconque > >& tab_liQ
	                            ,List_io < TypeQuelconque > & liQ_travail,int cas)
		   { tabMaillage(numMail)->TransfertPtIntegAuNoeud(ele,tab_liQ,liQ_travail,cas);};
	    // D) dernière étape: (par exemple  calcul des moyennes en chaque noeuds)
	   void FinTransfertPtIntegAuNoeud(const List_io < Ddl_enum_etendu >& lienu
	                                , const Tableau <List_io < TypeQuelconque > * >& tabQ,int cas)
     { for (int i=1;i<=nbMaillageTotal;i++) tabMaillage(i)->FinTransfertPtIntegAuNoeud(lienu,tabQ,cas);};
	   void FinTransfertPtIntegAuNoeud(int numMail,const List_io < Ddl_enum_etendu >& lienu
	                                , const Tableau <List_io < TypeQuelconque > * >& tabQ,int cas)
     { tabMaillage(numMail)->FinTransfertPtIntegAuNoeud(lienu,tabQ,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)  InitUpdateElementAuNoeud: avant le cumul, initialise les conteneurs
    //                                initialise uniquement les grandeurs qui sont gérées par l'élément
    //  C)  Accumul_aux_noeuds : balaie les éléments avec cumul aux noeuds, uniquement des grandeurs gérées par l'élement
    //  D)  MoyenneCompteurAuNoeud : effectue les moyennes aux noeuds
 
    // accumulation aux noeuds de grandeurs venant de tous les éléments vers ses 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(int numMail,const List_io < Ddl_enum_etendu >& lietendu
                            ,List_io < TypeQuelconque > & liQ,int cas)
		           { tabMaillage(numMail)->Accumul_aux_noeuds(lietendu,liQ,cas);};

    // fonctions utilitaires du même genre pour tous les maillages
 
    // ajout sur tous les maillages d'un conteneur particulier quelconque
    void AjoutConteneurAuNoeud(TypeQuelconque& tQ)
     { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->AjoutConteneurAuNoeud(tQ);};

    // ajout sur tous les maillages d'un ou plusieur ddl_enum_etendu comme conteneur
	   void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu)
		   { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->AjoutConteneurAuNoeud(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)
		    { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->InitUpdateAuNoeud(lienu);};
	   // idem pour un seul ddl_etendu	 
    void InitUpdateAuNoeud(const Ddl_enum_etendu & enu)
		    { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->InitUpdateAuNoeud(enu);};
	   // moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié)	 
	   void MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu)	 
		    { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->MoyenneCompteurAuNoeud(enu);};

    // initialisation d'un ou de plusieurs nouveau cas d'assemblage
    // ramène le numéro du premier nouveau cas d'assemblage
    Nb_assemb InitNouveauCasAssemblage(int nb_cas);
    
    // ramène le nombre total de cas d'assemblage actuellement pris en compte dans les
    // maillages
    int Nb_total_en_cours_de_cas_Assemblage() const {return tab_nb_assemb;};


    // met a jour les pointeurs d'assemblage dans les noeuds pour un cas d'assemblage  
    // a effectuer si l'on a changer de nb de noeuds, de nb de ddl, de nb de maillage  
    // casAssemb : donne le cas d'assemblage qui est a considérer
    void MiseAJourPointeurAssemblage(const Nb_assemb& nb_casAssemb);

    // mise a zero de tous les ddl actifs autres que les deplacements
    // si indic = false; pas de creation des tableaux a t+dt
    // si indic = true; creation des tableaux a t+dt
    // cas = true; les coordonnées à t et éventuellement à t+dt sont initialisées
    //             aux valeurs de t=0 (cas par défaut),
    //             sinon on ne les modifies pas.
    void ZeroDdl(bool indic,bool cas = true);
	  
	   // 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)
	     { for (int imail=1;imail<=nbMaillageTotal;imail++) 
		        tabMaillage(imail)->Force_Ddl_aux_noeuds_a_une_valeur(enu,val,temps,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)
	     { for (int imail=1;imail<=nbMaillageTotal;imail++) 
		        tabMaillage(imail)->Force_Ddl_etendu_aux_noeuds_a_zero(tab_enu);}; 
    
    // ramene la demi largeur de bande en ddl et la largeur de bande
    // casAssemb : donne le cas d'assemblage qui est a considérer
    void Largeur_Bande(int& demi, int& total,const Nb_assemb& nb_casAssemb);
    
	   // méthode permettant le calcul des matrices de connexion pour chaque
	   // élément ceci par rapport à la numérotation absolu des ddl
    // casAssemb : donne le cas d'assemblage qui est a considérer
	   void Table_connexion
	    (Tableau < Tableau <int> >& petites_matricespetites_matrices
	     ,const Nb_assemb& nb_casAssemb) const;

    // actualisation des ddl et des grandeurs actives de t+dt vers t      
    void TdtversT();
    // actualisation des ddl et des grandeurs actives de t vers tdt      
    void TversTdt();
    
    // actualisation des ddl  a t+dt, a partir du resultat de la resolution
    // casAssemb : donne le cas d'assemblage qui est a considérer
    void PlusDelta_tdt(Vecteur& sol,const Nb_assemb& nb_casAssemb);
    // actualisation des ddl actifs a t, a partir du resultat de la resolution
    // casAssemb : donne le cas d'assemblage qui est a considérer
    void PlusDelta_t(Vecteur& sol,const Nb_assemb& nb_casAssemb);
    // récupération du vecteur correspondant à l'incrément de ddl entre t et tdt
    // en paramètre le vecteur vide et en sortie le vecteur rempli
    // casAssemb : donne le cas d'assemblage qui est a considérer
    Vecteur& RecupDepde_tatdt(Vecteur& sol,const Nb_assemb& nb_casAssemb);
    // changement des ddl à tdt par ceux correspondant au vecteur passé en paramètre
    // casAssemb : donne le cas d'assemblage qui est a considérer
    void ChangeDdla_tdt(Vecteur& sol,const Nb_assemb& nb_casAssemb);
    
    // retrouver le ddl correspondant  a un pointeur de position
    // d'assemblage, le nb du noeud et du maillage
    // insol = le pointeur d'assemblage;
    // ddl = le ddl en sortie;  a t+dt  si elle il existe
    // sinon la valeur a t
    // casAssemb : donne le cas d'assemblage qui est a considérer
    Ddl  NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage
                    ,const Nb_assemb& nb_casAssemb);
    // idem en ramenant en plus la valeur du ddl a 0
    // casAssemb : donne le cas d'assemblage qui est a considérer
    Ddl  NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage, double& val0
                    ,const Nb_assemb& nb_casAssemb);
 
    // 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()
       { for (int imail=1;imail<=nbMaillageTotal;imail++)
           tabMaillage(imail)->InitNormaleAuxNoeuds();};
    // mise à jour -> mise à jour des normales à t
    void MiseAjourNormaleAuxNoeuds()
       { for (int imail=1;imail<=nbMaillageTotal;imail++)
           tabMaillage(imail)->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()
       { for (int imail=1;imail<=nbMaillageTotal;imail++)
           tabMaillage(imail)->MiseAjourNormaleAuxNoeuds_de_tdt_vers_T();};

    // ---------- particularité aux contacts ----------
    // creation des elements frontiere: cela n'a lieu qu'une seule fois
    // si les frontières existent déjà, --> aucune action, --> ramène 0
    // sinon il y a réellement création, et --> ramène 1
    // NB: il s'agit ici des frontière minimales permettant de représenter toute la frontière
    // Ainsi:
    // en 1D on retrouve:
    //    - des points uniquement
    // en 2D on retrouve :
    //    - des segments dans le cas d'une surface  (les noeuds sont exclus car intégrés aux lignes)
    //    - points et segment pour les lignes
    // en 2D axi, on retrouve :
    //    - des segments dans le cas d'une surface  (les noeuds sont exclus car intégrés aux lignes)
    //    - points et segment pour les lignes
    // en 3D, on retrouve
    //    - des faces pour les éléments volumique (noeuds et lignes sont exclus)
    //    - une face et des lignes pour les éléments 2D (pas de noeuds)

    int CreeElemFront();
    // ramene le nombre de maillage esclave
    inline int NbEsclave() const { return domEsclave;};
    // ramene le tableau des list des elements frontiere minimales (cf. explication dans CreeElemFront())
    inline Tableau <LaLIST <Front>*>& ListFrontiere() { return listFrontiere;}; 
    // ramene un tableau des noeuds des frontières des maillages esclaves
    Tableau < Tableau <Noeud*> *> Tab_noeud_frontiere_esclave();   
    // ramene le tableau des noeuds des frontières des maillages
    const Tableau <Tableau <Noeud*> *>& Tab_noeud_frontiere()  {return tt_noeud_front;}; 
    // calcul et ramene le tableau de tous les noeuds des maillages esclaves 
    // noeuds de la frontière et noeuds internes
    // s'ils existent, sinon le tableau est vide
    // le tableau n'est pas sauvegarde
    const Tableau<Noeud *> Esclave();
    
    // création forcée en 3D de toutes les frontières lignes (non traités par CreeElemFront())
    // qui appartiennent à la frontière globales, ceci uniquement pour les éléments volumiques
    // - Ces frontières ne sont pas intégrées dans la liste de frontière minimale
    // - une même ligne peut appartenir à plusieurs éléments finis, elle n'est donc pas ici
    //   définit de manière unique (contrairement aux frontières minimales)
    // NB: cela n'a lieu qu'une seule fois
    // si les frontières existent déjà, --> aucune action, --> ramène 0
    // sinon il y a réellement création, et --> ramène 1
    int CreeListFrontiere_ligne_3D();
    // ramène le tableau de pointeurs de frontières ligne 3D créées par CreeListFrontiere_ligne_3D
    inline Tableau <LaLIST <Front>*>&  ListFront_ligne_3D() { return listFrontiere_ligne_3D;};
    
    // mise à jour des boites d'encombrements des éléments, qui contiennent des éléments frontières
    // et des éléments frontières eux-même
    void Mise_a_jour_boite_encombrement_elem_front(Enum_dure temps);
	   // crée et ramene pour tous les maillages, la liste des éléments qui contiennent chaque noeud
	   // mis à jour lorsque lors de la création des frontières
	   const Tableau < const Tableau <List_io < Element* > > *>&  Indice() ;					
    
    // inactive  tous les ddl et les données
    void Inactive_ddl_et_donnees();
    // inactive  les ddl mais pas les données
    void Inactive_ddl();

    // inactive les ddl primaires 
    void Inactive_ddl_primaire();  
    // active les ddl primaires 
    void Active_ddl_primaire();  
    // introduction des ddl de contraintes si cela veut dire quelques chose
    // pour l'élément
    void Plus_ddl_Sigma();
    // inactivation des ddls de contraintes si cela veut dire quelques chose
    // pour l'élément
    void Inactive_ddl_Sigma();
    // activation des ddls de contraintes si cela veut dire quelques chose
    // pour l'élément
    void Active_ddl_Sigma();
    // activation du premier  ddl de contraintes si cela veut dire quelques chose
    // pour l'élément
    void Active_premier_ddl_Sigma();
    // introduction des ddl d'erreur si cela veut dire quelques chose
    // pour l'élément
    void Plus_ddl_Erreur();
    // inactivation des ddls d'erreur si cela veut dire quelques chose
    // pour l'élément
    void Inactive_ddl_Erreur();
    // activation des ddls d'erreur si cela veut dire quelques chose
    // pour l'élément
    void Active_ddl_Erreur();
    
    // active un ddl particulier
    void Active_un_ddl_particulier(Enum_ddl en);
    // inactive un ddl particulier
    void Inactive_un_ddl_particulier(Enum_ddl en);

    // d'une manière plus générique une fonction pour activer une série de ddl
    // donnée par un identificateur, si c'est une grandeur vectoriel c'est l'ensemble
    // des ddl du vecteur qui sont inactivé. 
    void Active_un_type_ddl_particulier(Enum_ddl en);  
    void Active_un_type_ddl_particulier(Tableau<Enum_ddl>& tab_en);  // idem mais pour un tableau
    void Active_un_type_ddl_particulier(const list<Enum_ddl>& list_en);  // idem pour une liste
    // idem la fonction Active_ddl_noeud mais ici pour l'inactivation
    void Inactive_un_type_ddl_particulier(Enum_ddl en);  
    void Inactive_un_type_ddl_particulier(Tableau<Enum_ddl>& tab_en); // idem mais pour un tableau
    void Inactive_un_type_ddl_particulier(const list <Enum_ddl>& list_en);  // idem pour une liste
    // -- encore plus générique
    // changement de toutes les conditions données (service, variable, fixage ..)  
    // selon le tableau de ddl passé en paramètre
    // par contre les valeurs de ta ne sont pas utilisé donc les valeurs actuelles restent inchangé
    void ChangeToutesLesConditions(const Tableau<Ddl>& ta);
    // changement de statu des ddl d'une combinaison, en fonction du statut
    // de enuta dans chaque noeud, les ddl de la combinaison, prennent le même statut que celui
    // de enuta dans chaque noeud.
    // cas est la combinaison,
    void ChangeStatut(int cas,Enum_ddl enuta);
    // changement de statu des ddl d'une combinaison dans chaque noeud, en fonction
    // de enubold, les ddl de la combinaison, prennent le même statut que enubold
    // cas est la combinaison,
    void ChangeStatut(int cas,Enum_boolddl enubold);
 
    //change le statut de tous les ddl liés à la physique en cours
    //par exemple: met à libre ou bloque les ddl liés à la physique en cours
    void Libere_Ddl_representatifs_des_physiques(Enum_boolddl enubold);
 
    // Calcul de l'erreur  sur l'ensemble des éléments
    // type indique le type d'erreur retenue
    // type = 1 : cas d'un calcul aux moindres carrés
    // et retour un tableau de tableau de grandeurs sur les maillages en cours
    //      ret(i) : concerne le maillage i
    //      ret(i)(1) : somme des erreurs sur l'ensemble des éléments: est homogêne à
    //                  un |delta contrainte| * domaine
    //      ret(i)(2) : somme de la grandeur de ref du calcul d'erreur sur l'ensemble des
    //                  éléments: est homogêne à une |contrainte| * domaine
    //      ret(i)(3) : le maxi pour les tous les éléments de |delta contrainte| * domaine
    //      ret(i)(4) : le maxi pour les tous les éléments de |contrainte| * domaine
    Tableau <Tableau <double > >   ErreurSurChaqueElement(int type);
    
    // lecture de donnée en fonction d'un indicateur : type
    // type = 1 , on lit les tenseurs de contraintes
    void   LectureDonneesExternes(const int type ,const string& nomMaillage);
    
    // mise en place du travail à t  sur les maillages
    // indique que l'on va utiliser les ddl en 0, t
    // si les grandeurs en tdt existaient, elles sont supprimées
	   void Travail_t();
	   // idem pour un maillage donné de numéro num
	   void Travail_t(int num);
	 
	   // définition des coordonnées à t identiques à ceux à t=0,
	   void Insert_coord1();
 
    // mise en place du travail à t tdt sur les maillages
    // indique que l'on va utiliser les ddl en 0, t, tdt
    void Travail_tdt();
 
    // 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() { for (int imail=1;imail<=nbMaillageTotal;imail++)
                                     tabMaillage(imail)->Init_Xi_t_et_tdt_de_0();};
        
    // 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 pour tous les maillages
	   double Min_dist2Noeud_des_elements(Enum_dure temps) const ;
	  
	   // indique aux éléments un niveau de précision de calcul désiré pour les prochains calculs
	   // precision = 0 : aucune précision demandée, precision >=0 : précision maximale demandée
	   void Drapeau_preparation_calcul_precis(int precision);
	 
// --------- calcul dynamique ---------
    // ajout des ddl de vitesse pour tous les maillages
    // val_fixe indique si l'on veut des ddl libres ou pas 
    void Plus_Les_ddl_Vitesse(Enum_boolddl val_fixe);
    // ajout des ddl d'accélération pour tous les maillages
    // val_fixe indique si l'on veut des ddl libres ou pas 
    void Plus_Les_ddl_Acceleration(Enum_boolddl val_fixe);
    // calcul  de la longueur d'arrête d'élément minimal
    // divisé par la célérité dans le matériau
    double Longueur_arrete_mini_sur_c(Enum_dure temps);
    // initialisation éventuelle du bulk viscosity
    // choix peut-être égale à 0, 1 ou 2 
    void Init_bulk_viscosity(int choix,const DeuxDoubles &  coef);
    
	   //----- lecture écriture de restart -----
	   // 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(istream& 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(ostream& sort,const int cas);
    
  #ifdef UTILISATION_MPI
    // retour de la taille globale des sorties retardées gérées par par LesMaillages
    // concernant les sorties sur .BI
    int Taille_buffer_sortie_BI();
    // récupération de l'offset global sur .BI pour la classe
    // et mise à jour des offsets de classes dérivées si besoin
    void Mise_a_jour_Offset_BI_ecriture(int offset,const int cas);
    // idem en lecture, mais là il s'agit uniquement de la mise à jour
    // de l'offset seul puis c'est la classe qui s'en débrouille
    void Mise_a_jour_Offset_BI_lecture(int offset,const int cas);

    // lecture MPI des infos bufferisées
    void Lecture_base_info_MPI_IO(MPI_File * ent_MPI,const int cas);
    // écriture MPI des infos bufferisées
    void Ecriture_base_info_MPI_IO(MPI_File * sort_MPI, const int cas);
  #endif

    // sortie du schemaXML: en fonction de enu
    void SchemaXML_LesMaillages(ostream& sort,const Enum_IO_XML enu) const ;
	 
     
    // ------ informations utiles par exemples pour la visualisation 
    // retourne les dimensions minis et maxi suivant les axes du repère
    // absolu du maillage numéro nbmail (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_boite(int nbmail);
    // dans le cas ou aucun numéro de maillage n'est fournis
    // c'est l'encombrement de tous les maillages qui est fourni
    Tableau <Vecteur>  Taille_boite();
    
    
    // --------  utilitaires de manipulation de maillage
    // création de maillage quadratiques incomplets à partir de maillages linéaires. 
    // En fait il y création de maillages identiques aux maillages déjà existants, les éléments qui sont de types
    // linéaires  sont remplacés par des éléments quadratiques incomplets correspondants.
    // Il y a création de références correspondantes
    void CreeMaillagesQuadratiques_a_partir_des_lineaires(LesReferences* lesRef);
    // création de maillage quadratiques complets. En fait il y création de maillages identiques aux maillages
    // déjà existants, les éléments qui sont de types quadratiques incomplets sont remplacés par des éléments
    // quadratiques complets correspondants.
    // Il y a création de références correspondantes
    void CreeMaillagesQuadratiquesComplets_a_partir_des_incomplets(LesReferences* lesRef);
    // création de maillages par extrusion
    // Il y a création de références correspondantes
    void CreeMaillageExtrusion2D3D(LesReferences* lesRef);
    // 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);   
    // 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);
    // Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe
    void Collapse_element_supperpose(LesReferences* lesRef);
    // création d'un nouveau maillage issue de la fusion de maillages existants
    // nom_mails_a_fusionner : la liste des maillages à fusionner
    // new_mail              : le nom du nouveau maillage à construire
    // NB: si new_mail correspond à un maillage déjà existant, il y a fusion de ce maillage
    //     avec les autres, sans création d'un nouveau maillage
    void Fusion_maillages(List_io < string >& nom_mails_a_fusionner,const string& new_mail
                          ,LesReferences* lesRef);
    // création d'un nouveau maillage issue d'un maillages existants et d'une ref d'éléments
    // le nouveau maillage = les éléments de la ref
    void Cree_sous_maillage(int num_mail,LesReferences* lesRef, string nom_ref,const string& new_mail);
    // création d'éléments SFE en fonction d'éléments classiques
    // il y a création d'un nouveau maillage
    void CreationMaillageSFE();
     
    // Affiche les donnees des maillages dans des fichiers dont le nom est construit à partir du nom de 
    // chaque maillage au format  ".her" et ".lis"
    // le paramètre optionnel indique le numéro du maillage à afficher, s'il vaut -1, on affiche tous les maillages
    void Affiche_maillage_dans_her_lis(Enum_dure temps,LesReferences &lesRef,int imail=-1);
    
    // relocalisation des points milieux des arrêtes des éléments quadratiques
    void RelocPtMilieuMailleQuadra();
 
    // --- utilitaires pour calculs particuliers-------
    // calcul des diverses intégrations: volume et volume + temps,
    // alimentation des grandeurs globales associées
    void Integration();
    
    // calcul des diverses statistiques sur des ref de noeuds et avec éventuellement
    // cumul sur le temps
    // alimentation des grandeurs globales associées
    void CalStatistique();

  private :  
    // VARIABLES PROTEGEES :
    Tableau<Maillage *> tabMaillage ; // tableau de maillages
    // liste des noms de maillages associée à un numéro sous forme d'un arbre pour faciliter la recherche
    // cette liste est modifiée que par chaque maillage
    map < string, int , std::less <string> > mapNomMail;
    // const int nbEnreg; // nb de maillage initiaux
    int nbEnreg; // nb de maillage initiaux
    int nbMaillageTotal; // nb de maillage effectivement en cours
    int nbPortion ; // nbPortion = le nombre maxi de maillage enregistrable
    // avant une nouvelle allocation dynamique de nbEnreg places supplementaires
    UtilLecture * entreePrinc; // acces a la lecture du fichier principal
    ParaGlob * paraGlob ; // parametres globaux
    LesReferences* lesRef; // references
    int domEsclave; // nombre de domaine esclave, lorsqu'il est different de zero
     // il indique le nombre de maillage a partir de 1, qui sont esclave

    // ---- stockage des intégrales de volumes sur des références d'éléments ----
    // --- cas des intégrales volumiques: définition du conteneur, il peut également s'agir d'une intégration temporelle en +
    // d'où la grandeur courante et celle à t
    // 1) intégration de volume uniquement
    Tableau <TypeQuelconque>  integ_vol_typeQuel,  integ_vol_typeQuel_t;
    Tableau <const Reference*>   ref_integ_vol; // les références associées
    // si la référence est nulle, cela signifie que l'intégrale est figée: sa valeur ne change pas

    // 2) intégration de volume et en temps: donc on commule le delta
    Tableau <TypeQuelconque>  integ_vol_t_typeQuel,  integ_vol_t_typeQuel_t;
    Tableau <const Reference*>  ref_integ_vol_t; // les références associées
    // si la référence est nulle, cela signifie que l'intégrale est figée: sa valeur ne change pas

    // ---- stockage des statistiques sur des références de noeuds ----
    // --- cas des statistique: définition du conteneur, il peut également s'agir d'un cumul temporelle en +
    // d'où la grandeur courante et celle à t
    // 1) statistique de ref de noeuds uniquement
    Tableau <TypeQuelconque>  statistique_typeQuel,  statistique_typeQuel_t;
    Tableau <const Reference*>   ref_statistique; // les références associées
    // si la référence est nulle, cela signifie que la statistique
    // est figée: sa valeur ne change pas
 #ifdef UTILISATION_MPI
    // cas d'un calcul parallèle: // passage des infos entre process
    Temps_CPU_HZpp  temps_transfert_long ;
    Temps_CPU_HZpp  temps_serialisation ;
    Vecteur  v_integ; // conteneur intermédiaire de transfert
    // pour les i/o
    Tableau <std::string > buffer_ioBI_MPI; // les buffers pour la sortie retardée
      // uniquement les buffers propres à LesMaillages : taille 2 pour tous les proc
    std::vector<int>  tailles_buffer_ioBI_MPI; // les tailles qui sont transmises par proc 0
      // size 2 pour tous les proc
    // offsets pour chaque maillage, offset_maillage[0] est l'offset général pour LesMaillages
    // [i] : position du maillage i, [nbMaillageTotal+1] : position du second buffer de LesMaillages
    // [nbMaillageTotal+2] : 
    std::vector<int> offset_maillage;
 #endif

    //pour_statistique_de_ddl a la même dimension que ref_statistique
    // 1) Dans le cas où ref_statistique(i) est une statistique de Ddl_enum_etendu
    // pour_statistique_de_ddl(i) == le Ddl_enum_etendu
    // 2) sinon, pour_statistique_de_ddl(i) == NU_DDL
    Tableau < Ddl_enum_etendu > pour_statistique_de_ddl;

    // 2)  statistique avec cumul en temps: donc on commule le delta
    Tableau <TypeQuelconque>   statistique_t_typeQuel,   statistique_t_typeQuel_t;
    Tableau <const Reference*>  ref_statistique_t; // les références associées
    // si la référence est nulle, cela signifie que la statistique est figée: sa valeur ne change pas
    
    //pour_statistique_t_de_ddl a la même dimension que ref_statistique_t
    // 1) Dans le cas où ref_statistique_t(i) est une statistique de Ddl_enum_etendu
    // pour_statistique_t_de_ddl(i) == le Ddl_enum_etendu
    // 2) sinon, pour_statistique_de_ddl(i) == NU_DDL
    Tableau < Ddl_enum_etendu > pour_statistique_t_de_ddl;

    // cumule les 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 les 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)
    list <Enum_ddl >  ddl_representatifs_des_physiques;
    // idem au niveau des types de problèmes gérés par les éléments
    list <EnumElemTypeProblem > types_de_problemes;

    // stockage des pointeurd de listes d'element frontiere minimal
    // NB: il s'agit ici des frontière minimales permettant de représenter toute la frontière
    // Ainsi:
    // en 1D on retrouve:
    //    - des points uniquement
    // en 2D on retrouve :
    //    - des segments dans le cas d'une surface  (les noeuds sont exclus car intégrés aux lignes)
    //    - points et segment pour les lignes
    // en 2D axi, on retrouve :
    //    - des segments dans le cas d'une surface  (les noeuds sont exclus car intégrés aux lignes)
    //    - points et segment pour les lignes
    // en 3D, on retrouve
    //    - des faces pour les éléments volumique (noeuds et lignes sont exclus)
    //    - une face et des lignes pour les éléments 2D (pas de noeuds)
    Tableau <LaLIST <Front>*> listFrontiere;
    // idem pour les noeuds des frontières
    Tableau <Tableau <Noeud*> *> tt_noeud_front;
    
    // en 3D liste de toutes les frontières lignes (non traités par CreeElemFront())
    // qui appartiennent à la frontière globales, ceci uniquement pour les éléments volumiques
    // - Ces frontières ne sont pas intégrées dans la liste de frontière minimale
    // - une même ligne peut appartenir à plusieurs éléments finis, elle n'est donc pas ici
    //   définit de manière unique (contrairement aux frontières minimales)
    Tableau <LaLIST <Front>*> listFrontiere_ligne_3D;
    
	   // crée et ramene pour tous les maillages, la liste des éléments qui contiennent chaque noeud
	   // mis à jour lorsque lors de la création des frontières minimales
	   Tableau < const Tableau <List_io < Element* > > *>  tous_indices;					
    // tableau d'indexage des ddl géré par les noeuds 
    // t_i_n (i)(j) -> donne les infos pour retrouver le ddl numéro j du cas de charge i
    // le numéro j correspond au pointeur d'assemblage c-a-d la position du ddl dans l'assemblage
    Tableau < Tableau <Posi_ddl_noeud> > t_i_n;
    // nombre actuellement de cas d'assemblage initialisé
    int tab_nb_assemb;
    
    // METHODES PROTEGEES :
    // 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();

    // met a jour les pointeurs d'assemblage dans les noeuds pour un cas d'assemblage
    // a effectuer si l'on a changer de nb de noeuds, de nb de ddl, de nb de maillage
    // casAssemb : donne le cas d'assemblage qui est a considérer
    // ici, l'assemblage suit l'ordre du tableau de noeud passé en paramètre
    // le tableau de noeuds rassemble tous les noeuds des maillages mais avec une numérotation propre
    // verif_maillage: si true: on vérifie que les numéros de noeuds sont possibles pour le maillage
    //         mais cette vérification n'est pas effectuée si verif_maillage est false: c'est utile
    //         dans une phase transitoire de fabrication de t_i_n: bien noter que dans ce cas le tableau
    //         t_i_n n'est pas utilisable
    void MiseAJourPointeurAssemblage_interne(const Nb_assemb& nb_casAssemb,Tableau <Noeud* >& tab_N_final
                                             ,bool verif_maillage);
 
   // remise à jour des tableaux de pointeurs t_i_n uniquement, due à un changement de numéro de noeud
   // en fonction d'un changement de num de noeud (mais pas de changement de pointeur d'assemblage
   // pour chaque noeud, tab_N_final(i) correspond au noeud qui avait le numéro i ancien
   //   et qui a maintenant le numéro tab_N_final(i)->Num_noeud()
   void MiseAJourTableau_t_i_n(const Nb_assemb& nb_casAssemb,Tableau <Noeud* >& tab_N_final);


 };
 /// @}  // end of group

#endif