
// 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/>.

#include "Mail_initiale_Gmsh.h"

// pour le tableau de connection herezh -> gmsh
#include "Visualisation_Gmsh.h"

#include <iomanip>
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "CharUtil.h"
#include "GeomPoint.h"

    // CONSTRUCTEURS :
// par defaut
Mail_initiale_Gmsh::Mail_initiale_Gmsh () :
//   OrdreVisu("","visualisation des maillages initiaux","")
   OrdreVisu(".................................maillage initiale"
             ,"visualisation des maillages initiaux","mi")
   ,tabtab_sous_mesh(),tabli_sig_elem(),tabli_sous_mesh()
   ,decal_noeud(),decal_element(),nb_total_noeud(0),nb_total_element(0)
   ,nb_total_ref(0),tab_nom_tag_ref(),lesRefInitiales(),tab_num_tag(),t_jonction_N_Nelem()
	,nombre_noeud_ref_pti(0),nombre_ref_pti(0),t_jonction_N_NelemPti()
   ,t_Egmsh(),tab_dim_de_ref()
	,considerer_homothetie(false),t_homothetie(),t_orig(),t_fact_mult()
	,sortie_des_references(1)
     {}; 
     
     // constructeur de copie 
Mail_initiale_Gmsh::Mail_initiale_Gmsh (const Mail_initiale_Gmsh& ord) :
   OrdreVisu(ord),tabtab_sous_mesh(ord.tabtab_sous_mesh)
   ,tabli_sig_elem(ord.tabli_sig_elem)
   ,tabli_sous_mesh(ord.tabli_sous_mesh)
   ,decal_noeud(ord.decal_noeud),decal_element(ord.decal_element)
   ,nb_total_noeud(ord.nb_total_noeud),nb_total_element(ord.nb_total_element)
   ,nb_total_ref(ord.nb_total_ref),lesRefInitiales(ord.lesRefInitiales),tab_nom_tag_ref(ord.tab_nom_tag_ref)
	,tab_num_tag(ord.tab_num_tag)
	,t_jonction_N_Nelem(ord.t_jonction_N_Nelem)
	,nombre_noeud_ref_pti(ord.nombre_noeud_ref_pti),nombre_ref_pti(ord.nombre_ref_pti)
	,t_jonction_N_NelemPti()
	,tab_dim_de_ref(ord.tab_dim_de_ref)
   ,t_Egmsh(ord.t_Egmsh)
	,considerer_homothetie(ord.considerer_homothetie)
	,t_homothetie(ord.t_homothetie),t_orig(ord.t_orig),t_fact_mult(ord.t_fact_mult)
	,sortie_des_references(ord.sortie_des_references)
      {};
               
    // DESTRUCTEUR :
Mail_initiale_Gmsh::~Mail_initiale_Gmsh () 
     {};  
    
    // METHODES PUBLIQUES :
            
// initialisation : permet d'initialiser les différents paramètres de l'ordre
// lors d'un premier passage des différents incréments
// en virtuelle, a priori est défini si nécessaire dans les classes dérivées
void Mail_initiale_Gmsh::Initialisation(ParaGlob * paraGlob,LesMaillages * lesmail,LesReferences* lesRef
                      ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,Charge* charge
                      ,LesCondLim* lesCondLim,LesContacts* lesContacts
                      ,Resultats* resultats,EnumTypeIncre type_incre,int incre
                      ,const map < string, const double * , std::less <string> >& listeVarGlob
                      ,const List_io < TypeQuelconque >& listeVecGlob
                      ,bool fil_calcul) 
   { int nb_maillage = lesmail->NbMaillage();
     if (!fil_calcul)
       {// initialisation des tableaux
        tabtab_sous_mesh.Change_taille(nb_maillage);
        tabli_sig_elem.Change_taille(nb_maillage); 
        tabli_sous_mesh.Change_taille(nb_maillage);
       };
    
     //appel de l'ordre d'initialisation de la classe mère
     OrdreVisu::Initialisation(paraGlob,lesmail,lesRef,lesLoisDeComp,diversStockage,charge
                      ,lesCondLim,lesContacts,resultats,type_incre,incre
                      ,listeVarGlob,listeVecGlob,fil_calcul);
     // la sortie du maillage initial est a priori obligatoire donc on effectue le choix par défaut
     // de la classe mère, par contre on laisse l'interactif pour l'interne
     OrdreVisu::ChoixOrdre(); // appel de la méthode de la classe mère   
//     Mail_initiale_Gmsh::ChoixOrdre();
     if (!fil_calcul)
       {// on calcule le décalage de numéros de noeud, du au fait qu'il peut y avoir plusieurs maillages
        decal_noeud.Change_taille(nb_maillage); decal_element.Change_taille(nb_maillage);
        int decal_n = 0; int decal_e=0; // variables intermédiaires
        for (int nm=1;nm<=nb_maillage;nm++)
         {decal_noeud(nm)=decal_n; decal_element(nm)=decal_e;
          decal_n += lesmail->Nombre_noeud(nm);
          decal_e += lesmail->Nombre_element(nm);
         };
        // on enregistre le nombre total de noeud et le nombre total d'éléments	
        nb_total_noeud = decal_n;	
        nb_total_element = decal_e;
        // on va également calculer le nombre maxi de référence qui existent
        nb_total_ref=0; // init
        const Reference* premref =  lesRef->Init_et_Premiere();
        if (premref != NULL) nb_total_ref++; 
        while (lesRef->Reference_suivante() != NULL)
           nb_total_ref++;
        // def des homothétie éventuelles
        t_homothetie.Change_taille(nb_maillage);
        t_orig.Change_taille(nb_maillage);
        t_fact_mult.Change_taille(nb_maillage);
        int dim = ParaGlob::Dimension();	
        for(int i=1;i<= nb_maillage;i++)
           {t_orig(i).Change_dim(dim); t_fact_mult(i).Change_dim(dim);};
        // on construit le tableau des noms de référence qui seront sorties éventuellement
        // on définit un numéro pour chaque référence lue, en fait le numéro d'ordre
        tab_nom_tag_ref.Change_taille(nb_total_ref); // stockage des noms
        // --on balaie les ref
        int itab=1; // donne un numéro d'ordre pour les références
        const Reference* refcourante =  lesRef->Init_et_Premiere();
        lesRefInitiales.Change_taille(nb_total_ref);
        while (refcourante != NULL)
         { // on définie un nom qui contient le nom de la ref + le nom du maillage (son num)
           string nom_mail = lesmail->NomMaillage(refcourante->Nbmaille());
           tab_nom_tag_ref(itab) = refcourante->Nom()+" "
                            +nom_mail+"("+ChangeEntierSTring(refcourante->Nbmaille())+")";
              lesRefInitiales(itab)=refcourante;
           itab++;
           refcourante = lesRef->Reference_suivante();
         };
       };
   };
            
// execution de l'ordre
// tab_mail : donne les numéros de maillage concerné
// incre : numéro d'incrément qui en cours
// type_incre : indique si c'est le premier le dernier ou l'incrément courant a visualiser ou pas
// animation : indique si l'on est en animation ou pas
// unseul_incre : indique si oui ou non il y a un seul increment à visualiser
void Mail_initiale_Gmsh::ExeOrdre(ParaGlob * ,const Tableau <int>& tab_mail,LesMaillages * lesMail,bool 
            ,LesReferences* lesRef,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*
//                      ,LesContacts*,Resultats*,ostream & sort,EnumTypeIncre type_incre,int incre
                      ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre ,int incre
//                      ,bool animation)
                      ,bool,const map < string, const double * , std::less <string> >&
                      ,const List_io < TypeQuelconque >& listeVecGlob)
 {// --- la partie qui suie est systématiquement exécutée, que ce soit actif, ou pas et quelque soit l'incrément --
  // constitue une initialisation pour les autres ordres, mais que l'on ne peut pas mettre dans Mail_initiale_Gmsh::Initialisation
  // car dépend de tab_mail, qui dépend du choix de l'utilisateur
  
  // on recalcule les décalages de noeuds en fonction des maillages actifs, car c'est utilisé par les isovaleurs et autres
  // ordres, les maillages qui ne sont pas concerné, ont des décal_noe et éléments inchangé donc quelconques, ceci permet de garder les mêmes tailles
  int decal_n = 0; int decal_e=0; // variables intermédiaires
  int nbmail = tab_mail.Taille();
  for (int nm=1;nm<=nbmail;nm++)
   {int numMail=tab_mail(nm);
    decal_noeud(numMail)=decal_n; decal_element(numMail)=decal_e;
    decal_n += lesMail->Nombre_noeud(numMail);
    decal_e += lesMail->Nombre_element(numMail);
   };
  // on ré_enregistre le nombre total de noeud et le nombre total d'éléments	
  nb_total_noeud = decal_n;	
  nb_total_element = decal_e;

  if (incre==0) // dans tous les cas on sort le maillage initiale au premier incrément
  {ostream &sort = entreePrinc.Sort_initial_Gmsh();
   // --- pour l'instant, on prend l'option de sortir comme avec Gid, tout dans un seul maillag
   // il est possible de lire plusieurs maillage avec gmsh, mais il faut qu'ils soient dans plusieurs fichiers,
   // comme la manip existe avec gid, de globaliser dans un seul fichier, par simplicité, on l'utilise
   
   // quelques rappels: pas de commentaires entre deux $quelquechoses, il peut y avoir
   // plusieurs jeux d'éléments, et entre deux couple $quelquechoses on peut avoir des commentaires
   
   // 1) on s'intéresse d'abord à la définition des tag de PhysicalNames 
   //    (sert pour la différentiation des maillages)
   if (sortie_des_references)
      SortieTagPhysicalNames(tab_mail,lesMail,sort);
   // 2) maintenant on s'intéresse aux coordonnées des noeuds pour le fichier principal sort
   SortieDesNoeuds(tab_mail,lesMail,sort);
   // 3) puis les éléments
   SortieDesElements(tab_mail,lesMail,sort);
	  // 4) enfin les références
	  if (sortie_des_references)
	    SortieReferences(tab_mail,lesMail,entreePrinc);
   // et on vide le buffer de sortie
   sort << endl; 
   // constitution des sous maillages, utilisé par les isovaleurs par exemple
   // on suit la même logique que dans gid, un sous maillage par type d'élément
   // ce n'est pas nécessaire, c'est pas simplicité, à modifier si nécessaire par la suite
   CreaSousMaillages(tab_mail,lesMail);                      
   }; //-- fin de if ((actif)&&(incre==0)) 
  };

