// 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/>.


#include "AlgoUtils.h"

// CONSTRUCTEURS :
AlgoUtils::AlgoUtils () : // par defaut
   Algori()
  {  };   
     
// constructeur en fonction du type de calcul et du sous type
// il y a ici lecture des parametres attaches au type
AlgoUtils::AlgoUtils (const bool avec_typeDeCal
            ,const list <EnumSousTypeCalcul>& soustype
            ,const list <bool>& avec_soustypeDeCal
            ,UtilLecture& entreePrinc) :
         Algori(UTILITAIRES,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
  { // lecture des paramètres attachés au type de calcul (ici aucun)
    switch (entreePrinc.Lec_ent_info())
    { case 0 : 
       {// pour signaler à Algori qu'il n'y a pas eu de lecture de paramètre
        deja_lue_entete_parametre=0; 
        // puis appel de la méthode de la classe mère 
        Algori::lecture_Parametres(entreePrinc); break;}
      case -11 : // cas de la création d'un fichier de commande
       { Info_commande_parametres(entreePrinc); break;}
      case -12 : // cas de la création d'un schéma XML, on ne fait rien à ce niveau
       {  break;}
      default:
        Sortie(1); 
     }  
   };
      
// constructeur de copie
AlgoUtils::AlgoUtils (const AlgoUtils& algo):
  Algori(algo)
      {  };

// destructeur   
AlgoUtils::~AlgoUtils ()
  {
   }; 

// execution de l'algorithme 
void AlgoUtils::Execution(ParaGlob * p,LesMaillages * lesMail
               ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
               ,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock
               ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats)
  {
    tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
    Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(UTILITAIRES); // transfert info
    lesMail->Insert_coord1();
    lesMail->Travail_tdt(); // utile pour le travail avec des fonctions nD éventuelle
    lesMail->Init_Xi_t_et_tdt_de_0(); // ""
    // mise à jour au cas où
    Algori::MiseAJourAlgoMere(p,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp,divStock
                           ,charge,lesCondLim,lesContacts,resultats);

    // INITIALISATION particulière concernant le contact
    // ceci pour optimiser éventuellement la numérotation en prenant en compte un contact initial
    // mise a zero de tous les ddl et creation des tableaux a t+dt
    // les ddl de position ne sont pas mis a zero ! ils sont initialise
    // a la position courante
    lesMail->ZeroDdl(true);
    // on vérifie que les noeuds sont bien attachés à un élément sinon on met un warning si niveau > 2
    if (ParaGlob::NiveauImpression() > 2)
      lesMail->AffichageNoeudNonReferencer();
    // definition des elements de frontiere, ces elements sont utilises pour le contact
    int cal_front = lesMail->CreeElemFront();
    //  calcul éventuel des normales aux noeuds -> init des normales pour t=0
    lesMail->InitNormaleAuxNoeuds(); //utilisé pour la stabilisation des membranes par ex
    // dans le cas d'un contact éventuel on initialise les frontières et la répartition esclave et maître
    if (lesMail->NbEsclave() != 0)
     { // definition des elements de frontiere, ces elements sont utilises pour le contact
       lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_t);
       if (lesContacts->Init_contact_pas_effectue())
        {// initialisation des zones de contacts éventuelles
         lesContacts->Init_contact(*lesMail,*lesRef,lesFonctionsnD);
        }
       else if (cal_front)
        // si l'initialisation du contact a déjà été effectué et que les frontières viennent d'être
        // recalculée -> ce n'est pas normal, car les frontières ont dues être déjà calculées pour
        // initialiser le contact !!
          {  cout << "\n **** >>>>   ERREUR en initialisant le contact *****  ";
             cout << "\n les frontieres viennent d'etre recalculees alors que l'initialisation du contact "
                  << " etait deja effectif : ce n'est pas normal: les nouvelles frontieres ne seront pas "
                  << " coherentes avec celles utilisees pour l'initialisation du contact : arret !!! "
                  << flush;
             Sortie(1);
          };
       // verification qu'il n'y a pas de contact avant le premier increment de charge
       lesContacts->Verification();
       // definition des elements de contact eventuels
       //  et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact)
       try {
            lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul
           }
       // sortie anormale de l'initialisation du contact
       catch (ErrSortieFinale)
            // cas d'une direction voulue vers la sortie
            // on relance l'interuption pour le niveau supérieur
          { ErrSortieFinale toto;
            tempsCalEquilibre.Arret_du_comptage(); // temps cpu
            throw (toto);
          }
       catch (...)// erreur inconnue
          {  cout << "\n **** >>>>   ERREUR inconnuee en  en initialisant le contact *****  ";
             if (ParaGlob::NiveauImpression() >= 4)
               cout  << "\n AlgoUtils::Execution(..";
             cout << endl;
          };
     };

    // renseigne les variables définies par l'utilisateur via les valeurs déjà calculées par Herezh
    varExpor->RenseigneVarUtilisateur(*lesMail,*lesRef);
    lesMail->CalStatistique(); // calcul éventuel de statistiques
    // on définit le type de  calcul a effectuer :
    if ( soustypeDeCalcul->size()==0 )
      // cas où il n'y a pas de sous type, on fait le calcul 
      // de toutes les cas possibles
       cout << "\n rien pour l'instant (information)\n";
    else 
      // on boucle sur tous les sous_types
     { list <EnumSousTypeCalcul>::const_iterator ili,ili_fin = soustypeDeCalcul->end();
       list <bool>::const_iterator ila;
       for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin();
            ili!=ili_fin;ili++,ila++)
        if (*ila) // cas où le sous type est valide  
        {if ( (*ili) == LinVersQuad )
             // cas de la transformation de maillages linéaires  en maillages 
             // quadratiques complets
            { 
              cout << "\n================================================================="
                   << "\n|   Transformation des maillages lineaires en                     |"
                   << "\n|   maillages quadratiques incomplets                             | "
                   << "\n================================================================="
                   << endl;
              // on crée et on calcul les nouveaux maillages
              // en y intégrant les références associées
              // 1) on récupère le nombre de maillage actuellement actif
              int nb_maillages_actifs_initiaux = lesMail->NbMaillage();
              // 2) on crée les quadratiques incomplets
              lesMail->CreeMaillagesQuadratiques_a_partir_des_lineaires(lesRef);
              // 3) récup du nombre actuellement actif d'où des maillages créés
              int nb_maillages_actifs_finaux = lesMail->NbMaillage();           
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++)
                  lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i);
            }
         else if ( (*ili) == QuadIncVersQuadComp )
             // cas de la transformation de maillages quadratiques incomplets en maillages 
             // quadratiques complets
            { 
              cout << "\n================================================================="
                   << "\n|   Transformation des maillages quadratiques incomplets en     |"
                   << "\n|   maillages quadratiques complets                             | "
                   << "\n================================================================="
                   << endl;
              // on crée et on calcul les nouveaux maillages
              // en y intégrant les références associées
              // 1) on récupère le nombre de maillage actuellement actif
              int nb_maillages_actifs_initiaux = lesMail->NbMaillage();
              // 2) on crée les quadratiques complets
              lesMail->CreeMaillagesQuadratiquesComplets_a_partir_des_incomplets(lesRef);
              // 3) récup du nombre actuellement actif d'où des maillages créés
              int nb_maillages_actifs_finaux = lesMail->NbMaillage();           
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++)
                  lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i);
            }
         else if ( (*ili) == relocPtMilieuQuad ) 
           // cas de la relocalisation des points milieux sur les arrêtes des quadratiques
           {
              cout << "\n================================================================="
                   << "\n|   Relocalisation des points milieux appartenant aux arretes   |"
                   << "\n|   des elements quadratiques                                   | "
                   << "\n================================================================="
                   << endl;
     
              // appel de l'utilitaire dans lesMaillages
              lesMail->RelocPtMilieuMailleQuadra();
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
           }
         else if ( (*ili) == sauveMaillagesEnCours ) 
           // cas de la relocalisation des points milieux sur les arrêtes des quadratiques
           {
              cout << "\n================================================================="
                   << "\n|   ecriture des maillages en cours         en .her et .lis     |"
                   << "\n================================================================="
                   << endl;
     
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
           }
         else if ( (*ili) == extrusion2D3D ) 
           // cas de l'extrusion d'un maillage 2D en 3D
           {
              cout << "\n================================================================="
                   << "\n|             extrusion d'un maillage 2D en 3D                  |"
                   << "\n================================================================="
                   << endl;
     
              // on crée et on calcul les nouveaux maillages
              // en y intégrant les références associées
              // 1) on récupère le nombre de maillage actuellement actif
              int nb_maillages_actifs_initiaux = lesMail->NbMaillage();
              // 2) on crée les maillages extrudées
              lesMail->CreeMaillageExtrusion2D3D(lesRef);
              // 3) récup du nombre actuellement actif d'où des maillages créés
              int nb_maillages_actifs_finaux = lesMail->NbMaillage();           
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++)
                  lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i);
           }
         else if ( (*ili) == modif_orientation_element ) 
           // cas de la modification de l'orientation d'éléments
           {  // 1) on récupère le nombre de maillage actuellement actif
              int nb_maillages_actifs_initiaux = lesMail->NbMaillage();

              cout << "\n================================================================="
                   << "\n|      modification de l'orientation d'element                  |"
                   << "\n================================================================="
                   << endl;
              // 2) on demande à l'utilisation ce qu'il veut faire et on exécute
              bool choix_valide = false;
              int cas_orientation=0; // init
              while (!choix_valide)
              { 
                cout << "\n =========== choix du module d'orientation       ==============="
                     << "\n verification de l'orientation   ?                    (rep veor)"
                     << "\n orientation automatique pour un jacobien positif  ?  (rep oajp)"
							              << "\n orientation des faces d'elem 2D via un elem de ref?  (rep faor)"
							              << "\n orientation des faces d'elem 2D via un rayon      ?  (rep fray)"
                     << "\n fin (defaut)                                         (rep    f)";
                string rep;
                cout << "\n reponse ? ";   rep = lect_return_defaut(false,"f");
                if (rep == "veor")
                  // vérification de l'orientation 
                   {cas_orientation=-1;
                    lesMail->Modif_orientation_element(cas_orientation,lesRef);
                    }
                else if (rep == "oajp")
                  // cas d'une orientation automatique pour obtenir un jacobien positif 
                   {cas_orientation=1;
                    lesMail->Modif_orientation_element(cas_orientation,lesRef);
                    }
                else if (rep == "faor")
                  // cas d'une orientation automatique des faces d'un maillage 2D
                  // à partir d'une face de référence
                   {cas_orientation=2;
                    lesMail->Modif_orientation_element(cas_orientation,lesRef);
                    }
                else if (rep == "fray")
                  // cas d'une orientation automatique à partir de l'orientation d'un rayon
                   {cas_orientation=3;
                    lesMail->Modif_orientation_element(cas_orientation,lesRef);
                    }
                else if ((rep == "0") || (rep == "o") || (rep == "O") || (rep == "f"))
                    {choix_valide = true;cas_orientation=0;}
                else
                  cout << "\n la réponse : " << rep << " n'est pas utilisable, recommencez !";         
              };
              // 3) récup du nombre actuellement actif d'où des maillages créés
              int nb_maillages_actifs_finaux = lesMail->NbMaillage();           
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++)
                  lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i);
           }
         else if ( (*ili) == creationMaillageSFE ) 
           // cas de la création de maillage SFE
           {
              cout << "\n================================================================="
                   << "\n|                 creation de maillage SFE                      |"
                   << "\n|                                                               | "
                   << "\n================================================================="
                   << endl;
     
              // appel de l'utilitaire dans lesMaillages
              lesMail->CreationMaillageSFE();
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
           }
         else if ( (*ili) == suppression_noeud_non_references ) 
           // cas de la suppression des noeuds non référencés
           {
              cout << "\n================================================================="
                   << "\n|           suppression des noeuds non references               |"
                   << "\n|                                                               | "
                   << "\n================================================================="
                   << endl;
     
              // appel de l'utilitaire dans lesMaillages
              lesMail->SuppressionNoeudNonReferencer(*lesRef);
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
           }
         else if ( (*ili) == renumerotation_des_noeuds ) 
           // cas de la renumérotation des noeuds 
           {  // il s'agit ici de renuméroter les noeuds de chaques maillages, indépendamment
              // de conditions linéaires et de conditions de contact
              cout << "\n================================================================="
                   << "\n|               renumerotation des noeuds                       |"
                   << "\n|                                                               | "
                   << "\n================================================================="
                   << endl;
     
 
              // l'algo a besoin des éléments frontières, on les crée si elles n'existent pas
              lesMail->CreeElemFront();
              // appel de l'utilitaire dans lesMaillages
              bool changement = lesMail->Renumerotation(*lesRef);
              // on met à jour le tableau indice pour LesContacts
              lesContacts->Mise_a_jour_indice(lesMail->Indice());
              // -----  sort les informations sur fichiers
              // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
              // à partir du nom de chaque maillage au format  ".her" et ".lis"
              // s'il y a eu quelque chose de changé
              if (changement)
                {if (ParaGlob::NiveauImpression() > 2)
                   cout << "\n ===>> sauvegarde des maillages en .her et .lis  ";
                 lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
                }
              else
                {cout << "\n ===>> pas de changement dans un maillage -> aucune sauvegarde ";
                };
           }
         else if ( (*ili) == fusion_de_noeuds )
             // cas de la fusion de noeuds
         {
             cout  << "\n================================================================="
                  << "\n|               fusion de noeuds                                |"
                  << "\n|                                                               | "
                  << "\n================================================================="
                  << endl;
             // 2) on demande à l'utilisateur le rayon maxi en dessous duquel on va fusionner
             double rayon=0.; // init
             cout << "\n ++ choix de la distance en dessous de laquelle on fusionne les noeuds "
             << "\n deux noeuds sont fusionable s'ils appartiennent a des elements differents "
             << "\n et s'ils appartiennent a un meme maillage. "
             << "\n distances maxi pour la fusion ? ";
             rayon = lect_double();
             cout << "\n distance lue: "<< rayon << endl;
             // appel de l'utilitaire dans lesMaillages 
             lesMail->Collapse_noeuds_proches(rayon,lesRef);
             // -----  sort les informations sur fichiers
             // Affichage des donnees des maillages dans des fichiers dont le nom est construit
             // à partir du nom de chaque maillage au format  ".her" et ".lis"
             lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
         }
         else if ( (*ili) == fusion_elements )
             // cas de la fusion d'éléments
         {
             cout << "\n================================================================="
                  << "\n|               fusion d'elements                               |"
                  << "\n|                                                               | "
                  << "\n================================================================="
                  << endl;
             // appel de l'utilitaire dans lesMaillages 
             lesMail->Collapse_element_supperpose(lesRef);
             // -----  sort les informations sur fichiers
             // Affichage des donnees des maillages dans des fichiers dont le nom est construit
             // à partir du nom de chaque maillage au format  ".her" et ".lis"
             lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
         }
         else if ( (*ili) == fusion_maillages )
             // cas de la fusion de maillage
          {  // 1) affichage
             cout  << "\n================================================================="
                   << "\n|               fusion de maillages                             |"
                   << "\n|                                                               | "
                   << "\n================================================================="
                   << endl;
             // 2) on demande à l'utilisateur ce qu'il veut faire et on exécute
             bool choix_valide = false;
             List_io < string > lis_a_fusionner; // la liste des maillages à fusionner
             string nom_nouveau_maillage = " "; // nom du nouveau maillage
             int nbmail = lesMail->NbMaillage(); // les maillages actuellement enregistré

             while (!choix_valide)
              { if (lis_a_fusionner.size() != 0)
                  { cout << "\n liste des maillages a fusionner : ";
                    List_io < string >::iterator il,ilfin=lis_a_fusionner.end();
                    for (il = lis_a_fusionner.begin();il != ilfin; il++)
                      cout << (*il) << ", ";
                    cout << endl;
                  };
                
                
                 cout << "\n =========== choix des maillages a fusionner       ==============="
                      << "\n liste des maillages disponibles                      (rep list)"
                      << "\n vider la liste a fusionner                           (rep vlis)"
                      << "\n nom du maillage issu de la fusion                    (rep nfus)"
                      << "\n fusionner tous les maillages                         (rep   to)"
                      << "\n ajout d'un nom de maillage a fusionner               (rep nafu)"
                      << "\n fin (appel du programme de fusion)                   (rep    f)";
                 string rep;
                 cout << "\n reponse ? "; rep = lect_return_defaut(false,"f");
                 if (rep == "list")
                   // affichage de la liste des maillages existants 
                    {cout << "\n -- liste des maillages enregistres -- \n";
                     for (int i=1;i<=nbmail;i++)
                       cout << lesMail->NomMaillage(i) << " ";
                     cout << endl;
                     }
                 else if (rep == "vlis")
                   // on vide la liste
                    {lis_a_fusionner.erase(lis_a_fusionner.begin(), lis_a_fusionner.end());
                     }
                 else if (rep == "nfus")
                   // nom du maillage issu de la fusion
                   {cout << "\n nom du nouveau maillage : ";
                     nom_nouveau_maillage = lect_chaine(); cout << "\n nom lue: " << nom_nouveau_maillage << "\n";
                   }
                 else if (rep == "nafu")
                   // ajout d'un nom de maillage a fusionner
                   {string new_nom;
                    cout << "\n nom du maillage : ";
                     new_nom = lect_chaine();
                    // on vérifie que c'est bien un nom licite
                    if (!(lesMail->NumMaillage(new_nom)))
                     { cout << "\n erreur : ce maillage n'existe pas ! ";}
                    else
                     { // sinon c'est ok, on enregistre
                       lis_a_fusionner.push_back(new_nom);
                     };
                   }
                 else if (rep == "to")
                   // ajout de tous les noms de maillage
                   {for (int i=1;i<=nbmail;i++)
                        lis_a_fusionner.push_back(lesMail->NomMaillage(i));
                   }
                 else if ((rep == "0") || (rep == "o") || (rep == "O") || (rep == "f"))
                     { if (nom_nouveau_maillage == " ")
                         { cout << "\n ******* le nom du nouveau maillage reste a definir !! ***** " << endl;}
                       else
                         { choix_valide = true;};
                     }
                 else
                   cout << "\n la réponse : " << rep << " n'est pas utilisable, recommencez !";         
               };
             // appel de l'utilitaire dans lesMaillages 
             lesMail->Fusion_maillages(lis_a_fusionner,nom_nouveau_maillage,lesRef);
             // -----  sort les informations sur fichiers
             // récup du nombre actuellement actif d'où du dernier maillage créé
             int nb_maillages_actifs_final = lesMail->NbMaillage();
             // -----  sort les informations sur fichiers

             // Affichage des donnees du dernier maillage dans des fichiers dont le nom est construit
             // à partir du nom de chaque maillage au format  ".her" et ".lis"
             lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,nb_maillages_actifs_final);
          }
         else if ( (*ili) == cree_sous_maillage )
             // cas de la création d'un sous maillage à partir d'une référence d'éléments
          {  // 1) affichage
             cout  << "\n================================================================="
                   << "\n|               creation d'un sous maillages                    |"
                   << "\n|               a partir d'une ref d'elements                   | "
                   << "\n================================================================="
                   << endl;
             // 2) on demande à l'utilisateur le nom de la référence
             bool choix_valide = false;
             string nom_nouveau_maillage = " "; // nom du nouveau maillage
             string nom_ref = ""; // init
             int num_mail_ref = 1; // init par défaut

             while (!choix_valide)
               { cout << "\n =========== choix de la reference d'elements       ==============="
                        << "\n liste des ref d'elements disponibles                 (rep list)"
                        << "\n nom de la ref d'element du sous maillage             (rep nref)"
                        << "\n nom du maillage associe a la ref (defaut: le premier)(rep noma)"
                        << "\n nom du nouveau maillage                              (rep nmai)"
                        << "\n fin (appel de la methode de creation)                (rep    f)";
                   string rep;
                   cout << "\n reponse ? ";rep = lect_return_defaut(false,"f");
                   string nom_mail_ref(" ");
                   if (rep == "list")
                     // affichage de la liste des ref d'elements disponibles 
                      {lesRef->Affiche(2,1); // 2 pour éléments, 1 pour affichage uniquement des noms
                       cout << endl;
                      }
                   else if (rep == "nref")
                     // non de la ref d'element du sous maillage
                     {cout << "\n nom de la ref d'element du sous maillage : ";
                      nom_ref = lect_chaine(); cout << "\n nom lue: " << nom_ref << "\n";
                       }
                   else if (rep == "noma")
                     // non du maillage associé à la référence
                     {cout << "\n nom du maillage associe a la ref : ";
                       nom_mail_ref = lect_chaine(); cout << "\n nom lue: " << nom_mail_ref << "\n";
                     }
                   else if (rep == "nmai")
                     // nom du nouveau maillage
                     {cout << "\n nom du nouveau maillage : ";
                       nom_nouveau_maillage = lect_chaine(); cout << "\n nom lue: " << nom_nouveau_maillage << "\n";
                     }
                   else if ((rep == "0") || (rep == "o") || (rep == "O") || (rep == "f"))
                       { if (nom_nouveau_maillage == " ")
                           { cout << "\n ******* le nom du nouveau maillage reste a definir !! ***** " << endl;}
                         else if (nom_ref == "")
                           { cout << "\n ******* le nom de la ref d'elements reste a definir !! ***** " << endl;}
                         else if (nom_mail_ref != " ")
                           { //on vérifie que le maillage existe
                             if (lesMail->NumMaillage(nom_mail_ref))
                              { // on vérifie que la ref existe
                                if ( lesRef->Existe(nom_ref,&nom_mail_ref))
                                  { num_mail_ref = lesMail->NumMaillage(nom_mail_ref);
                                    choix_valide = true;
                                  } // là c'est ok
                                else
                                  { cout << "\n *** la reference "<< nom_ref << "du maillage "
                                         <<  nom_mail_ref <<" n'existe pas ??  " << endl;
                                  };
                              }
                             else
                              { cout << "\n *** le maillage " << nom_mail_ref << " n'existe pas ?? "
                                     << endl;
                              };
                           }
                         else
                           { choix_valide = true;};
                       }
                   else
                     cout << "\n la réponse : " << rep << " n'est pas utilisable, recommencez !";         
                 };
             // appel de l'utilitaire dans lesMaillages
             lesMail->Cree_sous_maillage(num_mail_ref,lesRef,nom_ref,nom_nouveau_maillage);
             // -----  sort les informations sur fichiers
             // récup du nombre actuellement actif d'où du dernier maillage créé
             int nb_maillages_actifs_final = lesMail->NbMaillage();
             // -----  sort les informations sur fichiers

             // Affichage des donnees du dernier maillage dans des fichiers dont le nom est construit
             // à partir du nom de chaque maillage au format  ".her" et ".lis"
             lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,nb_maillages_actifs_final);
          }
        };
       }
    // pour des pb de sortie de résultat qui peuvent bloquer on met à zéro les degrés
    // de liberté
    lesMail->ZeroDdl(true);
    tempsCalEquilibre.Arret_du_comptage(); // temps cpu

   };

