// 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 "Deformees_Gmsh.h"
#include "CharUtil.h"
#include "ConstMath.h"
#include "Visualisation_Gmsh.h"

#include <iomanip>

    // CONSTRUCTEURS :
// par defaut
Deformees_Gmsh::Deformees_Gmsh () :
   OrdreVisu("..........................................deformee"
             ,"visualisation des deformee","de")
   ,isovaleurs_Gmsh(NULL)
   ,num_mail_incr(),noms_matiere(),choix_mail(NULL)
   ,noms_couleurs(),nom_deplace("deplace")
   ,nom_vitesse("vitesse"),nom_acceleration("acceleration")
   ,li_bornes(),li_nom_bornes(),avec_vitesse(0),avec_acceleration(0)
   //,mailInitial(NULL),isovaleurs_Gmsh(NULL)
     {mailInitial=NULL;isovaleurs_Gmsh=NULL;}; 
     
     // constructeur de copie 
Deformees_Gmsh::Deformees_Gmsh (const Deformees_Gmsh& ord) :
    OrdreVisu(ord)
   ,isovaleurs_Gmsh(ord.isovaleurs_Gmsh)
   ,num_mail_incr(ord.num_mail_incr)
   ,noms_matiere(),choix_mail(ord.choix_mail)
   ,noms_couleurs(ord.noms_couleurs)
   ,li_bornes(ord.li_bornes),li_nom_bornes(ord.li_nom_bornes)
   ,nom_deplace(ord.nom_deplace)
   ,nom_vitesse(ord.nom_vitesse),nom_acceleration(ord.nom_acceleration)
   ,avec_vitesse(ord.avec_vitesse),avec_acceleration(ord.avec_acceleration)
//   ,mailInitial(ord.mailInitial),isovaleurs_Gmsh(ord.isovaleurs_Gmsh)
      {mailInitial=ord.mailInitial;
       isovaleurs_Gmsh=ord.isovaleurs_Gmsh;
       };
               
    // DESTRUCTEUR :
Deformees_Gmsh::~Deformees_Gmsh () 
     {};  
    
    // METHODES PUBLIQUES :
// 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 Deformees_Gmsh::ExeOrdre(ParaGlob * ,const Tableau <int>& tab_mail,LesMaillages * lesMail,bool ,LesReferences*
                      ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*
                      ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre type_incre,int incre