// sortie maillage initiale (sans références ni tag) avec le nouveau format
void Mail_initiale_Gmsh::sortie_maillage_initial(const Tableau <int>& tab_mail
              ,LesMaillages * lesMail, ostream &sort)
{  // écriture d'une entete locale 
   sort << "\n // ============================================================"
        << "\n // |      definition des noeuds des  maillages                |"
        << "\n // ============================================================";

   sort << "\n$Nodes ";  // mot clé de début des noeuds:
   sort  << "\n " << nb_total_noeud ;
   // sortie sur le flot passé en paramètre, de la partie noeud du maillage sans entête ni fin
   Sortie_noeuds_initiaux(tab_mail,lesMail,sort);
   // fin des noeuds  
   sort << "\n$EndNodes ";
   sort << "\n // ============================================================"
        << "\n // |      definition des elements des  maillages              |"
        << "\n // ============================================================";
   sort << "\n$Elements ";   
   sort  << "\n" << nb_total_element;
   // sortie sur le flot passé en paramètre, de la partie élément du maillage sans entête ni fin
   Sortie_element_initiaux(tab_mail,lesMail,sort);
   sort << "\n$EndElements";
   // et on vide le buffer de sortie
   sort << endl; 
};

// sortie de la définition des tag de PhysicalNames (sert pour les références)
void Mail_initiale_Gmsh::SortieTagPhysicalNames(const Tableau <int>& tab_mail,LesMaillages * lesMail
                                                ,ostream &sort)
 { // au niveau des PhysicalNames qui seront utilisées pour les éléments, on en a trois disponibles
   
   // 1 -> the number of the physical entity : on s'en sert pour le numéro de maillage 
   // 2 -> the number of the elementary geometrical entity : on s'en sert pour le numéro d'élément local
   // 3 -> the number of a mesh partition : = 0 on s'en sert pas pour l'instant, pourra servir éventuellement lorsque
   //                                           on voudra faire du calcul // ??

   
   // on construit un tableau de bool, pour savoir si le maillage est à sortir ou pas
   Tableau <bool> t_a_sortir(lesMail->NbMaillage(),false);
   int nb_a_sortir = tab_mail.Taille();
   for (int isa = 1; isa <= nb_a_sortir; isa++)
     t_a_sortir(tab_mail(isa))=true;
   
   // on définit un numéro pour chaque référence lue, en fait le numéro d'ordre

// modif le tableau tab_nom_tag: est définit dans l'initialisation, normalement il ne change
// pas en cours de calcul
//   tab_nom_tag_ref.Change_taille(nb_total_ref); // stockage des noms

   tab_dim_de_ref.Change_taille(nb_total_ref); // stockage dimension des ref
   tab_num_tag.Change_taille(nb_total_ref); // stockage des numéros de maillages associés 
   // --on balaie les ref
   int nbmail = tab_mail.Taille(); // le nombre de maillage à sortir
   int nbref = lesRefInitiales.Taille();
   //itab=1 donne un numéro d'ordre pour les références
   for (int itab=1;itab<=nbref;itab++)
	{ const Reference* refcourante =  lesRefInitiales(itab);
      // on définie un nom qui contient le nom de la ref + le nom du maillage (son num)
	  string nom_mail = lesMail->NomMaillage(refcourante->Nbmaille());
      
// modif: le tableau tab_nom_tag: est définit dans l'initialisation, normalement il ne change
// pas en cours de calcul
//	  tab_nom_tag_ref(itab) = refcourante->Nom()+" "
//	                      +nom_mail+"("+ChangeEntierSTring(refcourante->Nbmaille())+")";

	  tab_num_tag(itab) = itab+nbmail;	// on décale de nbmail, car il y a un tag/maillage avant les références						 
	  switch (refcourante->Indic()) 
		  {
			  case 1: case 6: tab_dim_de_ref(itab) = 0; break ; // ref de point
			  case 2: // ref d'élément: on récupère le premier élément pour voir le type
			    { const ReferenceNE * refi =  ((ReferenceNE *) refcourante);
					const Tableau<int>& tt = refi->Tab_num ();
					if(tt.Taille() != 0)
					 { const Element& ele = lesMail->Element_LesMaille_const(refi->Nbmaille(),refi->Numero(1)); 
					   switch (Type_geom_generique(ele.Id_geometrie()))
						{ case LIGNE : tab_dim_de_ref(itab) = 1; break ; // ref de ligne
						  case SURFACE : tab_dim_de_ref(itab) = 2; break ; // ref de surface
						  case VOLUME : tab_dim_de_ref(itab) = 3; break ; // ref de volume
						  default: tab_dim_de_ref(itab) = 0; break ;// autres cas pas pris en compte dans gmsh
						 };
					  };
					break;
				 }	  	  
			  case 3: tab_dim_de_ref(itab) = 2; break ; // ref de surface
			  case 4: tab_dim_de_ref(itab) = 1; break ; // ref d'arrêtes
			  default: tab_dim_de_ref(itab) = 0; break ;// autres cas pas pris en compte dans gmsh
		  };
	   	
	  // on traite en fonction du type de référence
	  switch (refcourante->Indic())
		{ case 5: // =5 -> des noeuds relatifs à des éléments
		   	{
		   		
		   	}
		  	  break;	
		// =6 -> de points d'intégrations relatifs à des éléments
/*		  case 6: // indic = 6 : il s'agit de reference de point d'intégration
		  	{ const ReferenceAF * ref1 = ((ReferenceAF *) refcourante);
		  	  int taille = ref1->Taille();
		  	  int num_maille = ref1->Nbmaille();
		  	  if (t_a_sortir(num_maille))
		  	    for (int i=1;i<=taille;i++)
		  	  	{ int numElem = ref1->NumeroElem(i);
		  	      // on redimentionne au cas où 
		  	  	  Element& elem  = lesMail->Element_LesMaille(num_maille,numElem); // récup de l'élément
		          const ElemGeomC0& elgeom = elem.ElementGeometrique_const();
		  	  	  t_ref_arete(num_maille)(numElem).Change_taille(elgeom.NonS().Taille());
		  	  	  // sauvegarde du numero d'arête
		  	  	  t_ref_arete(num_maille)(numElem)(ref1->NumeroFA(i)).push_back(itab);
		  	  	};
		  	  break;	
		  	}*/
		// pas traiter par gmsh
		};
      
	};
	// fin A)
	
	// B) -- sortie des PhysicalNames
// doc gmsh
//    $PhysicalNames
//     number-of-names
//     physical-dimension physical-number "physical-name"
//     ...
//     $EndPhysicalNames      
 
   sort << "\n$PhysicalNames ";   
   // def du nombre total de physical entity c'est-à-dire de maillage à sortir
   sort  << "\n " << (nbmail+nb_total_ref);
////   sort  << "\n " << nbmail;
   for (int i=1;i<=nbmail;i++)
	  // 3 c'est pour une dimension 3 par défaut, c'est possible que cela pose des pb dans le cas de maillages 2D
     sort << "\n  3 " << i << "  \"" << lesMail->NomMaillage(tab_mail(i)) << "\" ";
	// maintenant on boucle sur les noms de référence
	for (int i=1;i<= nb_total_ref;i++)
	  { 
	    sort << "\n " << tab_dim_de_ref(i) << " " << tab_num_tag(i) << "  \"" << tab_nom_tag_ref(i) << "\" ";
		};	  
   sort << "\n$EndPhysicalNames ";
 
   return;
 };
 
