#!/usr/bin/env perl
use strict;
use warnings;
use English;
use File::Glob qw(bsd_glob);
use File::Basename;
use IO::File;
use List::Util qw(uniq);
my $NOM_PROG = basename $PROGRAM_NAME;
#pattern d un reel pour les regex (desormais redondant avec $RE{num}{real} de Regexp::Common)
my $format_reel = '[+-]?[\.]?\d+[\.]?\d*(?:[eE][+-]?\d*)?';


my $VERSION = '1.04';
#####################################################################################################
#  script pour visualiser un ou plusieurs maillages dans Gmsh                                       #
#  version 1.00 : version initiale (version testee sur : MacOSX Darwin)                             #
#  version 1.01 : modif majeure de la lecture des "no_maillage ref_noeud" pour chaque sortie        #
#                 (on fait plutot le choix de lire un ensemble de paires "no_maillage ref_noeud"    #
#                  sur la premiere ligne, puis la liste des grandeurs (avec ou sans STAT) sur la    #
#                  seconde ligne => permettra de gerer le cas ou on veut une sortie sur une zone    #
#                  qui concerne plusieurs maillages a la fois)                                      #
#  version 1.02 : amelioration de la reconnaissance des grandeurs disponibles dans un repertoire    #
#                 Gmsh (modif subroutine make_table_grandeurs_Gmsh() )                              #
#  version 1.03 : correction d une erreur de code : remplacement d un signe = par == dans un if()   #
#  version 1.04 : remplacement du module List::MoreUtils par le module natif List::Util pour        #
#                 acceder a la fonction "uniq" (disponible en natif depuis Perl 5.26)               #
#####################################################################################################



#
# note :
#     l une des difficultes du traitement est que la numerotation des noeuds dans le fichier Gmsh n est pas
#  la meme que les fichiers maillage .her dans le cas ou il y a plusieurs maillages.
#
#    On doit donc connaitre les maillages .her, et en particulier connaitre l ordre dans lequel ils ont ete
#  declares dans la sortie Gmsh (fichier .CVisu). En general, c est le meme ordre que dans le fichier .info du calcul.
#  La connaissance des fichiers maillages et de leur ordre permettra de se baser sur les listes de references
#  existantes pour ces maillages et de determiner la correspondance entre numero de noeud du fichier .her et 
#  numero de noeud qui lui correspond dans le fichier Gmsh .pos
#
#  Cette problematique est a l origine du choix de passer par un fichier de commande (voir aide du script).
#  De toute facon, il est egalement plus simple de passer par un fichier de commande pour definir les sorties (qui peuvent
#  etre nombreuses)
#







sub affichage_aide {
  use Text::Wrap;
  #config du package Text::Wrap
  $Text::Wrap::columns = 101;#le nombre de caracteres maximum par ligne sera egal a ($Text::Wrap::columns - 1) dans le cas ou utilise wrap

  #indentation de longueur $NOM_PROG
  my $indent_NOM_PROG = ""; $indent_NOM_PROG .= " " for(1 .. length($NOM_PROG));

  print "----------------------------------------\n";
  print " script $NOM_PROG  (version $VERSION)\n";
  print "----------------------------------------\n";
  print "\n";
  print "But : convertir des donnees Gmsh (fichiers .pos) en fichier de type .maple\n";
  print "\n";
  print "Usage :\n";
  print wrap("  ","    $indent_NOM_PROG ", " $NOM_PROG [-h|help] [-v] [-l] [-trame nom_fic]\n", 
                                                     "rep_Gmsh fic_cmd fic_maple\n");
  print "\n";
  print "Arguments :\n";
  print "     o rep_Gmsh  : repertoire Gmsh\n";
  print "     o fic_cmd   : fichier de commande de sortie (voir \"Fonctionnement\")\n";
  print "     o fic_maple : fichier de type .maple a creer\n";
  print "\n";
  print "Fonctionnement :\n";
  print wrap("    ", "  ",
     "$NOM_PROG lit le fichier \"fic_cmd\" qui contient les mots-cles MAILLAGES et SORTIES. ",
   "Il produira le fichier \"fic_maple\" ",
   "qui contiendra un certain nombre de colonnes dans l ordre de ce qui est indique au mot-cle SORTIES.\n",
   "\n",
   "Le fichier \"fic_cmd\" aura la structure suivante :\n",
   "---------------------------------------------------------\n",
   "MAILLAGES #(mot-cle de declaration des maillages dans l ordre du .CVisu)\n",
   "nom_fichier #(fichier .her maillage 1)\n",
   "nom_fichier #(fichier .her maillage 2)\n",
   "...\n",
   "nom_fichier #(fichier .her maillage N)\n",
   "\n",
   "\n",
   "SORTIES #(mot-cle de declaration des grandeurs a sortir)\n",
   "\n",
   "#sortie 1\n",
   "no_mail_1 ref_n_1  no_mail_2 ref_n_2 ... #liste des no_maillage/ref_noeud\n",
   "[STAT ] var_1 var_2 ... var_N #liste des grandeurs voulues\n",
   "                              #(eventuellement precede du mot-cle STAT)\n",
   "#sortie 2\n",
   "no_mail_1 ref_n_1  no_mail_2 ref_n_2 ... #liste des no_maillage/ref_noeud\n",
   "[STAT ] var_1 var_2 ... var_N #liste des grandeurs voulues\n",
   "                              #(eventuellement precede du mot-cle STAT)\n",
   "...\n",
   "#sortie N\n",
   "no_mail_1 ref_n_1  no_mail_2 ref_n_2 ... #liste des no_maillage/ref_noeud\n",
   "[STAT ] var_1 var_2 ... var_N #liste des grandeurs voulues\n",
   "                              #(eventuellement precede du mot-cle STAT)\n",
   "---------------------------------------------------------\n",
   "\n",
   "L option -trame permet de generer un exemple de fichier de commande (voir Options).\n",
   "\n",
   "Le symbole \"#\" permet d ecrire des commentaires.\n", 
   "\n", 
   "Le mot-cle MAILLAGES permet de declarer les fichiers maillage (fichier .her). ",
   "Dans le cas a plusieurs maillages, il est tres important de les declarer dans le meme ordre que\n", 
   "celui dans le fichier .CVisu du calcul qui a cree le repertoire Gmsh.\n",
   "\n", 
   "Le mot-cle SORTIES permet de declarer les sorties. Une sortie est definie par un ensemble de paires \"no_maillage ref_noeud\" sur la premiere ligne. ",
   "Le numero de maillage (\"no_mail_...\") correspond a l ordre de declaration au mot-cle MAILLAGES. On indiquera comme reference ",
   "de noeud (\"ref_n_...\") soit un numero de noeud, soit une liste de reference de noeuds.\n",
   "  **remarque : une reference N_tout (tous les noeuds) est automatiquement generee pour chaque maillage si N_tout n existe pas deja\n",
   "Sur une seconde ligne, on indique la liste de grandeurs (\"var_...\") a sortir. L option -l permet de connaitre les ",
   "grandeurs disponibles. Le mot-cle \"STAT\" permet d indiquer que l on souhaite une statistique (somme, moyenne, min, max) sur ",
   "l ensemble des noeuds plutot que les valeurs par noeud.\n"
  );
  print "\n";
  print "Options :\n";
  print "    -v : affichage du numero de version\n";
  print "\n";
  print "    -l : affichage des grandeurs disponibles dans le repertoire \"rep_Gmsh\"\n";
  print "         **NB : dans ce cas, on peut lancer le script de la maniere suivante :\n";
  print "                  > $NOM_PROG -l rep_Gmsh\n";
  print "\n";
  print "    -trame nom_fic : genere une trame de fichier de commande\n";
  print "                     **NB : dans ce cas, on peut lancer le script de la\n";
  print "                            maniere suivante :\n";
  print "                              > $NOM_PROG -trame nom_fic\n";
  print "\n";
  print "Auteur :\n";
  print "   TROUFFLARD Julien\n";
  print "       julien.troufflard\@free.fr\n";
  print "----------------------------------------\n";
}