//                      ,LesContacts*,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre type_incre,int incre
                      ,bool ,const map < string, const double * , std::less <string> >&
                      ,const List_io < TypeQuelconque >& listeVecGlob)
{// visualisation du maillage pointé si actif
 if (actif)
  {
   // dans le cas où c'est l'incrément 0, c'est-à-dire le maillage initial, on ne sort rien dans le cas
   // de l'ancien format au niveau des déplacements sinon avec le nouveau format on sort la maillage initiale
   if (type_incre == PREMIER_INCRE)
     {if(!isovaleurs_Gmsh->Use_hold_gmsh_format())
        // dans le cas du nouveau format, on sort au début du fichier : le maillage initiale: noeuds et éléments
        // ensuite à chaque incrément on ne sortira que les vecteurs déplacements aux noeuds 
        { ostream &sort = entreePrinc.Sort_resultat_Gmsh(nom_deplace);
          mailInitial->sortie_maillage_initial(tab_mail,lesMail,sort);
          if (avec_vitesse) // cas avec la vitesse
           { ostream &sort_vit = entreePrinc.Sort_resultat_Gmsh(nom_vitesse);
             mailInitial->sortie_maillage_initial(tab_mail,lesMail,sort_vit);
           };
          if (avec_acceleration) // cas avec l'accélération
           { ostream &sort_acc = entreePrinc.Sort_resultat_Gmsh(nom_acceleration);
             mailInitial->sortie_maillage_initial(tab_mail,lesMail,sort_acc);
           };
        };
     };
	
   if (incre != 0)
     { ostream &sort = entreePrinc.Sort_resultat_Gmsh(nom_deplace);
       if (isovaleurs_Gmsh->Use_hold_gmsh_format())
	         {SortieDeformee_ancien_format(tab_mail,lesMail,sort,incre);}
       else 
	         {SortieDeformee(tab_mail,lesMail,sort,incre);
           if (avec_vitesse) // cas avec la vitesse
            { ostream &sort_vit = entreePrinc.Sort_resultat_Gmsh(nom_vitesse);
              SortieVitesse(tab_mail,lesMail,sort_vit,incre);
            };
           if (avec_acceleration) // cas avec l'accélération
            { ostream &sort_acc = entreePrinc.Sort_resultat_Gmsh(nom_acceleration);
              SortieAcceleration(tab_mail,lesMail,sort_acc,incre);
            };
          };
     }; //-- fin du if sur le premier incrément
  }; //-- fin du if actif
};  

 // 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 Deformees_Gmsh::ChoixOrdre()
{ // demande de précision
  bool choix_valide = false;
  cout << "\n ----> preparation de la visualisation des deformees"
       << "\n  parametre par defaut ? : pas de limites d'alerte sur les deplacements ,";
  // on regarde s'il y a des vitesses et accélération aux noeuds
  // récup  ddl aux noeuds possibles à visualiser
  const Tableau <List_io < Ddl_enum_etendu > >& tabnoeud_type_ddl = isovaleurs_Gmsh->Tabnoeud_type_ddl();
  int tail = tabnoeud_type_ddl.Taille();
  List_io < Ddl_enum_etendu >::iterator  il,ilfin;
  bool existe_vitesse = false; bool existe_acceleration = false;
  for (int i=1;i<=tail;i++)
   {ilfin = tabnoeud_type_ddl(i).end(); il = tabnoeud_type_ddl(i).begin();
    for (;il != ilfin; il++ )
      {if ((*il).Enum() == V1)
        {existe_vitesse = true;};
       if ((*il).Enum() == GAMMA1)
        {existe_acceleration = true;};
       if (existe_vitesse && existe_acceleration)
        break;
      };
   };
  if (existe_vitesse) cout << "\n vitesse ";
  if (existe_acceleration) cout << "et  acceleration ";
 
  cout << "   (rep 'o') pour accepter ces parametres sinon autre ";
  string rep;
  cout << "\n reponse ? "; rep = lect_return_defaut(false,"o");
  if (rep != "o")
   {// cas d'un choix autre que standart
    while (!choix_valide)
    {try 
     { int nb_choix = 3; // par défaut
       cout << "\n (0) fin modif"
            << "\n (1) nouvelle definition de limites d'alerte?   "               
            << "\n (2) effacer une limites d'alerte existante ?   "               
		          << "\n (3) ancien format gmsh (< ou = version 2.3.1) ?  ";               
       if (existe_vitesse)
          { cout << "\n (4)  vitesse ";nb_choix = 4;};
       if (existe_acceleration)
          { cout << "\n (5)  acceleration ";nb_choix = 5;};
       cout << "\n \n reponse ? ";
       rep = lect_return_defaut(false,"0");
       if (rep == "fin_prog") Sortie(1);
       // sinon
       int num = ChangeEntier(rep);
       if (num == 0) {choix_valide=true;}
       else if ((num > 0)&&(num < nb_choix))
           { choix_valide=false;
             switch (num)
              { case 1:  // definition des limites d'alerte 
                { cout << "\n donnez une borne inferieur "
                       << "\n (rep un reel ou 'no' pour utiliser le minimum total des valeurs ";
                  string numinf;DeuxDoubles dd; string nom_bornes;
                  numinf= lect_chaine();
                  if (numinf == "no")  
                    {dd.un= -ConstMath::trespetit;}
                  else
                    {dd.un=ChangeReel(numinf);};  
                  if ( numinf == "no") 
                    { // il faut absolument donner une borne supérieur
                      cout << "\n donnez une borne superieur (rep un reel) ";
                      numinf= lect_chaine();
                      dd.deux=ChangeReel(numinf);
                     }
                  else
                    {cout << "\n donnez une borne superieur "
                          << "\n (rep un reel ou 'no' pour utiliser le maximum total des valeurs ";
                     numinf= lect_chaine();
                     if (numinf == "no")  
                      {dd.deux= ConstMath::tresgrand;}
                     else
                      {dd.deux=ChangeReel(numinf);};
                    }; 
                  // définition du nom
                  cout << "\n donnez le nom que vous voulez donner a ces limites: ";
                  numinf= lect_chaine();
                  // maintenant on valide
                  li_bornes.push_back(dd); li_nom_bornes.push_back(numinf);
                  break;
                  }
                case 2:  // "effacer une limites d'alerte existante")
                 {cout << "\n liste actuelle des alertes enregistrees ";
                  list <DeuxDoubles>::iterator idd_n,idd_fin=li_bornes.end();
                  list <string>::iterator ili,ili_fin=li_nom_bornes.end();
                  ili=li_nom_bornes.begin();int num=1;
                  for (idd_n=li_bornes.begin();idd_n!=idd_fin;idd_fin++,num++)
                    { cout << "\n(" << num << ") " << *ili << (*idd_n).un << " " << (*idd_n).deux <<" ";};
                  cout << "\n donnez le numero d'alerte a supprimer ";
                  string num_choix;
                  num_choix= lect_chaine(); int num_c=ChangeEntier(num_choix);
                  if ((num_c >=1)&&(num_c<=num))
                   {ili=li_nom_bornes.begin();int num=1;
                    for (idd_n=li_bornes.begin();idd_n!=idd_fin;idd_fin++,num++)
                      if (num==num_c)
                        {li_nom_bornes.erase(ili_fin);li_bornes.erase(idd_n);};                                     
                    };
                  break;
					            }
                case 3:  // avec les vitesses
                 {cout << "\n ajout de la vitesse en sortie ";
                  avec_vitesse = 1;
                  break;
					            }
                case 4:  // avec les accélérations
                 {cout << "\n ajout de l'accélération en sortie ";
                  avec_acceleration = 1;
                  break;
					            }
				          }; // fin du switch (num)
				       }
       else { cout << "\n Erreur on attendait un entier entre 0 et "<< nb_choix << " !!, "
                      << "\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 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 Deformees_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_deformee")!=NULL)
     {// sauvegarde des paramètres  actuelles
      list <DeuxDoubles> li_bornes_sauve = li_bornes; // min max des alertes
      list <string> li_nom_bornes_sauve = li_nom_bornes;  // nom des alertes
      // essaie de lecture
      try 
        { string nom; 
          (*entreePrinc.entCVisu) >> nom ;
          if (nom != "debut_deformee")
            { cout << "\n Erreur en lecture des parametres de deformee a partir d'un fichier .CVisu,"
                   << " le premier enregistrement doit etre le mot clef: debut_deformee "
                   << " 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_deformee")==NULL)
              {// lecture  des alertes
               if (strstr(entreePrinc.tablcarCVisu,"deb_list_alerte")!=NULL)
                 { // lecture de la liste des alertes
                   entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement 
                   // on efface éventuellement les listes actuelles s'il y a quelque chose à lire
                   if (strstr(entreePrinc.tablcarCVisu,"fin_list_alerte")==NULL)
                    {li_nom_bornes.erase(li_nom_bornes.begin(),li_nom_bornes.end());
                     li_bornes.erase(li_bornes.begin(),li_bornes.end());
                     // lecture des  listes demandées
                     int compteur=0; // pour éviter une boucle infinie
                     DeuxDoubles dd_n; string nom_alerte,nom2;
                     while (compteur < 1000000)
                       { (*entreePrinc.entCVisu) >> nom >> nom2 >> nom_alerte; compteur++;
                         if (nom != "fin_list_alerte")
                           { dd_n.un=ChangeReel(nom); dd_n.deux=ChangeReel(nom2);
                             // on vérifie que le nom lu est acceptable
                             if (find(li_nom_bornes.begin(),li_nom_bornes.end(),nom_alerte) != li_nom_bornes.end())
                                {li_nom_bornes.push_back(nom_alerte);li_bornes.push_back(dd_n);}
                             else
                                cout << "\n lecture d'une alerte ( "<< nom << " ) errone ! on n'en tiens pas compte";   
                             entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
                            }
                         else break;                           
                        }
                     };
                  entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement   
                 }; //-- on sort du cas où il y avait une liste d'alerte
               // lecture des indicateurs pour la vitesse et l'accélération
               if (strstr(entreePrinc.tablcarCVisu,"avec_vitesse=")!=NULL)
                 { (*entreePrinc.entCVisu) >> nom >> avec_vitesse >> nom >> avec_acceleration;
                   entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
                 };
               
              } //-- on sort des paramètres de déformée 
             // on passe un enregistrement pour le prochain ordrevisu  
             entreePrinc.NouvelleDonneeCVisu();    
           }; // fin du cas d'une lecture de paramètre de dérivées
          }    
      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 de deformee a partir d'un fichier .CVisu,"
               << " on ne tiens pas compte  des parametres fournies !! ";
          // récup des infos  sauvées
          li_bornes = li_bornes_sauve; // min max des alertes
          li_nom_bornes = li_nom_bornes_sauve;  // nom des alertes
          if (ParaGlob::NiveauImpression() >= 4)     
             cout  << "\n Deformees_Gmsh::Lecture_parametres_OrdreVisu(..";
        }
      } 
  };