// sortie uniquement des noeuds avec éventuellement, def de noeud aux  points d'intégration
void Mail_initiale_Gmsh::SortieDesNoeuds(const Tableau <int>& tab_mail,LesMaillages * lesMail 
                                         , ostream &sort)
 { // --- pour l'instant, on prend l'option de sortir comme avec Gid, tout dans un seul maillage
   // il est possible de lire plusieurs maillage avec gmsh, mais il faut qu'ils soient dans plusieurs fichiers,
   // comme la manip existe avec gid, de globaliser dans un seul fichier, par simplicité, on l'utilise
   // par contre on met des ref différentes ce qui permettra de départager au moment de la visualisation
// doc gmsh
//     $Nodes
//     number-of-nodes
//     node-number x-coord y-coord z-coord
//     ...
//     $EndNodes

	// ---- on s'intéresse tout d'abord aux références de points d'intégrations s'il en existe 
	// la première étape étant de compter les noeuds 
   // on construit un tableau de bool, pour savoir si le maillage est à sortir ou pas
   Tableau <bool> t_a_sortir(lesMail->NbMaillage(),false);
   int nb_a_sortir = tab_mail.Taille();
   for (int isa = 1; isa <= nb_a_sortir; isa++)
     t_a_sortir(tab_mail(isa))=true;
	  
   nombre_noeud_ref_pti = 0;
   nombre_ref_pti = 0;
   int nbref = lesRefInitiales.Taille();
   //itab=1 donne un numéro d'ordre pour les références
   for (int itab=1;itab<=nbref;itab++)
    { const Reference* refcourante =  lesRefInitiales(itab);
      // on continu si le maillage est a sortir
      int numMail=refcourante->Nbmaille();
      if (t_a_sortir(numMail)) 
       {Tableau <Enum_geom > enum_geo; // les énuméré de la géométrie des éléments à sortir
        Tableau <Noeud *> tab_inter; // tableau de travail
        switch (refcourante->Indic())
         { case 6: // on ne s'intéresse qu'aux références de points d'intégration 
             { const ReferenceAF * ref1 = ((ReferenceAF *) refcourante);
               nombre_noeud_ref_pti += ref1->Taille();
               nombre_ref_pti++;
             };
           break;
         };
       };
    };


   // écriture d'une entete locale 
   sort << "\n // ============================================================"
        << "\n // |      definition des noeuds des  maillages                |"
        << "\n // ============================================================";

   sort << "\n$Nodes ";  // mot clé de début des noeuds:
   if (sortie_des_references) 
     {sort  << "\n " << nb_total_noeud + nombre_noeud_ref_pti;} // nombre total de noeuds des éléments
   else 
     {sort  << "\n " << nb_total_noeud ;};
  
   // sortie sur le flot passé en paramètre, de la partie noeud du maillage sans entête ni fin
   Sortie_noeuds_initiaux(tab_mail,lesMail,sort);
	  
   // ---- on s'intéresse maintenant aux références de points d'intégrations s'il en existe
   // et si il est prévu de les sortir
   // on met la procédure dans un test, pour le cas où il y aurait des refs illicites donc qui ne pourraient pas se visualiser
   try
   { int dim = ParaGlob::Dimension(); // récup de la dimension
     if (sortie_des_references)
      {int num_courant_noeud_Pti = 1;
       int nbref = lesRefInitiales.Taille();
       //itab=1 donne un numéro d'ordre pour les références
       for (int itab=1;itab<=nbref;itab++)
        { const Reference* refcourante =  lesRefInitiales(itab);
          // on continu si le maillage est a sortir
          int numMail=refcourante->Nbmaille();
          if (t_a_sortir(numMail)) 
           {Tableau <Enum_geom > enum_geo; // les énuméré de la géométrie des éléments à sortir
            Tableau <Noeud *> tab_inter; // tableau de travail
            switch (refcourante->Indic())
             { case 6: // on ne s'intéresse qu'aux références de points d'intégration
                 { const ReferenceAF * ref1 = ((ReferenceAF *) refcourante);
                   int taille = ref1->Taille();
                   for (int i=1;i<=taille;i++) // on parcours la liste
                    { int numElem = ref1->NumeroElem(i);
                      int numPti = ref1->NumeroFA(i);
                      // on redimentionne au cas où 
                      Element& elem  = lesMail->Element_LesMaille(numMail,numElem); // récup de l'élément
                      // on récupère les coodonnées du point d'intégration
                      bool erreur=false;
                      Coordonnee co = elem.CoordPtInteg(TEMPS_0,SIG11,numPti,erreur);
                      if (erreur)
                       { cout << "\n erreur en recuperation des coordonnees du pt d'integ: "
                              << numPti <<" de l'element "<<numElem<<" du maillage "<< numMail;
                         cout << "\n concerne la reference de pti : " << refcourante->Nom();
                         cout << "\n la sortie gmsh ne sera pas exploitable !! ";
                         if(ParaGlob::NiveauImpression() > 2)
                           { cout << "\n Mail_initiale_Gmsh::SortieDesNoeuds(...";};
                         cout << endl;
                       }
                      else	// cas ok  
                       { sort << "\n" << num_courant_noeud_Pti+nb_total_noeud << " " ;
                         // deux cas soit on applique une pseudo-homothetie ou non
                         if (!(considerer_homothetie && t_homothetie(numMail)))
                          { // cas sans homothetie : cas classique
                            co.Affiche(sort,ParaGlob::NbdigdoGR());
                            switch (dim) // dans le cas d'une dimension diff de 3, on complète avec des 0
                             { case 1: sort << "  0.   ";
                               case 2: sort << "  0.   ";
                             };             
                          }
                         else // cas avec Homothetie
                          {Coordonnee& orig = t_orig(numMail);           // pour simplifier
                           Coordonnee& fact_mult = t_fact_mult(numMail); // pour simplifier
                           Coordonnee A(co-orig); int dim = A.Dimension();
                           switch (dim) // dans le cas d'une dimension diff de 3, on complète avec des 0
                            { case 3: A(3) *= fact_mult(3);
                              case 2: A(2) *= fact_mult(2);
                              case 1: A(1) *= fact_mult(1);
                            };             
                           A +=orig;			 
                           A.Affiche(sort,ParaGlob::NbdigdoGR()); 
                           switch (dim) // dans le cas d'une dimension diff de 3, on complète avec des 0
                            { case 1: sort << "  0.   ";
                              case 2: sort << "  0.   ";
                            };
                          };
                          num_courant_noeud_Pti++;	// cas ok
                       };
                    };
                 };
               break;
             };
           };
        };
      };
   }
   catch (ErrSortieFinale)
        // cas d'une direction voulue vers la sortie
        // on relance l'interuption pour le niveau supérieur
      { ErrSortieFinale toto;
        throw (toto);
      }
   catch (...)
   { cout << "\n **** erreur en sortie des references de noeud, l'operation a generee une erreur, sans doute une numerotation "
          << " dans le fichier d'entree de maillage ? le fichier resultat (maillage initiale) ne sera pas correct !! " << endl;
     if (ParaGlob::NiveauImpression() > 4 )
        cout << "\n Mail_initiale_Gmsh::SortieDesNoeuds(... ";
   };
  
	  // fin des noeuds
   sort << "\n$EndNodes ";

   return;
 };