#------------------------------------
#pas d arguments ou option -h ou -help => affichage de l aide et arret du programme
#------------------------------------
#cas sans argument
if($#ARGV == -1) {
  affichage_aide();
  exit;
}
# cas option -h/-help (rq : insensible a la casse)
foreach my $arg (@ARGV) {
  if(($arg =~ /^-h$/i) or ($arg =~ /^-help$/i)) {
    affichage_aide();
    exit;
  }
}

#------------------------------------
#option -v => affichage de la version et arret du programme
#------------------------------------
foreach my $arg (@ARGV) {
  if($arg eq '-v') {
    print "\n $NOM_PROG : version $VERSION\n\n";
    exit;
  }
}

#------------------------------------
#option -trame => creation du fichier de commande et arret du programme
#------------------------------------
for(my $i=0; $i<=$#ARGV; $i++) {
  if($ARGV[$i] eq '-trame') {
    defined($ARGV[$i+1]) or die "\n**Erreur (prog:$NOM_PROG,opt:-trame) : argument manquant (voir aide -h|-help)...\n\n";
    print_fic_cmd($ARGV[$i+1]);
    print "\nFichier cree : $ARGV[$i+1]\n\n";
    exit;
  }
}




#------------------------------------
#recuperation des arguments et options
#------------------------------------
my $rep_Gmsh;#repertoire Gmsh
my $fic_cmd;#fichier de commande
my $fic_maple_a_creer;#fichier de type .maple a creer

my $is_opt_l = 0;#indicateur de l option -l (affichage de la liste des grandeurs dispo dans le repertoire $rep_Gmsh)

#on parcourt la liste des arguments (on traite les options connues et on stocke les autres dans @args)
my $opt;
my @args;
while($#ARGV != -1) {
  $opt = shift(@ARGV);

  #option -l
  if($opt eq '-l') {
    $is_opt_l = 1;
  }

  #cas d une option inconnue
  elsif($opt =~ /^-/) {
    warn "**Attention : option $opt inconnue (on ignore cette option)...\n";
  }

  #autres arguments
  else {
    push(@args,$opt);
  }
}#while($#ARGV != -1)