// écriture des paramètres de l'ordre dans un flux
void Deformees_Gmsh::Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc)
 { // récup du flot  
   ostream & sort = (*(entreePrinc.Sort_CommandeVisu()));
   // on commente le fonctionnement
   sort << "\n #  ----------------------------- definition des parametres de deformee: ---------------- "
        << "\n debut_deformee  #  un mot cle de debut de liste";
   // appel de l'ordre de la classe mère
   OrdreVisu::Ecrit_para_OrdreVisu_general(entreePrinc);
   // --- on sort l'entête des paramètres pour les alertes
   sort << "\n # definition des alertes: deb_list_alerte "
        << "\n # un mot clef de debut "
        << "\n # puis deux nombres: un mini et un maxi, et un nom "
        << "\n # un mot clef de fin: fin_list_alerte ";   
   // puis la liste des alertes
   sort << "\n deb_list_alerte ";            
   list <DeuxDoubles>::iterator idd_n,idd_fin=li_bornes.end();
   list <string>::iterator ili,ili_fin=li_nom_bornes.end();
   ili=li_nom_bornes.begin();int num=1;
   for (idd_n=li_bornes.begin();idd_n!=idd_fin;idd_fin++,num++)
      { sort << "\n" << (*idd_n).un << " " << (*idd_n).deux << " " << *ili << " ";};
   sort << "\n fin_list_alerte  ";
   // indicateurs la vitesse et l'accélération si dispo
   sort << "\n avec_vitesse= " << avec_vitesse << " avec_acceleration= " << avec_acceleration
        << " # 1 ou 0 pour la sortie si disponible ";
   // fin      
   sort << "\n fin_deformee " << " #   un mot cle de fin  \n";    
  };
    
