#!/usr/bin/env perl
use strict;
use English;
use File::Basename;
my $NOM_PROG = basename $PROGRAM_NAME;

my $VERSION = '1.02';
######################################################################################################
#  script pour visualiser un resultat Gmsh (exploitation du repertoire  _Gmsh cree par Herezh++)     #
#  version 1.00 : version initiale                                                                   #
#                 (version testee sur : MacOSX Darwin, Linux Xubuntu)                                #
#  version 1.01 : ajout option -repair => reecriture du repertoire Gmsh afin de traiter divers       #
#                                         problemes : principalement gerer les incoherences dans les #
#                                         numeros d increments et splitter les fichiers qui          #
#                                         contiennent plusieurs grandeurs (exemple : DIRECTION_PLI)  #
#                 remaniement mineur de l aide -h                                                    #
#  version 1.02 : refonte du fonctionnement option -repair (on se base maintenant sur le temps pour  #
#                 dresser la liste des increments a conserver; les numeros d increment peuvent etre  #
#                 modifies a l issue de l option -repair)                                            #
######################################################################################################



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# VARIABLES QUE L UTILISATEUR PEUT ETRE AMENE A RENSEIGNER  #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# le variable $exeGMSH sert a imposer le choix de l executable Gmsh
#   (rq : les alias shell ne fonctionneront pas)
#
#commande gmsh definie par l utilisateur (modifiable egalement avec l option -exeGMSH)
my $exeGMSH = 'gmsh';
#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                                 #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# VARIABLES DEVELOPPEUR (NE PAS MODIFIER : RESERVEES AUX DEVELOPPEURS)#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#pattern d un reel pour les regex
my $format_reel = '[+-]?[\.]?\d+[\.]?\d*(?:[eE][+-]?\d*)?';

#option -merge : liste des extensions de fichier autorisees pour cette option
#                IMPORTANT : quand un type de fichier peut prendre plusieurs extensions, on les range toutes
#                            au sein d une meme chaine de caracteres separees par un ou plusieurs espaces
#                            (exemple : ".step .stp" pour un fichier STEP)
#                            (NB : la verification sera insensible a la casse => inutile de mettre des majuscules)
my @EXTENSION_OPT_MERGE = (".geo", ".step .stp");

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# FIN VARIABLES DEVELOPPEUR                                 #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #



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 des resultats Herezh Gmsh\n";
  print "\n";
  print wrap("","        $indent_NOM_PROG ", 
             "Usage : $NOM_PROG [-h|help] rep_gmsh [nom_isoval1 ... nom_isovalN]\n", 
             "[-v] [-exeGMSH path_GMSH] [-l] [-tps val_temps] [-factor fact]",
             "[-adaptVisu nb_recur] [-line_ini] [-iso_per_step] [-time] [-gris]",
             "[-noGrid] [-noLight] [-saveVisu nom_geo] [-quit] [-merge fic]",
             "[-line_width val]",
"\n");
  print "\n";
  print "--------------------------------------------\n";
  print "Arguments\n";
  print "--------------------------------------------\n";
  print "    o rep_gmsh : repertoire Gmsh cree par un calcul Herezh++\n";
  print "    o [nom_isoval1 .. nom_isovalN] : liste des isovaleurs a visualiser\n";
  print "                                     (ou \"all\" pour voir toutes les\n";
  print "                                      isovaleurs disponibles)\n";
  print "         **NB : voir rubrique \"Remarques sur le choix des isovaleurs\"\n";
  print "\n";
  print "--------------------------------------------\n";
  print "Fonctionnement\n";
  print "--------------------------------------------\n";
  print wrap("    ", "  ", "$NOM_PROG permet d afficher les resultats Gmsh avec les choix de visualisation suivants :\n");
  print "    - visualisation des isovaleurs sur le maillage deforme\n";
  print "    - desactivation du maillage initial\n";
  print "    - activation du maillage deforme (desactivable avec option -noGrid)\n";
  print "    - affichage des isovaleurs en mode \"displacement\" (sauf pour\n";
  print "      les grandeurs de type vecteur)\n";
  print "    - affichage du dernier increment disponible par defaut\n";
  print "      (modifiable avec option -tps)\n";
  print "    - desactivation des vues (View) hors \"deplace\" au lancement\n";
  print "\n";
  print wrap("    ", "  ", "  voir egalement rubrique \"Remarques sur le choix des isovaleurs\" pour plus d infos sur le lancement de $NOM_PROG\n");
  print "\n";

  print "--------------------------------------------\n";
  print "Options\n";
  print "--------------------------------------------\n";
  my $_4espaces = "    ";

  #
  # affichage des options (si possible en suivant le style d indentation et dans l ordre alphabetique, selon votre patience :) :) )
  #

  $_ = $_4espaces.chaine2espaces("-adaptVisu nb_recur : ");
  print wrap($_4espaces, $_, "-adaptVisu nb_recur : utiliser l option \"Adapt visualization grid\"",
                                        "avec un nombre de recursion egal a nb_recur (typiquement nb_recur=1 ou 2 devrait suffir)\n");
  $_ = $_4espaces.chaine2espaces("**Avertissement : ");
  print wrap($_4espaces.$_4espaces, $_4espaces.$_,
                   "**Avertissement : avec cette option, la transformation pour afficher",
                   "les isovaleurs sur la deformee n est valide que pour",
                   "l increment selectionne dans la vue \"deplace\". Donc,",
                   "quand on utilise cette option, la vue \"deplace\" est activee",
                   "au demarrage et doit rester active pour que les numeros",
                   "d increments soient synchrones entre \"deplace\" et l isovaleur",
                   "que l on souhaite voir sur le maillage deforme\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-exeGMSH path_GMSH : ");
  print wrap($_4espaces, $_, "-exeGMSH path_GMSH : choisir l executable Gmsh. La visualisation Gmsh se ",
                             "fera avec l executable path_GMSH\n",
                             "par defaut : path_GMSH=$exeGMSH_defaut\n",
                             "(**Attention : les alias shell ne fonctionneront pas)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-factor fact : ");
  print wrap($_4espaces, $_, "-factor fact : facteur d amplification de la deformee (par defaut : fact=1)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-gris : ");
  print wrap($_4espaces, $_, "-gris  : isovaleurs en niveaux de gris de 0 a 255\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-iso_per_step : ");
  print wrap($_4espaces, $_, "-iso_per_step : affichage des isovaleurs en mode \"Per time step\"\n",
                                        "(option : View[...]->General->Range mode->Per time step)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-l : ");
  print wrap($_4espaces, $_, "-l : affichage de la liste des isovaleurs disponibles dans le repertoire Gmsh\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-line_ini : ");
  print wrap($_4espaces, $_, "-line_ini : affichage du maillage initial (seulement les aretes)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-line_width val : ");
  print wrap($_4espaces, $_, "-line_width val : epaisseur de ligne pour afficher les elements\n",
                                        "(par defaut : val=1)\n");
  print "\n";
  $_ = $_4espaces.chaine2espaces("-merge nom_fic : ");
  print wrap($_4espaces, $_, "-merge nom_fic  : inclure un fichier compatible avec gmsh (Merge de fichiers .geo, .stp, ...)\n",
                                        "(cette option peut etre repetee autant de fois que necessaire)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-noGrid : ");
  print wrap($_4espaces, $_, "-noGrid  : desactiver l affichage des lignes des elements\n",
                                        "(option : View[...]->Visibility->Draw elements outlines)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-noLight : ");
  print wrap($_4espaces, $_, "-noLight  : desactiver les reflets de lumiere\n(option : color->enable lightning)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-quit : ");
  print wrap($_4espaces, $_, "-quit : executer $NOM_PROG sans lancer la visualisation Gmsh\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-repair : ");
  print wrap($_4espaces, $_, "-repair : reparation du repertoire Gmsh (modification definitive des fichiers .pos", 
                             "pour corriger les incoherences sur les numeros d increments et splitter les",
                             "fichiers contenant plusieurs grandeurs)\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-saveVisu nom_geo : ");
  print wrap($_4espaces, $_, "-saveVisu nom_geo : sauvegarder le fichier de visualisation sous le nom nom_geo\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-time : ");
  print wrap($_4espaces, $_, "-time  : affichage du temps au lieu du numero d increment\n");

  print "\n";
  $_ = $_4espaces.chaine2espaces("-tps val_temps : ");
  print wrap($_4espaces, $_, "-tps val_temps : affichage de l increment le plus proche du temps \"val_temps\"\n",
                             "(par defaut : le dernier increment)\n",
                             "(rq : cf affichage dans le terminal pour voir le temps reellement selectionne)\n");
  print "\n";
  $_ = $_4espaces.chaine2espaces("-v : ");
  print wrap($_4espaces, $_, "-v : affichage du numero de version\n");

  print "\n";
  print "--------------------------------------------\n";
  print "Remarques sur le choix des isovaleurs\n";
  print "--------------------------------------------\n";
  print "  1) un repertoire Gmsh produit par Herezh++ contient des fichiers dont\n";
  print "     les noms sont, par exemple pour un fichier .info \"mon_calcul.info\" :\n";
  print "         - mon_calcul_deplace_Gmsh.pos\n";
  print "         - mon_calcul_EPS11_pti_Gmsh.pos\n";
  print "         - mon_calcul_contrainte_mises_pti_Gmsh.pos\n";
  print "         - etc...\n";
  print "     c est-a-dire des noms de la forme \"mon_calcul_[nom isoval]_Gmsh.pos\"\n";
  print "\n";
  print "     => un nom d isovaleur \"nom_isoval\" est donc la chaine de caracteres\n";
  print "        situee entre le prefixe \"mon_calcul_\" et le suffixe \"_Gmsh.pos\",\n";
  print "        y compris les eventuels \"_pti\", \"_ddl_noe\", etc...\n";
  print "\n";
  print "        Exemples : EPS11_pti  X1_ddl_noe  contrainte_mises_pti\n";
  print "\n";
  print "  2) la grandeur \"deplace\" doit obligatoirement exister dans le repertoire\n";
  print "     Gmsh/. Il n y a pas besoin de l indiquer dans la liste.\n";
  print "\n";
  print "  3) si aucune isovaleur n est demandee => affichage des deplacements\n";
  print "     (grandeur \"deplace\")\n";
  print "\n";
  print "  4) l option -l permet de voir la liste des isovaleurs disponibles.\n";
  print "\n";
  print "  5) si on indique \"all\" a la place d une liste d isovaleurs, toutes les\n";
  print "     isovaleurs disponibles seront affichees.\n";
  print "\n";
  print "  Exemples :\n";
  print "    1) visualiser les isovaleurs de deformation EPS11 et contrainte SIG11 :\n";
  print "       $NOM_PROG mon_calcul_Gmsh/  EPS11_pti SIG11_pti\n";
  print "\n";
  print "    2) visualiser toutes les isovaleurs :\n";
  print "       $NOM_PROG mon_calcul_Gmsh/  all\n";
  print "\n";
  print "Auteur :\n";
  print "   TROUFFLARD Julien\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();
}

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