#recuperation des arguments obligatoires
#
#-on recupere d abord le repertoire Gmsh (pour appliquer directement une eventuelle option -l)
($#args >= 0) or die "\n**Erreur (prog:$NOM_PROG) : arguments manquants (voir aide : option -h ou -help)...\n\n";
$rep_Gmsh = shift(@args);
$rep_Gmsh =~ s/\/+$//;

#verif existence repertoire Gmsh
(-d $rep_Gmsh) or die "\n**Erreur (prog:$NOM_PROG) : repertoire Gmsh ($rep_Gmsh/) introuvable...\n\n";

#construction de la table des grandeurs et fichiers associes dans le repertoire Gmsh
my %table_grandeurs_rep_Gmsh;
#table de hashage : @{$table_grandeurs_rep_Gmsh{'liste_grandeurs'}} = (liste des noms de grandeur)
#
#                   $table_grandeurs_rep_Gmsh{nom grandeur}{'fichier'} = fichier .pos correspondant a la grandeur
#                   $table_grandeurs_rep_Gmsh{nom grandeur}{'nb_composantes'} = nombre de composantes de la grandeur
#
make_table_grandeurs_Gmsh($rep_Gmsh, \%table_grandeurs_rep_Gmsh);


#cas particulier : aucune grandeurs dispo
if($#{$table_grandeurs_rep_Gmsh{'liste_grandeurs'}} == -1) {
  die "\n**Erreur (prog:$NOM_PROG) : aucune grandeur n a ete trouve dans le repertoire Gmsh ($rep_Gmsh/) (plus precisement, aucun fichier d extension .pos n existe dans ce repertoire)...\n\n";
}



#option -l => affichage des grandeurs disponibles et sortie du programme
if($is_opt_l) {
  print "\n";
  print "--------------------------------------------------------------\n";
  print "Liste des grandeurs dans le repertoire $rep_Gmsh/ :\n";
  print "--------------------------------------------------------------\n";
  foreach my $grandeur (@{$table_grandeurs_rep_Gmsh{'liste_grandeurs'}}) {
    my $fpos = basename $table_grandeurs_rep_Gmsh{$grandeur}{'fichier'};
    print "  - $grandeur    ( fichier : $fpos )\n";
  }
  print "\n";
  exit;
}


#-on recupere le fichier de commande et le fichier .maple a creer
($#args >= 1) or die "\n**Erreur (prog:$NOM_PROG) : arguments manquants (voir aide : option -h ou -help)...\n\n";
$fic_cmd = shift(@args);
$fic_maple_a_creer = shift(@args);


#verif existence fichier commande
(-e $fic_cmd) or die "\n**Erreur (prog:$NOM_PROG) : fichier de commande ($fic_cmd) introuvable...\n\n";



#saisie des infos dans le fichier de commande
#
# - table des fichiers maillage
my %FHER;
#  table de hashage : $FHER{'nb_maillages'} = nombre de maillages
#
#                     $FHER{i}{'nb_noeuds'} = nombre de noeuds du maillage i
#                     $FHER{i}{'fichier'} = fichier .her du maillage i
#
$FHER{'nb_maillages'} = 0;


my $is_mot_cle_MAILLAGES_ok = 0;
my $is_mot_cle_SORTIES_ok = 0;

open(FIC, "<$fic_cmd");
my $nb_ligne_cmd = 0;
while(<FIC>) {
  $nb_ligne_cmd++;

  next if(/^\s*\#/);
  s/\s*#.*$//;
  next if(/^\s*$/);
  next if(not /^\s*MAILLAGES\s*$/);

  $is_mot_cle_MAILLAGES_ok = 1;

  while(<FIC>) {
    $nb_ligne_cmd++;

    next if(/^\s*\#/);
    s/\s*#.*$//;
    next if(/^\s*$/);
    if(/^\s*SORTIES\s*$/) {
      $is_mot_cle_SORTIES_ok = 1;
      last;
    }

    my ($fher) = split;
    my $nb_noeuds = nb_noeuds_maillage($fher);
    ($nb_noeuds > 0) or die "\n**Erreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) le fichier de maillage $fher n est pas valide (impossible d y saisir le nombre de noeuds)...\n\n";
    $FHER{'nb_maillages'}++;
    $FHER{$FHER{'nb_maillages'}}{'fichier'} = $fher;
    $FHER{$FHER{'nb_maillages'}}{'nb_noeuds'} = $nb_noeuds;
  }
  last;
}

$is_mot_cle_MAILLAGES_ok or die "\n**Erreur (prog:$NOM_PROG) : le mot-cle MAILLAGES n a pas ete trouve dans le fichier $fic_cmd ...\n\n";
$is_mot_cle_SORTIES_ok or die "\n**Erreur (prog:$NOM_PROG) : le mot-cle SORTIES n a pas ete trouve dans le fichier $fic_cmd ...\n\n";


# - table des grandeurs a sortir
my %SORTIES;
# table de hashage : $SORTIES{'nb_sorties'} = nombre de commandes de sortie
#
#                    @{$SORTIES{i}{'no_maillage'}} = liste des numeros de maillage de la commande
#                    @{$SORTIES{i}{'ref_noeud'}} = liste des noeud ou nom de la liste de ref
#                    @{$SORTIES{i}{'no_maillage'}{'liste_noeuds_her'} = liste des noeuds numerotation .her par maillage
#                    @{$SORTIES{i}{'no_maillage'}{'liste_noeuds_Gmsh'} = liste des noeuds numerotation Gmsh par maillage
#                    @{$SORTIES{i}{'liste_grandeurs'}} = liste des grandeurs a sortir pour ce/ces noeud(s)
#
#                    $SORTIES{i}{'STAT'} : indicateur d une sortie de type STATISTIQUE
#
while(<FIC>) {
  $nb_ligne_cmd++;

  next if(/^\s*\#/);
  s/\s*#.*$//;
  next if(/^\s*$/);
  next if(not /^\s*(\d+)\s+/);

  @_ = split;
  (($#_+1) % 2 == 0) or die "\n**Erreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) ligne non conforme (on doit y trouver des paires \"no_maillage  ref_noeud\")...\n\n";

  $SORTIES{'nb_sorties'}++;
  my $no_sortie = $SORTIES{'nb_sorties'};

  while($#_ != -1) {
    my $no_maillage = shift(@_);
    my $ref_noeud = shift(@_);

    ($no_maillage =~ /^\d+$/) or die "\n**Erreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) la paire maillage/ref noeud ($no_maillage $ref_noeud) n est pas conforme (le no maillage n est pas un entier)...\n\n";
    ($ref_noeud =~ /^\d+$/ or $ref_noeud =~ /^N/) or die "\n**Erreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) la paire maillage/ref noeud ($no_maillage $ref_noeud) n est pas conforme (ref noeud n est pas un entier ou une liste de reference de noeuds)...\n\n";

    push(@{$SORTIES{$no_sortie}{'no_maillage'}}, $no_maillage);
    push(@{$SORTIES{$no_sortie}{'ref_noeud'}}, $ref_noeud);
  }

  #verif maillage, existence ref noeud et remplissage des listes de noeuds (her et gmsh)
  for(my $i=0; $i<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $i++) {
    my $no_maillage = $SORTIES{$no_sortie}{'no_maillage'}[$i];
    my $ref_noeud = $SORTIES{$no_sortie}{'ref_noeud'}[$i];

    #existence maillage
    ($no_maillage <= $FHER{'nb_maillages'}) or die "\n**Erreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) le numero de maillage ($no_maillage) est plus grand que le nombre total de maillages ($FHER{'nb_maillages'}...\n\n";

    #-- cas d un numero de noeud
    if($ref_noeud =~ /^\d+$/) {
      ($ref_noeud <= $FHER{$no_maillage}{'nb_noeuds'}) or die "\n**Erreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) le noeud $ref_noeud n existe pas dans le maillage $no_maillage (fichier $FHER{$no_maillage}{'fichier'})...\n\n";
      @{$SORTIES{$no_sortie}{'liste_noeuds_her'}[$i]} = ($ref_noeud);
    }
    #-- cas d une liste de reference
    else {
      #lecture du maillage concerne
      my ($nom_maillage, $nb_noeuds, $ref_tab_noeuds, $nb_elts, $ref_tab_elements, @ref_listes) = lecture_mail_her($FHER{$no_maillage}{'fichier'});
      #-on ajoute automatiquement la reference N_tout (tous les noeuds) si elle n existe pas
      if(not defined $ref_listes[0]->{'N_tout'}[0]) {
        push(@{$ref_listes[0]->{'N_tout'}}, 1 .. $nb_noeuds);
      }

      #verif existence reference
      (defined $ref_listes[0]->{$ref_noeud}[0]) or die "\nErreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) liste de reference $ref_noeud n existe pas dans le maillage $no_maillage (fichier $FHER{$no_maillage}{'fichier'})...\n\n";
      @{$SORTIES{$no_sortie}{'liste_noeuds_her'}[$i]} = @{$ref_listes[0]->{$ref_noeud}};
    }

    #conversion de la liste de noeuds en numerotation Gmsh
    # (on applique un decalage egal a la somme des noeuds des maillages precedant le maillage $no_maillage)
    my $decalage_no_noeud_Gmsh = 0;
    for(my $j=1; $j<=$no_maillage-1; $j++) {$decalage_no_noeud_Gmsh += $FHER{$j}{'nb_noeuds'};}
    foreach my $noeud_her (@{$SORTIES{$no_sortie}{'liste_noeuds_her'}[$i]}) {
      push(@{$SORTIES{$no_sortie}{'liste_noeuds_Gmsh'}[$i]}, $noeud_her + $decalage_no_noeud_Gmsh);
    }

  }

  while(<FIC>) {
    $nb_ligne_cmd++;

    next if(/^\s*\#/);
    s/\s*#.*$//;
    next if(/^\s*$/);
    next if(not /^\s*(STAT)?\s*\S+/);

    #on repere si une STATISTIQUE a ete demandee
    if(/^\s*STAT\s+/) {
      s/\s*STAT\s+//;
      $SORTIES{$SORTIES{'nb_sorties'}}{'STAT'} = 1;
    }

    my @grandeurs = split;
    
    #verif des grandeurs demandees
    foreach my $grandeur (@grandeurs) {
      (defined $table_grandeurs_rep_Gmsh{$grandeur}) or die "\nErreur (prog:$NOM_PROG) : (ligne $nb_ligne_cmd fichier $fic_cmd) grandeur $grandeur n existe pas dans le repertoire Gmsh $rep_Gmsh/ ...\n\n";
      push(@{$SORTIES{$no_sortie}{'liste_grandeurs'}}, $grandeur);
    }

    last;
  }#while(<FIC>)

}#while(<FIC>)
close(FIC);


($SORTIES{'nb_sorties'} > 0) or die "\nErreur (prog:$NOM_PROG) : aucune sortie n a ete trouve dans le fichier $fic_cmd ...\n\n";



#ecriture de l en-tete du fichier .maple
#
#
#
open(Fmaple, ">$fic_maple_a_creer");

print Fmaple "#------- script : $NOM_PROG (version $VERSION) -------\n";
print Fmaple "#\n";
print Fmaple "#fichier de commande : $fic_cmd\n";
print Fmaple "#repertoire Gmsh : $rep_Gmsh/\n";
print Fmaple "#\n";
print Fmaple "#--------------------------------------\n";
print Fmaple "#lien entre grandeur et fichier .pos\n";
print Fmaple "#--------------------------------------\n";
foreach my $grandeur (@{$table_grandeurs_rep_Gmsh{'liste_grandeurs'}}) {
  print Fmaple "#  - $grandeur   ==>  fichier : $table_grandeurs_rep_Gmsh{$grandeur}{'fichier'}\n";
}
print Fmaple "#\n";
print Fmaple "#----------------------------\n";
print Fmaple "#description des colonnes\n";
print Fmaple "#----------------------------\n";
print Fmaple "#\n";
my $nb_colonnes = 1;
print Fmaple "#[$nb_colonnes] temps\n";
print Fmaple "#\n";
for(my $no_sortie=1; $no_sortie<=$SORTIES{'nb_sorties'}; $no_sortie++) {

  my @grandeurs = @{$SORTIES{$no_sortie}{'liste_grandeurs'}};
  my $is_STAT = 0; $is_STAT = 1 if(defined $SORTIES{$no_sortie}{'STAT'});

  print Fmaple "#\n";
  print Fmaple "#-- sortie $no_sortie --\n";
  print Fmaple "#  ----------------------------------\n";
  print Fmaple "#  > liste grandeurs : @grandeurs\n";
  print Fmaple "#     ==> STATISTIQUE (somme, moyenne, min, max)\n" if($is_STAT);
  print Fmaple "#  > listes noeuds  :\n";
  for(my $i=0; $i<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $i++) {
    print Fmaple "#      - maillage : $FHER{$SORTIES{$no_sortie}{'no_maillage'}[$i]}{'fichier'} / liste noeuds : $SORTIES{$no_sortie}{'ref_noeud'}[$i]\n";
  }
  print Fmaple "#  ----------------------------------\n";

  #cas d une STATISTIQUE
  if($is_STAT) {
    print Fmaple "# STATISTIQUE :";
    foreach my $grandeur (@grandeurs) {
      print Fmaple " ";
      my $nb_comp = $table_grandeurs_rep_Gmsh{$grandeur}{'nb_composantes'};
      if($nb_comp == 1) {
        $nb_colonnes++;
        print Fmaple " [$nb_colonnes] $grandeur(SOMME)";
        $nb_colonnes++;
        print Fmaple " [$nb_colonnes] $grandeur(MOYENNE)";
        $nb_colonnes++;
        print Fmaple " [$nb_colonnes] $grandeur(MIN)";
        $nb_colonnes++;
        print Fmaple " [$nb_colonnes] $grandeur(MAX)";
      }
      else {
        for(my $i=1; $i<=$nb_comp; $i++) {
          $nb_colonnes++;
          print Fmaple " [$nb_colonnes] $grandeur(comp_$i, SOMME)";
          $nb_colonnes++;
          print Fmaple " [$nb_colonnes] $grandeur(comp_$i, MOYENNE)";
          $nb_colonnes++;
          print Fmaple " [$nb_colonnes] $grandeur(comp_$i, MIN)";
          $nb_colonnes++;
          print Fmaple " [$nb_colonnes] $grandeur(comp_$i, MAX)";

          print Fmaple "\n#             : " if($i != $nb_comp);
        }
      }
    }
    print Fmaple "\n";
  }

  #cas normal
  else {
    for(my $i=0; $i<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $i++) {
      my @liste_noeuds_her = @{$SORTIES{$no_sortie}{'liste_noeuds_her'}[$i]};

      foreach my $no_noeud_her (@liste_noeuds_her) {
        print Fmaple "# noeud\_$no_noeud_her  :";
        foreach my $grandeur (@grandeurs) {
          print Fmaple " ";
          my $nb_comp = $table_grandeurs_rep_Gmsh{$grandeur}{'nb_composantes'};
          if($nb_comp == 1) {
            $nb_colonnes++;
            print Fmaple " [$nb_colonnes] $grandeur";
          }
          else {
            for(my $i=1; $i<=$nb_comp; $i++) {
              $nb_colonnes++;
              print Fmaple " [$nb_colonnes] $grandeur(comp_$i)";
            }
          }
        }
        print Fmaple "\n";
      }
    }
  }

}#for(my $no_sortie=1; $no_sortie<=$SORTIES{'nb_sorties'}; $no_sortie++)

print Fmaple "#\n";
print Fmaple "#\n";
print Fmaple "\n";



#---------------------------
#ecriture des donnees
#---------------------------

#-d abord : saisie du temps (on se base sur le fichier .pos de la premiere grandeur de la table des grandeurs)
my @liste_temps;
$_ = $table_grandeurs_rep_Gmsh{'liste_grandeurs'}[0];
my $fic = $table_grandeurs_rep_Gmsh{$_}{'fichier'};
open(FIC, "<$fic");
while(<FIC>) {
  next if(not /^\s*\$nodedata\s*$/io);
  for(1 .. 3) {<FIC>;}
  $_ = <FIC>;
  my ($temps) = split;
  ($temps =~ /^$format_reel$/) or die "\nErreur (prog:$NOM_PROG) : temps non conforme ($temps) ligne $. du fichier $fic ...\n\n";
  push(@liste_temps, $temps);
}
close(FIC);



#-ensuite comme on va lire les fichiers nodedata par nodedata simultanement
# => on les ouvre tous via un hash de handle de fichiers
my %handle;
# => on cree la liste de noeuds (numerotation Gmsh) concernes pour chaque grandeur parmi toutes les sorties
my %liste_noeuds_Gmsh_grandeur;# @{$liste_noeuds_Gmsh_grandeur{nom grandeur}} = (liste de noeuds triee ordre croissant)
# => on creera un hash de valeur que l on rangera correctement dans l ordre des colonnes prevu
my %hash_valeurs;# $hash_valeurs{no noeud Gmsh}{grandeur}{no composante} = valeur
#                    (NB : no noeud Gmsh vient de la liste @{$SORTIES{no_sortie}{'liste_noeuds_Gmsh'})

#creation du handle de fichier pour chaque grandeur demandee
my %table_tmp_grandeurs_demandees;
my @liste_grandeurs_demandees;
my %handle_line_number;#  (NB : hash permettant de connaitre la ligne courante de chaque fichier pour plus tard)
for(my $no_sortie=1; $no_sortie<=$SORTIES{'nb_sorties'}; $no_sortie++) {
  foreach my $grandeur (@{$SORTIES{$no_sortie}{'liste_grandeurs'}}) {
    if(not defined $table_tmp_grandeurs_demandees{$grandeur}) {
      $table_tmp_grandeurs_demandees{$grandeur} = 1;
      push(@liste_grandeurs_demandees, $grandeur);
      $handle{$grandeur} = IO::File->new();
      $handle{$grandeur}->open("<$table_grandeurs_rep_Gmsh{$grandeur}{'fichier'}");
      $handle_line_number{$grandeur} = 0;
    }
  }
}

#liste de noeuds (numerotation Gmsh) concernes pour chaque grandeur parmi toutes les sorties
for(my $no_sortie=1; $no_sortie<=$SORTIES{'nb_sorties'}; $no_sortie++) {
  my @grandeurs = @{$SORTIES{$no_sortie}{'liste_grandeurs'}};

  for(my $i=0; $i<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $i++) {
    my @liste_noeuds_Gmsh = @{$SORTIES{$no_sortie}{'liste_noeuds_Gmsh'}[$i]};

    foreach my $grandeur (@grandeurs) {
      push(@{$liste_noeuds_Gmsh_grandeur{$grandeur}}, @liste_noeuds_Gmsh);
    }
  }
}
#tri ordre croissant et suppression des doublons eventuels
foreach my $grandeur (@liste_grandeurs_demandees) {
  @{$liste_noeuds_Gmsh_grandeur{$grandeur}} = sort {$a <=> $b} @{$liste_noeuds_Gmsh_grandeur{$grandeur}};
  @{$liste_noeuds_Gmsh_grandeur{$grandeur}} = uniq @{$liste_noeuds_Gmsh_grandeur{$grandeur}};
}


#debut de la lecture
foreach my $temps (@liste_temps) {

  #positionnement de tous les fichiers sur le prochain $nodedata (et verif du temps)
  #  plus exactement : on se positionnera juste avant le debut des valeurs noeud composantes... du nodedata
  foreach my $grandeur (@liste_grandeurs_demandees) { 
    while($_ = $handle{$grandeur}->getline) {
      $handle_line_number{$grandeur}++;
      last if(/^\s*\$nodedata\s*$/io);
    }
    #verif temps
    for(1 .. 3) {$handle{$grandeur}->getline; $handle_line_number{$grandeur}++;}
    $_ = $handle{$grandeur}->getline; $handle_line_number{$grandeur}++;
    my ($temps_) = split;
    ($temps_ == $temps) or die "\nErreur (prog:$NOM_PROG) : temps non conforme ($temps) ligne $handle_line_number{$grandeur} du fichier $table_grandeurs_rep_Gmsh{$grandeur}{'fichier'} ...\n\n";
    #positionnement final juste avant le debut des valeurs du nodedata
    for(1 .. 4) {$handle{$grandeur}->getline; $handle_line_number{$grandeur}++;}
  }


  #parcours de chaque grandeur
  #pour l instant on parcours les noeuds de chaque sortie dans l ordre croissant et dans la numerotation Gmsh
  #==> remplissage de $hash_valeurs{no noeud Gmsh}{grandeur}{no composante}
  foreach my $grandeur (@liste_grandeurs_demandees) {
    foreach my $no_noeud_Gmsh (@{$liste_noeuds_Gmsh_grandeur{$grandeur}}) {
      while($_ = $handle{$grandeur}->getline) {
        $handle_line_number{$grandeur}++;
        @_ = split;
        next if($_[0] != $no_noeud_Gmsh);

        for(my $no_comp=1; $no_comp<=$#_; $no_comp++) {
          $hash_valeurs{$no_noeud_Gmsh}{$grandeur}{$no_comp} = $_[$no_comp];
        }
        last;
      }
    }
  }

  #parcours de chaque sortie dans le meme ordre que l en-tete afin d ecrire les colonnes dans le bon ordre
  #-ecriture du temps
  print Fmaple "$temps";

  #-ecriture des grandeurs pour chaque sortie
  for(my $no_sortie=1; $no_sortie<=$SORTIES{'nb_sorties'}; $no_sortie++) {

    my @grandeurs = @{$SORTIES{$no_sortie}{'liste_grandeurs'}};
    my $is_STAT = 0; $is_STAT = 1 if(defined $SORTIES{$no_sortie}{'STAT'});

    #cas d une STATISTIQUE
    if($is_STAT) {
      foreach my $grandeur (@grandeurs) {

        my $nb_comp = $table_grandeurs_rep_Gmsh{$grandeur}{'nb_composantes'};

        if($nb_comp == 1) {
          my $somme = 0.;
          my $moyenne;
          my ($min,$max);
          my $nb_val = 0;
          for(my $i=0; $i<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $i++) {
            my @liste_noeuds_Gmsh = @{$SORTIES{$no_sortie}{'liste_noeuds_Gmsh'}[$i]};
            $nb_val += $#liste_noeuds_Gmsh + 1;

            foreach my $no_noeud_Gmsh (@liste_noeuds_Gmsh) {
              my $val = $hash_valeurs{$no_noeud_Gmsh}{$grandeur}{1};
              $somme += $val;
              $min = $max = $val if(not defined $min);
              $min = $val if($val < $min);
              $max = $val if($val > $max);
            }
          }
          $moyenne = $somme/$nb_val;
          print Fmaple " $somme $moyenne $min $max";
        }
        else {
          for(my $i=1; $i<=$nb_comp; $i++) {
            my $somme = 0.;
            my $moyenne;
            my ($min,$max);
            my $nb_val = 0;
            for(my $j=0; $j<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $j++) {
              my @liste_noeuds_Gmsh = @{$SORTIES{$no_sortie}{'liste_noeuds_Gmsh'}[$j]};
              $nb_val += $#liste_noeuds_Gmsh + 1;

              foreach my $no_noeud_Gmsh (@liste_noeuds_Gmsh) {
                my $val = $hash_valeurs{$no_noeud_Gmsh}{$grandeur}{$i};
                $somme += $val;
                $min = $max = $val if(not defined $min);
                $min = $val if($val < $min);
                $max = $val if($val > $max);
              }
            }
            $moyenne = $somme/$nb_val;
            print Fmaple " $somme $moyenne $min $max";
          }#for(my $i=1; $i<=$nb_comp; $i++)
        }#else
      }#foreach my $grandeur (@grandeurs)
    }#if($is_STAT)

    #cas normal
    else {
      for(my $i=0; $i<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $i++) {
        my @liste_noeuds_Gmsh = @{$SORTIES{$no_sortie}{'liste_noeuds_Gmsh'}[$i]};

        foreach my $no_noeud_Gmsh (@liste_noeuds_Gmsh) {
          foreach my $grandeur (@grandeurs) {
            my $nb_comp = $table_grandeurs_rep_Gmsh{$grandeur}{'nb_composantes'};
            if($nb_comp == 1) {
              print Fmaple " $hash_valeurs{$no_noeud_Gmsh}{$grandeur}{1}";
            }
            else {
              for(my $j=1; $j<=$nb_comp; $j++) {
                print Fmaple " $hash_valeurs{$no_noeud_Gmsh}{$grandeur}{$j}";
              }
            }
          }#foreach my $grandeur (@grandeurs)
        }#foreach my $no_noeud_Gmsh (@liste_noeuds_Gmsh)
      }#for(my $i=0; $i<=$#{$SORTIES{$no_sortie}{'no_maillage'}}; $i++)
    }#else
  }#for(my $no_sortie=1; $no_sortie<=$SORTIES{'nb_sorties'}; $no_sortie++)
  print Fmaple "\n";


}#foreach my $temps (@liste_temps)



close(Fmaple);

#fermeture des fichiers .pos
foreach my $grandeur (@liste_grandeurs_demandees) {
  close($handle{$grandeur});
}

print "\nFichier cree : $fic_maple_a_creer\n\n";





#----------------
#subroutine make_table_grandeurs_Gmsh
#
#  construction de la table de hashage des grandeurs d un repertoire Gmsh
#
#  entree :
#    - repertoire Gmsh
#    - reference vers la table de hashage des grandeurs du repertoire Gmsh
#
sub make_table_grandeurs_Gmsh {
  my $rep_Gmsh = shift;
  my $ref_table_grandeurs = shift;

  my @fpos;
  foreach my $fichier (bsd_glob("$rep_Gmsh/*_Gmsh.pos")) {
    (-T $fichier) or next;
    is_fic_pos_valide($fichier) or next;

    my $fichier_bn = basename $fichier;
    push(@fpos, $fichier_bn);
  }

  ###inutile depuis version 1.02 => my $racine_commune = chaine_commune(@fpos);

  foreach my $fpos (@fpos) {
    my $grandeur = get_nom_grandeur_fpos("$rep_Gmsh/$fpos");

    #cas ou cette grandeur a deja ete trouve => on ne peut pas avoir 2 fichiers .pos de meme grandeur
    if(defined $ref_table_grandeurs->{$grandeur}{'fichier'}) {
      die "\nErreur (prog:$NOM_PROG) : (subroutine make_table_grandeurs_Gmsh) la grandeur $grandeur correspond a 2 fichiers .pos differents :\
         - fichier 1 : $ref_table_grandeurs->{$grandeur}{'fichier'}\
         - fichier 2 : $rep_Gmsh/$fpos\
         ===> effacer l un des fichiers sinon le programme $NOM_PROG ne peut fonctionner...\n\n";
    }

    $ref_table_grandeurs->{$grandeur}{'fichier'} = "$rep_Gmsh/$fpos";
    $ref_table_grandeurs->{$grandeur}{'nb_composantes'} = get_nb_comp_fpos("$rep_Gmsh/$fpos");

    push(@{$ref_table_grandeurs->{'liste_grandeurs'}}, $grandeur);
  }

}#sub make_table_grandeurs_Gmsh
#----------------


#----------------
#subroutine get_nom_grandeur_fpos
#
# lit le nom de la grandeur liee a un fichier .pos
#(lecture du nom de grandeur du premier nodedata trouve dans le fichier)
#
#  entree :
#    - fichier .pos
#
#  sortie :
#    - nom grandeur
#
sub get_nom_grandeur_fpos {
  my $fpos = shift;

  my $nom_grandeur;
  open(my $Hlocal, "<$fpos");
  while(<$Hlocal>) {
    next if(not /^\s*\$nodedata\s*$/io);
    <$Hlocal>;
    $_ = <$Hlocal>;
    ($nom_grandeur) = split;
    $nom_grandeur =~ s/^[\"\']+//;
    $nom_grandeur =~ s/[\"\']+$//;
    last;
  }
  close($Hlocal);

  defined($nom_grandeur) or die "\nErreur (prog:$NOM_PROG) : (subroutine get_nom_grandeur_fpos) impossible de trouver le nom de grandeur dans le fichier $fpos ...\n\n";

  return $nom_grandeur;
}#sub get_nom_grandeur_fpos
#----------------


#----------------
#subroutine get_nb_comp_fpos
#
#  saisie du nombre de composantes d une grandeur dans un fichier Gmsh .pos
#
#  entree :
#    - nom fichier .pos
#
#  sortie :
#    - nombre de composantes
#
sub get_nb_comp_fpos {
  my $fpos = shift;

  open(my $Hlocal, "<$fpos");
  while(<$Hlocal>) {
    next if(not /^\s*\$nodedata\s*$/io);
    for(1 .. 6) {<$Hlocal>;}
    $_ = <$Hlocal>;
    my ($nb_comp) = split;
    ($nb_comp =~ /^\d+$/) or die "\nErreur (prog:$NOM_PROG) : impossible de lire le nombre de composantes dans le fichier $fpos ...\n\n";
    close($Hlocal);
    return $nb_comp;
  }
  close($Hlocal);

  die "\nErreur (prog:$NOM_PROG) : impossible de lire le nombre de composantes dans le fichier $fpos ...\n\n";
}#sub get_nb_comp_fpos
#----------------



#----------------
#subroutine print_fic_cmd
#
#  ecriture d un fichier exemple de commande
#
#  entree :
#    - nom fichier a creer
sub print_fic_cmd {
  my $fic_cmd = shift;

  open(my $Hlocal, ">$fic_cmd");
  print $Hlocal 'MAILLAGES #mot-cle de declaration des fichiers maillage
nom_fichier_1.her
nom_fichier_2.her


SORTIES #mot-cle de declaration des sorties de grandeurs

#sortie des grandeurs EPS11 et SIG11
# pour les noeuds de la liste N_tout du maillage 1 
1 N_tout
EPS11 SIG11

#sortie des grandeurs Def_principaleI et Sigma_principaleI
# pour le noeud 129 du maillage 2
2 129
Def_principaleI Sigma_principaleI

#sortie des grandeurs def_duale_mises et contrainte_mises
# pour les noeuds de la liste N_S du maillage 1 
1 N_S
def_duale_mises contrainte_mises

#sortie des grandeurs def_duale_mises et contrainte_mises
# statistiques sur les valeurs aux noeuds de la liste N_S du maillage 1 
1 N_S
STAT  def_duale_mises contrainte_mises

#sortie de la grandeur deplace
# statistiques sur les valeurs aux noeuds de la liste N_E du maillage 1 
# et de la liste N_O du maillage 2
1 N_E  2 N_O
STAT   deplace
';

  close($Hlocal);
}#sub print_fic_cmd
#----------------


#----------------
#subroutine is_fic_pos_valide
#
#  verification rapide de la valide d un fichier .pos (par une heuristique : presence du mot-cle $nodedata au moins une fois)
#
#  entree :
#    - nom fichier a verifier
#
#  sortie :
#    - indicateur (1 si fichier valide, sinon 0)
#
sub is_fic_pos_valide {
  my $fic = shift;

  open(my $Hlocal, "<$fic");
  while(<$Hlocal>) {
    next if(not /^\s*\$nodedata\s*$/io);
    close($Hlocal);
    return 1;
  }
  close($Hlocal);

  return 0;
}#sub is_fic_pos_valide


#----------------
#subroutine nb_noeuds_maillage
#
#  renvoie le nombre de noeuds si le fichier est un maillage .her valide (par une heuristique sur NOEUDS)
#  sinon 0
#
#  entree :
#    - nom fichier
#
#  sortie :
#    - nombre de noeuds (ou 0 si le maillage n est pas valide)
sub nb_noeuds_maillage {
  my $fher = shift;

  my $nb_noeuds = 0;

  open(my $Hlocal, "<$fher");
  while(<$Hlocal>) {
    next if(not /^\s*(\d+)\s+NOEUDS/o);
    $nb_noeuds = $1;
    last;
  }
  close($Hlocal);

  return $nb_noeuds;
}#sub nb_noeuds_maillage


#----------------
#subroutine chaine_commune
#
#  determine la chaine de caracteres commune a une liste de chaine de caractere (en commencant par le debut des chaines)
#
#  entree :
#    - liste de chaines de caracteres
#
#  sortie :
#    - chaine commune
#
sub chaine_commune {
  my @liste = @_;

  return '' if($#liste == -1);

  my $chaine_commune = '';
  MAIN:while(length($liste[0]) > 0) {
    $liste[0] =~ s/^(.)//;
    my $lettre_commune = $1;
    for(my $i=1; $i<=$#liste; $i++) {
      last MAIN if(length($liste[$i]) == 0);
      $liste[$i] =~ s/^(.)//;
      my $lettre = $1;
      last MAIN if($lettre ne $lettre_commune);
    }
    $chaine_commune .= $lettre_commune;
  }

  return $chaine_commune;
}#sub chaine_commune



#----------------
#sub qui lit un maillage herezh++ pour recuperer les noeuds, les elements et les listes de references
#et les renvoier sous forme de reference (lecture du .her et d un .lis si il existe)
#
# exemple d appel :
#  my ($nom_maillage, $nb_noeuds, $ref_tab_noeuds, $nb_elts, $ref_tab_elements, @ref_listes) = lecture_mail_her("fic_her");
#
#  avec - $nom_maillage     : nom du maillage (si il y en a un. sinon $nom_maillage sera egal a undef
#       - $nb_noeuds        : nombre de noeuds (entier)
#       - $ref_tab_noeuds   : reference vers un tableau de noeuds => $ref_tab_noeuds->[no noeud][0] : coordonnee x
#                                                                    $ref_tab_noeuds->[no noeud][1] : coordonnee y
#                                                                    $ref_tab_noeuds->[no noeud][2] : coordonnee z)
#       - $nb_elts          : nombre d elements (entier)
#       - $ref_tab_elements : reference vers une table de hashage => $ref_tab_elements->{no elt}{'TYPE'}      : type d element
#                                                                    @{$ref_tab_elements->{no elt}{'CONNEX'}} : (liste des noeuds)
#       - @ref_listes       : liste de references vers les tables de hashage contenant les listes de references de noeuds, aretes, faces et elements
#                             => $ref_listes[0] : reference vers la table de hashage des listes de noeuds  => @{$ref_listes[0]->{'nom liste'}} : (liste des noeuds)
#                                $ref_listes[1] : reference vers la table de hashage des listes d aretes   => @{$ref_listes[1]->{'nom liste'}} : (liste des aretes)
#                                $ref_listes[2] : reference vers la table de hashage des listes de faces   => @{$ref_listes[2]->{'nom liste'}} : (liste des faces)
#                                $ref_listes[3] : reference vers la table de hashage des listes d elements => @{$ref_listes[3]->{'nom liste'}} : (liste des elements)
#                                $ref_listes[4] : reference vers la table de hashage des listes de points d integration => @{$ref_listes[4]->{'nom liste'}} : (liste des points d integration)
#                                
sub lecture_mail_her {
  my $fher = shift;

  my $nom_maillage;

  #------------------------
  # lecture du maillage .her
  #------------------------
  #-lecture de noeuds
  my @tab_noeuds; my $nb_noeuds;
  my $no_noeud = 0;
  open(Fher, "<$fher");
  while(<Fher>) {
    if(/^\s*nom_maillage\s+(\S+)/o) {$nom_maillage = $1; next;}
    next if(not /(\d+)\s+NOEUDS/o);
    $nb_noeuds = $1;
    last;
  }
  while(<Fher>) {
    last if($no_noeud == $nb_noeuds);
    next if(not /^\s*(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s*$/o);
    $no_noeud = $1;
    @{$tab_noeuds[$no_noeud]} = ($2,$3,$4);
  }

  #-lecture des elements
  my %tab_elements; my $nb_elts;
  my $no_elt = 0;
  while(<Fher>) {
    next if(not /(\d+)\s+ELEMENTS/o);
    $nb_elts = $1;
    last;
  }
  while(<Fher>) {
    last if($no_elt == $nb_elts);
    next if(not /^\s*\d+\s+\w+\s+\w+/o);
    s/^\s+//;s/\s+$//;
    $_ =~ /^(\d+)\s+/;
    $no_elt = $1; s/^(\d+)\s+//;
    $_ =~ /\s+(\d+(?:\s+\d+)*)$/;
    @{$tab_elements{$no_elt}{'CONNEX'}} = split(/\s+/, $1); s/\s+(\d+(?:\s+\d+)*)$//;
    $tab_elements{$no_elt}{'TYPE'} = $_; $tab_elements{$no_elt}{'TYPE'} =~ s/\s+/ /g;
  }
  close(Fher);


  #------------------------
  # lecture des references (dans le .her et dans un eventuel .lis)
  #------------------------
  my $flis = $fher; $flis =~ s/.her$/.lis/;
  my $nom_liste;
  my $is_liste_en_cours;
  my %listes_NOEUDS;
  my %listes_ARETES;
  my %listes_FACES;
  my %listes_ELEMENTS;
  my %listes_PTI;

  #-dans le .her
  open(Fher, "<$fher");
  $is_liste_en_cours = 0;
  while(<Fher>) {
    chomp;
    if(/^\s*(N\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*N\S+\s+//; s/\s+$//;
      push(@{$listes_NOEUDS{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/i or /^\s*[AFEG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_NOEUDS{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Fher);

  open(Fher, "<$fher");
  $is_liste_en_cours = 0;
  while(<Fher>) {
    chomp;
    if(/^\s*(A\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*A\S+\s+//; s/\s+$//;
      push(@{$listes_ARETES{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/i or /^\s*[NFEG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_ARETES{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Fher);

  open(Fher, "<$fher");
  $is_liste_en_cours = 0;
  while(<Fher>) {
    chomp;
    if(/^\s*(F\S+)/) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*F\S+\s+//; s/\s+$//;
      push(@{$listes_FACES{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/i or /^\s*[NAEG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_FACES{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Fher);

  open(Fher, "<$fher");
  $is_liste_en_cours = 0;
  while(<Fher>) {
    chomp;
    if(/^\s*(E\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*E\S+\s+//; s/\s+$//;
      push(@{$listes_ELEMENTS{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/io or /^\s*[NAFG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_ELEMENTS{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Fher);

  open(Fher, "<$fher");
  $is_liste_en_cours = 0;
  while(<Fher>) {
    chomp;
    if(/^\s*(G\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*G\S+\s+//; s/\s+$//;
      push(@{$listes_PTI{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/io or /^\s*[NAFE]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_PTI{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Fher);


  #dans le .lis (si il existe)
  if(-e $flis) {

  open(Flis, "<$flis");
  $is_liste_en_cours = 0;
  while(<Flis>) {
    chomp;
    if(/^\s*(N\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*N\S+\s+//; s/\s+$//;
      push(@{$listes_NOEUDS{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/io or /^\s*[AFEG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_NOEUDS{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Flis);

  open(Flis, "<$flis");
  $is_liste_en_cours = 0;
  while(<Flis>) {
    chomp;
    if(/^\s*(A\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*A\S+\s+//; s/\s+$//;
      push(@{$listes_ARETES{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/io or /^\s*[NFEG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_ARETES{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Flis);

  open(Flis, "<$flis");
  $is_liste_en_cours = 0;
  while(<Flis>) {
    chomp;
    if(/^\s*(F\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*F\S+\s+//; s/\s+$//;
      push(@{$listes_FACES{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/io or /^\s*[NAEG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_FACES{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Flis);

  open(Flis, "<$flis");
  $is_liste_en_cours = 0;
  while(<Flis>) {
    chomp;
    if(/^\s*(E\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*E\S+\s+//; s/\s+$//;
      push(@{$listes_ELEMENTS{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/io or /^\s*[NAFG]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_ELEMENTS{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Flis);

  open(Flis, "<$flis");
  $is_liste_en_cours = 0;
  while(<Flis>) {
    chomp;
    if(/^\s*(G\S+)/o) {
      $nom_liste = $1;
      $is_liste_en_cours = 1;
      s/^\s*G\S+\s+//; s/\s+$//;
      push(@{$listes_PTI{$nom_liste}},split(/\s+/,$_));
    }
    elsif(/^\s*noeuds/io or /^\s*elements/io or /^\s*[NAFE]/o) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/io) {
      s/^\s+//; s/\s+$//;
      push(@{$listes_PTI{$nom_liste}},split(/\s+/,$_));
    }
  }
  close(Flis);

  }#if(-e $flis)

  #AFFICHAGE DES LISTES DE NOEUDS
  #foreach my $nom (keys(%listes_NOEUDS)) {
  #  print "$nom : @{$listes_NOEUDS{$nom}}\n";
  #}
  #AFFICHAGE DES LISTES D ARETES
  #foreach my $nom (keys(%listes_ARETES)) {
  #  print "$nom : @{$listes_ARETES{$nom}}\n";
  #}
  #AFFICHAGE DES LISTES DE FACES
  #foreach my $nom (keys(%listes_FACES)) {
  #  print "$nom : @{$listes_FACES{$nom}}\n";
  #}
  #AFFICHAGE DES LISTES D ELEMENTS
  #foreach my $nom (keys(%listes_ELEMENTS)) {
  #  print "$nom : @{$listes_ELEMENTS{$nom}}\n";
  #}
  #AFFICHAGE DES LISTES DE POINTS D INTEGRATION
  #foreach my $nom (keys(%listes_PTI)) {
  #  print "$nom : @{$listes_PTI{$nom}}\n";
  #}

  return($nom_maillage, $nb_noeuds, \@tab_noeuds, $nb_elts, \%tab_elements,
         \%listes_NOEUDS, \%listes_ARETES,
         \%listes_FACES, \%listes_ELEMENTS, \%listes_PTI);
}#sub lecture_mail_her
