
// 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-2021 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 "EnumTypeCalcul.h"
#include <stdlib.h>
#include "Sortie.h"
#include "CharUtil.h"

// Retourne le nom d'un type de calcul a partir de son identificateur de
// type enumere id_TypeCalcul correspondant
string Nom_TypeCalcul (const EnumTypeCalcul id_TypeCalcul)
{	
	string result;
	switch (id_TypeCalcul)
	{case RIEN_TYPECALCUL : result="aucun_TYPE_de_CALCUL"; break;
		case DYNA_IMP : result="dynamique_implicite"; break;
		case DYNA_EXP : result="dynamique_explicite"; break;
		case DYNA_EXP_TCHAMWA : result="dynamique_explicite_tchamwa"; break;
		case DYNA_EXP_CHUNG_LEE: result="dynamique_explicite_chung_lee"; break;
		case DYNA_EXP_ZHAI : result="dynamique_explicite_zhai"; break;
		case DYNA_RUNGE_KUTTA : result="dynamique_Runge_Kutta"; break;
		case NON_DYNA : result="non_dynamique"; break;
		case NON_DYNA_CONT : result="non_dynamique_avec_contact"; break;
		case FLAMB_LINEAIRE : result="flambement_lineaire_en_implicite_non_dynamique"; break;
		case INFORMATIONS : result="informations"; break;
		case UTILITAIRES : result="utilitaires"; break;
		case DEF_SCHEMA_XML : result="def_schema_xml"; break;
		case UMAT_ABAQUS : result="umat_abaqus"; break;
		case DYNA_EXP_BONELLI : result="dynamique_explicite_bonelli"; break;
		case RELAX_DYNA : result="dynamique_relaxation_dynam"; break;
		case STAT_DYNA_EXP : result="mixte_statique_dynamique_explicite"; break;
  case COMBINER : result="combiner"; break;
		default :
			cout << "\nErreur : valeur incorrecte du type EnumTypeCalcul !\n";
			cout << "string Nom_TypeCalcul (EnumTypeCalcul id_TypeCalcul)" << endl;
			Sortie(1);
	};
	return result;
	
};

// Retourne le nom du sous type de calcul a partir de son identificateur de
// type enumere id_SousTypeCalcul correspondant, si il existe sinon retourne : aucun_soustypedecalcul
string Nom_SousTypeCalcul (const EnumSousTypeCalcul id_SousTypeCalcul)
{	
	string result;
	switch (id_SousTypeCalcul)
	{case aucun_soustypedecalcul : result="aucun_sous_TYPE_de_CALCUL"; break;
		case  avec_remonte : result="avec_remontee_aux_valeurs_aux_noeuds"; break;
		case avec_remonte_erreur : result="avec_remontee_et_calcul_d'erreur"; break;
		case avec_remonte_erreur_relocation : result="avec_remonte_erreur_et_relocalion"; break;
		case avec_remonte_erreur_raffinement_relocation : result="avec_remontee_erreur_raffinement_et_relocation"; break;
		case remonte : result="uniquement_remontee"; break;
		case remonte_erreur : result="remontee_et_erreur"; break;
		case remonte_erreur_relocation : result="remontee_erreur_et_relocation"; break;
		case remonte_erreur_raffinement_relocation : result="remontee_erreur_raffinement_et_relocation"; break;
		case frontieres : result="frontieres"; break;
		case visualisation : result="visualisation"; break;
		case LinVersQuad : result="LinVersQuad"; break;
		case QuadIncVersQuadComp : result="QuadIncVersQuadComp"; break;
		case relocPtMilieuQuad : result="relocPtMilieuQuad"; break;
		case sauveCommandesVisu : result="sauveCommandesVisu"; break;
		case lectureCommandesVisu : result="lectureCommandesVisu"; break;
		case commandeInteractive : result="commandeInteractive"; break;
		case sauveMaillagesEnCours : result="sauveMaillagesEnCours"; break;
		case extrusion2D3D : result="extrusion2D3D"; break;
		case creation_reference : result="creation_reference"; break;
		case prevision_visu_sigma : result="prevision_visu_sigma"; break;
		case prevision_visu_epsilon : result="prevision_visu_epsilon"; break;
		case prevision_visu_erreur : result="prevision_visu_erreur"; break;
		case modif_orientation_element : result="modif_orientation_element"; break;
		case creationMaillageSFE : result="creationMaillageSFE"; break;
		case suppression_noeud_non_references : result="suppression_noeud_non_references"; break;
		case renumerotation_des_noeuds : result="renumerotation_des_noeuds"; break;
		case fusion_de_noeuds : result="fusion_de_noeuds"; break;
		case fusion_elements : result="fusion_elements"; break;
		case fusion_maillages : result="fusion_maillages"; break;
		case cree_sous_maillage : result="cree_sous_maillage"; break;
		case calcul_geometrique : result="calcul_geometrique"; break;
		default :
			cout << "\nErreur : valeur incorrecte du type EnumSousTypeCalcul !\n";
			cout << "string Nom_SousTypeCalcul (EnumSousTypeCalcul id_SousTypeCalcul)" << endl;
			Sortie(1);
	};
	return result;
	
};