// sortie de la déformée dans le cas de l'ancien format
void Deformees_Gmsh::SortieDeformee_ancien_format(const Tableau <int>& tab_mail,LesMaillages * lesMail
																 ,ostream & sort,int incre)
{ // pour  boucler sur les maillages
  int nbmail = tab_mail.Taille();
  sort << "\n//------------------- increment "<<incre<<" ----------------------------\n";
  // ----- on commence par sortir les noeuds avec un identificateur, pour optimiser la taille fichier
  isovaleurs_Gmsh->SortieDefCoordonnees_old_format(sort,incre,nbmail,tab_mail,lesMail);
  
  // on sort l'entête
  int numero = 0;
  isovaleurs_Gmsh->EnteteView(sort,incre,nom_deplace,numero );
  // récupération de l'instanceConstructTabScalVecTensGmsh 
  const Isovaleurs_Gmsh::ConstructTabScalVecTensGmsh& tabScalVecTensGmsh = isovaleurs_Gmsh->TabScalVecTensGmsh();
  // ramène le tableau t_Egmsh
  // t_Egmsh(im)(ie): donne pour le maillage im, et pour l'élément ie, le numéro gmsh de l'élément
  const Tableau < Tableau < int > >& t_Egmsh = mailInitial->TabEgmsh(); 
  // 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(); 

  for (int im=1;im<=nbmail;im++)
    { int numMail=tab_mail(im);
      int nbmaxelem = lesMail->Nombre_element(numMail);
      int dcaN = mailInitial->DecalNumNoeud(numMail);
      for (int numElem = 1; numElem <= nbmaxelem; numElem++)
        {Element& elem  = lesMail->Element_LesMaille(numMail,numElem); // récup de l'élément
         Tableau<Noeud *>& t_n = elem.Tab_noeud();
			      int num_elem_gmsh = t_Egmsh(im)(numElem);  // numéro de classement du type d'élément gmsh
         // maintenant on sort en fonction de  d'élément
         //-- 1) le type
   // ***** a complèter pour les éléments quadratiques incomplet et les autres non possibles *****            
         sort << "\n" << tabScalVecTensGmsh.vector_pourView(num_elem_gmsh)<< "(";
         //-- 2) les coordonnées des noeuds
         int nbNmax = t_n.Taille();
			  // dans le cas des éléments sfe, il faut utiliser uniquement les noeuds centraux
 	       switch (elem.Id_interpolation())
		            {  case SFE3C : case SFE3 : case SFE2: case SFE1 : 
		               case SFE3C_3D : case SFE3_3D : case SFE2_3D: case SFE1_3D :
				              nbNmax = 3 ; break;
                 case QSFE1 : case QSFE3:
                  nbNmax = 6 ; break;
                 default: break;
				          };
			  
         for (int ino=1;ino<=nbNmax;ino++) // ino = numéro gmsh // tous les coordonnées sauf le dernier noeud
           { //int num_N = t_n(ino)->Num_noeud()+dcaN;
             int num_her = tGmshHer(num_elem_gmsh)(ino); // --> num HZpp
				         int num_N = t_n(num_her)->Num_noeud()+dcaN; // num global
 				        isovaleurs_Gmsh->SortieUseUneCoordonnee(incre,sort,(ino == nbNmax),num_N);
           };
         //-- 3)  les grandeurs
         for (int ino=1;ino<=nbNmax;ino++) // sortie des grandeurs avec un traitement particulier pour  la dernière
           { int num_her = tGmshHer(num_elem_gmsh)(ino); // --> num HZpp
				         Noeud& noe = *t_n(num_her); // pour simplifier
//				  Noeud& noe = *t_n(ino); // pour simplifier
//           int num_noeud = ino + dcaN;
             const Coordonnee& dep = noe.Coord2() - noe.Coord0();
             switch (ParaGlob::Dimension()) 
                { case 1: sort << dep(1) <<", 0. , 0. ";break;
                  case 2: sort << dep(1) <<", "<< dep(2) << ", 0. " ;break;
                  case 3: sort << dep(1) <<", "<< dep(2) << ", " << dep(3) ;break;
                };
             if (ino != nbNmax){sort << ", ";} else {sort << "};";};
           };
        }; //-- fin de la boucle sur les éléments
    }; //-- fin de la boucle sur les maillages
  // fin de la view
  sort << "\n }; "; 
  // et on vide le buffer de sortie
  sort << endl; 
};

