#!/usr/bin/env perl
use strict;
use warnings;
use English;
use File::Basename;
use File::Spec::Functions qw(rel2abs);
use Cwd;
my $NOM_PROG = basename $PROGRAM_NAME;
#pattern d un reel pour les regex
my $format_reel = '[+-]?[\.]?\d+[\.]?\d*(?:[eE][+-]?\d*)?';


my $VERSION = '1.00';
#####################################################################################################
#  script pour visualiser un ou plusieurs maillages dans Gmsh                                       #
#  version 1.00 : version initiale                                                                  #
#####################################################################################################











# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# VARIABLES QUE L UTILISATEUR PEUT ETRE AMENE A RENSEIGNER  #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# les variables $exeHZ et $exeGMSH servent a imposer le choix des executables Herezh et Gmsh
#   (rq : les alias shell ne fonctionneront pas)
#
#commande HZ++ definie par l utilisateur (modifiable egalement avec l option -exeHZ)
my $exeHZ; # = 'mon_executable_a_moi';
#commande gmsh definie par l utilisateur (modifiable egalement avec l option -exeGMSH)
my $exeGMSH; # = 'mon_executable_a_moi';


#commande Herezh par defaut selon la plateforme
#  rq : ces variables seront utilisees uniquement si la variable $exeHZ n a pas ete definie
my $EXE_HZ_Linux64bits = 'HZppfast64';#linux 64 bits
my $EXE_HZ_MacOSX = 'HZppfast_Vn-1';#MacOSX
my $EXE_HZ_autres = 'HZppfast';#tous les autres systemes
#commande gmsh par defaut (quelque soit la plateforme)
#  rq : cette variable sera utilisee uniquement si la variable $exeGMSH n a pas ete definie
my $exeGMSH_defaut = 'gmsh';

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# FIN VARIABLES UTILISATEUR                                 #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #






sub affichage_aide {
  use Text::Wrap;
  #config du package Text::Wrap
  $Text::Wrap::columns = 81;#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 : visualiser la position des points d integration d un\n";
  print "      element avec Gmsh\n";
  print "\n";
  print "Usage : $NOM_PROG [-h|help] [-exeHZ path_HZ] [-exeGMSH path_GMSH] fher no_elt\n";
  print "\n";
  print "Dependance :\n";
  print "    > script hz_splitMail.pl\n";
  print "\n";
  print "Fonctionnement :\n";
  print wrap("      ", "    ", "$NOM_PROG lance des calculs herezh pour lire la ",
                               "position des points d integration dans le .maple et ",
                               "cree une visu Gmsh de l element et ses points ",
                               "d integration\n");
  print "\n";
  print "Arguments :\n";
  print "     o fher   : fichier .her\n";
  print "     o no_elt : numero de l element\n";
  print "\n";
  print "Options :\n";
  print "    -v : affichage du numero de version\n";
  print "\n";
  print wrap("    ", "                     ", "-exeHZ path_HZ : choisir l executable Herezh++. Le calcul Herezh se ",
                                                               "fera avec l executable path_HZ\n",
                                                               "par defaut : linux 64 bits   => path_HZ=HZppfast64\n", 
                                                               "             MacOSX (darwin) => path_HZ=HZppfast_Vn-1\n",
                                                               "             autres          => path_HZ=HZppfast\n",
                                                               "(a noter que les alias shell ne fonctionneront pas)\n");
  print "\n";
  print wrap("    ", "                         ", "-exeGMSH path_GMSH : choisir l executable Gmsh. La visualisation Gmsh se ",
                                                                       "fera avec l executable path_GMSH\n",
                                                                       "par defaut : path_GMSH=gmsh\n",
                                                                       "(a noter que les alias shell ne fonctionneront pas)\n");
  print "\n";
  print "Remarque :\n";
  print "    Liste des elements supportes par ce script :\n";
  foreach my $type_elt (conversion_eltType_her2gmsh('-liste_elts',0)) {
    print "      > $type_elt\n";
  }
  print "\n";
  print "Auteur :\n";
  print "   TROUFFLARD Julien\n";
  print "       julien.troufflard\@univ-ubs.fr\n";
  print "       julien.troufflard\@free.fr\n";
  print "----------------------------------------\n";
  exit;
}