// retourne le type d'évolution temporelle du calcul
Enum_evolution_temporelle Evolution_temporelle_du_calcul(const EnumTypeCalcul id_TypeCalcul)
{Enum_evolution_temporelle result;;
	switch (id_TypeCalcul)
	 {  case RIEN_TYPECALCUL : result=AUCUNE_EVOLUTION; break;
		   case DYNA_IMP : result=DYNAMIQUE; break;
		   case DYNA_EXP : result=DYNAMIQUE; break;
		   case DYNA_EXP_TCHAMWA : result=DYNAMIQUE; break;
		   case DYNA_EXP_CHUNG_LEE: result=DYNAMIQUE; break;
		   case DYNA_EXP_ZHAI : result=DYNAMIQUE; break;
		   case DYNA_RUNGE_KUTTA : result=DYNAMIQUE; break;
		   case NON_DYNA : result=STATIQUE; break;
		   case NON_DYNA_CONT : result=STATIQUE; break;
		   case FLAMB_LINEAIRE : result=STATIQUE; break;
		   case INFORMATIONS : result=AUCUNE_EVOLUTION; break;
		   case UTILITAIRES : result=AUCUNE_EVOLUTION; break;
		   case DEF_SCHEMA_XML : result=AUCUNE_EVOLUTION; break;
		   case UMAT_ABAQUS : result=AUCUNE_EVOLUTION; break;
		   case DYNA_EXP_BONELLI : result=DYNAMIQUE; break;
		   case RELAX_DYNA : result=DYNAMIQUE; break;
		   case STAT_DYNA_EXP : result=DYNAMIQUE; break;
     case COMBINER : result=DYNAMIQUE; break;
		   default :
		   	cout << "\nErreur : valeur incorrecte du type EnumTypeCalcul !\n";
		   	cout << "Enum_evolution_temporelle Evolution_temporelle_du_calcul(const EnumTypeCalcul id_TypeCalcul)"
		   	     << endl;
		   	Sortie(1);
  };
	return result;	
};

// Retourne l'identificateur de type enumere associe au nom du type de calcul
EnumTypeCalcul Id_nom_TypeCalcul (const string& nom_TypeCalcul)
{
	
	EnumTypeCalcul result;
	if (( nom_TypeCalcul == "RIEN_TYPECALCUL" )
	    ||( nom_TypeCalcul == "aucun_TYPE_de_CALCUL" ))
		result=RIEN_TYPECALCUL;
	else if (( nom_TypeCalcul == "DYNA_IMP" )
	    ||( nom_TypeCalcul == "dynamique_implicite" ))
		result=DYNA_IMP;
	else if (( nom_TypeCalcul == "DYNA_EXP" )
	    ||( nom_TypeCalcul == "dynamique_explicite" ))
		result=DYNA_EXP;
	else if (( nom_TypeCalcul == "DYNA_EXP_TCHAMWA" )
	    ||( nom_TypeCalcul == "dynamique_explicite_tchamwa" ))
		result=DYNA_EXP_TCHAMWA;
	else if (( nom_TypeCalcul == "DYNA_EXP_CHUNG_LEE" )
	    ||( nom_TypeCalcul == "dynamique_explicite_chung_lee" ))
		result=DYNA_EXP_CHUNG_LEE;
	else if (( nom_TypeCalcul == "DYNA_EXP_ZHAI" )
	    ||( nom_TypeCalcul == "dynamique_explicite_zhai" ))
		result=DYNA_EXP_ZHAI;
	else if (( nom_TypeCalcul == "DYNA_RUNGE_KUTTA" )
	    ||( nom_TypeCalcul == "dynamique_Runge_Kutta" ))
		result=DYNA_RUNGE_KUTTA;
	else if (( nom_TypeCalcul == "NON_DYNA" )
	    ||( nom_TypeCalcul == "non_dynamique" ))
		result=NON_DYNA;
	else if (( nom_TypeCalcul == "NON_DYNA_CONT" )
	    ||( nom_TypeCalcul == "non_dynamique_avec_contact" ))
		result=NON_DYNA_CONT;
	else if (( nom_TypeCalcul == "FLAMB_LINEAIRE" )
	    ||( nom_TypeCalcul == "flambement_lineaire_en_implicite_non_dynamique" ))
		result=FLAMB_LINEAIRE;
	else if (( nom_TypeCalcul == "INFORMATIONS" )
	    ||( nom_TypeCalcul == "calcul_d'information_relatives_aux_maillages_d'entrees" ))
		result=INFORMATIONS;
	else if (( nom_TypeCalcul == "UTILITAIRES" )
	    ||( nom_TypeCalcul == "utilitaires" ))
		result=UTILITAIRES;
	else if (( nom_TypeCalcul == "DEF_SCHEMA_XML" )
	    ||( nom_TypeCalcul == "def_schema_xml" ))
		result=DEF_SCHEMA_XML;
	else if (( nom_TypeCalcul == "UMAT_ABAQUS" )
	    ||( nom_TypeCalcul == "umat_abaqus" ))
		result=UMAT_ABAQUS;
	else if (( nom_TypeCalcul == "DYNA_EXP_BONELLI" )
	    ||( nom_TypeCalcul == "dynamique_explicite_bonelli" ))
		result=DYNA_EXP_BONELLI;
	else if (( nom_TypeCalcul == "RELAX_DYNA" )
	    ||( nom_TypeCalcul == "dynamique_relaxation_dynam" ))
		result=RELAX_DYNA;
	else if (( nom_TypeCalcul == "STAT_DYNA_EXP" )
	    ||( nom_TypeCalcul == "mixte_statique_dynamique_explicite" ))
		result=STAT_DYNA_EXP;
 else if (( nom_TypeCalcul == "COMBINER" )
     ||( nom_TypeCalcul == "combiner" ))
  result=COMBINER;
	else
	{
		cout << "\nErreur : nom de type de calcul inconnu !\n";
		cout << " nom_TypeCalcul = " << nom_TypeCalcul << '\n';
		cout << "Id_nom_TypeCalcul (string& nom_TypeCalcul) " << endl;
		Sortie(1);
	};
	return result;
	
};