// sortie de la déformée dans le cas du nouveau format
void Deformees_Gmsh::SortieDeformee(const Tableau <int>& tab_mail,LesMaillages * lesMail
																 ,ostream & sort,int incre)
{
  // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  double temps_actuel = ParaGlob::Variables_de_temps().TempsCourant();
  // def de l'entete
	 int nb_composante=3;
  int dim = ParaGlob::Dimension();
	 isovaleurs_Gmsh->EnteteNodeData(sort,incre,temps_actuel,nom_deplace,nb_composante);
     // -- sortie des grandeurs
     // on balaie les maillages
	 int nbmail = tab_mail.Taille();
	 Coordonnee A(dim); // une variable de travail
  for (int im =1; im <= nbmail; im++)
      {// on ne continue que si le maillage est à sortir
       int numMail = tab_mail(im);
       int decal_noe = mailInitial->DecalNumNoeud(numMail);
       Tableau<Noeud *>& t_n = lesMail->Tab_noeud(numMail);
       int nbmaxinoeud = t_n.Taille();
       for (int numNoeud=1; numNoeud<= nbmaxinoeud;numNoeud++) 
              { // recup du noeud
                Noeud & noe = lesMail->Noeud_LesMaille(numMail,numNoeud);
                sort << "\n" << noe.Num_noeud()+decal_noe << " " ;//<< fixed ;
                //--   le déplacement
				            if (noe.ExisteCoord2()) 
					            { A=(noe.Coord2() - noe.Coord0());
					              A.Affiche(sort, ParaGlob::NbdigdoGR());
					              switch (dim) // on rajoute des 0 si la dimension n'est pas 3
					               	{case 1:  sort << " 0. ";
					               	 case 2:  sort << " 0. ";
					               	};

 //debug       					                    cout << " noeud: " << noe.Num_noeud() <<" mailage:"<<noe.Num_Mail();
					            }
				            else  // si la valeur n'existe pas on sort 0  
					            { sort << " 0. 0. 0. ";};
              };
      };
  // fin de la view
  sort << "\n$EndNodeData \n"; 
};
                            

