/*! \file herezh.cc
    \brief programme principal herezh++.
*/

// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *                                                                      *
 *     DATE:        15/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:         programme de calcul de structure par elements finis *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                      *
 *                                                                $     *
 *                                                                      *
 ************************************************************************/
//#include <altivec.h> 
# include <iostream>
using namespace std;  //introduces namespace std

#include "herezh.h" 
//#include "Debug.h"
//#include "DebugNew.h"  // peut-etre à virer ensuite ?

#include <math.h>
//# include "EnteteParaGlob.h"
#include "ConstantePrinc.h"
# include "ParaGlob.h"

// ------- specifiques tenseur -------------------------------
// 1- second ordre
# include "Tenseur3.h"
# include "Tenseur2.h"
# include "Tenseur1.h"
// 2- quatrieme ordre
# include "TenseurQ-3.h"
# include "TenseurQ-2.h"
# include "TenseurQ-1.h"
#include "Tenseur1_TroisSym.h"
#include "Tenseur2_TroisSym.h"
#include "Tenseur3_TroisSym.h"
// def des variables statiques permettant entre autre d'effacer les tenseurs intermediaires
# include "EnteteTenseur.h" 
// fonction permettant  la definition de nouveaux tenseurs
#include "NevezTenseur.h"
// def des constantes tenseur
# include "TypeConsTensPrinc.h"
// lorsque l'on veut faire reference a des constantes tenseurs dans un autre
// fichier que le prog principal il faut inclure :
// # include "TypeConsTens.h"
// uniquement, ceci a la place de :
// "TypeConsTensPrinc.h"
// "DefValConsTens.h" 
// est a placer dans le fichier qui defini les valeurs des constantes
// --------- fin specifique tenseur ---------------

//-------- listes globales de petits tableaux ------------
//#include "PtTabRel_Princ.h"

#include "Projet.h" 
#include "Biellette.h"
#include "BielletteQ.h"
#include "Biel_axi.h"
#include "Biel_axiQ.h"
#include "TriaMembL1.h"
#include "TriaMembQ3.h"
#include "TriaMembQ3_cm1pti.h"
#include "TriaQ3_cmpti1003.h"
#include "TriaCub.h"
#include "TriaCub_cm4pti.h"
#include "Quad.h"
#include "Quad_cm1pti.h"
#include "QuadQ.h"
#include "QuadQCom.h"
#include "QuadQCom_cm4pti.h"
#include "Hexa.h"
#include "Hexa_cm1pti.h"
#include "Hexa_cm27pti.h"
#include "Hexa_cm64pti.h"
#include "HexaQ.h"
#include "HexaQ_cm1pti.h"
#include "HexaQ_cm27pti.h"
#include "HexaQ_cm64pti.h"
#include "HexaQComp.h"
#include "HexaQComp_cm1pti.h"
#include "HexaQComp_cm27pti.h"
#include "HexaQComp_cm64pti.h"
#include "Tetra.h"
#include "TetraQ.h"
#include "TetraQ_cm1pti.h"
#include "TetraQ_cm15pti.h"
#include "PentaL.h"
#include "PentaL_cm1pti.h"
#include "PentaL_cm6pti.h"
#include "PentaQ.h"
#include "PentaQ_cm3pti.h"
#include "PentaQ_cm9pti.h"
#include "PentaQ_cm12pti.h"
#include "PentaQ_cm18pti.h"
#include "PentaQComp.h"
#include "PentaQComp_cm9pti.h"
#include "PentaQComp_cm12pti.h"
#include "PentaQComp_cm18pti.h"
#include "TriaSfe1.h"
#include "TriaSfe1_cm5pti.h"
#include "TriaSfe2.h"
#include "TriaSfe3.h"
#include "TriaSfe3_3D.h"
#include "TriaSfe3_cm3pti.h"
#include "TriaSfe3_cm4pti.h"
#include "TriaSfe3_cm5pti.h"
#include "TriaSfe3_cm6pti.h"
#include "TriaSfe3_cm7pti.h"
#include "TriaSfe3_cm12pti.h"
#include "TriaSfe3_cm13pti.h"
#include "TriaSfe3C.h"
#include "TriaQSfe3.h"
#include "TriaQSfe1.h"
#include "PoutSimple1.h"
#include "QuadCCom.h"
#include "QuadCCom_cm9pti.h"
#include "TriaAxiL1.h"
#include "TriaAxiQ3.h"
#include "TriaAxiQ3_cm1pti.h"
#include "TriaAxiQ3_cmpti1003.h"
#include "QuadAxiL1.h"
#include "QuadAxiL1_cm1pti.h"
#include "QuadAxiQ.h"
#include "QuadAxiQComp.h"
#include "QuadAxiQComp_cm4pti.h"
#include "QuadAxiCCom.h"
#include "QuadAxiCCom_cm9pti.h"
#include "ElemPoint.h"
#include "ElemPoint_CP.h"
#include "BielletteThermi.h"
#include <iostream>