// Retourne l'identificateur de type enumere associe au nom du sous type de calcul
EnumSousTypeCalcul Id_nom_SousTypeCalcul (const string& nom_SousTypeCalcul)
{
	
	EnumSousTypeCalcul result;
	if ( nom_SousTypeCalcul == "aucun_sous_TYPE_de_CALCUL" ) result=aucun_soustypedecalcul;
	else if ( nom_SousTypeCalcul == "avec_remontee_aux_valeurs_aux_noeuds" ) result=avec_remonte;
	else if ( nom_SousTypeCalcul == "avec_remontee_et_calcul_d'erreur" ) result=avec_remonte_erreur;
	else if ( nom_SousTypeCalcul == "avec_remonte_erreur_et_relocalion" ) result=avec_remonte_erreur_relocation;
	else if ( nom_SousTypeCalcul == "avec_remontee_erreur_raffinement_et_relocation" )
		result=avec_remonte_erreur_raffinement_relocation;
	else if ( nom_SousTypeCalcul == "uniquement_remontee" ) result=remonte;
	else if ( nom_SousTypeCalcul == "remontee_et_erreur" )result=remonte_erreur;
	else if ( nom_SousTypeCalcul == "remontee_erreur_et_relocation" ) result=remonte_erreur_relocation;
	else if ( nom_SousTypeCalcul == "remontee_erreur_raffinement_et_relocation" )
		result=remonte_erreur_raffinement_relocation;
	else if ( nom_SousTypeCalcul == "frontieres" ) result=frontieres;
	else if ( nom_SousTypeCalcul == "visualisation" ) result=visualisation;
	else if ( nom_SousTypeCalcul == "LinVersQuad" )result=LinVersQuad;
	else if ( nom_SousTypeCalcul == "QuadIncVersQuadComp" )result=QuadIncVersQuadComp;
	else if ( nom_SousTypeCalcul == "relocPtMilieuQuad" ) result=relocPtMilieuQuad;
	else if ( nom_SousTypeCalcul == "sauveCommandesVisu" ) result=sauveCommandesVisu;
	else if ( nom_SousTypeCalcul == "lectureCommandesVisu" ) result=lectureCommandesVisu;
	else if ( nom_SousTypeCalcul == "commandeInteractive" ) result=commandeInteractive;
	else if ( nom_SousTypeCalcul == "sauveMaillagesEnCours" ) result=sauveMaillagesEnCours;
	else if ( nom_SousTypeCalcul == "extrusion2D3D" ) result=extrusion2D3D;
	else if ( nom_SousTypeCalcul == "creation_reference" ) result=creation_reference;
	else if ( nom_SousTypeCalcul == "prevision_visu_sigma" ) result=prevision_visu_sigma;
	else if ( nom_SousTypeCalcul == "prevision_visu_epsilon" ) result=prevision_visu_epsilon;
	else if ( nom_SousTypeCalcul == "prevision_visu_erreur" ) result=prevision_visu_erreur;
	else if ( nom_SousTypeCalcul == "modif_orientation_element" ) result=modif_orientation_element;
	else if ( nom_SousTypeCalcul == "creationMaillageSFE" ) result=creationMaillageSFE;
	else if ( nom_SousTypeCalcul == "suppression_noeud_non_references" ) result=suppression_noeud_non_references;
	else if ( nom_SousTypeCalcul == "renumerotation_des_noeuds" ) result=renumerotation_des_noeuds;
	else if ( nom_SousTypeCalcul == "fusion_de_noeuds" ) result=fusion_de_noeuds;
	else if ( nom_SousTypeCalcul == "fusion_elements" ) result=fusion_elements;
	else if ( nom_SousTypeCalcul == "fusion_maillages" ) result=fusion_maillages;
	else if ( nom_SousTypeCalcul == "cree_sous_maillage" ) result=cree_sous_maillage;
	else if ( nom_SousTypeCalcul == "calcul_geometrique" ) result=calcul_geometrique;
	else
	{
		cout << "\nErreur : nom de sous type de calcul inconnu !\n";
		cout << " nom_SousTypeCalcul = " << nom_SousTypeCalcul << '\n';
		cout << "Id_nom_SousTypeCalcul (string& nom_SousTypeCalcul)" << endl;
		Sortie(1);
	};
	return result;
	
};


// indique si le calcul est de type dynamique explicite ou non
bool DynamiqueExplicite(const EnumTypeCalcul id_TypeCalcul)
{	bool result=false;
	 switch (id_TypeCalcul)
	  {  case DYNA_EXP : result=true; break;
		    case DYNA_EXP_TCHAMWA : result=true; break;
		    case DYNA_EXP_CHUNG_LEE: result=true; break;
		    case DYNA_EXP_ZHAI : result=true; break;
		    case DYNA_RUNGE_KUTTA : result=true; break;
		    case DYNA_EXP_BONELLI : result=true; break;
		    case RELAX_DYNA : result=true; break;
		    case STAT_DYNA_EXP : result=true; break;
      case COMBINER : result=true; break;
		    default :
		    	cout << "\nErreur : valeur incorrecte du type EnumTypeCalcul ! = " << id_TypeCalcul << "\n";
		    	cout << "DynamiqueExplicite(const EnumTypeCalcul id_TypeCalcul)"
		    	     << endl;
		    	Sortie(1);
	  };
	 return result;	
};