// sortie uniquement des éléments, y compris les éléments points éventuellement
void Mail_initiale_Gmsh::SortieDesElements(const Tableau <int>& tab_mail,LesMaillages * lesMail
                                          ,ostream &sort)
 { // --- pour l'instant, on prend l'option de sortir comme avec Gid, tout dans un seul maillage
   // il est possible de lire plusieurs maillage avec gmsh, mais il faut qu'ils soient dans plusieurs fichiers,
   // comme la manip existe avec gid, de globaliser dans un seul fichier, par simplicité, on l'utilise
   // par contre on met des ref différentes ce qui permettra de départager au moment de la visualisation
//doc gmsh
//     $Elements
//     number-of-elements
//     elm-number elm-type number-of-tags < tag > ... node-number-list
//     ...
//     $EndElements
//  
//  number-of-tags
//   gives the number of integer tags that follow for the n-th element. By default, the first tag is the number 
//   of the physical entity to which the element belongs; the second is the number of the elementary geometrical
//   entity to which the element belongs; the third is the number of mesh partitions to which the element belongs, 
//   followed by the partition ids (negative partition ids indicate ghost cells). A zero tag is equivalent to no tag.
   
   // écriture d'une entete locale (sous maillage nb im) 
	  // (il n'est pas possible d'écrire des infos dans le corps de la liste des éléments)
   sort << "\n // ============================================================"
        << "\n // |      definition des elements des  maillages              |"
        << "\n // ============================================================";
   sort << "\n$Elements ";   

   // ----- on s'occupe du tableau de liaison entre les éléments herezh des maillages et les numéros associés de gmsh
   // ce tableau est également utilisé par d'autre classes, il est donc initialisé ici
   // t_Egmsh(im)(ie): donne pour le maillage im, et pour l'élément ie, le numéro gmsh de l'élément
   int nbmail = tab_mail.Taille();
   t_Egmsh.Change_taille(nbmail); 

   // on construit un tableau de bool, pour savoir si le maillage est à sortir ou pas
   Tableau <bool> t_a_sortir(lesMail->NbMaillage(),false);
   int nb_a_sortir = tab_mail.Taille();
   for (int isa = 1; isa <= nb_a_sortir; isa++)
     t_a_sortir(tab_mail(isa))=true;

   // -on commence par dénombrer l'ensemble des éléments des références, l'idée est ensuite de sortir des éléments correspondants
   // aux différentes références 
   // 	pour les ref de noeuds,  on définit un tableau de bool, de dimension le nombre de noeud permettant de savoir les noeuds 
   // qui sont réellement utilisé dans les références,
   Tableau <Tableau <int > > t_no_utilise(lesMail->NbMaillage());
   for (int i=1;i<=nbmail;i++)
	   t_no_utilise(tab_mail(i)).Change_taille(lesMail->Nombre_noeud(tab_mail(i)),0);

   // a) on compte le nombre d'éléments de face et segment, qui servent dans les ref
   //    et on remplit le tableau t_no_utilise
   int nb_total_elemRef = 0;
    {int nbref = lesRefInitiales.Taille();
     //itab=1 donne un numéro d'ordre pour les références
     for (int itab=1;itab<=nbref;itab++)
      { const Reference* refcourante =  lesRefInitiales(itab);
        // on continu si le maillage est a sortir
        int numMail=refcourante->Nbmaille();
        Tableau <int >& no_utilise= t_no_utilise(numMail); // pour simplifier
        if (t_a_sortir(numMail))
         {switch (refcourante->Indic()) 
          { case 3: case 4: // 3 et 4 -> surfaces et segments relatives à des éléments,
             { const ReferenceAF * ref1 = ((ReferenceAF *) refcourante);
               nb_total_elemRef += ref1->Taille();
               break;
             }
            case 1: // ref de points: ici il s'agit uniquement de remplir le tableau t_no_utilise
             { const ReferenceNE * refi = ((ReferenceNE *) refcourante);
               const Tableau<int>& tt = refi->Tab_num ();
               int taill_N = tt.Taille();
               for (int i=1;i<=taill_N;i++)
                {no_utilise(tt(i))=1;};
               break;
             }
          };
         };
      };
    };
   // b) maintenant on compte le nombre de noeud élément qu'il va falloir créer en plus
	  int nb_point_elem = 0;
	  Tableau <int > t_tail(nbmail); // contiendra les tailles pour chaque maillage des noeuds ajouté
	  for (int i=1;i<=nbmail;i++)
	   { Tableau <int >& no_utilise= t_no_utilise(tab_mail(i)); // pour simplifier
      int tail = no_utilise.Taille();
	     int t_tail_inter = 0;
	     for (int j=1;j<=tail;j++)
			   t_tail_inter += no_utilise(j);
		    // on enregistre
		    nb_point_elem += t_tail_inter;
		    t_tail(i) = t_tail_inter;
    };

   // -- sortie de l'entête --
   if (sortie_des_references)
	  // on sort le nombre total d'éléments (y compris les éléments de types noeuds, arêtes, faces etc..
    {sort  << "\n" << nb_total_element + nb_total_elemRef + nb_point_elem + nombre_noeud_ref_pti;}
	  else
	   {sort  << "\n" << nb_total_element;};
   
   //----------------------------------------------------------------
   //        cas des éléments originaux du maillage
   //----------------------------------------------------------------
  
   // sortie sur le flot passé en paramètre, de la partie élément du maillage sans entête ni fin
   Sortie_element_initiaux(tab_mail,lesMail,sort);
     
   //----------------------------------------------------------------
   //        cas des références 
   //----------------------------------------------------------------
   // --maintenant on s'occupe des références qui conduisent à définir des éléments supplémentaires (ceux qui correspondent
   // --aux références  d'arêtes, de faces: l'idée est de définir des step de visualisation: un par référence
   // pour cela on parcours l'ensemble des  ref, et on sort les infos en conséquence
   
   // on met la procédure dans un test, pour le cas où il y aurait des refs illicites donc qui ne pourraient pas se visualiser
   try
   { if (	sortie_des_references)
      {// 1-- on s'occupe des ref de face, arrete dans la première passe
     
       int num_courant_element = 1;
       int decal_ele_sup = nb_total_element; // initialisation du décalage d'éléments supplémentaires, 
       int nbref = lesRefInitiales.Taille();
       //itab=1 donne un numéro d'ordre pour les références
       for (int itab=1;itab<=nbref;itab++)
       { const Reference* refcourante =  lesRefInitiales(itab);
         bool modifier_t_Egmsh = false; // il s'agit d'éléments supplémentaire, donc on ne met pas à jour t_Egmsh
         // on continu si le maillage est a sortir
         int numMail=refcourante->Nbmaille();
         if (t_a_sortir(numMail)) 
          {int decal_noe=decal_noeud(numMail); // pour simplifier
           Tableau <Enum_geom > enum_geo; // les énuméré de la géométrie des éléments à sortir
           Tableau <Noeud *> tab_inter; // tableau de travail
           switch (refcourante->Indic())
            {case 1: case 2: // cas d'une référence d'éléments et de noeud : on ne crée pas de nouveaux éléments
              break; // car ils existent déjà pour les éléments, on les utilisera tels quels
                     // et pour les noeuds se sera l'opération 2
             case 3: // 3 -> surfaces  relatives à des éléments,
              {const ReferenceAF * ref1 = ((ReferenceAF *) refcourante);
               int taille = ref1->Taille();
               for (int i=1;i<=taille;i++) // on parcours la liste
                { int numElem = ref1->NumeroElem(i);
                  int numFace = ref1->NumeroFA(i);
                  // on redimentionne au cas où 
                  Element& elem  = lesMail->Element_LesMaille(numMail,numElem); // récup de l'élément
                  const ElemGeomC0& elgeom = elem.ElementGeometrique_const();
                  // a) construction du tableau de noeud de l'élément
                  Tableau<Noeud *>& tab_noeud = elem.Tab_noeud();
                  // le tableau de connection local, c-a-d par rapport au tableau de noeud de l'élément
                  const Tableau<int>& tlocN = elgeom.Nonf()(numFace);
                  int nbN = tlocN.Taille();
                  tab_inter.Change_taille(nbN);
                  for (int e=1;e<= nbN;e++)
                    tab_inter(e) = tab_noeud(tlocN(e));
                  // b) récup des énumérés et string décrivant la géométrie et l'interpolation
                  const ElemGeomC0 & eleface = elgeom.ElemFace(numFace);
                  SortieDunElements(true, i, sort, decal_ele_sup, tab_inter
                                     , decal_noe, eleface.TypeGeometrie(), eleface.TypeInterpolation()
                                     ,modifier_t_Egmsh, tab_num_tag(itab));
                  num_courant_element++;
                };
               decal_ele_sup += taille; // on met à jour le décalage d'éléments pour les prochaines référence
               break;
              }
             case 4: //  -> arrêtes relatives à des éléments,
              {const ReferenceAF * ref1 = ((ReferenceAF *) refcourante);
               int taille = ref1->Taille();
               for (int i=1;i<=taille;i++) // on parcours la liste
                 { int numElem = ref1->NumeroElem(i);
                   int numArrete = ref1->NumeroFA(i);
                   // on redimentionne au cas où 
                   Element& elem  = lesMail->Element_LesMaille(numMail,numElem); // récup de l'élément
                   const ElemGeomC0& elgeom = elem.ElementGeometrique_const();
                   // a) construction du tableau de noeud de l'élément
                   Tableau<Noeud *>& tab_noeud = elem.Tab_noeud();
                   // le tableau de connection local, c-a-d par rapport au tableau de noeud de l'élément
                   const Tableau<int>& tlocN = elgeom.NonS()(numArrete);
                   int nbN = tlocN.Taille();
                   tab_inter.Change_taille(nbN);
                   for (int e=1;e<= nbN;e++)
                     tab_inter(e) = tab_noeud(tlocN(e));
                   // b) récup des énumérés et string décrivant la géométrie et l'interpolation
                   const ElemGeomC0 & eleseg = elgeom.ElemSeg(numArrete);
                   SortieDunElements(true, i, sort, decal_ele_sup, tab_inter
                                      , decal_noe, eleseg.TypeGeometrie(), eleseg.TypeInterpolation()
                                      ,modifier_t_Egmsh, tab_num_tag(itab));
                   num_courant_element++;
                 };
               decal_ele_sup += taille; // on met à jour le décalage d'éléments pour les prochaines référence
               break;
              }
            };
         // on sort les éléments correspondants à la référence que l'on vient de parcourir
          
          }
          };	
    
       // 2-- on s'occupe maintenant des éléments points qu'il faut rajouter pour voir sous gmsh les références de noeud !!
       // on construit un tableau d'adressage indirecte : t_jonction_N_Nelem qui permettra d'utiliser ces noeuds éléments
       t_jonction_N_Nelem.Change_taille(lesMail->NbMaillage());
       // t_jonction_N_Nelem(i)(j) donne le numéro de noeud_élément correspondant à l'ancien numéro j pour le maillage i
       // ne sera rempli que pour les noeuds ayant conduit à la création d'un noeud_élément
     
       // pour tous les noeud_element on utilise un numero de ref qui n'exite pas, c'est celui qui suit les ref enregistrée
       // il y a un pb sous gmsh au niveau des num de ref, il semblerait qu'il ne faut pas utiliser un trop grand nombre de
       // même valeurs donc on l'incrément dans la définition des éléments tous les 50
       int num_ref_des_noeud_element = tab_num_tag.Taille() + tab_mail.Taille() + 1;
     
       for (int i=1;i<=nbmail;i++)
        t_jonction_N_Nelem(tab_mail(i)).Change_taille(lesMail->Nombre_noeud(tab_mail(i)),0);
       Tableau <Noeud *> tab_inter(1); // tableau de travail
     
       // on parcours tous les noeuds
       // on crée l'élément géométrique adoc
       GeomPoint elpoint;int num_courant=1;
       bool modifier_t_Egmsh = false;
       for (int i=1;i<=nbmail;i++)
          { int num_mail = tab_mail(i);
            int decal_noe=decal_noeud(num_mail); // pour simplifier
            Tableau <int >& no_utilise= t_no_utilise(num_mail); // pour simplifier
            int tail = no_utilise.Taille();
            for (int j=1;j<=tail;j++)
             { if (no_utilise(j))
                { if ((num_courant % 30) == 0)
                    num_ref_des_noeud_element++; // pour palier un bug de gmsh
                  tab_inter(1)= &(lesMail->Noeud_LesMaille(i,j));
                  SortieDunElements(true, num_courant, sort, decal_ele_sup, tab_inter
                                     , decal_noe, elpoint.TypeGeometrie(), elpoint.TypeInterpolation()
                                     ,modifier_t_Egmsh, num_ref_des_noeud_element);
                  t_jonction_N_Nelem(num_mail)(j) = num_courant + decal_ele_sup;
                  num_courant++;
                };
             };
          };
      
       // 3 --- enfin on s'occupe des éléments points qu'il faut rajouter pour voir sous gmsh les références de pti
       // on construit un tableau d'adressage indirecte : tab_num_tag qui permettra d'utiliser ces noeuds éléments
       t_jonction_N_NelemPti.Change_taille(nombre_ref_pti);
       // t_jonction_N_NelemPti(i)(j) donne le numéro de noeud_élément correspondant au numéro de la référence
       // ne sera rempli que pour les noeuds ayant conduit à la création d'un noeud_élément
       for (int i=1;i<=nbmail;i++)
        { int num_courant_noeud_Pti = 1;
          int num_courant_ref_Pti = 0;
          Tableau <Noeud *> tab_inter(1); // tableau de travail
          decal_ele_sup = nb_total_element + nb_total_elemRef + nb_point_elem;
          // on crée l'élément géométrique adoc
          GeomPoint elpoint;
          // on crée un noeud qui ne sert que pour son numéro de noeud
          Noeud noeu_inter(0,3,0);
          tab_inter(1) = &noeu_inter;
          bool modifier_t_Egmsh = false;
          // pour tous les noeud_element on utilise un numero de ref qui n'exite pas, c'est celui qui suit les ref enregistrée
          //	  int num_ref_des_noeud_element = tab_num_tag.Taille() + tab_mail.Taille() + 2;
          int nbref = lesRefInitiales.Taille();
          //itab=1 donne un numéro d'ordre pour les références
          for (int itab=1;itab<=nbref;itab++)
           { const Reference* refcourante =  lesRefInitiales(itab);
             // on continu si le maillage est a sortir
             int numMail=refcourante->Nbmaille();
             if (t_a_sortir(numMail))
              { Tableau <Enum_geom > enum_geo; // les énuméré de la géométrie des éléments à sortir
                switch (refcourante->Indic())
                 { case 6: // on ne s'intéresse qu'aux références de points d'intégration
                    { const ReferenceAF * ref1 = ((ReferenceAF *) refcourante);
                      int taille = ref1->Taille();
                      num_courant_ref_Pti++;
                      t_jonction_N_NelemPti(num_courant_ref_Pti).Change_taille(taille); 
                      for (int i=1;i<=taille;i++) // on parcours la liste
                       { if ((num_courant_noeud_Pti % 30) == 0)
                           num_ref_des_noeud_element++; // pour palier un bug de gmsh
                         noeu_inter.Change_num_noeud(num_courant_noeud_Pti+nb_total_noeud);
                         SortieDunElements(true, num_courant_noeud_Pti, sort, decal_ele_sup, tab_inter
                                            , 0, elpoint.TypeGeometrie(), elpoint.TypeInterpolation()
                                            ,modifier_t_Egmsh, num_ref_des_noeud_element);
                         t_jonction_N_NelemPti(num_courant_ref_Pti)(i)=num_courant_noeud_Pti+decal_ele_sup;
                         num_courant_noeud_Pti++;
                       };
                    };
                   break;
                 };
              };
           };
         };

     }; // fin de la sortie conditionelle sur les références
   }
   catch (ErrSortieFinale)
        // cas d'une direction voulue vers la sortie
        // on relance l'interuption pour le niveau supérieur
      { ErrSortieFinale toto;
        throw (toto);
      }
   catch (...)
   { cout << "\n **** erreur en sortie des references d'elements, l'operation a generee une erreur, sans doute une numerotation "
          << " dans le fichier d'entree de maillage ? le fichier resultat (maillage initiale) ne sera pas correct !! " << endl;
     if (ParaGlob::NiveauImpression() > 4 )
        cout << "\n Mail_initiale_Gmsh::SortieDesElements(... ";
   };
    
   sort << "\n$EndElements";
   // et on vide le buffer de sortie
   sort << endl; 
  };