// idem pour le champ de vitesse dans le cas du nouveau format
void Deformees_Gmsh::SortieVitesse(const Tableau <int>& tab_mail,LesMaillages * lesMail
																 ,ostream & sort,int incre)
{
  // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  double temps_actuel = ParaGlob::Variables_de_temps().TempsCourant();
  // def de l'entete
	 int nb_composante=3;
  int dim = ParaGlob::Dimension();
	 isovaleurs_Gmsh->EnteteNodeData(sort,incre,temps_actuel,nom_vitesse,nb_composante);
     // -- sortie des grandeurs
     // on balaie les maillages
	 int nbmail = tab_mail.Taille();
	 Coordonnee A(dim); // une variable de travail
  for (int im =1; im <= nbmail; im++)
      {// on ne continue que si le maillage est à sortir
       int numMail = tab_mail(im);
       int decal_noe = mailInitial->DecalNumNoeud(numMail);
       Tableau<Noeud *>& t_n = lesMail->Tab_noeud(numMail);
       int nbmaxinoeud = t_n.Taille();
       for (int numNoeud=1; numNoeud<= nbmaxinoeud;numNoeud++) 
              { // recup du noeud
                Noeud & noe = lesMail->Noeud_LesMaille(numMail,numNoeud);
                sort << "\n" << noe.Num_noeud()+decal_noe << " " ;//<< fixed ;
                //--   la vitesse
                switch (dim)
                 {case 3: // on est en dim 3
                    {if (noe.Existe_ici(V3))
					                 { A(3) = noe.Ddl_noeud_tdt(V3).Valeur();
                        A(2) = noe.Ddl_noeud_tdt(V2).Valeur();
                        A(1) = noe.Ddl_noeud_tdt(V1).Valeur();
                      }
                     else {A.Zero();}
                     break;
                    }
                  case 2: // on est en dim 2
                     {if (noe.Existe_ici(V2))
					                 { A(3) = 0.;
                        A(2) = noe.Ddl_noeud_tdt(V2).Valeur();
                        A(1) = noe.Ddl_noeud_tdt(V1).Valeur();
                      }
                     else {A.Zero();}
                     break;
                    }
                  case 1: // on est en dim 1
                     {if (noe.Existe_ici(V2))
					                 { A(3) = 0.;
                        A(2) = 0.;
                        A(1) = noe.Ddl_noeud_tdt(V1).Valeur();
                      }
                     else {A.Zero();}
                     break;
                    }
                  default: break;
                 };
                A.Affiche(sort, ParaGlob::NbdigdoGR());
              };
      };
  // fin de la view
  sort << "\n$EndNodeData \n"; 
};
                            