// indique si le calcul est de type implicite ou non
bool Implicite(const EnumTypeCalcul id_TypeCalcul)
{ bool result=false;
  switch (id_TypeCalcul)
   {case RIEN_TYPECALCUL : result=false; break;
    case DYNA_IMP : result=true; break;
    case DYNA_EXP : result=false; break;
    case DYNA_EXP_TCHAMWA : result=false; break;
    case DYNA_EXP_CHUNG_LEE: result=false; break;
    case DYNA_EXP_ZHAI : result=false; break;
    case DYNA_RUNGE_KUTTA : result=false; break;
    case NON_DYNA : result=true; break;
    case NON_DYNA_CONT : result=true; break;
    case FLAMB_LINEAIRE : result=true; break;
    case INFORMATIONS : result=false; break;
    case UTILITAIRES : result=false; break;
    case DEF_SCHEMA_XML : result=false; break;
    case UMAT_ABAQUS : result=true; break;
    case DYNA_EXP_BONELLI : result=false; break;
    case RELAX_DYNA : result=false; break;
    case STAT_DYNA_EXP : result=false; break;
    case COMBINER : result=false; break;
    default :
       cout << "\nErreur : valeur incorrecte du type EnumTypeCalcul ! = " << id_TypeCalcul << "\n";
       cout << " Implicite(..."
            << endl;
       Sortie(1);
   };
  return result;
};


//lecture du type de calcul et d'une liste de  sous-type eventuel
// la lecture se fait via UtilLecture.
// Le booléen indique si le type_calcul ou le sous_type_calcul est actif ou pas
// au niveau de syntaxe on a : 
// - tout d'abord le type de calcul suivi ou non de la chaine "avec" 
//   dans le premier cas le booleen avec_Calcul est mis a true sinon false
// - puis une liste de sous type qui chacun sont précèdé ou non de la chaine "plus" 
//   dans le premier cas  le booleen avec_sousCalcul correspondant est true sinon false
//   les sous_types sont stocké par ordre d'arrivé
void LectureTypeCalcul(UtilLecture& entreePrinc,EnumTypeCalcul& typeCalcul,bool& avec_Calcul
                      ,list<EnumSousTypeCalcul> & sousTypeCalcul
                      ,list<bool>& avec_sousCalcul)
 { // tout d'abord le type de calcul
   int nbmot; // nb de mot du type principal
   if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
       (strstr(entreePrinc.tablcar,"implicite")!=NULL))
           { typeCalcul=DYNA_IMP; nbmot = 1; }
   else if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
            (strstr(entreePrinc.tablcar,"explicite")!=NULL) &&
            (strstr(entreePrinc.tablcar,"zhai")!=NULL))
           { typeCalcul=DYNA_EXP_ZHAI; nbmot = 1; }
   else if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
            (strstr(entreePrinc.tablcar,"Runge_Kutta")!=NULL))
           { typeCalcul=DYNA_RUNGE_KUTTA; nbmot = 1; }
   else if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
            (strstr(entreePrinc.tablcar,"explicite")!=NULL) &&
            (strstr(entreePrinc.tablcar,"chung_lee")!=NULL))
           { typeCalcul=DYNA_EXP_CHUNG_LEE; nbmot = 1; }
   else if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
            (strstr(entreePrinc.tablcar,"explicite")!=NULL) &&
            (strstr(entreePrinc.tablcar,"tchamwa")!=NULL))
           { typeCalcul=DYNA_EXP_TCHAMWA; nbmot = 1; }
   else if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
            (strstr(entreePrinc.tablcar,"explicite")!=NULL) &&
            (strstr(entreePrinc.tablcar,"bonelli")!=NULL))
           { typeCalcul=DYNA_EXP_BONELLI; nbmot = 1; }
   else if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
            (strstr(entreePrinc.tablcar,"relaxation")!=NULL) &&
            (strstr(entreePrinc.tablcar,"_dynam")!=NULL))
           { typeCalcul=RELAX_DYNA; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"mixte_statique_dynamique_explicite")!=NULL)
           { typeCalcul=STAT_DYNA_EXP; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"combiner")!=NULL)
           { typeCalcul=COMBINER; nbmot = 1; }

// !!! attention !!!           
// il faut que le cas dynamique_explicite soit le dernier, car sinon il est pris par défaut
   else if ((strstr(entreePrinc.tablcar,"dynamique")!=NULL) &&
            (strstr(entreePrinc.tablcar,"explicite")!=NULL))
           { typeCalcul=DYNA_EXP; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"non_dynamique")!=NULL)
           { typeCalcul=NON_DYNA; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"non_dyna_contact")!=NULL)
           { typeCalcul=NON_DYNA_CONT; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"flamb_lineaire")!=NULL)
           { typeCalcul=FLAMB_LINEAIRE; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"informations")!=NULL)
           { typeCalcul=INFORMATIONS; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"utilitaires")!=NULL)
           { typeCalcul=UTILITAIRES; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"def_schema_xml")!=NULL)
           { typeCalcul=DEF_SCHEMA_XML; nbmot = 1; }
   else if (strstr(entreePrinc.tablcar,"umat_abaqus")!=NULL)
           { typeCalcul=UMAT_ABAQUS; nbmot = 1; }
   else
     { cout << "\nErreur : nom de type de calcul : " << entreePrinc.tablcar
		          << ",  inconnu !\n";
       cout << "LectureTypeCalcul(UtilLecture& lec);" << endl;
		     Sortie(1);
	    };
   // décalage dans la lecture
   string sous_type;
   for (int i=1;i<= nbmot;i++) (*entreePrinc.entree) >> sous_type;
   // on regarde si le prochain mot est "avec" si oui on valide le type principal
   (*entreePrinc.entree) >> sous_type; sous_type = Minuscules (sous_type);
   if ((sous_type.length() == 0)|| (entreePrinc.entree->rdstate()))
