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

my $VERSION = '1.01';
######################################################################################################
#  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                                                    #
######################################################################################################



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# 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 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 :
#    1) 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.
#
#    2) suppression de l increment 0 dans le cas ou cet increment est absent dans au moins un fichier .pos
#       raison : ca peut arriver que les fichiers generes par Herezh ne soient pas coherents sur l increment 0.
#                (deja vu des fichiers X1, X2, X3 avec increment 0 alors que le fichier "deplace" n en avait pas.
#                 Si ca arrive, il aura des erreurs a l ouverture de Gmsh)
#
#    3) verification des numeros d increments (apres eventuelle suppression des increments 0)
#       3.1) nombre d increment : si tous les fichiers n ont pas le meme nombre d increments, on ne gardera que
#                                 les N premiers increments ou "N" est le plus nombre d increments trouve parmi les fichiers .pos
#                                 (on parle ici de nombre d increments, pas de leur numero)
#
#       3.2) si on constate que 2 increments ont le meme numero d increment, alors on renumerotera les
#       numeros d increments de 1 a N. Dans ce cas, il n y aura plus de coherence avec les "vrais"
#       numeros d increments d origine du calcul Herezh (ce qui sera affiche sous forme de
#       warning dans le terminal). La seule donnee qui gardera la coherence avec le calcul herezh est le temps.
#
#       dans tous les cas, les fichiers .pos seront reecrits en tenant compte des eventuelles incoherences relevees en 3.1) et 3.2)
#
#
# 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)
  #       
  #--------------------------------------
  #--------------------------------------

  #on commence par recuperer dans un tableau tous les numeros d increments disponibles dans tous les fichiers .pos
  my @liste_incr_par_fichier;#tableau 2 indices : $liste_incr_par_fichier[i][j] = numero du j-eme increment du i-eme fichier
  for(my $no_fic=0; $no_fic <= $#liste_fic_pos; $no_fic++) {
    my $nom_fic = $liste_fic_pos[$no_fic];

    if(not -e $nom_fic) {
      print "Erreur (prog:$NOM_PROG) : fichier $nom_fic introuvable...\n\n";
      next;
    }

    # saisie liste increments de ce fichier
    @{$liste_incr_par_fichier[$no_fic]} = __get_liste_numeros_incr($nom_fic);
  }

  #---ETAPE 2.1) verif incoherence sur le nombre d increments par fichier (on se base sur le premier fichier de la liste)

  my $is_probleme_nb_incr = 0;#indicateur d un probleme sur le nombre d increments

  print "\n  => Verification du nombre d increments...\n";
  my $nb_incr_ref = $#{$liste_incr_par_fichier[0]} + 1;
  my $min_nb_incr = $nb_incr_ref;
  my $max_nb_incr = $nb_incr_ref;
  print "  - $liste_fic_pos[0] : $nb_incr_ref\n";
  for(my $no_fic=1; $no_fic <= $#liste_fic_pos; $no_fic++) {
    my $nb_incr = $#{$liste_incr_par_fichier[$no_fic]} + 1;
    print "  - $liste_fic_pos[$no_fic] : $nb_incr\n";
    ($nb_incr == $nb_incr_ref) or print "      **Attention : nombre different du premier fichier\n";

    $min_nb_incr = $nb_incr if($min_nb_incr > $nb_incr);
    $max_nb_incr = $nb_incr if($max_nb_incr < $nb_incr);
  }
  #si min different du max, c est qu au moins 1 fichier n a pas le meme nombre d increments que les autres
  # => si c est le cas => indicateur de pb
  if($min_nb_incr != $max_nb_incr) {
    $is_probleme_nb_incr = 1;
  }

  #---ETAPE 2.2) verif des numeros d increments (on recupere la liste des no d increments commune a tous les fichiers)

  my $is_probleme_numero_incr = 0;#indicateur d un probleme sur les numeros d increments
  my @liste_numeros_incr_communs;#liste des increments communs a tous les fichiers .pos

  print "\n  => Verification des numeros d increments...\n";
  #on commence par trier ordre croissant les listes de tous les fichiers
  for(my $no_fic=0; $no_fic <= $#liste_fic_pos; $no_fic++) {
    @{$liste_incr_par_fichier[$no_fic]} = sort {$a <=> $b} @{$liste_incr_par_fichier[$no_fic]};
  }
  #on veut construire la liste des increments qui figurent dans tous les fichiers .pos
  #  methode : on compte le nombre de fois qu un numero d increment apparait dans les listes
  #              => si un numero d increment apparait autant de fois que le nombre de fichiers .pos, 
  #                 alors ca veut dire qu il est present dans tous les fichiers .pos
  my %table_comptage;
  for(my $no_fic=0; $no_fic <= $#liste_fic_pos; $no_fic++) {
    foreach my $no_incr (@{$liste_incr_par_fichier[$no_fic]}) {
      if(defined $table_comptage{$no_incr}) {
        $table_comptage{$no_incr}++;#numero existe dans la table => on incremente son decompte
      }
      else {
        $table_comptage{$no_incr} = 1;#initialisation du comptage pour ce numero increment
      }
    }
  }
  #liste commune (a mettre dans @liste_numeros_incr_communs)
  #  (on va egalement garder une liste des increments qui sont a supprimer)
  my @liste_incr_a_supprimer;
  foreach my $no_incr (sort {$a <=> $b} keys(%table_comptage)) {
    #si ce numero ne figure pas dans tous les fichiers => on ne le garde pas et on indique qu il y a un pb de coherence sur les numeros
    if($table_comptage{$no_incr} != $#liste_fic_pos+1) {
      $is_probleme_numero_incr = 1;
      push(@liste_incr_a_supprimer, $no_incr);#ajout a la liste des incr a supprimer
      next;
    }
    push(@liste_numeros_incr_communs, $no_incr);
  }

  #affichage des pb eventuels
  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 est dans @liste_numeros_incr_communs
  #--------------------------------------
  #--------------------------------------

  if($is_probleme_nb_incr or $is_probleme_numero_incr) {
    print "  => Reecriture des fichiers .pos en ne gardant que les increments communs\n";
    print "     Liste des increments supprimes : ";
    if($#liste_numeros_incr_communs == -1) {
      print "aucun\n";
    }
    else {
      print "@liste_incr_a_supprimer\n";
    }
  }
  #SI AUCUN PROBLEME => arret du traitement -repair
  else {
    print "\n-- fin traitement option -repair --\n";
    return;
  }

  #preparation d une chaine de caracteres contenant tous les increments
  # a conserver (transfo de la liste @liste_numeros_incr_communs en chaine)
  my $str_liste_no_incr_communs = " @liste_numeros_incr_communs ";

  print "\n";
  foreach my $nom_fic (@liste_fic_pos) {
    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;
      }

      #sinon on doit verifier si le nodedata a un no increment a conserver
      my $en_tete = $_;#on accumule l en-tete dans une variable
                       # (a ce stade, elle contient "Nodedata" i.e le contenu de $_)
      #on accumule les 5 lignes suivantes
      for(my $i=1; $i<=5; $i++) {
        $en_tete .= <$HLOCAL>;
      }
      #numero increment a la 6eme ligne
      $_ = <$HLOCAL>; $en_tete .= $_;
      my ($no_incr) = split;
      #si le numero increment figure dans la liste => on ecrit le nodedata
      if($str_liste_no_incr_communs =~ / $no_incr /) {
        print $HLOCAL2 $en_tete;
        while(<$HLOCAL>) {
          print $HLOCAL2 $_;
          last if(/^\s*\$endnodedata\b/io);
        }
      }
      #sinon on passe le nodedata
      else {
        while(<$HLOCAL>) {
          last if(/^\s*\$endnodedata\b/io);
        }
      }
    }
    close($HLOCAL2);
    close($HLOCAL);

    #remplacement definifif du fichier d origine
    system("mv -f $nom_fic.tmp $nom_fic");
  }

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



  sub __get_liste_numeros_incr {
    my $fic = shift;

    my @liste_incr;
    open(my $H___, "<$fic");
    while(<$H___>) {#NB : le numero d increment est situe a la 6eme ligne apres Nodedata
      next if(not /^\s*\$nodedata\b/io);
      <$H___> for(1 .. 5);#on passe 5 lignes
      $_ = <$H___>;
      @_ = split;
      push(@liste_incr, $_[0]);
    }
    close($H___);

    return @liste_incr;
  }


}#sub execute_option_repair