// sortie des références
void Mail_initiale_Gmsh::SortieReferences(const Tableau <int>& tab_mail,LesMaillages * lesMail 
                           ,UtilLecture & entreePrinc)
{  // en fait chaque référence est sortie sous forme d'un step de data
//   ostream &sort = entreePrinc.Sort_initial_Gmsh();
   // on construit un tableau de bool, pour savoir si le maillage est à sortir ou pas
   Tableau <bool> t_a_sortir(lesMail->NbMaillage(),false);
   int nb_a_sortir = tab_mail.Taille();
   for (int isa = 1; isa <= nb_a_sortir; isa++)
     t_a_sortir(tab_mail(isa))=true;

// debug
//fin debug

   int itab_pti=1; // donne un numéro d'ordre pour les références de pti
   int decal_eleRef = nb_total_element;

   int nbref = lesRefInitiales.Taille();
   //itab=1 donne un numéro d'ordre pour les références
   for (int itab=1;itab<=nbref;itab++)
    {const Reference* refcourante =  lesRefInitiales(itab);
     // on continu si le maillage est a sortir
     int numMail=refcourante->Nbmaille();
     if (t_a_sortir(numMail)) 
      {int decal_ele =decal_element(numMail);
       Tableau <Enum_geom > enum_geo; // les énuméré de la géométrie des éléments à sortir
       Tableau <Noeud *> tab_inter; // tableau de travail
       // on commence par définir le fichier de sortie: soit un seul fichier, soit plusieurs fichiers
       ostream * sortinter=NULL; // variable intermédiaire de travail
       if (sortie_des_references==2) // cas de fichier indépendant
           {sortinter = &(entreePrinc.Sort_resultat_Gmsh(tab_nom_tag_ref(itab)));
            // on est obligé de sortir les noeuds et éléments pour définir le maillage à sortir en rajoutant des éléments noeuds
            SortieDesNoeuds(tab_mail,lesMail,*sortinter);
            SortieDesElements(tab_mail,lesMail,*sortinter);
           }
       else 
           {sortinter = &(entreePrinc.Sort_initial_Gmsh());};
       ostream &sort = *sortinter;
       // écriture d'une entete locale (sous maillage nb im) 
       // (il n'est pas possible d'écrire des infos dans le corps de la liste des éléments)
       sort << "\n // ============================================================"
            << "\n // |         references relies aux   maillages                |"
            << "\n // ============================================================";
       switch (refcourante->Indic())
        {case 1:  // cas d'une référence de noeud
            { const ReferenceNE * refi =  ((ReferenceNE *) refcourante);
              const Tableau<int>& tt = refi->Tab_num ();
              int taill_N = tt.Taille();
        
              sort << "\n // ============================================================"
                   << "\n // |         "<<tab_nom_tag_ref(itab) << "           |"
                   << "\n // ============================================================";
              sort << "\n$ElementData "; // l'entête
  //    $ElementData
  //     number-of-string-tags
  //     < "string-tag" >
  //     ...
  //     number-of-real-tags
  //     < real-tag >
  //     ...
  //     number-of-integer-tags
  //     < integer-tag >
  //     ...
  //     elm-number value ...
  //     ...
  //     $EndElementData				  
             sort << "\n1 \n\"" << tab_nom_tag_ref(itab)<<"\""
                  << "\n0  \n3 \n" << itab << "\n1 \n" << taill_N;
             for (int ine = 1;ine<=taill_N;ine++)
                sort << "\n" << t_jonction_N_Nelem(numMail)(tt(ine))  << " " << 1. << " ";
             sort << "\n$EndElementData "; // fin
             break;
            }
         case 2:  // cas d'une référence d'élément
           { const ReferenceNE * refi =  ((ReferenceNE *) refcourante);
             const Tableau<int>& tt = refi->Tab_num ();
             int taill_N = tt.Taille();
           
             sort << "\n // ============================================================"
                  << "\n // |         "<<tab_nom_tag_ref(itab) << "           |"
                  << "\n // ============================================================";
             sort << "\n$ElementData "; // l'entête
   //    $ElementData
   //     number-of-string-tags
   //     < "string-tag" >
   //     ...
   //     number-of-real-tags
   //     < real-tag >
   //     ...
   //     number-of-integer-tags
   //     < integer-tag >
   //     ...
   //     elm-number value ...
   //     ...
   //     $EndElementData				  
             sort << "\n1 \n\"" << tab_nom_tag_ref(itab)<<"\""
                  << "\n0  \n3 \n" << itab << "\n1 \n" << taill_N;
             for (int ine = 1;ine<=taill_N;ine++)
                sort << "\n" << tt(ine) + decal_ele << " " << 1. << " ";
             sort << "\n$EndElementData "; // fin
             break;
           }
         case 3: case 4:  // cas d'une référence de face ou segment
           { const ReferenceAF * ref1 =  ((ReferenceAF *) refcourante);
             int taille = ref1->Taille();				  
             sort << "\n // ============================================================"
                  << "\n // |         "<<tab_nom_tag_ref(itab) << "           |"
                  << "\n // ============================================================";
             sort << "\n$ElementData "; // l'entête
  //    $ElementData
  //     number-of-string-tags
  //     < "string-tag" >
  //     ...
  //     number-of-real-tags
  //     < real-tag >
  //     ...
  //     number-of-integer-tags
  //     < integer-tag >
  //     ...
  //     elm-number value ...
  //     ...
  //     $EndElementData				  
             sort << "\n1 \n\"" << tab_nom_tag_ref(itab)<<"\""
                  << "\n0  \n3 \n" << itab << "\n1 \n" << taille;
             for (int ine = 1;ine<=taille;ine++)
                sort << "\n" << ine + decal_eleRef << " " << 1. << " ";
             sort << "\n$EndElementData "; // fin
             decal_eleRef += taille; // on met à jour le décalage d'éléments pour les prochaines référence
             break;
           }
         case 6:  // cas d'une référence de points d'intégration
           { const ReferenceAF * ref1 =  ((ReferenceAF *) refcourante);
             int taille = ref1->Taille();
             sort << "\n // ============================================================"
                  << "\n // |         "<<tab_nom_tag_ref(itab) << "           |"
                  << "\n // ============================================================";
             sort << "\n$ElementData "; // l'entête
  //    $ElementData
  //     number-of-string-tags
  //     < "string-tag" >
  //     ...
  //     number-of-real-tags
  //     < real-tag >
  //     ...
  //     number-of-integer-tags
  //     < integer-tag >
  //     ...
  //     elm-number value ...
  //     ...
  //     $EndElementData				  
             sort << "\n1 \n\"" << tab_nom_tag_ref(itab)<<"\""
                  << "\n0  \n3 \n" << itab << "\n1 \n" << taille;
             for (int ine = 1;ine<=taille;ine++)
                 {sort << "\n" << t_jonction_N_NelemPti(itab_pti)(ine) << " " << 1. << " ";}
             sort << "\n$EndElementData "; // fin
             itab_pti++; // incrémente le nombre courant de ref pti pour la prochaine
             break;
           }
        };
      };
    };

};								
 