//      #ifndef ENLINUX
//             ( (entreePrinc.entree->rdstate() & ios_base::badbit) == ios_base::badbit)) 
//     #else  
//             ( (entreePrinc.entree->rdstate() & ios::badbit) == ios::badbit)) 
//     #endif
     // cas ou le type est seul alors la validation est par défaut
     avec_Calcul = true;
   else // cas où il y a des sous types  
   {if (sous_type == "avec") 
        { avec_Calcul = true;}
    else 
        { avec_Calcul=false;};
    // puis on lit les sous types avec leur validation éventuelle
    // puis les sous-types eventuels
    bool valide = true;
    // dans le cas où on a lue "avec" il faut tout de suite lire le premier sous type
    if (avec_Calcul)
      (*entreePrinc.entree) >> sous_type;
    EnumSousTypeCalcul enum_sous_type;
    bool fin_lecture=false; // fin due à un manque d'info
    while ((!entreePrinc.entree->rdstate())&&(!fin_lecture))
     { if (sous_type.length() != 0)
         { if (sous_type == "plus")
             {valide = true;
              (*entreePrinc.entree) >> sous_type;
               if (sous_type.length() == 0)
                 {cout << " \n *** erreur dans la lecture des sous_types de calcul,"
                       << " présence du nom : plus, mais pas de sous_type qui suit !!"
                       << "\n LectureTypeCalcul(UtilLecture& entreePrinc,...) \n";
                  Sortie(1);
                 };
               enum_sous_type=Id_nom_SousTypeCalcul(sous_type.c_str()); 
               // on sauvegarde dans la liste
               sousTypeCalcul.push_back(enum_sous_type);
               avec_sousCalcul.push_back(valide);     
             }
           else 
             {valide = false;
              (*entreePrinc.entree) >> sous_type;
               if (sous_type.length() == 0)
                 {// cas où il n'y a pas de sous_type, normalement on devrait
                  // l'avoir détecté avant mais dans le cas ou il y aurait un "avec"
                  // et rien d'autre après
                  fin_lecture = true;
                 }
               enum_sous_type=Id_nom_SousTypeCalcul(sous_type.c_str()); 
               // on sauvegarde dans la liste
               sousTypeCalcul.push_back(enum_sous_type);
               avec_sousCalcul.push_back(valide);     
             };
         }
        else
         {fin_lecture = true;};
        // arrivée ici on retente une lecture d'un autre sous type
        (*entreePrinc.entree) >> sous_type;
       
     };
   };           
   // on remet le flot de lecture dans sa position originale
   entreePrinc.FlotDebutDonnee();   

 };  