#------------------------------------
#premier balayage des arguments
# => si option du style -h ou -help => affichage aide
#------------------------------------
my $isOpt_help = 0;
foreach my $arg (@ARGV) {
  if(($arg =~ /^-h$/i) or ($arg =~ /^-help$/i)) {
    $isOpt_help = 1;
  }
}
#si option -h|-help ou pas d arguments => affichage aide
if($isOpt_help or ($#ARGV == -1)) {
  affichage_aide();
}

#------------------------------------
#recuperation des arguments et options
#------------------------------------
my $fher;#fichier .her
my $no_elt;#numero de l element

my $opt;
my @args;
while($#ARGV != -1) {
  $opt = shift(@ARGV);

  #affichage numero version
  if($opt eq '-v') {
    print "\n $NOM_PROG : version $VERSION\n\n";
    exit;
  }
  #option -exeHZ
  elsif($opt eq '-exeHZ') {
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG,opt:-exeHZ) : pas assez d arguments donnes pour cette option...\n\n";
    $exeHZ = shift(@ARGV);
  }
  #option -exeGMSH
  elsif($opt eq '-exeGMSH') {
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG,opt:-exeGMSH) : pas assez d arguments donnes pour cette option...\n\n";
    $exeGMSH = shift(@ARGV);
  }

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