#------------------------------------
#recuperation des arguments et options
#------------------------------------
my $rep_Gmsh;#repertoire Gmsh
my $is_opt_l = 0;#indicateur de l option -l (affichage de la liste des isovaleurs disponibles pour les fichiers commencant par $racine_fic
my @liste_isoval_demandees = ();#liste des isovaleurs a visualiser
my $temps_requis = -1;#numero de l increment a afficher le plus proche de $temps_requis
                      #(par defaut le dernier increment, modifiable avec option -tps)
my $incr_temps_requis = -1;#numero de l increment a afficher
my $facteur_ampli = 1.;#facteur d amplification de la deformee (par defaut : 1, modifiable avec option -factor)
my $adaptvizu_high_order = 0;#nombre de recursion pour utiliser l option adaptvisualizationgrid (subdivision pour ameliorer le rendu des isovaleurs des elements d ordre eleve)
my $is_opt_line_ini = 0;#indicateur de l option -line_ini (affichage des aretes du maillage initial)
my $is_opt_iso_per_step = 0;#indicateur de l option -iso_per_step (les echelles des isovaleurs seront "Per time step")
my $is_opt_time = 0;#indicateur de l option -time (affichage du temps au lieu du numero d increment)
my $is_opt_gris = 0;#indicateur de l option -gris (isovaleurs en niveaux de gris de 0 a 255)
my $is_opt_noGrid = 0;#indicateur de l option -noGrid (desactiver l affichage des lignes des elements)
my $is_opt_noLight = 0;#indicateur de l option -noLight (desactiver les reflets de lumiere (color->enable lightning))
my $is_opt_saveVisu = 0;#indicateur de l option -saveVisu (sauvegarder les fichiers de visualisation)
my $opt_saveVisu_nom_geo;#nom du fichier de visu pour l option -saveVisu
my $is_opt_quit = 0;#indicateur de l option -quit (executer le script sans lancer la visualisation Gmsh)
my @opt_merge_fic;#liste des fichiers a inclure via Merge (option -merge)
my $line_width = 1.;#epaisseur de ligne des elements dans les "view" (modifiable avec option -line_width)
my $is_opt_repair = 0;#indicateur de l option -repair (modif des fichiers .pos pour retablir la coherence des increments et grandeurs (reecriture du repertoire Gmsh))


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

  #option -exeGMSH
  if($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);
  }
  #option -l
  elsif($opt eq "-l") {
    $is_opt_l = 1;
  }
  #option -tps
  elsif($opt eq "-tps") {
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG,opt:-tps) : pas assez d arguments pour cette option...\n\n";
    $temps_requis = shift(@ARGV);
    ($temps_requis =~ /^$format_reel$/ and $temps_requis >= 0.) or die "\nErreur (prog:$NOM_PROG, opt -tps) : la valeur ($temps_requis) doit etre un reel positif...\n\n";
  }
  #option -factor
  elsif($opt eq "-factor") {
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG,opt:-factor) : pas assez d arguments pour cette option...\n\n";
    $facteur_ampli = shift(@ARGV);
    ($facteur_ampli =~ /^$format_reel$/ and $facteur_ampli >= 0.) or die "\nErreur (prog:$NOM_PROG, opt -factor) : la valeur ($facteur_ampli) doit etre un reel positif...\n\n";
  }
  #option -adaptVisu
  elsif($opt eq "-adaptVisu") {
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG,opt:-adaptVisu) : pas assez d arguments pour cette option...\n\n";
    $adaptvizu_high_order = shift(@ARGV);
    ($adaptvizu_high_order =~ /^\d+/ and $adaptvizu_high_order >= 0) or die "\nErreur (prog:$NOM_PROG, opt -adaptVisu) : la valeur ($adaptvizu_high_order) doit etre un entier positif...\n\n";
    warn "**Attention (prog:$NOM_PROG, opt:-adaptVisu) : voir information sur cette option dans l aide (-h/help)...\n";
  }
  #option -line_ini
  elsif($opt eq "-line_ini") {
    $is_opt_line_ini = 1;
  }
  #option -iso_per_step
  elsif($opt eq "-iso_per_step") {
    $is_opt_iso_per_step = 1;
  }
  #option -time
  elsif($opt eq "-time") {
    $is_opt_time = 1;
  }
  #option -gris
  elsif($opt eq "-gris") {
    $is_opt_gris = 1;
  }
  #option -noGrid
  elsif($opt eq "-noGrid") {
    $is_opt_noGrid = 1;
  }
  #option -noLight
  elsif($opt eq "-noLight") {
    $is_opt_noLight = 1;
  }
  #option -saveVisu
  elsif($opt eq "-saveVisu") {
    $is_opt_saveVisu = 1;
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG, opt -saveVisu) : pas assez d arguments pour cette option...\n\n";
    $opt_saveVisu_nom_geo = shift(@ARGV);
  }
  #option -quit
  elsif($opt eq '-quit') {
    $is_opt_quit = 1;
  }
  #option -merge
  elsif($opt eq "-merge") {
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG,opt:-merge) : pas assez d arguments pour cette option...\n\n";
    my $fic = shift(@ARGV);

    #existence fichier
    (-e $fic) or die "\nErreur (prog:$NOM_PROG,opt:-merge) : fichier $fic introuvable...\n\n";

    #verification de la validite de l extension du fichier (doit figurer dans la liste @EXTENSION_OPT_MERGE)
    $_ = basename $fic;
    /(\.\S+)$/ or die "\nErreur (prog:$NOM_PROG,opt:-merge) : impossible de saisir l extension du fichier $fic (le fichier doit finir par l une des extensions suivantes : @EXTENSION_OPT_MERGE )...\n\n";
    my $ext = $1;
    $ext =~ tr/A-Z/a-z/;
    my $is_ext_ok = 0;
    foreach my $extension_autorisee (split(/\s+/, "@EXTENSION_OPT_MERGE")) {
      (my $extension_autorisee_ = $extension_autorisee) =~ tr/A-Z/a-z/;#on passe en minuscule au cas ou, mais normalement les elements de la liste @EXTENSION_OPT_MERGE sont deja en minuscule
      next if($ext ne $extension_autorisee_);
      $is_ext_ok = 1;
      last;
    }
    $is_ext_ok or die "\nErreur (prog:$NOM_PROG,opt:-merge) : le fichier $fic n est pas d un type supporte par l option -merge. Il doit finir par l une des extensions suivantes : @EXTENSION_OPT_MERGE ...\n\n";

    #ajout a la liste des fichiers a merger
    push(@opt_merge_fic, $fic);
  }
  #option -line_width
  elsif($opt eq "-line_width") {
    ($#ARGV >= 0) or die "\nErreur (prog:$NOM_PROG,opt:-line_width) : pas assez d arguments pour cette option...\n\n";
    $line_width = shift(@ARGV);
    ($line_width =~ /^$format_reel$/ and $line_width > 0) or die "\nErreur (prog:$NOM_PROG,opt:-line_width) : epaisseur de ligne ($line_width) doit etre un reel positif...\n\n";
  }
  #option -repair
  elsif($opt eq "-repair") {
    $is_opt_repair = 1;
  }

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

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



#---------------------
#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_cmd($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";



#---------------------
#application de l option -repair
#
# => reecriture du repertoire Gmsh pour le motif suivant :
#
#  But : retablir une coherence dans les increments des fichiers .pos
#        et egalement dans les donnees car certains .pos contiennent plusieurs grandeurs (par exemple : DIRECTION_PLI)
#
# suite a certains calculs Herezh, il peut y avoir un ou plusieurs problemes a traiter :
#    * split en plusieurs fichiers pour les fichiers contenant plusieurs grandeurs
#       raison : le script he_visuGmsh.pl n est pas prevu pour gerer le cas d un fichier
#                .pos contenant plusieurs grandeurs. La construction de son fichier .geo de
#                visualisation considere 1 fichier = 1 grandeur = 1 "View Gmsh". Si un fichier contient
#                2 grandeurs ou plus, il y aura une incoherence entre le nombre de "View Gmsh" et
#                le nombre de grandeurs.
#
#    * probleme de coherence dans le nombre et numeros d increments
#         il peut manquer certains increments, il peut y avoir 2 Nodedata avec le meme numero d increments, etc...
#
#         le but est de retablir la coherence :
#           - en supprimant des increments ayant le meme temps (doublon de temps)
#                **NB : ce cas est peu probable et n a jamais ete rencontre pour l instant
#           - en renumerotant les increments si les numeros ne sont pas strictement croissants
#
#           Suite a ce traitement, il est possible que les nouveaux numeros d increments dans les fichier .pos
#           ne soient plus en accord avec les increments reellement calcules par Herezh
#
#           ==> La seule donnee qui gardera la coherence avec le calcul herezh est le temps <==
#
# NB : la subroutine execute_option_repair() realise tous les traitements lies a l option -repair
#---------------------
execute_option_repair($rep_Gmsh) if($is_opt_repair);



#---------------------
#verif de la presence du fichier "..._deplace_Gmsh.pos" dans le repertoire Gmsh
#    ( presence obligatoire de la grandeur "deplace", i.e un )
#    ( fichier de la forme $rep_Gmsh/[...]_deplace_Gmsh.pos  )
#
#  **NB : on en profite pour saisir la racine du nom des fichiers .pos
#         les fichiers .pos ont tous un format tel que : [racine_fic][nom_isoval]_Gmsh.pos
#---------------------
#-on saisit la liste des fichiers qui contiendrait le suffixe "deplace_Gmsh.pos"
#   normalement, il ne doit y en avoir qu un seul
#   => si on en trouve aucun ou plus que 1 => erreur et arret
my @liste_fic_deplace = glob("$rep_Gmsh/*deplace_Gmsh.pos");
($#liste_fic_deplace != -1) or die "\nErreur (prog:$NOM_PROG) : aucun fichier \"deplace_Gmsh.pos\" n a ete trouve dans le repertoire $rep_Gmsh (la presence de ce fichier est obligatoire)...\n\n";
($#liste_fic_deplace < 2) or die "\nErreur (prog:$NOM_PROG) : il ne doit y avoir qu un seul fichier \"deplace_Gmsh.pos\" dans le repertoire $rep_Gmsh. Plusieurs fichiers \"deplace_Gmsh.pos\" ont ete trouves (liste : @liste_fic_deplace)...\n\n";
my $fic_deplace = shift(@liste_fic_deplace);
#racine des fichiers (on la saisit en exploitant le fichier deplace)
my ($racine_fic) = $fic_deplace =~ /(.+)deplace_Gmsh.pos/;





#---------------------
#liste des isovaleurs disponibles pour les fichiers commencant par $racine_fic
#
#  remarque : par facilite, on considere ques les eventuels suffixes _pti, _ddl_noe, etc... font partis du nom de l isovaleur.
#               on considere un format de fichier [racine_fic][nom_isoval]_Gmsh.pos
#
#---------------------
my @liste_isoval_disponibles = ();
my @liste_fic = glob("$racine_fic*_Gmsh.pos");
foreach my $fic (@liste_fic) {
  $fic =~ /${racine_fic}(\S+)_Gmsh.pos/ or die "\nErreur (prog:$NOM_PROG) : fichier $fic n est pas un fichier de resultats...\n\n";
  next if($1 =~ /deplace/);#on ne tient pas compte du fichier "deplace" (il est considere comme present obligatoirement)
  push(@liste_isoval_disponibles, $1);
}

#---------------------
#verif de la presence eventuelle de "all" dans les isovaleurs demandees
#  (dans ce cas, on prend toutes les isoval de @liste_isoval_disponibles)
#---------------------
foreach my $isoval (@liste_isoval_demandees) {
  if($isoval =~ /^all$/) {
    @liste_isoval_demandees = @liste_isoval_disponibles;
    last;
  }
}


#---------------------
#suppression de la grandeur "deplace" dans la liste des isovaleurs demandees
#  (si l utilisateur l a indiquee dans la liste, ca va creer un bug
#   car cette grandeur aura un traitement special par la suite)
#
#  on en profite pour reperer toute isovaleur inconnue et la supprimer de la liste
#    => si des isovaleurs demandees n existent pas, on affiche un warning
#       avec la liste des isovaleurs inconnues (mais pas d arret du programme)
#---------------------
my @liste_isoval_inconnues;
my @tmp_liste_isoval = @liste_isoval_demandees;
@liste_isoval_demandees = ();
foreach my $isoval (@tmp_liste_isoval) {
  #on ne garde pas "deplace"
  next if($isoval eq "deplace");

  #on regarde si l isovaleur existe
  #-- si oui => ajout a la liste definitive
  if(" @liste_isoval_disponibles " =~ / $isoval /) {
    push(@liste_isoval_demandees, $isoval);
  }
  #-- si non => ajout a la liste des isoval inconnues
  else {
    push(@liste_isoval_inconnues, $isoval);
  }
}
@tmp_liste_isoval = ();
#affichage warning si des isoval sont inconnues
if($#liste_isoval_inconnues != -1) {
  warn "\nAttention (prog:$NOM_PROG) : certaines isovaleurs demandees n ont pas ete trouvees\n";
  warn "         Liste des isovaleurs inconnues :\n";
  warn "           - $_\n" for @liste_isoval_inconnues;
  warn "\n";
}




#---------------------
#cas de l option -l : affichage des isovaleurs disponibles (et arret du programme)
#---------------------
if($is_opt_l) {
  print "\n";
  print "--------------------------------\n";
  print "liste des isovaleurs disponibles\n";
  print "--------------------------------\n";
  print "$_\n" for @liste_isoval_disponibles;
  print "--------------------------------\n";
  print "\n";
  exit;
}






#---------------------
#cas de l option -tps : on verifie que le temps demande existe et on recherche le numero d increment le plus proche (par defaut le dernier increment)
#---------------------
if($temps_requis != -1) {
  my $incr_lu;
  my $temps_lu;
  my $alarme_incr_valide;
  my $PREC = 1e-5;
  my $norme;
  my $norme_min = 1e90;
  my $incr_norme_min = -1;
  my $temps_norme_min = -1;
  open(FIC, "<${racine_fic}deplace_Gmsh.pos");
  while(<FIC>) {
    chomp;
    next if(not /^\s*\$\S*Nodedata\s*$/io);
    $incr_lu = -1;
    $temps_lu = -1;
    $alarme_incr_valide = 0;
    #lecture du temps
    $_ = <FIC>; $_ = <FIC>; $_ = <FIC>; $_ = <FIC>; chomp; s/^\s+//; s/\s+$//; $temps_lu = $_;
    #lecture du numero d increment
    $_ = <FIC>; $_ = <FIC>; chomp; s/^\s+//; s/\s+$//; $incr_lu = $_;
    #verif que l increment est valide (valide si on a la presence du mot-cle $End\S*NodeData)
    while(<FIC>) {if(/^\s*\$End\S*Nodedata\s*$/i) {$alarme_incr_valide = 1; last;}}
    #on regarde si le temps voulu avec l option -tps est superieur ou egal au temps lu $temps_lu : si oui, on selectionne l increment comme etant celui que l on recherche
    if($alarme_incr_valide) {
      $norme = abs($temps_requis-$temps_lu);
      if($norme < $norme_min) {
        $norme_min = $norme;
        $incr_norme_min = $incr_lu;
        $temps_norme_min = $temps_lu;
      }
    }#if($alarme_incr_valide)
  }#while(<FIC>)
  close(FIC);

  #on selectionne l increment le plus proche dans $incr_temps_requis
  $incr_temps_requis = $incr_norme_min;

  #afficahge du temps reel
  print "option -tps : temps requies : $temps_requis => temps reel : $temps_norme_min (increment $incr_norme_min)\n";
}#if($temps_requis != -1)


#---------------------
#on ecrit un .geo temporaire dans le repertoire courant qui va "Merge" les fichiers .pos
#  et contiendra les divers options Gmsh
#---------------------
my $racine_fic_basename = basename ${racine_fic};
my $fvisu = $racine_fic_basename.rand(999999).'.geo'; while(-e $fvisu) {$fvisu = $racine_fic_basename.rand(999999).'.geo';}
#cas de l option -saveVisu : nom du fichier de visu impose
if($is_opt_saveVisu) {
  $fvisu = $opt_saveVisu_nom_geo;
  $fvisu .= '.geo' if(not $fvisu =~ /\.geo$/);
}


my $no_view_deplace = $#liste_isoval_demandees + 1;#numero de la vue "deplace" (on la mettra en dernier)

open(Fgeo, ">$fvisu");
print Fgeo "Mesh.NumSubEdges = 10;\n";
print Fgeo "Mesh.Points = 0;\n";
print Fgeo "Mesh.Lines = $is_opt_line_ini;\n";
print Fgeo "Mesh.SurfaceEdges = $is_opt_line_ini;\n";
print Fgeo "Mesh.SurfaceFaces = 0;\n";
print Fgeo "Mesh.VolumeEdges = $is_opt_line_ini;\n";
print Fgeo "Mesh.VolumeFaces = 0;\n";

#les parametres suivants sont generaux a toutes les vues
print Fgeo "View.GeneralizedRaiseView = $no_view_deplace;\n";#numero de la vue pour la transfo (on met $no_view_deplace car "deplace" est en $no_view_deplace)
print Fgeo "View.ShowElement = 1;\n";#affichage des elements en mode deformee
print Fgeo "View.TimeStep = $incr_temps_requis;\n";#visu de l increment $incr_temps_requis (par defaut : $incr_temps_requis = -1)
print Fgeo "View.UseGeneralizedRaise = 1;\n";#activation de la transfo
print Fgeo "View.GeneralizedRaiseFactor = $facteur_ampli;\n";#facteur d amplification de la deformee
print Fgeo "View.VectorType = 5;\n";#affichage des isovaleurs en type "displacement"
#echelle des isovaleurs (par defaut : View[...]->General->Range mode->Default)
#  (peut etre modifie avec option -iso_per_step)
if($is_opt_iso_per_step == 0) {
  print Fgeo "View.RangeType = 1;\n";#mode par defaut
}
else {
  print Fgeo "View.RangeType = 3;\n";#cas de l option -iso_per_step => View[...]->General->Range mode->Per time step
}
print Fgeo "View.Visible = 0;\n";#desactivation des vues au demarrage
#option -time : affichage du temps a la place du no increment
print Fgeo "View.ShowTime = 1;\n" if($is_opt_time);#par defaut : 3
#option -gris : isovaleurs en niveaux de gris
if($is_opt_gris) {
  print Fgeo "View.ColorTable = {{0, 0, 0, 255}";
  for(my $i=1; $i<=255; $i++) {
    print Fgeo ", {$i, $i, $i, 255}";
  }
  print Fgeo "};\n";
}
#option -noGrid : desactiver l affichage des lignes des elements
if($is_opt_noGrid) {
  print Fgeo "View.ShowElement = 0;\n";
}
#option -noLight : desactiver les reflets de lumiere (color->enable lightning)
if($is_opt_noLight) {
  print Fgeo "View.Light = 0;\n";
}
#option -line_width : epaisseur de ligne
print Fgeo "View.LineWidth = $line_width;\n";


#on charge toutes les vues (une par fichier .pos, sauf "deplace" qui sera chargee en dernier)
my $fpos;
for(my $i=0; $i<=$#liste_isoval_demandees; $i++) {
  my $nom_isoval = $liste_isoval_demandees[$i];
  $fpos = "${racine_fic}${nom_isoval}_Gmsh.pos";
  print Fgeo "Merge \"$fpos\";\n";
}
#ajout de la vue "deplace" en dernier
$fpos = "${racine_fic}deplace_Gmsh.pos";
print Fgeo "Merge \"$fpos\";\n";



#application de AdaptVisualizationGrid (en cas d option -adaptVisu)
if($adaptvizu_high_order >= 1) {
  for(my $i=0; $i<=$#liste_isoval_demandees+1; $i++) {
    print Fgeo "View[$i].AdaptVisualizationGrid = 1;\n";
    print Fgeo "View[$i].MaxRecursionLevel = $adaptvizu_high_order;\n";
    print Fgeo "View[$i].TargetError = -0.0001;\n";
  }
}

#modif du cas special : "deplace" (View[0])
#  =>pour "deplace", on retranche 1 au facteur d ampli car le fait de l afficher en mode "displacement" applique deja une fois le deplacement
$_ = $facteur_ampli - 1.;
print Fgeo "View[$no_view_deplace].GeneralizedRaiseFactor = $_;\n";#facteur d amplification de la deformee
#-la vue "deplace" sera la seule vue active au lancement de Gmsh
print Fgeo "View[$no_view_deplace].Visible = 1;\n";


#modif du mode de visu pour les resu vectoriels (sauf "deplace")
for(my $i=0; $i<=$#liste_isoval_demandees; $i++) {
  my $nom_isoval = $liste_isoval_demandees[$i];

  next if($nom_isoval eq 'deplace');#on saute la grandeur "deplace"

  #saisie du nombre de composantes dans le .pos dans le 1er $\S*NodeData du fichier
  my $is_VECTEUR = 0;#indicateur d une grandeur vectorielle : =0 si pas un vecteur, =1 si 3 composantes i.e un vecteur
  open(FIC, "<${racine_fic}${nom_isoval}_Gmsh.pos");
  while(<FIC>) {
    next if(not /^\s*\$\S*NodeData\b/io);
    for(my $i=1; $i<=6; $i++) {$_ = <FIC>;}
    $_ = <FIC>; @_ = split;
    $is_VECTEUR = 1 if($_[0] eq '3');
    last;
  }
  close(FIC);

  #modif des options si c est une grandeur vectorielle
  if($is_VECTEUR) {
    print Fgeo "View[$i].VectorType = 4;\n";#affichage de type "3D arrow"
    print Fgeo "View[$i].ArrowSizeMax = 100;\n";#taille max de fleche  \
    print Fgeo "View[$i].ArrowSizeMin = 1;\n";#taille min de fleche    / ce sont les bornes pour regler la taille des vecteurs les uns par rapport aux autres (selon leur norme)
    print Fgeo "View[$i].GlyphLocation = 2;\n";#position des fleche (2= aux sommets i.e aux noeuds)
    print Fgeo "View[$i].CenterGlyphs = 0;\n";#alignement (0= Left-aligned i.e la fleche demarre depuis la GlyphLocation)

    #on affiche toujours le maillage pour les vecteurs
    # meme si il y a une eventuelle option -noGrid
    print Fgeo "View[$i].ShowElement = 1;\n";
  }
}


#ajout des fichiers a merger (option : -merge)
if($#opt_merge_fic != -1) {
  print Fgeo "\n";
  print Fgeo "//ajout de fichiers option -merge\n";
  foreach my $fic (@opt_merge_fic) {
    print Fgeo "Merge \"$fic\";\n";
  }
}


close(Fgeo);


#lancement de la visualisation (sauf si l option -quit a ete utilisee)
if($is_opt_quit) {
  print "\n($NOM_PROG,opt:-quit) pas de visualisation Gmsh...\n\n";
}
else {
  system("$exeGMSH $fvisu");
}


#destruction du fichier de visu (sauf si option -saveVisu)
if($is_opt_saveVisu) {
  print "\n($NOM_PROG,opt:-saveVisu) fichier de visualisation $fvisu a ete sauvegarde...\n\n";
}
else {
  system("rm -f $fvisu") ;
}




#prend en argument une chaine de caracteres et renvoie 
#une chaine de caracteres de meme longueur constituee d espaces
sub chaine2espaces {
  my $chaine = shift;
  (my $chaine_espaces = $chaine) =~ s/./ /g;
  return $chaine_espaces;
}


#cette subroutine verifie l existence d une commande dans $PATH
sub verif_cmd {
  my $cmd = shift;

  #verif directe : est-ce que le fichier existe et est executable
  return 1 if(-x $cmd);

  #sinon, on regarde dans les path
  foreach my $path (split(/\s*:\s*/, $ENV{PATH})) {
    return 1 if(-x "$path/$cmd");
  }

  #cas ou la commande n existe pas
  return 0;
}

#cette subroutine reecrit (definitivement) le repertoire Gmsh pour retablir la coherence dans les numeros d increments
# et avoir une seule grandeur par fichier .pos (cf explication plus exhaustive dans les commentaires precedents son appel dans le script)
sub execute_option_repair {
  my $rep_Gmsh = shift;

  print "\n-- prog:$NOM_PROG : traitement option -repair --\n";


  #variables qui vont servir de handle de fichier local a cette subroutine
  my $HLOCAL;
  my $HLOCAL2;

  #verif existence repertoire
  (-d $rep_Gmsh) or die "\nErreur (prog:$NOM_PROG, sub:execute_option_repair) : repertoire $rep_Gmsh n existe pas...\n\n";

  #liste des fichiers a traiter
  my @liste_fic_pos = glob("$rep_Gmsh/*.pos");

  #arret si aucun fichier
  ($#liste_fic_pos != -1) or die "\nErreur (prog:$NOM_PROG, sub:execute_option_repair) : aucun fichier .pos dans le repertoire $rep_Gmsh ...\n\n";


  #arret dans le cas d un seul fichier .pos
  #  car : - pas possible d etablir une coherence entre fichiers s il y en a qu un seul)
  #        - il ne sera pas possible de determiner une racine commune de nom de fichiers .pos avec un seul fichier
  ($#liste_fic_pos != 0) or die "
Erreur (prog:$NOM_PROG, sub:execute_option_repair) : le repertoire $rep_Gmsh ne contient qu un seul fichier .pos ($liste_fic_pos[0])
  => aucun traitement possible dans le cas d un seul fichier .pos
  => le fichier $liste_fic_pos[0] n a pas ete modifie...
";

  #--------------------------------------
  #--------------------------------------
  #ETAPE 1)  split des fichiers a grandeurs multiples
  #--------------------------------------
  #--------------------------------------
  #tout d abord, on etablit la racine du nom des fichiers .pos (partie commune de tous les noms des .pos)
  my $racine_commune;
  my @liste_carac_fic;
  my $is_premier_fic_traite = 0;#pour gerer l affichage terminal au premier fichier concerne par un split
  foreach my $fic (@liste_fic_pos) {
    @{$liste_carac_fic[$#liste_carac_fic+1]} = split(//, $fic);
  }
  my $ind_carac = -1;
  MAIN_WHILE:while() {
    $ind_carac++;
    my $carac_commun = $liste_carac_fic[0][$ind_carac];
    for(my $i=1; $i<=$#liste_carac_fic; $i++) {
      next if($liste_carac_fic[$i][$ind_carac] eq $carac_commun);
      last MAIN_WHILE;
    }
    $racine_commune .= $carac_commun;
  }

  #et ensuite, on splitte les fichiers (on utilisera $racine_commune pour nommer les eventuels nouveaux fichiers a creer)
  my @liste_fic_pos_new;
  foreach my $fic (@liste_fic_pos) {
    my @liste_grandeurs;
    open($HLOCAL, "<$fic");
    while(<$HLOCAL>) {
      next if(not /^\s*\$nodedata\b/io);
      <$HLOCAL>;
      $_ = <$HLOCAL>;
      /^\s*\"(.+)\"/ or die "Erreur (prog:$NOM_PROG, sub:execute_option_repair) : impossible de lire un nom de grandeur dans fichier $fic ligne $. ...\n\n";
      my $grandeur = $1; $grandeur =~ s/^\s+//; $grandeur =~ s/\s+$//;

      #on ajoute la grandeur a la liste si elle n existe pas dans la liste
      if(not " @liste_grandeurs " =~ / $grandeur /) {
        push(@liste_grandeurs, $grandeur);
      }
    }
    close($HLOCAL);

    #si il n y a qu une seule grandeur, rien a faire sur ce fichier (on le garde en l etat)
    if($#liste_grandeurs == 0) {
      push(@liste_fic_pos_new, $fic);
      next;
    }

    #sinon, on splitte le fichier

    print "\n  => Split de fichiers a grandeurs multiples :\n" if($is_premier_fic_traite);
    $is_premier_fic_traite = 0;

    print "  - $fic devient :\n";
    #--ouverture d autant de fichier qu il y a de grandeur
    #    on gere les handles de fichier avec une table hashage : $Handle{$grandeur} = handle du fichier lie a la grandeur $grandeur
    my %Handle;
    foreach my $grandeur (@liste_grandeurs) {
      (my $nom_fichier = $grandeur) =~ s/\s+/_/g;#on remplace d eventuels espaces en milieu de mot par "_"
      $nom_fichier = $racine_commune."$nom_fichier\_Gmsh.pos";
      print "      > $nom_fichier\n";
      push(@liste_fic_pos_new, $nom_fichier);#ajout d un nouveau fichier .pos dans la liste des fichiers
      open($Handle{$grandeur}, ">$nom_fichier");
    }
    #recopie des grandeurs dans les fichiers adequats
    open($HLOCAL, "<$fic");
    while(<$HLOCAL>) {
      #pour n importe quoi d autre qu un nodedata, on recopie la ligne dans tous les fichiers
      # (principalement l en-tete du fichier (i.e le maillage initial) mais aussi les lignes vides entre 2 nodedata)
      if(not /^\s*\$nodedata\b/io) {
        foreach my $key (keys %Handle) {
          my $H = $Handle{$key};
          print $H $_;
        }
        next;
      }

      #sinon, on recopie le nodedata dans le bon fichier en fonction du nom de la grandeur
      my $entete = $_;
      $_ = <$HLOCAL>; $entete .= $_;
      $_ = <$HLOCAL>; $entete .= $_;
      /^\s*\"(.+)\"/ or die "Erreur (prog:$NOM_PROG, sub:execute_option_repair) : impossible de lire un nom de grandeur dans fichier $fic ligne $. ...\n\n";
      my $grandeur = $1; $grandeur =~ s/^\s+//; $grandeur =~ s/\s+$//;
      #-- selection du fichier concerne par la grandeur $grandeur pour y ecrire tout le contenu du nodedata en cours
      my $H = $Handle{$grandeur};
      print $H $entete;
      while(<$HLOCAL>) {
        print $H $_;
        last if(/^\s*\$endnodedata\b/io);
      }
    }#while(<$HLOCAL>)
    close($HLOCAL);
    #fermeture de tous les fichiers
    foreach my $key (keys %Handle) {
      my $H = $Handle{$key};
      close($H);
    }

    #suppression du fichier original
    system("rm -rf $fic");
  }#foreach my $fic (@liste_fic_pos)

  #remplacement de l ancienne liste de fichiers .pos par la nouvelle
  @liste_fic_pos = ();
  @liste_fic_pos = @liste_fic_pos_new;


  #--------------------------------------
  #--------------------------------------
  #ETAPE 2) gestion des incoherences sur nombre et numeros d increments
  #
  #  rq : on est dans la cas ou l ETAPE 1 a ete appliquee avec eventuellement des fichiers
  #       qui ont ete splittes
  #
  #       la variable qui contient la liste de fichiers .pos est @liste_fic_pos
  #       et elle est a jour (elle tient compte des eventuels split de fichier)
  #       
  #--------------------------------------
  #--------------------------------------

  #----
  #---- saisie d une liste increment-temps-numero Nodedata par fichier et verification de la coherence
  #----

  #--- les indicateurs ci-dessous seront mis a 1 en cas de probleme de coherence
  #    $is_probleme_nb_incr     => pb sur le nombre
  my $is_probleme_nb_incr = 0;
  #    $is_probleme_numero_incr => pb sur les numeros
  my $is_probleme_numero_incr = 0;


  #--- recuperation d un tableau "increment - temps - no Nodedata" pour chaque fichier
  #  NB : no Nodedata correspond a l ordre d apparition du Nodedata dans le fichier .pos (en commencant a 1 pour le premier)
  my @nofic_incr_temps_noNodedata;
  for(my $no_fic=0; $no_fic<=$#liste_fic_pos; $no_fic++) {
    my $nom_fic = $liste_fic_pos[$no_fic];
    $_ = __get_tab_incr_temps_noNodedata($nom_fic);
    @{$nofic_incr_temps_noNodedata[$no_fic]} = @$_;
  }

  #--- si il n y a pas autant d increments dans chaque fichier => indicateur probleme nb incr $is_probleme_nb_incr
  print "\n  => Verification du nombre d increments...\n";
  my $nb_incr_ref = $#{$nofic_incr_temps_noNodedata[0]}+1;
  print "  - $liste_fic_pos[0] : $nb_incr_ref\n";
  for(my $no_fic=1; $no_fic<=$#liste_fic_pos; $no_fic++) {
    my $nb_incr = $#{$nofic_incr_temps_noNodedata[$no_fic]} + 1;
    print "  - $liste_fic_pos[$no_fic] : $nb_incr\n";
    if($nb_incr != $nb_incr_ref) {
      print "      **Attention : nombre different du premier fichier\n";
      $is_probleme_nb_incr = 1;
    }
  }

  #--- si les numeros increment ne sont pas croissants dans au moins un fichier => indicateur probleme no incr $is_probleme_numero_incr
  print "\n  => Verification ordre des numeros d increments...\n";
  for(my $no_fic=0; $no_fic<=$#liste_fic_pos; $no_fic++) {
    my @liste_incr_fic = map { $_->[0] } @{$nofic_incr_temps_noNodedata[$no_fic]};
    my $is_croissante = !grep { $liste_incr_fic[$_] <= $liste_incr_fic[$_ - 1] } 1 .. $#liste_incr_fic;
    print "  - $liste_fic_pos[$no_fic] : ";
    if($is_croissante) {
      print "OK\n";
    }
    else {
      print "PROBLEME\n";
      $is_probleme_numero_incr = 1;
    }
  }


  #----
  #---- etablissement d un tableau de reference incr-temps preliminaire construit a partir du premier fichier .pos de la liste
  #----

  #-- liste originale
  my @ref_incr_temps_ORIG = map {[$_->[0], $_->[1]]} @{$nofic_incr_temps_noNodedata[0]};

  #-- suppression des doublons en temps
  my @ref_incr_temps_DOUBLON = do {
    my %seen;
    grep {not $seen{$_->[1]}++} @ref_incr_temps_ORIG;
  };
  #si des doublons de temps ont ete supprimes : on le signale (NB : normalement ca n arrive jamais)
  if($#ref_incr_temps_ORIG != $#ref_incr_temps_DOUBLON) {
    print "\n  **Attention : certains increments avaient le meme temps\n";
    my $nb_doublon = $#ref_incr_temps_ORIG - $#ref_incr_temps_DOUBLON;
    print "              (nombre de doublons supprimes : $nb_doublon)\n";
  }

  #-- modif des no increments si l ordre n est pas sctrictement croissant 
  #   => on leur redonne arbitrairement un ordre strictement croissant par la regle :
  #         si un no increment est inferieur ou egal a son increment precedent => no increment = no precedent + 1
  my @ref_incr_temps_NUMERO = @ref_incr_temps_DOUBLON;
  for(my $i=1; $i<=$#ref_incr_temps_NUMERO; $i++) {
    if($ref_incr_temps_NUMERO[$i][0] <= $ref_incr_temps_NUMERO[$i-1][0]) {
      #changement numero increment
      $ref_incr_temps_NUMERO[$i][0] = $ref_incr_temps_NUMERO[$i-1][0] + 1;
    }
  }

  # a ce stade, la liste de reference preliminaire est @ref_incr_temps_NUMERO
  #   => elle reste a confirmer en verifiant que chaque temps est present dans chaque fichier
  #   => on la range dans une nouvelle variable (c est juste pour changer de nom de variable)
  my @ref_incr_temps_PRELIMINAIRE = @ref_incr_temps_NUMERO;

  #on ecrase les autres devenues inutiles
  @ref_incr_temps_NUMERO = ();
  @ref_incr_temps_DOUBLON = ();
  @ref_incr_temps_ORIG = ();

  #----
  #---- construction de la table definitive incr-temps en ne gardant que les temps communs a tous les fichiers
  #----
  my @ref_incr_temps_COMMUNS;

  MAIN_FOR:for(my $i_ref=0; $i_ref<=$#ref_incr_temps_PRELIMINAIRE; $i_ref++) {
    my $no_incr_ref = $ref_incr_temps_PRELIMINAIRE[$i_ref][0];
    my $temps_ref   = $ref_incr_temps_PRELIMINAIRE[$i_ref][1];

    #verif si le temps ref existe dans tous les fichiers
    for(my $no_fic=0; $no_fic <= $#liste_fic_pos; $no_fic++) {
      my $liste_temps_fic_str = ' ' . join(' ', map { $_->[1] } @{$nofic_incr_temps_noNodedata[$no_fic]}) . ' ';
      next MAIN_FOR if(not $liste_temps_fic_str =~ / $temps_ref /);
    }

    #ce temps est commun a tous les fichiers => ajout a la liste commune de reference
    push(@ref_incr_temps_COMMUNS, [$no_incr_ref, $temps_ref]);
  }

  #----
  #---- construction de la liste de no Nodedata par fichier correspondant aux temps de @ref_incr_temps_COMMUNS
  #----
  my @liste_Nodedata_par_fic;

  for(my $no_fic=0; $no_fic<=$#liste_fic_pos; $no_fic++) {

    #indice de depart pour rechercher le no Nodedata (il va evoluer : inutile de repartir du debut a chaque fois)
    my $ind_fic_depart = 0;

    for(my $i_ref=0; $i_ref<=$#ref_incr_temps_PRELIMINAIRE; $i_ref++) {
      my $temps_ref   = $ref_incr_temps_PRELIMINAIRE[$i_ref][1];

      for(my $i_fic=$ind_fic_depart; $i_fic<=$#{$nofic_incr_temps_noNodedata[$no_fic]}; $i_fic++) {
        my $temps_fic = $nofic_incr_temps_noNodedata[$no_fic][$i_fic][1];
        next if($temps_fic ne $temps_ref);

        #ce nodedata correspondant au temps $temps_ref => ajout a la liste pour ce fichier
        my $no_Nodedata = $nofic_incr_temps_noNodedata[$no_fic][$i_fic][2];
        push(@{$liste_Nodedata_par_fic[$no_fic]}, $no_Nodedata);

        #modif indice de depart : on repartira de l indice $i_fic qui vient d etre utilise
        $ind_fic_depart = $i_fic;
        last;
      }
    }

    # verification : il faut que l ordre des no Nodedata soit strictement croissant
    # (peut-etre a modifier un jour, mais pour l instant, on arrete tout si ce n est pas respecte
    #  car ca impliquerait de parcourir le fichier .pos d une maniere particuliere
    #  ... et ca parait peu probable que l ordre de parcours necessite un retour en arriere dans le fichier .pos)
    my @liste_tmp = @{$liste_Nodedata_par_fic[$no_fic]};
    my $is_croissante = !grep { $liste_tmp[$_] <= $liste_tmp[$_ - 1] } 1 .. $#liste_tmp;
    $is_croissante or die "\nErreur (prog:$NOM_PROG, sub:execute_option_repair) : reparation du fichier $liste_fic_pos[$no_fic] impliquerait un parcours non lineaire du fichier d origine (ordre des Nodedata non croissant)...\n\n";
  }

  #liste PRELIMINAIRE devenue inutile
  @ref_incr_temps_PRELIMINAIRE = ();


  # --- bilan de la verification ---
  print "\n  ======= Bilan verification =======\n";
  #-nombre d increments
  print "    > nombre d increments  : ";
  if($is_probleme_nb_incr) {
    print "ERREUR\n";
  }
  else {
    print "OK\n";
  }
  #-numeros d increments
  print "    > numeros d increments : ";
  if($is_probleme_numero_incr) {
    print "ERREUR\n";
  }
  else {
    print "OK\n";
  }
  print "\n";


  #--------------------------------------
  #--------------------------------------
  #ETAPE 3) en cas de pb => reecriture des fichiers .pos en ne gardant que les numeros d increments communs a tous les fichiers
  #
  # rappel : la liste commune incr-temps est dans @ref_incr_temps_COMMUNS (NB : avec eventuellement des numeros d increment modifies)
  #          et pour chaque fichier, on a la liste @{$liste_Nodedata_par_fic[no fichier]} qui donne la liste des no Nodedatas a recopier dans le fichier final
  #--------------------------------------
  #--------------------------------------

  if($is_probleme_nb_incr or $is_probleme_numero_incr) {
    my $nb_incr_COMMUNS = $#ref_incr_temps_COMMUNS + 1;
    print "  => Reecriture des fichiers .pos avec :\n";
    print "       - uniquement les increments communs (nombre final : $nb_incr_COMMUNS)\n" if($is_probleme_nb_incr);
    if($is_probleme_numero_incr) {
      print "       - des nouveaux numeros d increments\n";
      print "            NB : les nouveaux numeros n auront peut-etre plus de rapport avec le calcul d origine\n";
      print "                   (conseil : se baser sur le temps pour faire le lien entre increment Gmsh\n";
      print "                              et increment d origine du calcul Herezh)\n";
    }
  }
  #SI AUCUN PROBLEME => arret du traitement -repair
  else {
    print "\n-- fin traitement option -repair --\n";
    return;
  }

  print "\n";
  for(my $no_fic=0; $no_fic<=$#liste_fic_pos; $no_fic++) {
    my $nom_fic = $liste_fic_pos[$no_fic];

    #conversion de la liste de Nodedata en chaine pour reperer rapidement les Nodedata a conserver
    my $liste_noNodedata_str = " @{$liste_Nodedata_par_fic[$no_fic]} ";

    #liste des numeros d increments a reporter dans le fichier .pos
    #  => on se base sur les numeros de la liste commune @ref_incr_temps_COMMUNS
    #     on sait deja que le temps sera bon car il a ete utilise pour constituer la liste @{$liste_Nodedata_par_fic[$no_fic]}
    my @liste_no_incr = map { $_->[0] } @ref_incr_temps_COMMUNS; # NB : on va la depiler valeur par valeur avec shift()

    #compteur de Nodedata
    my $noNodedata_actuel = 0;

    print "  > Reecriture : $nom_fic\n";
    open($HLOCAL, "<$nom_fic");
    open($HLOCAL2, ">$nom_fic.tmp");
    while(<$HLOCAL>) {
      #pour autre chose qu un nodedata => ecriture dans le fichier final
      if(not /^\s*\$nodedata\b/io) {
        print $HLOCAL2 $_;
        next;
      }

      #on commence a accumuler l en-tete
      my $en_tete = $_;#on accumule l en-tete dans une variable
                       # (a ce stade, elle contient "$Nodedata" i.e le contenu de $_)

      #on est donc arrive dans un Nodata => incrementation compteur
      $noNodedata_actuel++;

      #on est actuellement dans le Nodedata numero "$noNodedata_actuel"
      # => si ce numero de Nodedata n est pas dans la liste => on ne le traite pas => on passe au prochain Nodedata
      next if(not $liste_noNodedata_str =~ / $noNodedata_actuel /);


      #ce Nodedata doit etre ecrit et il lui correspond le premier no d increment disponible dans la liste @liste_no_incr
      my $no_incr_a_ecrire = shift(@liste_no_incr);#on depile une valeur de @liste_no_incr


      #on accumule les 5 lignes suivantes dans l en-tete
      for(my $i=1; $i<=5; $i++) {
        $en_tete .= <$HLOCAL>;
      }

      #le numero increment est a la 6eme ligne :
      # => on saute cette ligne
      <$HLOCAL>;
      # => et on la remplace par le numero d increment venant de @ref_incr_temps_COMMUNS
      $en_tete .= "$no_incr_a_ecrire\n";

      #on ecrit le nodedata dans le fichier final
      print $HLOCAL2 $en_tete;
      while(<$HLOCAL>) {
        print $HLOCAL2 $_;
        last if(/^\s*\$endnodedata\b/io);
      }
    }
    close($HLOCAL2);
    close($HLOCAL);

    # verification : normalement tous les increments de @ref_incr_temps_COMMUNS ont ete traites pour ce fichier
    #  => donc la liste @liste_no_incr que l on a depilee (shift) doit etre vide
    if($#liste_no_incr != -1) {
      system("rm -f $nom_fic.tmp");
      die "\nErreur (prog:$NOM_PROG, sub:execute_option_repair) : probleme fatal dans la reparation du fichier $nom_fic ; tous les increments n ont pas ete traites; Le fichier d origine a ete conserve...\n\n";
    }
    else {
      #remplacement definifif du fichier d origine
      system("mv -f $nom_fic.tmp $nom_fic");
    }
  }

  print "\n-- fin traitement option -repair --\n";


  #renvoie une reference vers un tableau de la forme : ([no incr, temps, no Nodedata], [no incr, temps, no Nodedata], ...)
  sub __get_tab_incr_temps_noNodedata {
    my $fic = shift;

    my @tab_incr_temps_noNodedata;
    my $no_Nodedata = 0;
    open(my $H___, "<$fic");
    while(<$H___>) {
      next if(not /^\s*\$nodedata\b/io);
      $no_Nodedata++;

       #NB : le temps est situe a la 4eme ligne apres Nodedata
       #     le numero d increment est situe a la 6eme ligne apres Nodedata

      <$H___> for(1 .. 3);#on passe 3 lignes pour recuperer le temps
      $_ = <$H___>;#4eme ligne = temps
      my ($temps) = split;

      <$H___>;#5eme
      $_ = <$H___>;#6eme ligne = no increment
      my ($no_incr) = split;

      push(@tab_incr_temps_noNodedata, [$no_incr, $temps, $no_Nodedata]);
    }
    close($H___);

    return \@tab_incr_temps_noNodedata;
  }

}#sub execute_option_repair