// affichage des différents type de calcul et choix du type et éventuellement
//  de sous type
void Info_commande_type_calcul(UtilLecture& lec,EnumTypeCalcul& typeCalcul,bool& avec_Calcul
                      ,list<EnumSousTypeCalcul> & sousTypeCalcul
                      ,list<bool>& avec_sousCalcul)                     
 { int num; 
   int nbmot; // nb de mot du type principal
   //cout << "\n ";
   string rep; bool choix_valide=false;
   cout << "\n ==>Type principal de calcul (defaut 7) : ?  ";
   while (!choix_valide)
    {
     try 
      { 
        cout 
        << "\n (1) dynamique_implicite             (2) dynamique_explicite_zhai "
        << "\n (3) dynamique_explicite_chung_lee   (4) dynamique_explicite_tchamwa "
        << "\n (5) dynamique_explicite             (6) dynamique_Runge_Kutta "
        << "\n (7) non_dynamique                   (8) non_dyna_contact"
        << "\n (9) flamb_lineaire                  (10) informations "
        << "\n (11) utilitaires                    (12) umat_abaqus  "
        << "\n (13) dynamique_explicite_bonelli    (14) dynamique_relaxation_dynam "         
        << "\n (15) combiner    "
        << " "<< endl;
        rep = "_";
        int c = std::cin.peek();  // peek character (sans changer le flux !!)
        if (( c == EOF )||(c=='\n'))
           {rep = "7";
            cout << "--> valeur par defaut : 7 "<<endl;
            c = getchar(); // on lit quand même le caractère
           }
        else // sinon on peut lire
          {std::getline (std::cin,rep);
           // a priori les prochaines lectures vont utilisées un getline
          };
        // si la taille de rep == 0 cela veut dire que c'est un retour chariot
        if (rep.size()==0)
           {rep = "7";
            cout << "--> valeur par defaut : 7 "<<endl;
           };
        if (rep == "fin_prog") {Sortie(1);}
        else // sinon
          num = ChangeEntier(rep);
        if ((num >= 1)&&(num<=15)) 
             { choix_valide=true;}
        else { cout << "\n Erreur on attendait un entier entre 1 et 15 !!, "
                    << "\n redonnez une bonne valeur"
                    << "\n ou taper fin_prog pour arreter le programme"; 
               choix_valide=false;
             };
        switch (num)
         { case 1:  //"dynamique_implicite")
           { typeCalcul=DYNA_IMP; nbmot = 1; break;}
           case 2:  // "dynamique_explicite_zhai")
           { typeCalcul=DYNA_EXP_ZHAI; nbmot = 1; break;}
           case 3:  // "dynamique_explicite_chung_lee")
           { typeCalcul=DYNA_EXP_CHUNG_LEE; nbmot = 1; break;}
           case 4:  // "dynamique_explicite_tchamwa")
           { typeCalcul=DYNA_EXP_TCHAMWA; nbmot = 1; break;}
           case 5:  // "dynamique_explicite")
           { typeCalcul=DYNA_EXP; nbmot = 1; break;}
           case 6:  // "dynamique_Runge_Kutta")
           { typeCalcul=DYNA_RUNGE_KUTTA; nbmot = 1; break;}
           case 7:  // "non_dynamique")
           { typeCalcul=NON_DYNA; nbmot = 1; break;}
           case 8:  // "non_dyna_contact")
           { typeCalcul=NON_DYNA_CONT; nbmot = 1; break;}
           case 9:  // "flamb_lineaire")
           { typeCalcul=FLAMB_LINEAIRE; nbmot = 1; break;}
           case 10:  // "informations")
           { typeCalcul=INFORMATIONS; nbmot = 1; break;}
           case 11:  // "utilitaires")
           { typeCalcul=UTILITAIRES; nbmot = 1; break;}
           case 12:  // "umat abaqus")
           { typeCalcul=UMAT_ABAQUS; nbmot = 1; break;}
           case 13:  // "dynamique_explicite_bonelli")
           { typeCalcul=DYNA_EXP_BONELLI; nbmot = 1; break;}
           case 14:  // "dynamique_relaxation_dynam")
           { typeCalcul=RELAX_DYNA; nbmot = 1; break;}
//           case 15:  // "mixte_statique_dynamique_explicite")
//           { typeCalcul=STAT_DYNA_EXP; nbmot = 1; break;}
           case 15:  // "combiné")
           { typeCalcul=COMBINER; nbmot = 1; break;}
         }
       }    
     catch (ErrSortieFinale)
          // cas d'une direction voulue vers la sortie
          // on relance l'interuption pour le niveau supérieur
        { ErrSortieFinale toto;
          throw (toto);
        }
     catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
      {  cout << "\n Erreur on attendait un des mots clés proposés !!, "
              << "\n redonnez une bonne valeur"
              << "\n ou taper fin_prog pour arreter le programme"; 
         choix_valide=false;
      };
    }; //-- fin du while
   cout << "--> choix: " <<  Nom_TypeCalcul(typeCalcul) << endl;
 
   // cas du sous type de calcul
   cout << "\n ==> Sous type de calcul souhaite (defaut 5) : ?  ";
   EnumSousTypeCalcul enum_sous_type;choix_valide=false;
   rep = " ";
   string chaine_a_ecrire=" ";
   int indic_avec_Calcul = 0; // on initialise une variable entière car pb avec les booléens
   cout
        << "\n (0)  (pas de sous type)               (f)  fin "
        << "\n (1)  avec_remonte                     (2)  remonte "
        << "\n (3)  avec_remonte_erreur              (4)  remonte_erreur"
        << "\n (5)  avec plus visualisation          (6)  visualisation"
        << "\n (7)  frontieres                       (8)  lineaire -> quadra incomplet" 
        << "\n (9)  quadra incomplet -> quadra complet"
        << "\n (10)  reloc pt milieu Quadra          (11) sauveCommandesVisu"
        << "\n (12) lectureCommandesVisu             (13) prevision_visu_sigma " 
        << "\n (14) prevision_visu_epsilon           (15) prevision_visu_erreur" 
        << "\n (16) commandeInteractive              (17) sauveMaillagesEnCours " 
        << "\n (18) extrusion2D3D                    (19) creation_de_references "
        << "\n (20) modif_orientation_element        (21) creationMaillageSFE  " 
        << "\n (22) suppression_noeud_non_references (23) renumerotation_des_noeuds  " 
        << "\n (24) fusion_de_noeuds                 (25) fusion_elements "
        << "\n (26) fusion_maillages                 (27) cree_sous_maillage "
        << "\n (28) calcul_geometrique  \n "
        << endl;
   bool non_choix_defaut=false; // pour controller une sortie d'un choix par défaut
   while ((!choix_valide) || (!((rep == "f")||(rep == "0"))) // (!(choix_valide || (rep != "f")||(rep != "0")))
          && !non_choix_defaut
         )
    {
     try 
      {
        rep = "_";
        int c = std::cin.peek();  // peek character (sans changer le flux !!)
        if (( c == EOF )||(c=='\n'))
           {rep = "5";
            cout << "--> valeur par defaut : 5 "<<endl;
            c = getchar(); // on lit quand même le caractère
            non_choix_defaut=true;
           }
        else // sinon on peut lire
          {std::getline (std::cin,rep);
           // a priori les prochaines lectures vont utilisées un getline
          };
        if (rep.size()==0)
           {rep = "5";
            cout << "--> valeur par defaut : 5 "<<endl;
            non_choix_defaut=true;
           };
        if (rep == "fin_prog") {Sortie(1);}
        else // sinon
          num = ChangeEntier(rep);
//cout << "\n debug info_commande_type_calcul: num= "<< num << flush;
        if (rep == "f") num = -1; // cas particulier pour la sortie
        if ((num >= -1)&&(num<=28))
             { choix_valide=true; }
        else { cout << "\n Erreur on attendait un entier entre 0 et 26 !!, "
                    << "\n redonnez une bonne valeur"
                    << "\n ou taper fin_prog pour arreter le programme"; 
               choix_valide=false;
             }
        switch (num)
         { case -1:  //pas de sous type
           { indic_avec_Calcul +=0;enum_sous_type= aucun_soustypedecalcul;  break;}
           case 0:  //pas de sous type
           { indic_avec_Calcul +=1;enum_sous_type= aucun_soustypedecalcul;  break;}
           case 1:  // avec_remonte
           { indic_avec_Calcul +=1;enum_sous_type= avec_remonte;  break;}
           case 2:  // remonte
           { indic_avec_Calcul += 0 ;enum_sous_type= remonte;  break;}
           case 3:  // avec_remonte_erreur
           { indic_avec_Calcul +=1;enum_sous_type= avec_remonte_erreur;  break;}
           case 4:  // remonte_erreur
           { indic_avec_Calcul += 0;enum_sous_type= remonte_erreur;  break;}
           case 5:  // avec plus visualisation
           { indic_avec_Calcul +=1;enum_sous_type= visualisation;  break;}
           case 6:  //  visualisation
           { indic_avec_Calcul += 0;enum_sous_type= visualisation;  break;}
           case 7:  //  frontieres
           { indic_avec_Calcul += 0;enum_sous_type= frontieres;  break;}
           case 8:  //  transformation lineaire en quadratique incomplet
           { indic_avec_Calcul += 0;enum_sous_type= LinVersQuad;  break;}
           case 9:  //  transformation quadratique incomplet en quadratique complet
           { indic_avec_Calcul += 0;enum_sous_type= QuadIncVersQuadComp;  break;}
           case 10:  //  transformation quadratique incomplet en quadratique complet
           { indic_avec_Calcul += 0;enum_sous_type= relocPtMilieuQuad;  break;}
           case 11:  //  sauvegarde des commandes de visualisation
           { indic_avec_Calcul += 0;enum_sous_type= sauveCommandesVisu;  break;}
           case 12:  //  lecture des commandes de visualisation
           { indic_avec_Calcul += 0;enum_sous_type= lectureCommandesVisu;  break;}
           case 13:  //  visualisation automatique par fichier de commande
           { indic_avec_Calcul += 0;enum_sous_type= prevision_visu_sigma;  break;}
           case 14:  //  visualisation automatique par fichier de commande
           { indic_avec_Calcul += 0;enum_sous_type= prevision_visu_epsilon;  break;}
           case 15:  //  visualisation automatique par fichier de commande
           { indic_avec_Calcul += 0;enum_sous_type= prevision_visu_erreur;  break;}
           case 16:  //  prise en compte interactive de commande 
           { indic_avec_Calcul += 0;enum_sous_type= commandeInteractive;  break;}
           case 17:  //  prise en compte interactive de commande 
           { indic_avec_Calcul += 0;enum_sous_type= sauveMaillagesEnCours;  break;}
           case 18:  //  prise en compte interactive de commande 
           { indic_avec_Calcul += 0;enum_sous_type= extrusion2D3D;  break;}
           case 19:  //  création de références 
           { indic_avec_Calcul += 0;enum_sous_type= creation_reference;  break;}
           case 20:  //  modification de l'orientation des éléments 
           { indic_avec_Calcul += 0;enum_sous_type= modif_orientation_element;  break;}
           case 21:  //  création de maillages SFE 
           { indic_avec_Calcul += 0;enum_sous_type= creationMaillageSFE;  break;}
           case 22:  //  suppression des noeuds non referencés
           { indic_avec_Calcul += 0;enum_sous_type= suppression_noeud_non_references;  break;}
           case 23:  //  renumerotation des noeuds
           { indic_avec_Calcul += 0;enum_sous_type= renumerotation_des_noeuds;  break;}
           case 24:  //  fusion de noeuds
           { indic_avec_Calcul += 0;enum_sous_type= fusion_de_noeuds;  break;}
           case 25:  //  fusion d'éléments
           { indic_avec_Calcul += 0;enum_sous_type= fusion_elements;  break;}
           case 26:  //  fusion de maillages
           { indic_avec_Calcul += 0;enum_sous_type= fusion_maillages;  break;}
           case 27:  //  création d'un sous maillage
           { indic_avec_Calcul += 0;enum_sous_type= cree_sous_maillage;  break;}
           case 28:  //  calculs géométriques
           { indic_avec_Calcul += 0;enum_sous_type= calcul_geometrique;  break;}
          }
        if (choix_valide)
          {// comme il ne s'agit pas de faire un calcul (pour l'instant) on met systématiquement
           // avec_Calcul true pour que dans projet il y ait effectivement création de l'algo
           // peut-être par la suite il faudra modifier, donc on laisse les cas dans les case précédents
           if (enum_sous_type != aucun_soustypedecalcul)
              chaine_a_ecrire += "  plus " + Nom_SousTypeCalcul(enum_sous_type);
           // on sauvegarde dans la liste
           sousTypeCalcul.push_back(enum_sous_type);
           avec_sousCalcul.push_back(true);
           if (chaine_a_ecrire != " ")
              cout << "--> choix: " <<  chaine_a_ecrire << endl;
           else
              cout << "--> choix: aucun sous type " <<  endl;
          };
        if ((rep == "f")||(rep == "0"))
          // on veut l'arrêt
          choix_valide=true;
       }
     catch (ErrSortieFinale)
          // cas d'une direction voulue vers la sortie
          // on relance l'interuption pour le niveau supérieur
        { ErrSortieFinale toto;
          throw (toto);
        }
     catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
      {  cout << "\n Erreur on attendait un des mots clés proposés !!, "
              << "\n redonnez une bonne valeur"
              << "\n ou taper fin_prog pour arreter le programme"; 
         choix_valide=false;
      };
    }; //-- fin du while
    if ((indic_avec_Calcul)&&(chaine_a_ecrire != " ")) // on indique si on veut ou non un calcul
      chaine_a_ecrire = " avec  " + chaine_a_ecrire;
   if(chaine_a_ecrire != " ") cout << "\n choix global: " <<  chaine_a_ecrire << endl;
   // écriture dans le fichier de commande
   ofstream & sort = *(lec.Commande_pointInfo()); // pour simplifier
   sort << "\n#-------------------------------"
        << "\n# definition du type de calcul |" 
        << "\n#-------------------------------"
        << "\n TYPE_DE_CALCUL"
        << "\n \n"<< Nom_TypeCalcul(typeCalcul) ;
   if(chaine_a_ecrire != " ")
      sort << chaine_a_ecrire;
   sort  << endl;
   // mise à jour du booléen de calcul, ici par défaut = 1, pour que l'algo continue
   avec_Calcul = true;

} ;  