// idem pour le champ d'accélération dans le cas du nouveau format
void Deformees_Gmsh::SortieAcceleration(const Tableau <int>& tab_mail,LesMaillages * lesMail
																 ,ostream & sort,int incre)
{
  // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  double temps_actuel = ParaGlob::Variables_de_temps().TempsCourant();
  // def de l'entete
	 int nb_composante=3;
  int dim = ParaGlob::Dimension();
	 isovaleurs_Gmsh->EnteteNodeData(sort,incre,temps_actuel,nom_acceleration,nb_composante);
     // -- sortie des grandeurs
     // on balaie les maillages
	 int nbmail = tab_mail.Taille();
	 Coordonnee A(dim); // une variable de travail
  for (int im =1; im <= nbmail; im++)
      {// on ne continue que si le maillage est à sortir
       int numMail = tab_mail(im);
       int decal_noe = mailInitial->DecalNumNoeud(numMail);
       Tableau<Noeud *>& t_n = lesMail->Tab_noeud(numMail);
       int nbmaxinoeud = t_n.Taille();
       for (int numNoeud=1; numNoeud<= nbmaxinoeud;numNoeud++) 
              { // recup du noeud
                Noeud & noe = lesMail->Noeud_LesMaille(numMail,numNoeud);
                sort << "\n" << noe.Num_noeud()+decal_noe << " " ;//<< fixed ;
                //--   l'accélération
                switch (dim)
                 {case 3: // on est en dim 3
                    {if (noe.Existe_ici(GAMMA3))
					                 { A(3) = noe.Ddl_noeud_tdt(GAMMA3).Valeur();
                        A(2) = noe.Ddl_noeud_tdt(GAMMA2).Valeur();
                        A(1) = noe.Ddl_noeud_tdt(GAMMA1).Valeur();
                      }
                     else {A.Zero();}
                     break;
                    }
                  case 2: // on est en dim 2
                     {if (noe.Existe_ici(GAMMA2))
					                 { A(3) = 0.;
                        A(2) = noe.Ddl_noeud_tdt(GAMMA2).Valeur();
                        A(1) = noe.Ddl_noeud_tdt(GAMMA1).Valeur();
                      }
                     else {A.Zero();}
                     break;
                    }
                  case 1: // on est en dim 1
                     {if (noe.Existe_ici(GAMMA2))
					                 { A(3) = 0.;
                        A(2) = 0.;
                        A(1) = noe.Ddl_noeud_tdt(GAMMA1).Valeur();
                      }
                     else {A.Zero();}
                     break;
                    }
                  default: break;
                 };
                A.Affiche(sort, ParaGlob::NbdigdoGR());
              };
      };
  // fin de la view
  sort << "\n$EndNodeData \n"; 
};