// choix de l'ordre, cet méthode peut entraîner la demande d'informations
// supplémentaires si nécessaire. qui sont ensuite gérer par la classe elle même
void Mail_initiale_Gmsh::ChoixOrdre()
{ // demande de précision
  bool choix_valide = false;
  cout << "\n ----> preparation de la visualisation des coordonnees initiales "
       << "\n  parametre par defaut ? : resultat brut du calcul elements finis ,"
       << "\n                           pas d'homotheties sur les coordonnees initiales ,"
       << "\n                           sortie des references dans un seul fichier,"
       << "\n  ---> (rep 'o') pour accepter ces parametres sinon autre ";
  string rep;
  cout << "\n reponse ? "; rep = lect_return_defaut(true,"o");
  if (rep == "o") 
	  {considerer_homothetie=false; 	   
	   sortie_des_references=1;cout << "\n";
		 }
  else
   {// cas d'un choix autre que standart
	  	int nbmail = t_homothetie.Taille(); // le nombre de maillage
	   for (int imail = 1; imail <= nbmail; imail++)
	    { cout << "\n --- cas du maillage numero: "<< imail ;
         choix_valide=false;
         while (!choix_valide)
          {try 
            { cout << "\n (0 ou f) fin modif"
                   << "\n (1) isometries sur les coordonnees initiales ?  "               
                   << "\n (2) sortie des references dans un seul fichier ou aucune ref ?  "               
                   << "\n (3) sortie des ref dans des fichiers separes ou aucune ?  ";               
              cout << "\n \n reponse ? ";
              rep = lect_return_defaut(false,"f");
              if (rep == "fin_prog") Sortie(1);
              // sinon
              int num = ChangeEntier(rep);
              if ((num == 0) || (rep == "f")){choix_valide=true;}
              else if ((num > 0)&&(num < 4))
               { choix_valide=false;
		               considerer_homothetie = true;
                 switch (num)
                  { case 1:  // isometries sur les coordonnees initiales ?  ";
                     {bool choix_val = false;
					                 cout << "\n ---- definition d'une pseudo-homothetie sur les axes ---- ";
					                 string rep;
					                 while (!choix_val)
					                  { // on récupère la dimension
                         int dim = ParaGlob::Dimension();
					                    cout << "\n (0 ou f ou fin) fin modif"
					                         << "\n (1) def de l'origine de la pseudo-homothetie "
					                         << "\n (2) def des rapports d'homothetie selon les axes";
					                         cout << "\n \n reponse ? ";
					                    rep = lect_return_defaut(false,"f");
					                    // sinon
					                    if ((rep == "0")||(rep == "f")||(rep == "fin"))
					                      { choix_val=true; }
                         else
                           { // initialisation
                             t_homothetie(imail)=true;
                             t_orig(imail).Change_dim(dim);t_orig(imail).Zero();
                             t_fact_mult(imail).Change_dim(dim);t_fact_mult(imail).Zero();
                             t_fact_mult(imail).Ajout_meme_valeur(1.); // par défaut
                             if (rep=="1")
                              { cout << "\n donner l'origine de la pseudo-homothetie ("
                                     << dim << ") reels ? ";
								                        t_orig(imail).Lecture();		 
                               }
                             else if (rep =="2")
                               { cout << "\n donner les rapports d'homothetie selon les axes ("
                                      << dim << ") reels ? ";
								                         t_fact_mult(imail).Lecture();		 
                                }
                             else
                                { cout << "\n Erreur on attendait un entier entre 0 et 2 !!, "
                                       << "\n redonnez une bonne valeur";
                                  choix_val=false;
                                };
                           };
                       }; //-- fin du while
                      break;
                     }
                    case 2:  // sortie des références dans un seul fichier
                     {bool choix_val = false;
                      cout << "\n -- par defaut on sort les references, ce qui entraine la creation "
                           << " de noeuds, elements (points, lignes et surfaces) supplementaires au "
                           << " maillage initiale, ceci dans un seul fichier ";
                      string rep;
                      while (!choix_val)
					                   { cout << "\n (0 ou f ou fin) fin modif"
					                          << "\n (1) sortie des references dans un fichier unique, pour visualisation "
					                          << "\n (2) pas de sortie des references ";
                          cout << "\n \n reponse ? ";
					                     rep = lect_return_defaut(false,"f");
					                     // sinon
					                     int num = ChangeEntier(rep);
					                     if ((rep == "0")||(rep == "f")||(rep == "fin"))
					                       { choix_val=true; }
                          else
					                       { // def du format
							                       if (num == 1) { sortie_des_references = 1;}
                              else if (num == 2) { sortie_des_references = 0;}
                              else 
								                       { cout << "\n Erreur on attendait un entier entre 0 et 2 !!, "
										                            << "\n redonnez une bonne valeur";
								                         choix_val=false;
								                       };
                             };
                        }; //-- fin du while
                      break;	
                     }
                    case 3:  // sortie des références dans des fichiers sépararés
					                {bool choix_val = false;
                      cout << "\n -- par defaut on sort les references, ce qui entraine la creation "
                           << " de noeuds, elements (points, lignes et surfaces) supplementaires au "
                           << " maillage initiale, ceci dans un seul fichier ";
                      string rep;
                      while (!choix_val)
					                   { cout << "\n (0 ou f ou fin) fin modif"
					                          << "\n (1) sortie des references dans des fichiers separes, pour visualisation "
					                          << "\n (2) pas de sortie des references ";
					                          cout << "\n \n reponse ? ";
					                     rep = lect_return_defaut(false,"f");
					                     // sinon
					                     int num = ChangeEntier(rep);
					                     if ((rep == "0")||(rep == "f")||(rep == "fin"))
					                       { choix_val=true; }
                          else
							                     { // def du format
							                       if (num == 1) { sortie_des_references = 2;}
                               else if (num == 2) { sortie_des_references = 0;}
                               else 
								                        { cout << "\n Erreur on attendait un entier entre 0 et 2 !!, "
										                             << "\n redonnez une bonne valeur";
								                          choix_val=false;
								                        };
                            };
                        }; //-- fin du while
                      break;	
                     }
                  } // fin du switch (num)
               } // fin du else if ((num > 0)&&(num < 3))				  
              else { cout << "\n Erreur on attendait un entier entre 0 et 3 (ou f) !!, "
                          << "\n redonnez une bonne valeur"
								                  << "\n ou taper fin_prog pour arreter le programme"; 
                     choix_valide=false;
                   };
            }    
           catch (ErrSortieFinale)
                // cas d'une direction voulue vers la sortie
                // on relance l'interuption pour le niveau supérieur
              { ErrSortieFinale toto;
                throw (toto);
              }
           catch (...)// erreur de lecture
            {  cout << "\n Erreur on attendait un des mots cles proposés !!, "
						              << "\n redonnez une bonne valeur"
						              << "\n ou taper fin_prog pour arreter le programme"; 
               choix_valide=false;
            };
          }; //-- fin du while
		   }; //-- fin du for(in imail 	  
   }; //-- fin du if (rep != "o") du départ c'est-à-dire du cas non standart
  // appel de la méthode de la classe mère
  OrdreVisu::ChoixOrdre();    
};     
            
    
// lecture des paramètres de l'ordre dans un flux
void Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(UtilLecture & entreePrinc)
 { // si dans le flot il existe l'identificateur adoc on lit sinon on passe
   if (strstr(entreePrinc.tablcarCVisu,"debut_maillage_initial")!=NULL)
     {// sauvegarde des paramètres  actuelles pour l'homothetie
	   bool considerer_homothetie_sauve = considerer_homothetie; 
	   Tableau < bool > t_homothetie_sauve(t_homothetie) ; 
	   Tableau <Coordonnee > t_orig_sauve(t_orig),t_fact_mult_sauve(t_fact_mult); 
		int nb_maillage = t_orig.Taille();
      // essaie de lecture
      try 
        { string nom; 
          (*entreePrinc.entCVisu) >> nom ;
          if (nom != "debut_maillage_initial")
            { cout << "\n Erreur en lecture des parametres du maillage initial a partir d'un fichier .CVisu,"
                   << " le premier enregistrement doit etre le mot clef: debut_maillage_initial "
                   << " on ne tiens pas compte  des parametres fournies !! ";
              }
          else
           { // appel de l'ordre de la classe mère
             OrdreVisu::Lect_para_OrdreVisu_general(entreePrinc);
             while (strstr(entreePrinc.tablcarCVisu,"fin_maillage_initial")==NULL)
				          {if (strstr(entreePrinc.tablcarCVisu,"pseudo-homothetie_sur_les_maillages_")!=NULL)
					           {(*entreePrinc.entCVisu) >> nom >> considerer_homothetie;
                 if (nom != "pseudo-homothetie_sur_les_maillages_")
                  { cout << "\n lecture de la pseudo-homothetie globale, on a lue ( "<< nom 
                         << " ) et on attendait pseudo-homothetie_sur_les_maillages_"
                         << " la suite de la lecture du .CVisu risque d'etre completement fausse, on arrete !!" ; 
                    cout << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(... ";
                    UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
                  };
				             if (considerer_homothetie)
                  { // cas où on veut considérer des homothétie
                    entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
                    // lecture du numéro de maillage
                    int imail = 0; // le numéro de maillage
                    (*entreePrinc.entCVisu) >> nom >> imail;
                    if (nom != "maillage_")
                     { cout << "\n lecture du num de maillage, on a lue ( "<< nom
                            << " ) et on attendait maillage_ "
									                   << " la suite de la lecture du .CVisu risque d'etre completement fausse, on arrete !!" ;
                       cout << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(... ";
                       UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
                     };
                   if ((imail > nb_maillage)||(imail < 1)) // vérif de la validité du numéro de maillage
                     // si nb maillage trop grand, erreur, on génère une erreur pour arrêter la lecture
                     { cout << "\n erreur, le numero de maillage est errone !! nombre lu " << imail 
                            << " alors que nb_maillage enregistre: " << nb_maillage ;
                       cout << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(... ";     
                       UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
                     };
                   entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
                   // le fait qu'il y a une pseudo-homothétie pour ce maillage ou nom	  
                   (*entreePrinc.entCVisu) >> nom >> t_homothetie(imail);
                   if (nom != "pseudo-homothetie_")
                    { cout << "\n lecture de la pseudo-homothetie, on a lue ( "<< nom 
						                     << " ) et on attendait pseudo-homothetie_ "
								                   << " la suite de la lecture du .CVisu risque d'etre completement fausse, on arrete !!" ;
                      cout << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(... ";     
                      UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
                    };
                   // lecture conditionnelle des paramètres
					              if (t_homothetie(imail))
						              { // lecture du centre
                      entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement 
						                (*entreePrinc.entCVisu) >> nom >> t_orig(imail);
							               if (nom != "centre_homothetie_")
                       { cout << "\n lecture du centre de la pseudo-homothetie, on a lue ( "<< nom 
							                       << " ) et on attendait centre_homothetie_ "
									                     << " la suite de la lecture du .CVisu risque d'etre completement fausse, on arrete !!" ;
                         cout << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(... ";     
                         UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
                       };
						                // lecture des coeffs
                      entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement 
						                (*entreePrinc.entCVisu) >> nom >> t_fact_mult(imail);
							               if (nom != "fact_mult_")
                       { cout << "\n lecture du centre des facteurs, on a lue ( "<< nom 
							                       << " ) et on attendait fact_mult_ "
									                     << " la suite de la lecture du .CVisu risque d'etre completement fausse, on arrete !!" ;
                         cout << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(... ";
                         UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
                       };
                    };
					              entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
                  }
					            else
                  {entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
//					   break;
					             };
					           } // fin du if existe pseudo-homothetie_sur_les_maillages_
				   else if (strstr(entreePrinc.tablcarCVisu,"visualisation_references_sur_les_maillages_")!=NULL)
					 {(*entreePrinc.entCVisu) >> nom >> sortie_des_references;
					  if (nom != "visualisation_references_sur_les_maillages_")
					   { cout << "\n lecture de l'indicateur de visualisation des references, on a lue ( "<< nom 
								<< " ) et on attendait visualisation_references_sur_les_maillages_"
								<< " la suite de la lecture du .CVisu risque d'etre completement fausse, on arrete !!" ; 
						  cout << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(... ";     
                       UtilLecture::ErrNouvelEnregCVisu sortie(-1) ; throw (sortie);
						}
					  else // sinon c'est ok
					   {entreePrinc.NouvelleDonneeCVisu();}; // on passe un enregistrement
//					 break;
					 } // fin du if visualisation_references_sur_les_maillages_
					else 
					 {entreePrinc.NouvelleDonneeCVisu();};
					}; // fin du while
             entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
            } // -- fin du if then else sur "debut_maillage_initial"       
         } // -- fin du try    
      catch (ErrSortieFinale)
           // cas d'une direction voulue vers la sortie
           // on relance l'interuption pour le niveau supérieur
         { ErrSortieFinale toto;
           throw (toto);
         }
      catch (...)// erreur de lecture
       {  cout << "\n Erreur en lecture des parametres du maillage initial a partir d'un fichier .CVisu,"
               << " on ne tiens pas compte  des parametres fournies !! ";
          // récup des infos  sauvées
          if (ParaGlob::NiveauImpression() >= 4)     
             cout  << "\n Mail_initiale_Gmsh::Lecture_parametres_OrdreVisu(..";
          // récup des infos  sauvées
	       considerer_homothetie = considerer_homothetie_sauve ; 
	       t_homothetie = t_homothetie_sauve ; 
	       t_orig = t_orig_sauve,t_fact_mult = t_fact_mult_sauve;
			 sortie_des_references=1;
			 	 
        }
      } 
  };

// écriture des paramètres de l'ordre dans un flux
void Mail_initiale_Gmsh::Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc)
{// récup du flot  
 ostream & sort = (*(entreePrinc.Sort_CommandeVisu()));
 // on commente le fonctionnement
 sort << "\n #  ----------------------------- definition des parametres du maillage initial: ---------------- "
      << "\n debut_maillage_initial  #  un mot cle de debut de liste ";
 // appel de l'ordre de la classe mère
 OrdreVisu::Ecrit_para_OrdreVisu_general(entreePrinc);
 // puis les paramètres
	sort << "\n pseudo-homothetie_sur_les_maillages_ " << considerer_homothetie << "  # 0 = aucune homothetie, 1 = il y en a ";
	// --- partie relative à une pseudo-homotétie sur les coordonnées initiales
	sort << "\n # --- def eventuelle de la pseudo-homothetie: une par maillage,  ";
	int nbmail = t_homothetie.Taille(); // le nombre de maillage
   for (int imail = 1; imail <= nbmail; imail++)
	  { sort << "\n #  pseudo-homothetie pour le maillage : " << imail;
	    if (considerer_homothetie)
	     {sort << "\n maillage_ "<< imail  << "\n # mot cle: maillage_  puis le numero du maillage, " ;}
		   else
		    {sort << "\n# maillage_ "<< imail  << "\n # mot cle: maillage_  puis le numero du maillage, " ;};
		  
		   // puis y-a-t-il une pseudi-homothétie sur ce maillage ou non   
	    if (considerer_homothetie)
	     {sort << "\n pseudo-homothetie_ " << t_homothetie(imail) << "  # 0 = non active, 1 = active ";}
		   else
		    {sort << "\n# pseudo-homothetie_ " << t_homothetie(imail) << "  # 0 = non active, 1 = active ";}; 
		   sort << "\n # ensuite si c'est active, on trouve : "
		        << "\n # mot cle: centre_homothetie_  puis les coordonnees du centre d'homothetie "
		        << "\n # puis mot cle: fact_mult_ puis les coordonnees donnant les coefs multiplicatifs selon les axes.  ";
     if (considerer_homothetie)
	     {if (t_homothetie(imail))
	      { sort << "\n centre_homothetie_ " << t_orig(imail);
	        sort << "\n fact_mult_ " << t_fact_mult(imail);
	       };
			   }
     else
	      { sort << "\n# centre_homothetie_ " ;
	        sort << "\n# fact_mult_ " ;
       };
   };
   // --- fin pseudo-homotétie 
	
	sort << "\n visualisation_references_sur_les_maillages_ " << sortie_des_references 
	     << "  # 0 = pas de visualisation des reference, 1 = sortie des ref dans fichier unique "
      << "  2= sortie des ref dans plusieurs fichiers ";
 // fin -- sortie des références
							       
 sort << "\n fin_maillage_initial " << " #   le mot cle de fin  \n";
};
                            
// constitution des sous maillages, utilisé par les isovaleurs par exemple
// on suit la même logique que dans gid, un sous maillage par type d'élément
// ce n'est pas nécessaire, c'est pas simplicité, à modifier si nécessaire par la suite
void Mail_initiale_Gmsh::CreaSousMaillages(const Tableau <int>& tab_mail,LesMaillages * lesMail)                      
  {// on boucle sur les maillages
   int nbmail = tab_mail.Taille();
   for (int im=1;im<=nbmail;im++)
    { int numMail=tab_mail(im);
      // on cherche tout d'abord le nombre d'éléments différents dans le maillage     
      List_io <Element::Signature>& li_sig_elem=tabli_sig_elem(numMail);
      li_sig_elem.erase(li_sig_elem.begin(),li_sig_elem.end());
      // on initialise également tabli_sous_mesh(numMail)
      tabli_sous_mesh(numMail).erase(tabli_sous_mesh(numMail).begin(),tabli_sous_mesh(numMail).end());
      // on balaie tous les éléments du maillage
      int nbmaxiElement = lesMail->Nombre_element(numMail);
      List_io <Element::Signature>::iterator ipos;
      for (int numElem=1; numElem<= nbmaxiElement;numElem++) 
        { // recup de la signature de l'élément
          Element::Signature  sig_elem = lesMail->Element_LesMaille(numMail,numElem).Signature_element();
          // on regarde s'il existe déjà
          ipos = find(li_sig_elem.begin(),li_sig_elem.end(),sig_elem);
          if (ipos == li_sig_elem.end()) // enregistrement s'il n'existe pas
               li_sig_elem.push_back(sig_elem);
          };
//cout << " fin du balaie de tous les éléments  " << endl;
      // dimensionne le tableau de sous maillages    
      tabtab_sous_mesh(numMail).Change_taille(li_sig_elem.size());   
      // simplification et préparation
      Tableau < List_io <  Element* > >& tab_sous_mesh = tabtab_sous_mesh(numMail);
//cout << " simplification et préparation  " << endl;
       
      // maintenant on boucle sur les types d'éléments
      List_io <Element::Signature>::iterator ifin=li_sig_elem.end();
      int num_type = 1;
      for (ipos= li_sig_elem.begin();ipos!=ifin;ipos++,num_type++)
       { // initialisation
//cout << " num_type=  " << num_type << endl;
         tab_sous_mesh(num_type).erase(tab_sous_mesh(num_type).begin(),tab_sous_mesh(num_type).end());
//cout << " tab_sous_mesh(num_type).erase  "  << endl;
         // création du nom du sous maillage 
         ostrstream tab_out;
         tab_out << lesMail->NomMaillage(numMail) << "_" << num_type << ends;
//cout << " tab_out << lesMail->NomMaillage(numMail)  "  << endl;
         string nom_sous_maillage = tab_out.str() ;  // le nom
//cout << " nom_sous_maillage=  " << nom_sous_maillage << endl;
//cout << " numMail= " << numMail << " tabli_sous_mesh.Taille()= " << tabli_sous_mesh.Taille() << endl;
//cout << " le tableau " << tabli_sous_mesh(1) << endl;
//nom_sous_maillage="toto";
         tabli_sous_mesh(numMail).push_back(nom_sous_maillage); // sauvegarde
//cout << " tabli_sous_mesh(numMail).push_back(nom_sous_maillage)  "  << endl;
         // définition du type d'élément
//cout << " définition du type d'élément  "  << endl;

         int nbmaxiElement = lesMail->Nombre_element(numMail);
         for (int numElem=1; numElem<= nbmaxiElement;numElem++) 
          { // recup de l'élément
//cout << " numElem=  "  << numElem << endl;
            Element & elem = lesMail->Element_LesMaille(numMail,numElem);
            // si c'est la bonne signature on sort l'élément
            if (elem.Signature_element() == *ipos)
              // on sauvegarde la ref à l'élément
              tab_sous_mesh(num_type).push_back(&elem);
          };
       }; // -- fin de la boucle sur les types différents de signatures
//cout << " fin de la boucle sur les types différents de signatures  " << endl;
    
    };//-- fin de la boucle sur les maillages
//cout << " fin de la boucle sur les maillages  " << endl;
  };
           
// sortie éventuelle d'un seul élément au format gmsh
// et modification éventuelle du tableau t_Egmsh
// num_elem : numero initial de l'élément
// decal_ele : décalage de numéro pour tenir compte de la présence de plusieurs maillages (ou sous maillages)
// decal_noe : décalage de numéro de noeud, pour tenir compte de la présence de plusieurs maillages
// tab_noeud : le tableau des noeuds de la connection
// id_geom et id_interpol : permettent de repérer un type d'élément fini associé (donc pas seulement géométrique)
//                        : il s'agit ici de la géométrie et interpolation "élément fini"  
// sort  : flux de sortie
// modifier_t_Egmsh : indique si pour l'élément considéré, on abonde le tableau t_Egmsh
//                    si oui c'est un vrai élément, sinon, c'est un élément de référence,
//                    l'indicateur est utiliser dans ce sens
// im : si modifier_t_Egmsh est vrai : num du maillage ou sous maillage
//      si modifier_t_Egmsh est faux : numéro de la référence associée
// elem_a_sortir : indique si pour l'élémen considéré, on le sort dans le fichier gmsh
void Mail_initiale_Gmsh::SortieDunElements(bool elem_a_sortir, const int& num_elem
                      , ostream &sort, const int& decal_ele, Tableau<Noeud *>& tab_noeud
                      , const int& decal_noe, Enum_geom id_geom, Enum_interpol id_interpol
                      , bool modifier_t_Egmsh , int im)
{
         
          // rappel des types d'éléments gérés par gmsh         
//         'rien pour le  numero 0',                       # '0' 
//         'segment lineaire a 2 noeuds' ,   	           # '1' 
//         'triangle lineaire a 3 noeuds' ,	               # '2' 
//         'quadrangle bilineaire a 4 noeuds' ,            # '3' 
//         'tetrahedre lineaire a 4 noeuds' ,	           # '4' 
//         'hexahedre trilineaire a 8 noeuds' ,            # '5' 
//         'pentaedre bilineaire a 6 noeuds' ,	           # '6' 
//         'pyramide a 5 noeuds' ,		                   # '7' 
//         'segment quadratique a 3 noeuds' ,	           # '8' 
//         'triangle quadratique a 6 noeuds' ,	           # '9' 
//         'quadrangle quadratique complet a 9 noeuds' ,   #'10'  
//         'tetraedre quadratique a 10 noeuds' , 	       #'11'  
//         'hexaedre quadratique complet a 27 noeuds' ,	   #'12'  
//         'pentaedre quadratique complet a 18 noeuds' ,   #'13'  
//         'pyramide quadratique a 14 noeuds' ,		       #'14'  
//         '  point a 1 noeud ' ,			               #'15'  
//         'quadrangle quadratique incomplet a 8 noeuds' , #'16'  
//         'hexaedre quadratique incomplet a 20 noeuds' ,  #'17'  
//         'pentaedre quadratique incomplet a 15 noeuds' , #'18'  
//         'pyramide quadratique incomplete a 13 noeuds'   #'19'  
         
   // maintenant on sort le type  d'élément
   bool erreur = false; // pas d'erreur par défaut
   int num_elem_gmsh = 0; // le numéro de numérotation gmsh
   int nb_noeud_centraux = 0; // ne sert que pour les SFE
   switch (id_geom)
     { case TRIANGLE : case TRIA_AXI:
         {switch (id_interpol)
           { case LINEAIRE :   { num_elem_gmsh= 2 ;  break;}
			          case QUADRACOMPL :{ num_elem_gmsh= 9 ;  break;}
		           case SFE3C : case SFE3 : case SFE2: case SFE1 : 
		           case SFE3C_3D : case SFE3_3D : case SFE2_3D: case SFE1_3D :
		               { num_elem_gmsh= 2 ;nb_noeud_centraux = 3;
                   break;} // on ne considère que les noeuds centraux
             case QSFE1 : case QSFE3:
                { num_elem_gmsh= 9 ; nb_noeud_centraux = 6;
                  break;} // on ne considère que les noeuds centraux
			          default : erreur = true;
           }
          break;
         }
			    case QUADRANGLE :   case QUAD_AXI:
			      {switch (id_interpol)
           { case LINEAIRE :    {num_elem_gmsh= 3 ; break;}
			          case QUADRATIQUE : {num_elem_gmsh= 16 ; break;}
			          case QUADRACOMPL : {num_elem_gmsh= 10 ; break;}
			          default : erreur = true;
           }
          break;
         }
			    case TETRAEDRE : 
         {switch (id_interpol)
           {case LINEAIRE :    {num_elem_gmsh= 4 ; break;}
		          case QUADRACOMPL : {num_elem_gmsh= 11 ; break;}
		          default : erreur = true;
           }
		        break;
         }
       case HEXAEDRE :
         {switch (id_interpol)
           {case LINEAIRE :    {num_elem_gmsh= 5 ; break;}
		          case QUADRATIQUE : {num_elem_gmsh= 17 ; break;}
		          case QUADRACOMPL : {num_elem_gmsh= 12 ; break;}
		          default : erreur = true;
           }
          break;
         }
       case POUT : case SEGMENT : case SEG_AXI:
         {switch (id_interpol)
            {case BIE1  :       num_elem_gmsh= 1 ; break;
             case LINEAIRE :    num_elem_gmsh= 1 ; break;
             case QUADRATIQUE : case BIE2 : num_elem_gmsh= 8 ; break;
             case QUADRACOMPL : num_elem_gmsh= 8 ; break;
             default : erreur = true;
            }
          break;
         }
       case POINT : num_elem_gmsh= 15 ; break;
       case PENTAEDRE :
         {switch (id_interpol)
           {case LINEAIRE :    {num_elem_gmsh= 6 ; break;}
		          case QUADRATIQUE : {num_elem_gmsh= 18 ; break;}
		          case QUADRACOMPL : {num_elem_gmsh= 13 ; break;}
		          default : erreur = true;
           }
          break;
         }
       default :
		   	   cout << "\nErreur : cas d'element non traite par Gmsh !" 
		   	        << Nom_geom(id_geom) << " " << Nom_interpol(id_interpol) 
			        << " **********  attention, le fichier de sortie ne sera pas exploitable !!!\n";
     };
   if (erreur)
	         cout << "\nErreur : cas d'element + interpolation non traite par Gmsh !" 
                  << Nom_geom(id_geom)
                  << " " <<  Nom_interpol(id_interpol) 
                  << " **********  attention, le fichier de sortie ne sera pas exploitable !!!\n";

   // --- traitement du tableau t_Egmsh
   if (modifier_t_Egmsh) // ne concerne que les vrais éléments, donc test pour différencier avec les elem de ref
		        t_Egmsh(im)(num_elem)=num_elem_gmsh; // enreg pour construire le tableau t_Egmsh 
                                                     // utilisée pour la sortie d'isovaleur et la déformée  
   // ---- sortie fichier gmsh
   // récup de la connection herezh->gmsh
   // t_GmshHer(i)(j) : donne pour le noeud j de l'élément i de gmsh, le numéro d'herezh  
   const Tableau < Tableau < int > >& tGmshHer = Visualisation_Gmsh::Tab_GmshHer();
   if (elem_a_sortir)
     { sort << "\n" << num_elem + decal_ele << " " // numéro d'élément
                      << " " << num_elem_gmsh << " "; // sortie du type d'élément gmsh
       // sortie du nombre de tag et des deux premiers tags principaux
       if (modifier_t_Egmsh)
         { sort << " " << 3 << " " << im << " " << num_elem << " 0 " ;}
       else
		       { sort << " " << 3 << " " << im << " " << im << " 0 " ;};
  
       // on sort les éléments la connection
       int nb_n = tab_noeud.Taille();
       if (ElementSfe(id_interpol))
          // dans le cas des sfe on ne sort que les noeuds du centre
          {for (int j=1;j<=nb_noeud_centraux;j++) // les noeuds centraux
							      { int num_her = tGmshHer(num_elem_gmsh)(j);
							        sort << tab_noeud(num_her)->Num_noeud()+decal_noe << " ";
             };
          }
       else
						    // cas normal
          {for (int j=1;j<=nb_n;j++) // j = gmsh
              {int num_her = tGmshHer(num_elem_gmsh)(j); // num HZ correspondant
               sort << tab_noeud(num_her)->Num_noeud()+decal_noe << " ";
              };
          };

     };
};

// sortie sur le flot passé en paramètre, de la partie noeud du maillage sans entête ni fin
void Mail_initiale_Gmsh::Sortie_noeuds_initiaux(const Tableau <int>& tab_mail
            ,LesMaillages * lesMail, ostream &sort)
{  int dim = ParaGlob::Dimension(); // récup de la dimension
   // on boucle sur les maillages
   int nbmail = tab_mail.Taille();

//   // on recalcule les décalages de noeuds en fonction des maillages actifs, car c'est utilisé par les isovaleurs et autres
//   // ordres, les maillages qui ne sont pas concerné, ont des décal_noe et éléments inchangé donc quelconques, ceci permet de garder les mêmes tailles
//   int decal_n = 0;  // variables intermédiaires
//   for (int nm=1;nm<=nbmail;nm++)
//    {int numMail=tab_mail(nm);
//     decal_noeud(numMail)=decal_n; 
//     decal_n += lesMail->Nombre_noeud(numMail);
//    };
//   // on ré_enregistre le nombre total de noeud 	
//   nb_total_noeud = decal_n;	

   for (int im=1;im<=nbmail;im++)
    { int numMail=tab_mail(im);
      int decal_noe=decal_noeud(numMail); // pour simplifier
      // maintenant on sort la liste de tous les noeuds 
      int nbmaxinoeud = lesMail->Nombre_noeud(numMail);
      // deux cas soit on applique une pseudo-homothetie ou non
      if (!(considerer_homothetie && t_homothetie(numMail)))
       {// cas sans homothetie : cas classique
        for (int numNoeud=1; numNoeud<= nbmaxinoeud;numNoeud++) 
        {// recup du noeud
          Noeud & noe = lesMail->Noeud_LesMaille(numMail,numNoeud);
          sort << "\n" << noe.Num_noeud()+decal_noe << " " ;
          const Coordonnee& co = noe.Coord0();
          co.Affiche(sort,ParaGlob::NbdigdoGR()); 
          switch (dim) // dans le cas d'une dimension diff de 3, on complète avec des 0
           { case 1: sort << "  0.   ";
             case 2: sort << "  0.   ";
            };             
         };
        }
      else // cas avec Homothetie 	
       {Coordonnee& orig = t_orig(numMail);           // pour simplifier
        Coordonnee& fact_mult = t_fact_mult(numMail); // pour simplifier
		  
        for (int numNoeud=1; numNoeud<= nbmaxinoeud;numNoeud++) 
        {// recup du noeud
          Noeud & noe = lesMail->Noeud_LesMaille(numMail,numNoeud);
          sort << "\n" << noe.Num_noeud()+decal_noe << " " ;
          const Coordonnee& co = noe.Coord0();
          Coordonnee A(co-orig); int dim = A.Dimension();
          switch (dim) // dans le cas d'une dimension diff de 3, on complète avec des 0
           { case 3: A(3) *= fact_mult(3);
             case 2: A(2) *= fact_mult(2);
             case 1: A(1) *= fact_mult(1);
            };             
          A +=orig;			 
          A.Affiche(sort,ParaGlob::NbdigdoGR()); 
          switch (dim) // dans le cas d'une dimension diff de 3, on complète avec des 0
           { case 1: sort << "  0.   ";
             case 2: sort << "  0.   ";
            };             
        };
       };			   
     };//-- fin de la boucle sur les maillages
};

// sortie sur le flot passé en paramètre, de la partie élément du maillage sans entête ni fin
void Mail_initiale_Gmsh::Sortie_element_initiaux(const Tableau <int>& tab_mail
                   ,LesMaillages * lesMail, ostream &sort)
{  // on construit un tableau de bool, pour savoir si le maillage est à sortir ou pas
   Tableau <bool> t_a_sortir(lesMail->NbMaillage(),false);
   int nb_a_sortir = tab_mail.Taille();
   for (int isa = 1; isa <= nb_a_sortir; isa++)
     t_a_sortir(tab_mail(isa))=true;
   // on boucle sur les maillages
   int nbmail = tab_mail.Taille();   
//
//   // on recalcule les décalages de noeuds en fonction des maillages actifs, car c'est utilisé par les isovaleurs et autres
//   // ordres, les maillages qui ne sont pas concerné, ont des décal_noe et éléments inchangé donc quelconques, ceci permet de garder les mêmes tailles
//   int decal_n = 0; int decal_e=0; // variables intermédiaires
//   for (int nm=1;nm<=nbmail;nm++)
//    {int numMail=tab_mail(nm);
//     decal_noeud(numMail)=decal_n; decal_element(numMail)=decal_e;
//     decal_n += lesMail->Nombre_noeud(numMail);
//     decal_e += lesMail->Nombre_element(numMail);
//    };
//   // on ré_enregistre le nombre total de noeud et le nombre total d'éléments	
//   nb_total_noeud = decal_n;	
//   nb_total_element = decal_e;
//
   for (int im=1;im<=nbmail;im++)
    { int numMail=tab_mail(im);
      int decal_ele =decal_element(numMail); // pour simplifier
      int decal_noe=decal_noeud(numMail); // pour simplifier
      // on balaie tous les éléments du maillage
      int nbmaxiElement = lesMail->Nombre_element(numMail);
      t_Egmsh(im).Change_taille(nbmaxiElement); // dimensionement 
      for (int numElem=1; numElem<= nbmaxiElement;numElem++) 
        {Element& elem  = lesMail->Element_LesMaille(numMail,numElem); // récup de l'élément
         // on appel la méthode pour sortir l'élément
         bool modifier_t_Egmsh = true; // il s'agit des vrais éléments donc on met à jour t_Egmsh
         SortieDunElements(t_a_sortir(numMail), elem.Num_elt(), sort,decal_ele, elem.Tab_noeud()
                           ,decal_noe, elem.Id_geometrie(), elem.Id_interpolation()
                           ,modifier_t_Egmsh, im);
        }; // -- fin de la boucle sur les éléments
    };//-- fin de la boucle sur les maillages
};







                            