// indique s'il y a remonte ou pas dans le  sous-type
bool Remonte_in(const EnumSousTypeCalcul sousTypeCalcul)  
  {   //if (Nom_SousTypeCalcul(sousTypeCalcul) == "remonte")
      if ( Nom_SousTypeCalcul(sousTypeCalcul).find("remonte") != -1)
           return true;
      return false;   
  };


// indique s'il y a "avec" ou pas dans le sous-type
bool Avec_in(const EnumSousTypeCalcul sousTypeCalcul)
  {   //if (Nom_SousTypeCalcul (sousTypeCalcul) == "avec")
      if ( Nom_SousTypeCalcul(sousTypeCalcul).find("avec") != -1)
           return true;
      return false ;  
  };


// indique s'il y a erreur dans le sous-type
bool Erreur_in(const EnumSousTypeCalcul sousTypeCalcul)
  {   //if (Nom_SousTypeCalcul (sousTypeCalcul) == "erreur")
      if ( Nom_SousTypeCalcul(sousTypeCalcul).find("erreur") != -1)
           return true;
      return false ;  
  };

// indique s'il y a un sous-type ou pas -> retour vrai s'il y a un sous type
bool SousType(const EnumSousTypeCalcul sousTypeCalcul)
 { bool retour = true;
   if (sousTypeCalcul==aucun_soustypedecalcul) 
       retour = false;
   return retour;
 };

   // surcharge de l'operator de lecture