//#ifdef ENLINUX_STREAM
//   #include "Profiler.h"
//#endif   
//#define USE_PROFILE

#ifdef  UTILISATION_DE_LA_LIBRAIRIE_BOOST
  #include <boost/chrono/include.hpp>
  #include <boost/system/error_code.hpp>
#endif
#ifdef UTILISATION_MPI
  #include "mpi.h"
  #include <boost/mpi/environment.hpp>
  #include <boost/mpi/communicator.hpp>
  #include <boost/serialization/string.hpp>
  #include <boost/mpi.hpp>
  namespace mpi = boost::mpi;
#endif

#include "Temps_CPU_HZpp.h"
#include "Temps_CPU_HZpp_3.h"




#ifdef SYSTEM_MAC_OS_X
int main (int argc, const char * argv[]) {
#else
  #ifdef ENLINUX_STREAM //ENLINUX
   int main (int argc, const char * argv[]) {
  #else
    #ifdef SYSTEM_MAC_OS_X_unix
      int main (int argc, const char * argv[]) {
    #else  
      int main ()
       { int argc=0; const char ** argv = NULL ;
    #endif
  #endif 
#endif

#ifdef UTILISATION_MPI
  #ifdef EN_DEBUG_MPI
  // intro d'une boucle infinie pour mettre en place les process en debug
  {volatile int i = 0;
   char hostname[256];
   gethostname(hostname, sizeof(hostname));
   printf("PID %d on %s ready for attach\n", getpid(), hostname);
   fflush(stdout);
   while (0 == i)
       sleep(5);
  }
  #endif

  // --- mise en route de la parallèlisation
  mpi::environment env;
  // def global d'un communicator
  mpi::communicator world;
  // on renseigne paraglob
  ParaGlob::Init_boost_environnement(&env);
  ParaGlob::Init_boost_communicator (& world);
#endif


// gestion du temps cpu global
Temps_CPU_HZpp_3 temps_CPU_Herezh_total;
temps_CPU_Herezh_total.Mise_en_route_du_comptage(); // comptage cpu
UtilLecture* pt_UtilLecture = NULL; // un pointeur qui doit-être renseigné par le projet

// écriture de l'entête du programme
#ifdef UTILISATION_MPI
  if (world.rank() == 0)
#endif
   Presentation();
   
// definition d'un projet
string retour ;
try
  {
   #ifdef UTILISATION_MPI
    // on dit à tous les process d'attendre sauf le master
    world.barrier(); // synchronisation ici de tous les process
    std::string message_mpi;
    if (world.rank() == 0)
      { cout << " ==> execution parallele (MPI) "<< world.size() << " proc ";
        message_mpi = "process_en_attente";
//        broadcast(world, message_mpi, 0); // 0 cas c'est le rang 0 qui cause
      };
    // envoi pour le maitre et réception pour les autres via broadcast
    broadcast(world, message_mpi, 0); // 0 cas c'est le rang 0 qui cause
    world.barrier(); // synchronisation ici de tous les process
    if (world.rank() == 0)
      { cout << "\n process 0: creation du projet ";
      }
    else
      { cout << "\n " << message_mpi << " " << world.rank() ;
        // attente jusqu'à ce que l'on récupère de 0 le tag 1
        // ce qui est effectué plus bas, juste après: projet.Lecture();
        world.probe(0, 1);
      };
   #endif

  
    // par la définition du projet, est définit également l'algo
    // on définit le projet en dehors du try qui suit, pour le projet demeure valide même s'il y a
    // une exception, ce qui permet quand même d'utiliser des fonction du projet,
    // par exemple l'acces aux fichier qui sont définit dans UtilLecture
    Projet projet(retour,argc,argv);
    if (retour != "fin")
     try
      {
       
       // les differents elements  
       // (sont ici définit pour qu'ils soient pris en compte à l'édition de lien  !!)
       Biellette b1;  // biellette
       BielletteQ b11;  // biellette quadratique
       Biel_axi baxi;  // biellette axisymétrique linéaire
       Biel_axiQ baxiQ;  // biellette axisymétrique quadratique
       TriaMembL1 t1; // triangle membranne, lineaire 1 pt d'integ
       TriaMembQ3 t2; // triangle membranne, quadratique 3 pt d'integ
       TriaMembQ3_cm1pti triaMembQ3_cm1pti; // triangle membranne, quadratique 1 pt d'integ
       TriaQ3_cmpti1003 t_cmpti1003; // triangle membranne, quadratique avec 3 pt d'integ interne    
       TriaCub triacub; // triangle cubique
       TriaCub_cm4pti triacub_cm4pti; // triangle cubique avec 4 pti
       Quad q1; // quadrangle membranne, lineaire 4 pt d'integ    
       Quad_cm1pti quad_cm1pti; // quadrangle membranne, lineaire 1 pt d'integ    
       QuadQ q2; // quadrangle membranne, quadratique incomplet 4 pt d'integ    
       QuadQCom q3; // quadrangle membranne, quadratique complet 9 pt d'integ 
       QuadQCom_cm4pti quadQCom_cm4pti; // quadrangle membranne, quadratique complet 4 pt d'integ 
       QuadCCom q4; // quadrangle membranne, cubique complet 16 pt d'integ 
       QuadCCom_cm9pti q4_9pti; // quadrangle membranne, cubique complet 9 pt d'integ 
       Hexa h1; // un hexaedre trilineaire, 8 pt d'integ   
       Hexa_cm1pti h1_cm1pti; // un hexaedre trilineaire, 1 pt d'integ
       Hexa_cm27pti h1_cm27pti; // un hexaedre trilineaire, 27 pt d'integ
       Hexa_cm64pti h1_cm64pti; // un hexaedre trilineaire, 64 pt d'integ
       HexaQ h2; // un hexaedre trilquadratique incomplet, 8 pt d'integ
       HexaQ_cm1pti h2_cm1pti; // un hexaedre trilquadratique incomplet, 1 pt d'integ
       HexaQ_cm27pti h2_cm27pti; // un hexaedre trilquadratique incomplet, 27 pt d'integ
       HexaQ_cm64pti h2_cm64pti; // un hexaedre trilquadratique incomplet, 64 pt d'integ
       HexaQComp h2comp; // un hexaedre trilquadratique complet, 8 pt d'integ 
       HexaQComp_cm1pti h2comp_1pti; // un hexaedre trilquadratique complet, 1 pt d'integ 
       HexaQComp_cm27pti h2comp_27pti; // un hexaedre trilquadratique complet, 27 pt d'integ 
       HexaQComp_cm64pti h2comp_64pti; // un hexaedre trilquadratique complet, 64 pt d'integ 
       Tetra te1; // un tetraedre trilineaire, 1 pt d'integ
       TetraQ te2; // un tetraedre triquadratique, 4 pt d'integ
       TetraQ_15pti te3; // un tetraedre triquadratique, 15 pt d'integ
       TetraQ_cm1pti te2_cm1pti; // un tetraedre triquadratique, 1 pt d'integ
       PentaL pe1; // un pentaedre trilinéaire, 2 pts d'intégration
       PentaL_cm1pti pe1_cm1pti; // un pentaedre trilinéaire, 1 pts d'intégration
       PentaL_cm6pti pe1_cm6pti; // un pentaedre trilinéaire, 6 pts d'intégration
       PentaQ pe2; // un pentaedre triquadratique incomplet, 6 pts d'intégration
       PentaQ_cm3pti pe2_cm3pti; // un pentaedre triquadratique incomplet, 3 pts d'intégration
       PentaQ_cm9pti pe2_cm9pti; // un pentaedre triquadratique incomplet, 9 pts d'intégration
       PentaQ_cm12pti pe2_cm12pti; // un pentaedre triquadratique incomplet, 12 pts d'intégration
       PentaQ_cm18pti pe2_cm18pti; // un pentaedre triquadratique incomplet, 18 pts d'intégration
       PentaQComp pe2Comp; // un pentaedre triquadratique complet, 6 pts d'intégration
       PentaQComp_cm9pti pe2Comp_cm9pti; // un pentaedre triquadratique complet, 9 pts d'intégration
       PentaQComp_cm12pti pe2Comp_cm12pti; // un pentaedre triquadratique complet, 12 pts d'intégration
       PentaQComp_cm18pti pe2Comp_cm18pti; // un pentaedre triquadratique complet, 18 pts d'intégration
       TriaSfe1 t3; // un triangle SFE1 
       TriaSfe1_cm5pti tfe1_cm5pti; // idem avec 5 pti
       TriaSfe2 t3_2; // un triangle SFE2
       TriaSfe3 t3_3; // un triangle SFE3
       TriaSfe3_3D t3_3_3D; // un triangle SFE3_3D
       TriaSfe3_cm4pti t3_3_cm4pti; // un triangle SFE3 avec 4pt d'integ
       TriaSfe3_cm6pti t3_3_cm6pti; // un triangle SFE3 avec 6pt d'integ
       TriaSfe3_cm12pti t3_3_cm12pti; // un triangle SFE3 avec 12pt d'integ
       TriaSfe3_cm3pti t3_3_cm3pti; // un triangle SFE3 avec 3pt d'integ type Gauss Lobatto
       TriaSfe3_cm5pti t3_3_cm5pti; // un triangle SFE3 avec 5pt d'integ type Gauss Lobatto
       TriaSfe3_cm7pti t3_3_cm7pti; // un triangle SFE3 avec 7pt d'integ type Gauss Lobatto
       TriaSfe3_cm13pti t3_3_cm13pti; // un triangle SFE3 avec 13pt d'integ type Gauss Lobatto
       TriaSfe3C t3_3C; // un triangle SFE3C
       TriaQSfe3 tqSfe3; // un triangle QSFE3
       TriaQSfe1 tqSfe1; // un triangle QSFE1
       PoutSimple1 p1; // poutre simple, interpolation quadratique en 2 D
       TriaAxiL1 triAxil1; // triangle axisymétrique linéaire
       TriaAxiQ3 triAxiq3; // triangle axisymétrique quadratique 3 pti
       TriaAxiQ3_cm1pti triaAxiQ3_cm1pti; // triangle axisymétrique quadratique 1 pti
       TriaAxiQ3_cmpti1003 triaAxiQ3_cmpti1003; // triangle axi quadra 3 pti hors arêtes
       QuadAxiL1 quadAxil1; // quadrangle axisymétrique linéaire
       QuadAxiL1_cm1pti quadAxiL1_cm1pti; // idem avec 1 pti
       QuadAxiQ quadAxiq; // quadrangle axisymétrique quadratique incomplet
       QuadAxiQComp quadAxiqcomp; // quad quadratique axisymétrique complet
       QuadAxiQComp_cm4pti quadAxiQComp_cm4pti; // idem mais avec 4 pti 	
       QuadAxiCCom quadAxicCom; // quad cubique axi complet
       QuadAxiCCom_cm9pti quadAxiCCom_cm9pti; // idem avec 9 pti
       ElemPoint elemPoint; // élément pour umat abaqus
       ElemPoint_CP elemPoint_CP; // idem mais pour les contraintes planes
       //.... cas de la thermique
       BielletteThermi bielletteThermi; // une biellette thermique
       
       // le projet étant définit, on peut définir le fichier de stockage des temps cpu
       pt_UtilLecture = projet.Def_sortie_temps_cpu();
     
       
       //il y a deux types d'entrée de donnée soit via un fichier info
       // --------------------------------------------------------
       // choix en fonction de la construction du projet
       // --------------------------------------------------------
       if (retour == "def_fichier_commande")
         // -------------------------------------------------
         // cas de la définition d'un fichier de commandes
         // -------------------------------------------------
         {projet.Def_fichier_commande(retour);} 
       else if (retour == "def_schema_XML")
         // ----------------------------------------------------------------------
         // cas de la définition d'un fichier de de shema XML d'entrée de données
         // ----------------------------------------------------------------------
         {projet.Def_fichier_SchemaXML(retour);} 
       else if (retour != "fin")
         // --------------------------------------------------------
         //                         cas d'un calcul
         //        definition des quatres grandes etapes du calcul 
         // --------------------------------------------------------
         {
           projet.Lecture();                    // 1- lecture initiale
          
     //   #ifdef USE_PROFILE
     //      // préparation du profiler
     //	  if (!ProfilerInit(collectDetailed, bestTimeBase,8000, 100))
     //	   {
     //    #endif 
           #ifdef UTILISATION_MPI
//int rank = world.rank();
//cout << "\n *** je suis le process " << rank << endl;
            if (world.rank() == 0)
             // on va demander successivement à tous les process de lire le .info
             // il s'agit d'un procédé séquentiel,
             // NB: je pense que c'est plus rapide et plus sûr de passer par le .info
             // pour construire et remplir dans chaque process la structure de stockage, que de le faire
             // en passant les données via mpi entre le master et les sous_process
             {int nb_process =  world.size();
              // NB: le process 0 c'est le main
              for (int i=1;i<nb_process;i++) // < absolu, donc le max c'est nb_process-1
               { // on envoie un signal de démarrage au process i
                 world.send(i, 1, std::string("lecture_info_sous_process"));
                 // on demande au projet de transmettre les info ad hoc
                 projet.Transmission_process_Lecture(i);
                 // et on attend du process i un signal de fin d'exécution
                 std::string msg;
                 world.recv(i, 2, msg);
                 // gestion d'erreur éventuelle
                 if (msg == "erreur_en_lecture")
                  // arrêt du traitement
                  Sortie(1);
               };
             }
            else
             {// on envoie à 0 le message de fin de lecture
              world.send(0, 2, std::string("OK"));
             };
            // arrivé ici tous les process ont la structuration interne les données de bases ad hoc

           #endif

           do
            { projet.Calcul();                     // 2- calcul
        
     //   #ifdef USE_PROFILE
     //        int erro;
     //        // sortie des infos pour le profiler
     //		erro= ProfilerDump("\pHerezh.prof");
     //		ProfilerTerm();
     //	   }
     //   #endif 
        
             projet.SortieDesResultats();          // 3- sortie automatique résultats
             projet.Visualisation_interactive();  // 4- sortie interactive résultats
                                                //    ou automatique via un fichier de commande
            } while (projet.Lecture_secondaire());
         };
       // fermeture des fichiers de visualisation liés au projet
       projet.FermetureFichiersVisualisation();
       
       // on sauvegarde les différents temps cpu, et on récupère l'adresse d'UtilLecture
       pt_UtilLecture = projet.Sortie_temps_cpu();
       // gestion du temps cpu global
       temps_CPU_Herezh_total.Arret_du_comptage(); // fin comptage cpu
       temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(cout);
       if (pt_UtilLecture != NULL) // sortie sur fichier si le fichier a été créé
         { // récupération du fichier des temps cpu
           ofstream & sort_cpu = pt_UtilLecture->Sort_temps_cpu();
           sort_cpu << "\n ------- temps globaux jour/heure:minute:seconde:centieme ------\n";
           temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(pt_UtilLecture->Sort_temps_cpu());
         };
      } // fin de la surveillance
    catch (ErrSortie erreur)
     {
    #ifndef UTILISATION_MPI
       cout << "\n ======== erreur (Sortie) detectee ======  " << endl;
    #else
       cout << "\n *** process " << world.rank() << " ======== erreur (Sortie) detectee ======   " << endl;
    #endif
       // on sauvegarde les différents temps cpu, et on récupère l'adresse d'UtilLecture
       projet.Arret_du_comptage_CPU(); // on termine les comptages non fermés
       pt_UtilLecture = projet.Sortie_temps_cpu();
       // gestion du temps cpu global
       temps_CPU_Herezh_total.Arret_du_comptage(); // fin comptage cpu
       temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(cout);
       if (pt_UtilLecture != NULL) // sortie sur fichier si le fichier a été créé
         { // récupération du fichier des temps cpu
           ofstream & sort_cpu = pt_UtilLecture->Sort_temps_cpu();
           sort_cpu << "\n ------- temps globaux jour/heure:minute:seconde:centieme ------\n";
           temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(pt_UtilLecture->Sort_temps_cpu());
         };
     }
    catch (ErrSortieFinale erreur)
     { 
    #ifndef UTILISATION_MPI
       cout << "\n ======== erreur (Sortie) detectee ======  " << endl;
    #else
       cout << "\n *** process " << world.rank() << " ======== erreur (Sortie) detectee ======   " << endl;
    #endif
       // on sauvegarde les différents temps cpu, et on récupère l'adresse d'UtilLecture
       projet.Arret_du_comptage_CPU(); // on termine les comptages non fermés
       pt_UtilLecture = projet.Sortie_temps_cpu();
       // gestion du temps cpu global
       temps_CPU_Herezh_total.Arret_du_comptage(); // fin comptage cpu
       temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(cout);
       if (pt_UtilLecture != NULL) // sortie sur fichier si le fichier a été créé
         { // récupération du fichier des temps cpu
           ofstream & sort_cpu = pt_UtilLecture->Sort_temps_cpu();
           sort_cpu << "\n ------- temps globaux jour/heure:minute:seconde:centieme ------\n";
           temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(pt_UtilLecture->Sort_temps_cpu());
         };
     }
    catch ( ... )
     {
    #ifndef UTILISATION_MPI
       cout << "\n ======== erreur  detectee ====== " << endl;
    #else
       cout << "\n *** process " << world.rank() << " ======== erreur  detectee ======  " << endl;
    #endif
       projet.Arret_du_comptage_CPU(); // on termine les comptages non fermés
       // on sauvegarde les différents temps cpu, et on récupère l'adresse d'UtilLecture
       pt_UtilLecture = projet.Sortie_temps_cpu();
       // gestion du temps cpu global
       temps_CPU_Herezh_total.Arret_du_comptage(); // fin comptage cpu
       temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(cout);
       if (pt_UtilLecture != NULL) // sortie sur fichier si le fichier a été créé
         { // récupération du fichier des temps cpu
           ofstream & sort_cpu = pt_UtilLecture->Sort_temps_cpu();
           sort_cpu << "\n ------- temps globaux jour/heure:minute:seconde:centieme ------\n";
           temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(pt_UtilLecture->Sort_temps_cpu());
         };
     };
       
  }
catch (ErrSortieFinale erreur)
 {
   #ifndef UTILISATION_MPI
      cout << "\n *** ======== erreur  fatale detectee ======*** " << endl;
   #else
      cout << "\n *** process " << world.rank() << " ======== erreur  fatale detectee ======*** " << endl;
   #endif

   // gestion du temps cpu global
   temps_CPU_Herezh_total.Arret_du_comptage(); // fin comptage cpu
   temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(cout);
   if (pt_UtilLecture != NULL) // sortie sur fichier si le fichier a été créé
     { // récupération du fichier des temps cpu
       ofstream & sort_cpu = pt_UtilLecture->Sort_temps_cpu();
       sort_cpu << "\n ------- temps globaux jour/heure:minute:seconde:centieme ------\n";
       temps_CPU_Herezh_total.Affiche_hh_mn_s_ml(pt_UtilLecture->Sort_temps_cpu());
     };
 }
catch ( ... )
 { cout << "\n *** ======== erreur  fatale detectee ======*** " << endl;
 };


// écriture de la fin du programme
#ifdef UTILISATION_MPI
  if (world.rank() == 0) // uniquement le process 0
#endif
   {cout << "\n =============================================================\n";
    cout <<   " |                     fin HEREZH++                          |\n";
    cout <<   " =============================================================";
    cout << endl;
   };
   
};