($#args >= 1) or die "\nErreur (prog:$NOM_PROG) : arguments manquants...\n\n";
$fher = shift(@args);
$no_elt = shift(@args);


#---------------------
#verif de l executable Herezh
#---------------------
#si la variable $exeHZ n a pas ete renseigne au prealable => on selectionne l executable par defaut en fonction de la plateforme
if(not defined($exeHZ)) {
  #- - - - - -
  #type de plateforme
  #- - - - - -
  my $type_OS;
  #-avec uname
  if(verif_commande('uname')) {
    $type_OS = qx(uname -a);
    chomp($type_OS);
  }
  #-sinon : warning (OS inconnue)
  else {warn "**Attention : impossible de saisir le type de systeme d exploitation avec uname -a ...\n";}

  #selection de l executable Herezh
  #-linux 64 bits
  if($type_OS =~ /linux/i and $type_OS =~ /x86_64/i) {$exeHZ = $EXE_HZ_Linux64bits;}
  #-MacOSX (darwin)
  elsif($type_OS =~ /darwin/i) {$exeHZ = $EXE_HZ_MacOSX;}
  #-tous les autres (y compris linux 32 bits)
  else{$exeHZ = $EXE_HZ_autres;}
}
#verif de l executable Herezh
verif_commande($exeHZ) or die "\n**Erreur (prog:$NOM_PROG) : executable Herezh ($exeHZ) introuvable (pour eviter cette erreur : vous pouvez soit utiliser l option -exeHZ, soit renseigner directement la commande Herezh dans la variable \$exeHZ au debut du script)...\n\n";

#---------------------
#verif de l executable Gmsh
#---------------------
#si la variable $exeGMSH n a pas ete renseigne au prealable => on selectionne l executable par defaut
$exeGMSH = $exeGMSH_defaut if(not defined($exeGMSH));
#verif de l executable Gmsh
verif_commande($exeGMSH) or die "\n**Erreur (prog:$NOM_PROG) : executable Gmsh ($exeGMSH) introuvable (pour eviter cette erreur : vous pouvez soit utiliser l option -exeGMSH, soit renseigner directement la commande Gmsh dans la variable \$exeGMSH au debut du script)...\n\n";







#existence du fichier .info
(-e $fher) or die "\nErreur (prog:$NOM_PROG) : fichier $fher introuvable...\n\n";
#extension du fichier .her
($fher =~ /\.her$/) or die "\nErreur (prog:$NOM_PROG) : fichier $fher n a pas l extension .her ...\n\n";

#verif de l exe HZ++
defined(( verif_commande($exeHZ) )[0]) or die "\nErreur (prog:$NOM_PROG) : l executable HZ++ ($exeHZ) est introuvable dans les \$PATH ...\n\n";
#verif de hz_splitMail.pl
defined(( verif_commande("hz_splitMail.pl") )[0]) or die "\nErreur (prog:$NOM_PROG) : l executable hz_splitMail.pl est introuvable dans les \$PATH ...\n\n";


#verif du numero d element
($_, $_, $_, $_[0]) = lecture_mail_her($fher);
$_[1] = 'element'; $_[1] .= 's' if($_[0] > 1);#petite bidouille pour afficher "element" sans "s" si il y a un seul element dans le maillage
($no_elt <= $_[0]) or die "\nErreur (prog:$NOM_PROG) : element $no_elt n existe pas dans le maillage $fher (qui contient $_[0] $_[1]) ...\n\n";


#racine fichier visu Gmsh
my $racine_fvisu = "visu_Gmsh";

#repertoire temporaire
my $rep_tmp = "/tmp/$NOM_PROG\_$PID";
mkdir $rep_tmp or die "\nErreur (prog:$NOM_PROG) : impossible de creer le repertoire $rep_tmp (message d erreur : $!)\n\n";

#recopie du maillage vers le repertoire temporaire
system("cp $fher $rep_tmp/.");
#-- et son eventuel .lis
($_ = $fher) =~ s/.her$/.lis/;
system("cp $_ $rep_tmp/.") if(-e $_);

#deplacement vers le repertoire temporaire
my $rep_original = cwd;#repertoire d origine ...
$rep_original = rel2abs($rep_original);#... en chemin absolu
chdir $rep_tmp;



#
# pour l instant, on travaille sur un maillage reduit au seul element $no_elt
#  on retabliera le maillage original par la suite
#
my $no_elt_original = $no_elt;
my $fher_original = basename $fher;
$no_elt = 1;
$fher = "$racine_fvisu.her";

#constitution des listes des elements 1D, 2D et 3D
my @PREFIXE_1D = qw(POUT);
my @PREFIXE_2D = qw(TRIA QUAD);
my @SUFFIXE_AXI = qw(_AXI);
#-maillage de l element $no_elt uniquement (on utilise $racine_fvisu pour nommer ce maillage)
system("hz_splitMail.pl $fher_original $no_elt_original > redir.txt");
#-recuperation du .her qui nous interesse en sortie de hz_splitMail.pl 
my @fic_generes_par_split;
open(FIC, "<redir.txt");
while(<FIC>) {
  if(/\b(\S+.her)\b/) {
    push(@fic_generes_par_split, $1);
  }
}
close(FIC);
system("mv $fic_generes_par_split[0] $fher");
my ($nom_maillage, $nb_noeuds, $ref_noeuds, $nb_elts, $ref_elements, @ref_listes) = lecture_mail_her($fher);
my (@ELEM_1D, @ELEM_2D, @ELEM_3D);
ELEM:for(my $i=1; $i<=$nb_elts; $i++) {
  #verif si element AXI (donc loi 3D)
  foreach my $suffixe (@SUFFIXE_AXI) {
    @_ = split(/\s+/, $ref_elements->{$i}{'TYPE'});
    if($_[0] =~ /$suffixe\s*$/) {
      push(@ELEM_3D, $i);
      next ELEM;
    }
  }
  #verif si element 1D
  foreach my $prefixe (@PREFIXE_1D) {
    if($ref_elements->{$i}{'TYPE'} =~ /^\s*$prefixe/) {
      push(@ELEM_1D, $i);
      next ELEM;
    }
  }
  #verif si element 2D
  foreach my $prefixe (@PREFIXE_2D) {
    if($ref_elements->{$i}{'TYPE'} =~ /^\s*$prefixe/) {
      push(@ELEM_2D, $i);
      next ELEM;
    }
  }
  #sinon, c est un element 3D
  push(@ELEM_3D, $i);
}


#saisie des coordonnees des points d integration de l element (on incremente $no_pti jusqu a ce que le calcul soit echec)
my $no_pti = 0;
my @COORD_PTI;
print "\n... calcul HZ++ pour connaitre les coord des points d integration ...\n";
print "     (rq : c est normal que le dernier calcul genere une erreur de segmentation)\n";
while() {
  $no_pti++;

  #preparation du calcul
  my $racine_fher = $fher; $racine_fher =~ s/\.her$//;
  my $racine_tmp = $racine_fher.int(rand(9999999)); while(-e "$racine_tmp.info") {$racine_tmp = $racine_fher.int(rand(9999999));}
  my $finfo = $racine_tmp.'.info';
  my $fCVisu = $racine_tmp.'.CVisu';
  my $fmaple = $racine_tmp.'_princ.maple';
  print_finfo($finfo);
  print_fCVisu($fCVisu);

  #lancement du calcul
  system("$exeHZ -f $finfo > /dev/null");


  #lecture du .maple
  my ($col_X, $col_Y, $col_Z);
  open(FIC, "<$fmaple");
  while(<FIC>) {
    next if(not (/element_/ and /pt_integ_/));
    $col_X = $1 if(/\[\s*(\d+)\s*\]\s*X /);
    $col_Y = $1 if(/\[\s*(\d+)\s*\]\s*Y /);
    $col_Z = $1 if(/\[\s*(\d+)\s*\]\s*Z /);
    last;
  }
  my ($X,$Y,$Z);
  while(<FIC>) {
    next if(not /^\s*$format_reel/);
    s/^\s+//;
    @_ = split(/\s+/, $_);
    $X = $_[$col_X-1] if(defined $col_X);
    $Y = $_[$col_Y-1] if(defined $col_Y);
    $Z = $_[$col_Z-1] if(defined $col_Z);
    last;
  }
  close(FIC);

  #destruction des fichiers de calcul
  system("rm -f $finfo $fCVisu $fmaple");

  if(defined $Z) {
    #print "\ncoord (X Y Z) elt $no_elt pti $no_pti : $X $Y $Z\n\n";
    @{$COORD_PTI[$no_pti]} = ($X, $Y, $Z);
  }
  elsif(defined $Y) {
    #print "\ncoord (X Y) elt $no_elt pti $no_pti : $X $Y\n\n";
    @{$COORD_PTI[$no_pti]} = ($X, $Y, 0);
  }
  elsif(defined $X) {
    #print "\ncoord (X) elt $no_elt pti $no_pti : $X\n\n";
    @{$COORD_PTI[$no_pti]} = ($X, 0, 0);
  }
  #fin de la boucle while() infinie
  else {$no_pti--; last;}
}

#on retablit le maillage original
system("rm -f $racine_fvisu.her $racine_fvisu.lis");
$no_elt = $no_elt_original;
$fher = $fher_original;
($nom_maillage, $nb_noeuds, $ref_noeuds, $nb_elts, $ref_elements, @ref_listes) = lecture_mail_her($fher);

#conversion des types d elements de herezh vers gmsh
conversion_eltType_her2gmsh($nb_elts,$ref_elements);


#creation d un fichier de visu Gmsh de l element $no_elt
# rq : en gardant la numerotation du maillage original
#-- on va ecrire seulement les $no_noeud_max premiers noeuds (c est a dire le no de noeud max parmi ceux de l element $no_elt)
my $no_noeud_max = 0;
foreach my $noeud_old (@{$ref_elements->{$no_elt}{'CONNEX'}}) {
  next if($noeud_old < $no_noeud_max);
  $no_noeud_max = $noeud_old;
}
open(Fmsh, ">$racine_fvisu.msh");
print Fmsh <<"_FIN_";
\$MeshFormat
2 0 8
\$EndMeshFormat
\$Nodes
$no_noeud_max
_FIN_
for(my $i=1; $i<=$no_noeud_max; $i++) {
  print Fmsh "$i  @{$ref_noeuds->[$i]}\n";
}
print Fmsh <<"_FIN_";
\$EndNodes
\$Elements
1
_FIN_
print Fmsh "1  $ref_elements->{$no_elt}{'TYPE'}   @{$ref_elements->{$no_elt}{'CONNEX'}}\n";
print Fmsh <<'_FIN_';
$EndElements
_FIN_
close(Fmsh);

#creation d un .geo pour y ecrire les points d integration sous forme de Point()
open(Fgeo, ">$racine_fvisu.geo");
for(my $i=1; $i<=$no_pti; $i++) {
  print Fgeo "Point($i) = {$COORD_PTI[$i][0], $COORD_PTI[$i][1], $COORD_PTI[$i][2], 1.e+22};\n";
}
print Fgeo '
Geometry.Light = 0;     //desactivation de la lumiere (geometrie)
Mesh.Light = 0;         //desactivation de la lumiere (maillage)
View.Light = 0;         //desactivation de la lumiere (vue)
Mesh.ColorCarousel = 0; //type de couleur (0=by element type, 1=by elementary entity, 2=by physical entity, 3=by partition)
Geometry.Points = 1;    //affichage des points (=0 desactiver, =1 activer)
Geometry.Color.Points = {255,0,0};
Geometry.PointNumbers = 1;//affichage des numeros de points (=0 desactiver, =1 activer)
Mesh.Points = 1;        //affichage des noeuds (=0 desactiver, =1 activer)
Mesh.Lines = 1;         //affichage des lignes (elements 1D) (=0 desactiver, =1 activer)
Mesh.SurfaceEdges = 1;  //affichage des aretes des elements 2D (=0 desactiver, =1 activer)
Mesh.SurfaceFaces = 0;  //affichage des faces des elements 2D (=0 desactiver, =1 activer)
Mesh.VolumeEdges = 1;   //affichage des aretes des elements 3D (=0 desactiver, =1 activer)
Mesh.VolumeFaces = 0;   //affichage des faces des elements 3D (=0 desactiver, =1 activer)
Mesh.PointSize = 3.;   //taille des noeuds
Mesh.PointNumbers = 1;//affichage des numeros de noeuds (=0 desactiver, =1 activer)
Mesh.Color.Points = {0,0,0};          //on met toutes les couleurs des elements en noir pour que les noeuds et les aretes des elements soient en noir
Mesh.Color.Lines = {0,0,0};
Mesh.Color.Triangles = {0,0,0};
Mesh.Color.Quadrangles = {0,0,0};
Mesh.Color.Tetrahedra = {0,0,0};
Mesh.Color.Hexahedra = {0,0,0};
Mesh.Color.Prisms = {0,0,0};
Mesh.Color.Pyramids = {0,0,0};
';

$_ = rel2abs("$racine_fvisu.msh");
print Fgeo "Merge \"$_\";\n";
close(Fgeo);


#lancement gmsh
system("$exeGMSH $racine_fvisu.geo");



#effacement repertoire temporaire
chdir $rep_original;
system("rm -rf $rep_tmp");



sub conversion_eltType_her2gmsh {
  my $premier_arg = shift;
  my $ref_elts = shift;

  my %table_conversion_elt;
  #elements 1D lineaire
  $table_conversion_elt{'POUT BIE1'}{'TYPE'} = "1 3 0 0 0";
  @{$table_conversion_elt{'POUT BIE1'}{'CONNEX'}} = (0, 1);
  #elements 2D lineaire
  $table_conversion_elt{'TRIANGLE LINEAIRE'}{'TYPE'} = "2 3 0 0 0";
  @{$table_conversion_elt{'TRIANGLE LINEAIRE'}{'CONNEX'}} = (0, 1, 2);
  $table_conversion_elt{'QUADRANGLE LINEAIRE'}{'TYPE'} = "3 3 0 0 0";
  @{$table_conversion_elt{'QUADRANGLE LINEAIRE'}{'CONNEX'}} = (0, 1, 2, 3);
  #elements 2D axisymetriques lineaire
  $table_conversion_elt{'TRIA_AXI LINEAIRE'}{'TYPE'} = "2 3 0 0 0";
  @{$table_conversion_elt{'TRIA_AXI LINEAIRE'}{'CONNEX'}} = (0, 1, 2);
  $table_conversion_elt{'QUAD_AXI LINEAIRE'}{'TYPE'} = "3 3 0 0 0";
  @{$table_conversion_elt{'QUAD_AXI LINEAIRE'}{'CONNEX'}} = (0, 1, 2, 3);
  #elements 2D quadratique
  $table_conversion_elt{'TRIANGLE QUADRACOMPL'}{'TYPE'} = "9 3 0 0 0";
  @{$table_conversion_elt{'TRIANGLE QUADRACOMPL'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5);
  $table_conversion_elt{'QUADRANGLE QUADRACOMPL'}{'TYPE'} = "10 3 0 0 0";#quadrangle quadratique complet 9 noeuds
  @{$table_conversion_elt{'QUADRANGLE QUADRACOMPL'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 7, 8);
  $table_conversion_elt{'QUADRANGLE QUADRATIQUE'}{'TYPE'} = "16 3 0 0 0";#quadrangle quadratique incomplet 8 noeuds
  @{$table_conversion_elt{'QUADRANGLE QUADRACOMPL'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 7);
  #elements 2D axisymetriques quadratique
  $table_conversion_elt{'TRIA_AXI QUADRACOMPL'}{'TYPE'} = "9 3 0 0 0";
  @{$table_conversion_elt{'TRIA_AXI QUADRACOMPL'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5);
  $table_conversion_elt{'QUAD_AXI QUADRACOMPL'}{'TYPE'} = "10 3 0 0 0";
  @{$table_conversion_elt{'QUAD_AXI QUADRACOMPL'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 7, 8);
  $table_conversion_elt{'QUAD_AXI QUADRATIQUE'}{'TYPE'} = "16 3 0 0 0";
  @{$table_conversion_elt{'QUAD_AXI QUADRATIQUE'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 7);
  #elements 3D lineaire
  $table_conversion_elt{'TETRAEDRE LINEAIRE'}{'TYPE'} = "4 3 0 0 0";
  @{$table_conversion_elt{'TETRAEDRE LINEAIRE'}{'CONNEX'}} = (0, 1, 2, 3);
  $table_conversion_elt{'HEXAEDRE LINEAIRE'}{'TYPE'} = "5 3 0 0 0";
  @{$table_conversion_elt{'HEXAEDRE LINEAIRE'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 7);
  $table_conversion_elt{'PENTAEDRE LINEAIRE'}{'TYPE'} = "6 3 0 0 0";
  @{$table_conversion_elt{'PENTAEDRE LINEAIRE'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5);
  #elements 3D quadratiques
  $table_conversion_elt{'PENTAEDRE QUADRATIQUE'}{'TYPE'} = "18 3 0 0 0";#pentaedre quadratique incomplet 15 noeuds
  @{$table_conversion_elt{'PENTAEDRE QUADRATIQUE'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 8, 9, , 7, 10, 11, 12, 14, 13);
  $table_conversion_elt{'PENTAEDRE QUADRACOMPL'}{'TYPE'} = "13 3 0 0 0";#pentaedre quadratique complet 18 noeuds
  @{$table_conversion_elt{'PENTAEDRE QUADRACOMPL'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 8, 9, 7, 10, 11, 12, 14, 13);
  $table_conversion_elt{'HEXAEDRE QUADRATIQUE'}{'TYPE'} = "17 3 0 0 0";
  @{$table_conversion_elt{'HEXAEDRE QUADRATIQUE'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 9, 13, 10, 14, 15, 16, 19, 17, 18);
  $table_conversion_elt{'HEXAEDRE QUADRACOMPL'}{'TYPE'} = "12 3 0 0 0";
  @{$table_conversion_elt{'HEXAEDRE QUADRACOMPL'}{'CONNEX'}} = (0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 9, 13, 10, 14, 15, 16, 19, 17, 18, 20, 21, 24, 22, 23, 25, 26);


  #option -liste_elts (on renvoie la liste des elements supportes par conversion_eltType_her2gmsh()
  my @LISTE_ELTS_SUPPORTES = keys %table_conversion_elt;
  if($premier_arg eq '-liste_elts') {
    return @LISTE_ELTS_SUPPORTES;
  }

  #sinon $premier_arg est un numero d element
  my $nb_elts = $premier_arg;

  my $type;
  my @connex_msh;
  my $ind;
  for(my $i=1; $i<=$nb_elts; $i++) {
    $type = $ref_elts->{$i}{'TYPE'};
    $type =~ s/_cm\d+pti//;#suppression d un eventuel changement du nombre de points d integration de l element
    $type =~ s/^\s+//; $type =~ s/\s+$//;
    $type =~ s/\s+/ /g;

    defined($table_conversion_elt{$type}{'TYPE'}) or die "\nErreur (prog:$NOM_PROG) : type d element \"$type\" non supporte...\n\n";

    $ref_elts->{$i}{'TYPE'} = $table_conversion_elt{$type}{'TYPE'};
    @connex_msh = ();
    for(my $j=0; $j<=$#{$table_conversion_elt{$type}{'CONNEX'}}; $j++) {
      $ind = $table_conversion_elt{$type}{'CONNEX'}[$j];
      push(@connex_msh, $ref_elts->{$i}{'CONNEX'}[$ind]);
    }
    for(my $j=0; $j<=$#{$table_conversion_elt{$type}{'CONNEX'}}; $j++) {
      $ref_elts->{$i}{'CONNEX'}[$j] = $connex_msh[$j];
    }
  }
}#sub conversion_her2gmsh



#####################################################################################################
#subroutine qui recherche l existence d une commande et renvoie le premier path trouve (renvoie 0 si commande introuvable)
#####################################################################################################
# en entree :
#    - nom de la commande
#
# en sortie :
#    - chemin absolu de la commande (0 si commande introuvable)
#
sub verif_commande {
  my $cmd = shift;#nom de la commande

  #cas d un chemin absolu ou relatif (si la commande commence par . ou /. Par exemple : ./HZpp ../HZppfast ou /Users/dupont/bin/HZppfast)
  if($cmd =~ /^\./ or $cmd =~ /^\//) {
    #on passe la commande en chemin absolu
    $cmd = rel2abs($cmd);
    return $cmd;
  }

  #sinon on regarde dans la variable environnement $PATH
  foreach my $path (split(/\s*:\s*/, $ENV{PATH})) {
    if(-x "$path/$cmd") {
      #on s assure que c est un chemin absolu
      $cmd = rel2abs("$path/$cmd");
      return $cmd;
    }
  }

  #on regarde a nouveau si la commande est en chemin absolu ou relatif
  #  (cas d une commande qui ne commence pas par . ou / et qui n est pas dans les PATH. Par exemple : rep/HZpp)
  if(-x $cmd) {
    #on passe la commande en chemin absolu
    $cmd = rel2abs($cmd);
    return $cmd;
  }

  #cas ou la commande est introuvable
  return 0;
}#sub verif_commande




#rq : on cree un calcul de dynamique explicite (plus rapide pour faire un increment)
sub print_finfo {

my $fic = shift;
open(FIC, ">$fic");
print FIC '
dimension   3

niveau_commentaire   3

TYPE_DE_CALCUL

dynamique_explicite   avec plus lectureCommandesVisu
';

print FIC "< $fher\n";

print FIC "ELEM_1D @ELEM_1D\n" if($#ELEM_1D > -1);
print FIC "ELEM_2D @ELEM_2D\n" if($#ELEM_2D > -1);
print FIC "ELEM_3D @ELEM_3D\n" if($#ELEM_3D > -1);

print FIC '
les_courbes_1D ----------------------------------------------

courbe_traction COURBEPOLYLINEAIRE_1_D
  Debut_des_coordonnees_des_points
    Coordonnee dim= 2 0. 0.
    Coordonnee dim= 2 1.  -0.30
  Fin_des_coordonnees_des_points

choix_materiaux ----------
';

print FIC "ELEM_1D MAT_1D\n" unless($#ELEM_1D == -1);
print FIC "ELEM_2D MAT_2D\n" unless($#ELEM_2D == -1);
print FIC "ELEM_3D MAT_3D\n" unless($#ELEM_3D == -1);

print FIC '
materiaux ----------------------------------------------

MAT_1D     LOI_RIEN1D
MAT_2D     LOI_RIEN2D_C
MAT_3D     LOI_RIEN3D

masse_volumique ----------------------------

E_tout  1
';

print FIC "\nsections\n\nELEM_1D 1\n\n" unless($#ELEM_1D == -1);
print FIC "\nepaisseurs\n\nELEM_2D 1\n" unless($#ELEM_2D == -1);

print FIC '
charges ------------------------------------

blocages ---------------------------------

controle ---------------------------------------

DELTAtMAXI   1
TEMPSFIN     1
DELTAt       1
ITERATIONS   15
PRECISION    1e-3
SAUVEGARDE   1
MAXINCRE     1

para_pilotage_equi_global ---------------------------------

para_syteme_lineaire ------------

para_affichage ------------

resultats  pas_de_sortie_finale_
COPIE 0

_fin_point_info_
';
close(FIC);
}

sub print_fCVisu {

my $fic = shift;
open(FIC, ">$fic");
print FIC '
     debut_fichier_commande_visu   # >>>>>> le mot cle: <debut_fichier_commande_visu> 
                                   # permet au programme de se positionner au debut du fichier, il est indispensable 
 #  =================================================================================
 #  ||       *****         demande dune visualisation maple:      *****           || 
 #  =================================================================================
 #  un mot cle de debut (debut_visualisation_maple)
 #  un mot cle de fin ( fin_visualisation_maple)
 #  la seule presence de ces deux mots cle suffit a activer la visualisation maple
 debut_visualisation_maple 

 #  ----------------------------- definition de la liste des increments a balayer: ---------------- 
 debut_list_increment #  un mot cle de debut de liste 
 actif 1   # <0 ou 1> indique si lordre est actif ou non 
 # une liste dentier separee par des blancs, ou le mot cle (tous_les_increments) 
 #   un mot cle de fin de liste ( fin_list_increment)
 dernier_increment    fin_list_increment 

 #  ----------------------------- choix des maillages a visualiser: ---------------- 
 #  la liste est facultative, par defaut la visualisation concerne le premier maillage
 debut_choix_maillage #  un mot cle de debut,
 actif 0   # <0 ou 1> indique si lordre est actif ou non 
 #  une liste dentiers , puis <fin_choix_maillage>, sur une meme ligne
 1  fin_choix_maillage 

 #  ----------------------------- definition des grandeurs a visualiser (maple): ---------------- 
 debut_grandeurs_maple  #  un mot cle de debut (debut_grandeurs_maple),
 actif 1   # <0 ou 1> indique si lordre est actif ou non 
 # les grandeurs globales (energie, puissance ....) un mot cle de debut, le nom des grandeurs puis un mot de fin
 debut_grandeurs_globales     fin_grandeurs_globales  
 #  ensuite pour chaque maillage:,
 #    le numero du maillage <un entier>,  
 #    les infos pour la visualisation eventuelle des torseurs de reaction,
 #    les infos pour la visualisation eventuelle aux noeud,
 #         - tout dabord les ddl principaux (position, deplacements, temperature etc.)
 #         - puis les ddl etendus et particulieres qui peuvent representer des grandeurs diverses 
 #    les infos pour la visualisation eventuelle aux elements,
 #         - tout dabord les grandeurs generiques (deformations, contraintes etc.)
 #         - puis les grandeurs particulieres, par exemple specifique a une loi de comp ou une mesure de def 
 #  enfin un mot cle de fin ( fin_grandeurs_maple)
 1 # le numero de maillage
 # les torseurs de reaction:  un mot cle de debut:  debut_list_torseur_reaction
 # une liste de nom  <chaine de caracteres >, puis <fin_list_torseur_reaction>
 debut_list_torseur_reaction   fin_list_torseur_reaction  
 debut_liste_ddl_et_noeud     # ** debut des ddl principaux aux noeuds 
 #  debut de la liste de noeuds,  puis une liste de numero de noeud <entier>, puis <fin_list_noeud>
 deb_list_noeud   fin_list_noeud  
 #  debut de la liste des ref de noeuds,  puis une liste de nom  <chaine de caracteres >, puis <fin_list_ref_noeud>
 deb_list_ref_noeud  fin_list_ref_noeud  
 #   debut de la liste des ddl a considerer aux noeuds, (une liste de ddl), puis <fin_list_ddl_noeud>
 deb_list_ddl_noeud          fin_list_ddl_noeud   
 type_sortie_ddl_retenue= 0
 #   debut de la liste des ddl etendus a considerer aux noeuds, (une liste de ddl), puis <fin_list_ddl_etendu_noeud>
 deb_list_ddl_etendu_noeud         fin_list_ddl_etendu_noeud    # fin des ddl etendu aux noeuds
 #   debut de la liste des grandeurs particulieres a considerer aux noeuds, (une liste de string), puis <fin_list_GrandParticuliere_noeud>
 deb_list_GrandParticuliere_noeud         fin_list_GrandParticuliere_noeud    # fin des grandeurs particulieres aux noeuds
 fin_liste_ddl_et_noeud      # fin des grandeurs aux noeuds
 debut_liste_ddl_ptinteg  # ** debut des grandeurs aux elements 
 #  debut de la liste des elements et points dintegration, une liste de   (un element, un numero de pt dinteg), puis <fin_list_NbElement_NbPtInteg>
';

print FIC " deb_list_NbElement_NbPtInteg $no_elt $no_pti  fin_list_NbElement_NbPtInteg  \n";

print FIC '
 #  debut de la liste des ref delements,  puis une liste de: nom  <chaine de caracteres > + numero dinteg, puis <fin_list_ref_element>
 deb_list_ref_element  fin_list_ref_element  
 #  debut de la liste des ref de ptinteg delements,  puis une liste de: nom  <chaine de caracteres >  puis <fin_list_ref_ptinteg_element>
 deb_list_ref_ptinteg_element    fin_list_ref_ptinteg_element  
 # debut de la liste des ddl a considerer pour les elements, (une liste de ddl),    puis <fin_list_ddl_element>
 deb_list_ddl_element  contrainte_mises       fin_list_ddl_element          # fin de la liste de ddl a considerer pour les elements
 #   debut de la liste des grandeurs particulieres a considerer pour les elements, (une liste de string), puis <fin_list_GrandParticuliere_element>
 deb_list_GrandParticuliere_element         fin_list_GrandParticuliere_element    # fin des grandeurs particulieres aux elements
 #   tableau de grandeurs evoluees  aux elements a visualiser, un par maillage
 deb_list_GrandEvoluee_element  fin_list_GrandEvoluee_element 
 fin_liste_ddl_ptinteg   # fin des grandeurs aux elements 
# informations particuliere dans le cas ou il y a une animation
# type_xi indique si oui ou non les grandeurs a tracer sont aux noeuds (sinon cest au elements)
# x1 et x2 indiquent les noms des ddls des grandeurs en x et y. accroi_x1 et accroi_x2 indiquent 
# si oui ou non x1 et x2 represente laccroissement entre 0 et t de la grandeur ou bien la grandeur elle meme.
 debut_info_particulier  grandeur_au_noeud? 1  x1=  NU_DDL x2=  NU_DDL accroi_x1= 0 accroi_x2= 1  fin_info_particulier 
# un parametre de pilotage du style de sortie
 parametre_style_de_sortie 1
# un parametre indiquant si les tenseurs sont en absolue (rep 1) ou suivant un repere ad hoc
# (tangent pour les coques, suivant la fibre moyenne pour les element 1D ) 
 tenseur_en_absolue_  0
 fin_grandeurs_maple  # fin des grandeurs a visualiser au format maple 

 #  ----------------------------- definition des parametres danimation: ---------------- 
 debut_animation #  un mot cle de debut de liste (debut_animation)
 actif 0   # <0 ou 1> indique si lordre est actif ou non 
 #  des parametres avec des valeurs: (sur une meme ligne) 
 cycleInterval 8 # cycleInterval  <un reel> (indique le temps en seconde du cycle de lanimation)
 fin_animation  #   un mot cle de fin  

 fin_visualisation_maple 
 #  =================================================================================
 #  ||                          fin de la  visualisation maple                     || 
 #  =================================================================================
     fin_fichier_commande_visu   # <<<<<<  le mot cle <fin_fichier_commande_visu> permet
                                 #  larret de la lecture des commandes, apres ce mot cle, aucune commande nest lu, de plus 
                                 #  sans le mot cle de fin de fichier, le fichier nest pas valide  
';
close(FIC);
}





#----------------
#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+)/) {$nom_maillage = $1; next;}
    next if(not /(\d+)\s+NOEUDS/);
    $nb_noeuds = $1;
    last;
  }
  while(<Fher>) {
    last if($no_noeud == $nb_noeuds);
    next if(not /^\s*(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s*$/);
    $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/);
    $nb_elts = $1;
    last;
  }
  while(<Fher>) {
    last if($no_elt == $nb_elts);
    next if(not /^\s*\d+\s+\w+\s+\w+/);
    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+)/) {
      $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/i or /^\s*elements/i or /^\s*[AFEG]/) {
      $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(Fher);

  open(Fher, "<$fher");
  $is_liste_en_cours = 0;
  while(<Fher>) {
    chomp;
    if(/^\s*(A\S+)/) {
      $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/i or /^\s*elements/i or /^\s*[NFEG]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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/i or /^\s*elements/i or /^\s*[NAEG]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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+)/) {
      $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/i or /^\s*elements/i or /^\s*[NAFG]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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+)/) {
      $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/i or /^\s*elements/i or /^\s*[NAFE]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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+)/) {
      $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/i or /^\s*elements/i or /^\s*[AFEG]/) {
      $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+)/) {
      $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/i or /^\s*elements/i or /^\s*[NFEG]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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+)/) {
      $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/i or /^\s*elements/i or /^\s*[NAEG]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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+)/) {
      $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/i or /^\s*elements/i or /^\s*[NAFG]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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+)/) {
      $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/i or /^\s*elements/i or /^\s*[NAFE]/) {
      $is_liste_en_cours = 0;
    }
    elsif($is_liste_en_cours and /^\s*\d+(\s+\d+)*\s*$/i) {
      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