istream & operator >> (istream & entree, EnumTypeCalcul& a)
 { char nom_EnumTypeCalcul[150];
   entree >> nom_EnumTypeCalcul;
   a = Id_nom_TypeCalcul ( nom_EnumTypeCalcul);
   return entree;
 };
   
   // surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort, const EnumTypeCalcul& a)
    { // on ecrit la forme caractère
       sort << Nom_TypeCalcul(a) << " ";
       return sort;      
    }; 

   // surcharge de l'operator de lecture
istream & operator >> (istream & entree, EnumSousTypeCalcul& a)
 { char nom_EnumSousTypeCalcul[150];
   entree >> nom_EnumSousTypeCalcul;
   a = Id_nom_SousTypeCalcul ( nom_EnumSousTypeCalcul);
   return entree;
 };
   
   // surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort, const EnumSousTypeCalcul& a)
    { // on ecrit la forme caractère
       sort << Nom_SousTypeCalcul(a) << " ";
       return sort;      
    }; 
//--------------------- cas de Enum_evolution_temporelle---------------

// Retourne le nom d'un type de Enum_evolution_temporelle a partir de son identificateur de
// type enumere id_Enum_evolution_temporelle correspondant
string Nom_evolution_temporelle(const Enum_evolution_temporelle id_evolution_temporelle)
{string result;
	switch (id_evolution_temporelle)
	{ case STATIQUE :         result="STATIQUE"; break;
		 case TRANSITOIRE :      result="TRANSITOIRE"; break;
		 case DYNAMIQUE :        result="DYNAMIQUE"; break;
		 case AUCUNE_EVOLUTION : result="AUCUNE_EVOLUTION"; break;
		 default :
			 cout << "\nErreur : valeur incorrecte du type Enum_evolution_temporelle !\n";
			 cout << "string Nom_evolution_temporelle (const Enum_evolution_temporelle id_evolution_temporelle)"
			      << id_evolution_temporelle << endl;
			 Sortie(1);
	};
	return result;	
};

// Retourne l'identificateur de type enumere associe au nom du type de Enum_evolution_temporelle
Enum_evolution_temporelle Id_nom_evolution_temporelle (const string& nom_evolution_temporelle)
{Enum_evolution_temporelle result;
	if ( nom_evolution_temporelle == "STATIQUE" )
		{result=STATIQUE;}
	else if ( nom_evolution_temporelle == "TRANSITOIRE" )
		{result=TRANSITOIRE;}
	else if ( nom_evolution_temporelle == "DYNAMIQUE" )
		{result=DYNAMIQUE;}
	else if ( nom_evolution_temporelle == "AUCUNE_EVOLUTION" )
		{result=AUCUNE_EVOLUTION;}
	else
	{
		cout << "\nErreur : nom de type d'evolution temporelle inconnu !\n";
		cout << " nom_evolution_temporelle = " << nom_evolution_temporelle << '\n';
		cout << "Id_nom_evolution_temporelle (const string& nom_evolution_temporelle) " << endl;
		Sortie(1);
	 };
	// retour
	return result; 
};	

// surcharge de l'operator de lecture
istream & operator >> (istream & entree, Enum_evolution_temporelle& a)
 { char nom_evolution_temporelle[150];
   entree >> nom_evolution_temporelle;
   a = Id_nom_evolution_temporelle( nom_evolution_temporelle);
   return entree;
 };
  
// surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort, const Enum_evolution_temporelle& a)
  { // on ecrit la forme caractère
    sort << Nom_evolution_temporelle(a) << " ";
    return sort;      
  }; 

