Herezh_dev/Algo/AlgorithmeCombiner/AlgoriCombine.cc

949 lines
48 KiB
C++
Executable file

// 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 "AlgoriCombine.h"
#include "TypeQuelconqueParticulier.h"
#include "Fonction_expression_litterale_nD.h"
// CONSTRUCTEURS :
AlgoriCombine::AlgoriCombine() : // par defaut
Algori()
{// a priori ce constructeur n'est pas utilisé
cout << "\n $$$$$$$$$ a priori ce constructeur n'est pas utilisable $$$$$$$ "
<< "\n revoir: AlgoriCombine::AlgoriCombine() " << endl;
Sortie(1);
};
// constructeur en fonction du type de calcul et du sous type
// il y a ici lecture des parametres attaches au type
AlgoriCombine::AlgoriCombine (const bool avec_typeDeCal
,const list <EnumSousTypeCalcul>& soustype
,const list <bool>& avec_soustypeDeCal
,UtilLecture& entreePrinc) :
Algori(COMBINER,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
// --------------------------------------------------------------------------------------
// -- variables privées --
// --------------------------------------------------------------------------------------
,tab_algo()
,nom_choix_algo(""),choix_algo(NULL),nom_gestion_sauvegarde(""),gestion_sauvegarde(NULL)
,nb_dernier_algo_qui_a_fait_une_sauvegarde(0)
,gestion_sortie_a_convergence(NULL),nom_gestion_sortie_a_convergence("")
,tb_combiner(NULL),cst_0(NULL),cst_1(NULL)
// des infos définit en local pour les péréniser
,list_sousTypeCalcul(),list_avec_sousCalcul()
{ // puis lecture des paramètres attachés au type de calcul
switch (entreePrinc.Lec_ent_info())
{ case 0 :
{// il s'agit tout d'abord de lire les différents algos
Lecture_algo_interne(avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc);
// appel de la méthode de lecture de paramètre
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);
};
Creation_fct_cst(); // création de cst_0 et cst_1
};
// constructeur de copie
AlgoriCombine::AlgoriCombine (const AlgoriCombine& algo):
Algori(algo)
// --------------------------------------------------------------------------------------
// -- variables privées --
// --------------------------------------------------------------------------------------
,tab_algo(algo.tab_algo)
,nom_choix_algo(algo.nom_choix_algo),choix_algo(NULL)
,nom_gestion_sauvegarde(algo.nom_gestion_sauvegarde),gestion_sauvegarde(NULL)
,nb_dernier_algo_qui_a_fait_une_sauvegarde(0)
,gestion_sortie_a_convergence(NULL)
,nom_gestion_sortie_a_convergence(algo.nom_gestion_sortie_a_convergence)
,tb_combiner(NULL),cst_0(NULL),cst_1(NULL)
// des infos définit en local pour les péréniser
,list_sousTypeCalcul(algo.list_sousTypeCalcul),list_avec_sousCalcul(algo.list_avec_sousCalcul)
{ // les algorithmes
list <list<EnumSousTypeCalcul> >::iterator ili=list_sousTypeCalcul.begin();
list <list<bool> >::iterator ala=list_avec_sousCalcul.begin();
// les listes sont rangées : la première -> le dernier algo, etc.
int nb_algo = algo.tab_algo.Taille();
if (nb_algo)
{for (int i=nb_algo;i>0;i--,ili++,ala++)
{tab_algo(i) = New_idem(algo.tab_algo(i));
// mise à jour des pointeurs relatifs aux types de calculs et sous types internes
tab_algo(i) -> Change_affectation_pointeur_sous_type((*ili),(*ala));
};
};
Creation_fct_cst(); // création de cst_0 et cst_1
// on renseigne la variable: ptalgocombi de la classe Algori pour tous les sous-algo
for (int i=1;i<=nb_algo;i++)
tab_algo(i)->Change_ptalgocombi (this);
};
// destructeur
AlgoriCombine::~AlgoriCombine ()
{ // les algorithmes
if (tab_algo.Taille())
{for (int i=1;i<= tab_algo.Taille();i++)
delete tab_algo(i);
};
tab_algo.Libere();
// les fonctions constantes
delete cst_0;
delete cst_1;
// les autres fonctions sont globales, donc à ne pas supprimer !!
};
//lecture des parametres de controle
// peut être modifié dans le cas d'un algo particulier
void AlgoriCombine::Lecture(UtilLecture & entreePrinc,ParaGlob & paraglob,LesMaillages& lesMail)
{ // --- on commence par lire les infos concernant les paramètres généraux via la méthode par défaut
Algori::Lecture(entreePrinc,paraglob,lesMail);
// --- ces paramètres permettent d'initialiser les paramètres d'algo internes
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
tab_algo(i)->Init_ParaAlgoControle(pa);
// lecture des paramètres d'algo spécifiques à chaque algo
MotCle motCle; // ref aux mots cle
// on se positionne sur un mot cle
while ( !motCle.SimotCle(entreePrinc.tablcar))
entreePrinc.NouvelleDonnee();
// PARA_SPECIFIQUE_SOUS_ALGO
string nom; int num_algo=0;
int val_defaut = 0;
const string nom_class_methode("AlgoriCombine::Lecture");
int min = 1; int max=nb_algo; string mot_cle("==PARA_SPECIFIQUE_SOUS_ALGO==");
if (strstr(entreePrinc.tablcar,"==PARA_SPECIFIQUE_SOUS_ALGO==")!=NULL)
{// a priori on a des paramètres spécifiques
while (strstr(entreePrinc.tablcar,"==PARA_SPECIFIQUE_SOUS_ALGO==")!=NULL)
{// on récupère le num d'algo
bool lec_eff = entreePrinc.Lecture_un_parametre_int(val_defaut,nom_class_methode
,min,max,mot_cle,num_algo);
if (lec_eff && (num_algo != 0))
{// on lit les paramètres spécifiques de l'algo
entreePrinc.NouvelleDonnee();
tab_algo(num_algo)->pa.Lecture_paraAlgoControle(entreePrinc);
}
else // sinon pb
{ cout << "\n *** erreur en lecture de parametres specifiques d'algo interne "
<< "\n AlgoriCombine::Lecture(.. ";
Sortie(1);
};
entreePrinc.NouvelleDonnee();
};
};
// on met à jour certains conteneurs internes des sous-algo
for (int i=1;i<=nb_algo;i++)
tab_algo(i)->Preparation_conteneurs_interne(lesMail);
};
// execution de l'algorithme dans le cas non dynamique, implicit, sans contact
void AlgoriCombine::Execution(ParaGlob * paraGlob,LesMaillages * lesMail
,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock
,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats)
{
Tableau < Fonction_nD* > * tb_combiner = NULL;
// 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 d'équilibre classique
// signifie que le type principal est forcément valide
{ // initialisation du calcul : deux cas, soit avec une lecture initiale du .info, soit une lecture secondaire
if (paraGlob->EtatDeLaLecturePointInfo() == 0)
{InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );}
else {MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );
};
// on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
// bref que l'on n'a pas fini, sinon on passe
if (! (charge->Fin(icharge,true) ) )
{ // calcul de l'équilibre
CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats
,tb_combiner);
// fin du calcul, pour l'instant on ne considère pas les autres sous-types
FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );
};
}
else
{if ( avec_typeDeCalcul )
// cas où le type principal est valide et qu'il y a des sous_types
{ // on regarde si le sous-type "commandeInteractive" existe, si oui on le met en place
// détermine si le sous type de calcul existe et s'il est actif
if (paraGlob->SousTypeCalcul(commandeInteractive))
{// -- cas avec commandes interactives
// initialisation du calcul
InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );
// calcul de l'équilibre tant qu'il y a des commandes
while (ActionInteractiveAlgo())
{// on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
if (! (charge->Fin(icharge,true) ) )
CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats
,tb_combiner);
};
// fin du calcul, pour l'instant on ne considère pas les autres sous-types
FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );
}
else // cas sans commandes interactives
{// on fait le calcul d'équilibre
// initialisation du calcul : deux cas, soit avec une lecture initiale du .info, soit une lecture secondaire
if (paraGlob->EtatDeLaLecturePointInfo() == 0)
{InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );;}
else {// on est en lecture secondaire
MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );;
};
// on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
if (! (charge->Fin(icharge,true) ) )
{ // calcul de l'équilibre
CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats
,tb_combiner);
// fin du calcul, pour l'instant on ne considère pas les autres sous-types
FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
,divStock,charge,lesCondLim,lesContacts,resultats );
};
};// fin du cas sans commandes interactives
// ensuite on teste en fonction des calculs complémentaires
// dépendant des sous_types. Pour l'instant ici uniquement la remontée
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 (Remonte_in(*ili)) // on test la présence du calcul de remonté
{ // certaines initialisations sont nécessaires car c'est le premier calcul
Algori::InitRemontSigma(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
Algori::InitErreur(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
Algori::RemontSigma(lesMail);
Algori::RemontErreur(lesMail);
}
else if ( (*ili) == sauveMaillagesEnCours )
{ 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_tdt,*lesRef);
};
};
}
else
// cas ou le type principal n'est pas valide
// on ne fait que le calcul complémentaire
{ 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 (Remonte_in(*ili)) // on test la présence du calcul de remonté
{ // certaines initialisations sont nécessaires car c'est le premier calcul
Algori::InitRemontSigma(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
Algori::InitErreur(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
Algori::RemontSigma(lesMail);
Algori::RemontErreur(lesMail);
}
else if ( (*ili) == sauveMaillagesEnCours )
{ 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"
// a priori ici on n'a pas fait de calcul donc on sort les grandeurs à t
lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
};
};
}
}
// si on a forcé la sortie des itérations et incréments, il faut réinitialiser l'indicateur
if (!(pa.EtatSortieEquilibreGlobal()))
pa.ChangeSortieEquilibreGlobal(false);
};
// lecture des paramètres du calcul
void AlgoriCombine::lecture_Parametres(UtilLecture& entreePrinc)
{ MotCle motCle; // ref aux mots cle
deja_lue_entete_parametre = 1; // a priori pas de lecture d'entête
// on se positionne sur le prochain mot clé
do
{ entreePrinc.NouvelleDonnee();
}
while ( !motCle.SimotCle(entreePrinc.tablcar)) ;
// si le mot clé est "PARA_TYPE_DE_CALCUL" cela signifie
// qu'il y a un paramètre à lire
bool lecture_effective = false;
if (strstr(entreePrinc.tablcar,"PARA_TYPE_DE_CALCUL")!=NULL)
{ //cas de la définition de paramètres
// on signale à Algori qu'il y a eu déjà une lecture de paramètre
deja_lue_entete_parametre=2;
// lecture du premier paramètres de l'algorithme
entreePrinc.NouvelleDonnee(); // ligne suivante
// on initialise tous les paramètres par défaut
// non, car cela permettra éventuellement de garder les anciens paramètres
// on s'arrête lorsqu'il n'y a plus de mot clé spécifique à lire
while ( (strstr(entreePrinc.tablcar,"choix_algo_")!=NULL)
|| (strstr(entreePrinc.tablcar,"gestion_sauvegarde_")!=NULL)
|| (strstr(entreePrinc.tablcar,"gestion_sortie_a_convergence_")!=NULL)
)
{bool lecture_effective_interne = false;
string nom_class_methode("AlgoriCombine::lecture_Parametres(...");
//=== cas où on utilise un choix d'algo interne via une fct nD
if (strstr(entreePrinc.tablcar,"choix_algo_")!=NULL)
{ string mot_cle="choix_algo_";
{ bool lec_eff = entreePrinc.Lecture_mot_cle_et_string
(nom_class_methode,mot_cle,nom_choix_algo);
lecture_effective_interne = lecture_effective_interne || lec_eff;
};
};
//=== cas où on utilise une gestion de la sauvegarde de chaque algo via une fct nD
if (strstr(entreePrinc.tablcar,"gestion_sauvegarde_")!=NULL)
{ string mot_cle="gestion_sauvegarde_";
// puis on lit
{ bool lec_eff = entreePrinc.Lecture_mot_cle_et_string
(nom_class_methode,mot_cle,nom_gestion_sauvegarde);
lecture_effective_interne = lecture_effective_interne || lec_eff;
};
};
//=== cas où on utilise une gestion de la sauvegarde de chaque algo via une fct nD
if (strstr(entreePrinc.tablcar,"gestion_sortie_a_convergence_")!=NULL)
{ string mot_cle="gestion_sortie_a_convergence_";
// puis on lit
{ bool lec_eff = entreePrinc.Lecture_mot_cle_et_string
(nom_class_methode,mot_cle,nom_gestion_sortie_a_convergence);
lecture_effective_interne = lecture_effective_interne || lec_eff;
};
};
if ((lecture_effective_interne) && ( !motCle.SimotCle(entreePrinc.tablcar)))
{
#ifdef ENLINUX
if ((entreePrinc.entree)->fail())
// on a atteind la fin de la ligne et on appelle un nouvel enregistrement
{ entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement
}
#else
if ((entreePrinc.entree)->eof())
// la lecture est bonne mais on a atteind la fin de la ligne
{ entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement
}
#endif
// sinon ce n'est pas une ligne ad hoc, la lecture s'arrêtera
};
};
};
// puis appel de la méthode de la classe mère
Algori::lecture_Parametres(entreePrinc);
};
// création de cst_0 et cst_1
void AlgoriCombine::Creation_fct_cst()
{ // on crée si les fct n'existent pas déjà
// 1) on crée les paramètres pour la création des fonctions
Tableau <string > nom_variables;// les variables non globales -> 0
Tableau <Enum_GrandeurGlobale > enu_variables_globale; // enu globaux -> 0
Tableau <string > nom_variables_globales; // idem sous forme de strings
// 2) maintenant on crée les fonctions
if (cst_0 == NULL)
{string nom_ref("_"); // nom de ref de la fonction
string expression_fonction("0"); // la valeur de la fonction
cst_0 = new Fonction_expression_litterale_nD
(nom_ref,nom_variables,enu_variables_globale,nom_variables_globales
,expression_fonction);
};
if (cst_1 == NULL)
{string nom_ref("_"); // nom de ref de la fonction
string expression_fonction("1"); // la valeur de la fonction
cst_1 = new Fonction_expression_litterale_nD
(nom_ref,nom_variables,enu_variables_globale,nom_variables_globales
,expression_fonction);
};
};
// -------------------- Méthodes protégées --------------------------
// écriture des paramètres dans la base info
// = 1 : on écrit tout
// = 2 : on écrit uniquement les données variables (supposées comme telles)
void AlgoriCombine::Ecrit_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas)
{
ofstream& sort = *entreePrinc.Sort_BI();
if (cas == 1)
{//-- tout d'abord les fonctions de gestion d'algo
// choix des sous_algo
if (nom_choix_algo == "")
{sort << "\n fct_choix_algo_ "<< "aucune ";}
else
{sort << "\n fct_choix_algo_ "<< nom_choix_algo;};
// gestion de sauvegarde
if (nom_gestion_sauvegarde == "")
{sort << "\n fct_gestion_sauvegarde_ "<< "aucune ";}
else
{sort << "\n fct_gestion_sauvegarde_ "<< nom_gestion_sauvegarde;};
// gestion de sortie à convergence
if (nom_gestion_sortie_a_convergence == "")
{sort << "\n fct_gestion_sortie_a_convergence_ "<< "aucune ";}
else
{sort << "\n fct_gestion_sortie_a_convergence_ "<< nom_gestion_sortie_a_convergence;};
//--- puis on passe en revue les algos internes
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
{ sort << "\n ----->>parametres_sous_algo_specifiques_ "<< Nom_TypeCalcul(tab_algo(i)->TypeDeCalcul());
tab_algo(i)->Ecrit_Base_info_Parametre(entreePrinc,cas);
sort << "\n ----->>fin_parametres_sous_algo_specifiques_ "<< Nom_TypeCalcul(tab_algo(i)->TypeDeCalcul());
};
};
};
// lecture des paramètres dans la base info
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
// choix = true : fonctionnememt normal
// choix = false : la méthode ne doit pas lire mais initialiser les données à leurs valeurs par défaut
// car la lecture est impossible
void AlgoriCombine::Lecture_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas,bool choix)
{
// récup du flot
ifstream * ent = entreePrinc.Ent_BI();
if (cas == 1)
{// dimensionnement
if (choix)
{// cas d'une lecture normale
ifstream * ent = entreePrinc.Ent_BI();
string toto;
(*ent) >> toto; // on passe l'entête
//-- tout d'abord les fonctions de gestion d'algo
// choix des sous_algo
(*ent) >> toto; // on passe l'entête
if (toto == "aucune")
{nom_choix_algo = "";choix_algo=NULL;}
else
{nom_choix_algo = toto;};
// gestion de sauvegarde
(*ent) >> toto; // on passe l'entête
if (toto == "aucune")
{nom_gestion_sauvegarde = "";gestion_sauvegarde=NULL;}
else
{nom_gestion_sauvegarde = toto;};
// gestion de sortie à convergence
(*ent) >> toto; // on passe l'entête
if (toto == "aucune")
{nom_gestion_sortie_a_convergence = "";gestion_sortie_a_convergence=NULL;}
else
{nom_gestion_sortie_a_convergence = toto;};
};
//--- puis on passe en revue les algos internes
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
{// si on est arrivée ici, cela veut dire que l'on a lue sur le .BI qu'il s'agit de paramètre spécifiques
// de sous-algo donc il y a une première ligne qui indique de quel sous algo il s'agit
// on suit la même logique que celle de Algori::Ecriture_base_info
string nom1,nom2;
(*ent) >> nom1 ;
if (nom1 == "----->>parametres_sous_algo_specifiques_")
{ // lecture du nom de l'algo
(*ent) >> nom2;
if (Id_nom_TypeCalcul(nom2.c_str()) == tab_algo(i)->TypeDeCalcul())
{ // les données sauvegardées correspondent à l'algo en cours, on peut les récupérer
Lecture_Base_info_Parametre(entreePrinc,cas,true);
// on finit la lecture en passant les dernières lignes jusqu'au mot clé
(*ent) >> nom1;
while (nom1 != "----->>fin_parametres_sous_algo_specifiques_")
(*ent) >> nom1;
(*ent) >> nom1; // enfin on passe le nom de l'algo
}
else
{ // l'algo ne correspond pas, on passe les informations correspondants
while (nom1 != "----->>fin_parametres_sous_algo_specifiques_:")
(*ent) >> nom1;
(*ent) >> nom1; // enfin on passe le nom de l'algo
// on demande à l'agorithme de faire une initialisation sans lecture
Lecture_Base_info_Parametre(entreePrinc,cas,false);
};
}
else
{ // erreur on est mal positionné dans le fichier
cout << "\n *** erreur en lecture des parametres specifiques de l'algorithme"
<< " on attendait le mot cle ----->>parametres_sous_algo_specifiques_ "
<< " et on a lue "<< nom1
<< "\n AlgoriCombine::Lecture_Base_info_Parametre(...";
// dans le cas où un comptage du calcul est en cours on l'arrête
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
Sortie(1);
};
tab_algo(i)->Lecture_Base_info_Parametre(entreePrinc,cas,choix);
}
}
};
// création d'un fichier de commande: cas des paramètres spécifiques
void AlgoriCombine::Info_commande_parametres(UtilLecture& entreePrinc)
{ // écriture dans le fichier de commande
ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
sort << "\n# exemple partiel de declaration d'un algorithme qui integre "
<< " 2 sous algorithmes " ;
sort << "\n ";
sort << "\n combiner avec plus visualisation "
<< "\n# ++++++++++++ liste des sous algorithmes ++++++++++++ "
<< " liste_algorithmes_a_combiner_ # mot cle de debut de liste "
<< "\n# "
<< "\n# ============ algo 1 ============ "
<< "\n# ----- Dynamic Relaxation "
<< "\n dynamique_relaxation_dynam "
<< "\n # puis les parametres particuliers de l'algorithme de relaxation ..."
<< "\n # ... a completer "
<< "\n "
<< "\n# ============ algo 2 ============ "
<< "\n# ----- newton statique "
<< "\n non_dynamique "
<< "\n PARA_TYPE_DE_CALCUL "
<< "\n mode_debug_= 1 # il s'agit ici du mode debug uniquement pour le non_dynamique "
<< "\n# ... "
<< "\n fin_liste_algorithmes_a_combiner_ # mot cle de fin de liste de sous algo "
<< "\n "
<< "\n# ++++++++++++ parametres de l'algorithme combiner ++++++++++++ "
<< "\n# ils sont facultatifs et ici commentes cf. doc pour + de prec "
<< "\n PARA_TYPE_DE_CALCUL "
<< "\n## --- gestion du choix de l'algo"
<< "\n# choix_algo_ fonc_choix_algo"
<< "\n# # --- gestion de la sauvegarde de chaque algo"
<< "\n# gestion_sauvegarde_ fonc_gestion_sauvegarde # idem sauvegarde"
<< "\n# # --- puis la sortie du sous algo si convergence"
<< "\n# gestion_sortie_a_convergence_ fonc_gestion_sortie_a_convergence"
<< "\n " << flush;
cout << "\n# description plus precise de l'algorithme combiner (rep o ou n defaut) ? ";
string rep("n");
// procédure de lecture avec prise en charge d'un retour chariot
rep = lect_return_defaut(true,"n");
// si la taille de rep == 0 cela veut dire que c'est un retour chariot
if (rep.size()==0)
{rep = "n";
};
if ((rep == "o") || (rep == "O") ||(rep == "0"))
{ sort << "\n --- AlgoriCombine --- "
<< "\n# l'algorithme combiner permets d'encapsuler et de controler "
<< "\n# plusieurs sous algorithmes a l'interieur d'un algorithme maitre. "
<< "\n# NB:"
<< "\n# - Il n'y a pas de limitation sur le nombre de sous algorithme "
<< "\n# - un meme type d'algorithme peut apparaitre plusieurs fois "
<< "\n# - les sous algorithmes sont reperes par leur numero d'apparition"
<< "\n# lors de la lecture (et non par leur type) "
<< "\n# "
<< "\n# Par defaut le fonctionnement est le suivant: "
<< "\n# - pour chaque increment de charge, l'ensemble des sous algorithmes "
<< "\n# est execute dans l'ordre de leur lecture "
<< "\n# - le programme sort d'un sous algorithme lorsque typiquement la precision "
<< "\n# requise pour cet algorithme en fonction de la norme choisit, est "
<< "\n# satisfaite (a noter que chaque algorithme peut redefinir sa propre "
<< "\n# norme et sa propre precision via des fonctions nD et/ou des parametres"
<< "\n# de controle specifique) "
<< "\n# - seul le dernier algorithme valide (si convergence) le resultat final"
<< "\n# "
<< "\n# Il est possible d'etendre ce fonctionnement avec les parametres "
<< "\n# facultatifs propres a l'algo combiner definit par le mot cle: "
<< "\n# PARA_TYPE_DE_CALCUL "
<< "\n# positionne apres la definition de tous les sous algo (cf. mot cle "
<< "\n# fin_liste_algorithmes_a_combiner_ ) "
<< "\n# "
<< "\n# - on peut definir une fonction nD, dependante de grandeurs globales "
<< "\n# qui doit retourner 1 scalaire. Ce scalaire indique le "
<< "\n# choix de l'algo voulu. Dans ce cas, a chaque increment "
<< "\n# de charge, la fonction est appelee et le nombre (entier) que retourne la"
<< "\n# fonction indique le numero du sous algo a utiliser. En sortie du sous algo "
<< "\n# on regarde s'il s'agissait d'un calcul avec validation ou non. "
<< "\n# Le sous algo ne rend la main que si le calcul s'est deroule correctement "
<< "\n# (cf. remarques si-dessous). Aussi si le calcul etait avec validation "
<< "\n# la charge est incremente sinon il n'y a pas d'incrementation de la charge. "
<< "\n# Puis la fonction de choix d'algo est appelee pour designer le nouveau "
<< "\n# sous algo a appeler."
<< "\n# "
<< "\n# . la definition de la fonction s'effectue avec le mot cle choix_algo_"
<< "\n# suivit du nom d'une fonction nD definit dans la suite de la mise"
<< "\n# en donnees. "
<< "\n# "
<< "\n# exemple de definition : "
<< "\n# choix_algo_ fonc_choix_algo # gestion du choix de l'algo "
<< "\n# "
<< "\n# - par defaut, c'est le dernier sous algo qui valide le calcul. On peut definir "
<< "\n# une fonction nD, dependante de grandeurs globales, qui redefinit quand le sous algo "
<< "\n# doit valider le calcul. Cette fonction est appelee a l'interieur du sous algo "
<< "\n# a la fin de chaque iteration (implicit) ou increment (explicit) "
<< "\n# et permet a l'utilisateur (par exemple en fonction de la precision obtenue) "
<< "\n# de valider le calcul. "
<< "\n# Conjointement avec la fonction de choix d'algo, la fonction de validation"
<< "\n# est egalement appelee apres le retour du sous algo, pour incrementer la charge"
<< "\n# ou non (cf. si-dessus)."
<< "\n# "
<< "\n# . la definition de la fonction s'effectue avec le mot cle gestion_sauvegarde_"
<< "\n# suivit du nom d'une fonction nD definit dans la suite de la mise"
<< "\n# en donnees. "
<< "\n# "
<< "\n# exemple de definition : "
<< "\n# gestion_sauvegarde_ fonc_gestion_sauvegarde # gestion de la convergence de chaque algo "
<< "\n# "
<< "\n# - Par defaut, le programme sort d'un sous algorithme lorsque typiquement la precision "
<< "\n# requise pour cette algorithme en fonction de la norme choisit, est "
<< "\n# satisfaite, ceci pour un increment de charge. "
<< "\n# Il est possible d'effectuer plusieurs increment de charge avec un meme sous algo."
<< "\n# A priori il faut dans ce cas utiliser conjointement les fonction de "
<< "\n# gestion de sauvegarde et de validation de calcul, et on utilise une troisieme"
<< "\n# fonction nD qui dit quand on sort du sous algo."
<< "\n# "
<< "\n# . la def de la fonction s'effectue avec le mot cle gestion_sortie_a_convergence_"
<< "\n# suivit du nom d'une fonction nD definit dans la suite de la mise"
<< "\n# en donnees. "
<< "\n# "
<< "\n# exemple de definition : "
<< "\n# gestion_sortie_a_convergence_ fonc_gestion_sortie_a_convergence # gestion de la sortie de chaque algo "
<< "\n# "
<< "\n# Autres remarques importantes: "
// << "\n# - dans le cas de l'utilisation des fct nD, l'incrementation du chargement peut "
// << "\n# s'effectuer a l'interieur d'un sous algo. Ainsi un certain sous algo peut "
// << "\n# (eventuellement) enchainer plusieurs increments de charge "
// << "\n# avant de rendre la main. "
<< "\n# - un sous algo ne rend la main que s'il a fonctionne correctement. Par exemple "
<< "\n# s'il ne converge pas, il suit sa logique propre (cf. ses propres parametres"
<< "\n# de controle) jusqu'a aboutir au resultat cible (increment, precision etc.)."
<< "\n# Aussi, tant que l'algo ne rend pas la main, un nouveau choix de sous algo"
<< "\n# n'est pas possible. Cependant, chaque test de convergence du sous algo"
<< "\n# peut se controler via une fonction nD qui prend en compte l'evolution du calcul."
<< "\n# On peut ainsi definir une strategie specifique, qui permet de sortir de l'algo."
<< "\n# "
<< "\n# - au cours de l'execution de l'algo combiner on peut consulter la variable"
<< "\n# globale : "
<< "\n# algo_global_actuel"
<< "\n# qui contient pendant l'execution, le numero de def du sous algo en cours "
<< "\n# (voir la doc pour l'equivalence numero <-> type d'algo, car ce n'est pas le "
<< "\n# numero de lecture !!)"
<< "\n# - au cours de la mise en donnees generale (= le .info) on definit un ensemble de "
<< "\n# parametres de controle (ex: pas de temps, increment, nombre d'iteration etc. )."
<< "\n# Ces parametres s'appliquent a l'algorithme principal c-a-d combiner ."
<< "\n# Par defaut, l'ensemble de ces parametres de controle, est re-attribue a chaque"
<< "\n# sous algorithme. Mais il est egalement possible de modifier specifiquement certains"
<< "\n# parametre pour un algorithme particulier. On se reportera a la documentation generale"
<< "\n# pour plus d'info : cf. les mots cle : "
<< "\n# ==PARA_SPECIFIQUE_SOUS_ALGO== "
<< "\n# et "
<< "\n# ==FIN_PARA_SPECIFIQUE_SOUS_ALGO_=="
<< "\n# Ces 2 mots cles permettent de definir des parametres de controle specifiques pour un "
<< "\n# sous algorithme. "
<< "\n# - Ils doivent etre utilises apres la definition des parametres de "
<< "\n# controle generaux (parametre par defaut de tous les sous algo)"
<< "\n# - le premier est suivi du numero d'algo auquel il s'applique "
<< "\n# - le second termine la definition specifique "
<< "\n# "
<< "\n# "
<< "\n# exemple de mise en donnees : "
<< "\n# "
<< "\n# "
<< "\n# para_affichage #------------ "
<< "\n#---------------------------"
<< "\n# PARAMETRE | VALEUR | "
<< "\n#--------------------------- "
<< "\n# FREQUENCE_AFFICHAGE_INCREMENT 1 "
<< "\n# FREQUENCE_AFFICHAGE_ITERATION 1 "
<< "\n# FREQUENCE_SORTIE_FIL_DU_CALCUL 1 "
<< "\n# ... fin des parametres generaux "
<< "\n# "
<< "\n# ==PARA_SPECIFIQUE_SOUS_ALGO== 1 # para specifiques sous algo 1 "
<< "\n# controle #------------ "
<< "\n#-------------------- "
<< "\n# PARAMETER | VALUE | "
<< "\n#-------------------- "
<< "\n# NORME E_cinetique/E_statique_ET_ResSurReact "
<< "\n# PRECISION 5e-1 "
<< "\n# etc. "
<< "\n# ==FIN_PARA_SPECIFIQUE_SOUS_ALGO_== "
<< "\n# "
<< "\n# ==PARA_SPECIFIQUE_SOUS_ALGO== 2 # para specifiques sous algo 2 "
<< "\n# .... "
<< "\n# ==FIN_PARA_SPECIFIQUE_SOUS_ALGO_== "
;
};
// appel de la classe mère
Algori::Info_com_parametres(entreePrinc);
sort << "\n" << endl;
};
// sortie sur fichier des temps cpu
// idem la forme générique de la classe mère
// + des infos partielles pour chaque sous-algorithme
void AlgoriCombine::Sortie_temps_cpu(const LesCondLim& lesCondLim
, const Charge& charge,const LesContacts & contact)
{// -- on commence par appeler la méthode générique
// mais auparavant, il faut abonder la partie loi de comportement
// qui globalise automatiquement, donc qui n'est pas spécifique à chaque algo
Algori::Sortie_temps_cpu(lesCondLim,charge,contact);
// -- puis on complète pour chaque sous algo
// NB: concernant le contact, le chargement et les CL ou CLL, les temps étant
// stockés dans les objets concernés, il n'y a pas de séparation pour chaque
// algo, donc on ne sort pas ces temps qui ne sont que globaux (pas spécifiques à
// chaque algo)
// on récupère le fichier des temps cpu
entreePrinc->Ouverture_fichier_temps_cpu(); // ouverture au cas où
// récupération du fichier des temps cpu
ofstream & sort_cpu = entreePrinc->Sort_temps_cpu();
int nbdigit = 6; // pour le pourcentage
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
{ // la petite méthode qui sert au transfert et qui doit-être appelé avant les sorties
tab_algo(i)->Temps_CPU_HZpp_to_lesTempsCpu(lesCondLim,charge,contact);
// on concatène la totalité pour ensuite sortir également des pourcentage
double total_cpu = tab_algo(i)->tempsInitialisation.Temps_CPU_User();
total_cpu += tab_algo(i)->tempsMiseAjourAlgo.Temps_CPU_User();
total_cpu += tab_algo(i)->tempsCalEquilibre.Temps_CPU_User();
total_cpu += tab_algo(i)->tempsSauvegarde.Temps_CPU_User();
total_cpu += tab_algo(i)->tempsSortieFilCalcul.Temps_CPU_User();
sort_cpu << fixed;
sort_cpu.precision(2);
// pour éviter de faire une division par 0
total_cpu = MaX(ConstMath::trespetit, total_cpu);
sort_cpu << "\n ----->> specifiquement au sous_algo: "<< Nom_TypeCalcul(tab_algo(i)->TypeDeCalcul());
sort_cpu << "\n ---> tps_total_sous_algo "
<< "("<< std::setw(nbdigit) << total_cpu/1000. << " ) ";
sort_cpu << "\n tps_InitAlgo "
<< "("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsInitialisation.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsInitialisation.Temps_CPU_User_milli();
sort_cpu << "\n tps_MiseAJourAlgo "
<< "("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsMiseAjourAlgo.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsMiseAjourAlgo.Temps_CPU_User_milli();
sort_cpu << "\n tps_CalEquilibre "
<< "("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsCalEquilibre.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsCalEquilibre.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_MatSmLoc "
<< ".("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsRaidSmEner.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsRaidSmEner.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_SmLoc "
<< ".("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsSecondMembreEnerg.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsSecondMembreEnerg.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_lois_comp "
<< "..("<< std::setw(nbdigit) << (100 * tab_algo(i)->temps_lois_comportement.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->temps_lois_comportement.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_metrique_KSM "
<< "...("<< std::setw(nbdigit) << (100 * tab_algo(i)->temps_metrique_K_SM.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->temps_metrique_K_SM.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_ResSystLineaire "
<< "("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsResolSystemLineaire.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsResolSystemLineaire.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_Sauvegarde "
<< "("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsSauvegarde.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsSauvegarde.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_SortieFilCalcul "
<< "("<< std::setw(nbdigit) << (100 * tab_algo(i)->tempsSortieFilCalcul.Temps_CPU_User()/total_cpu) << " % ) "
<< tab_algo(i)->tempsSortieFilCalcul.Temps_CPU_User_milli()
;
sort_cpu << "\n";
};
};
// une méthode qui a pour objectif de terminer tous les comptages, utile
// dans le cas d'un arrêt impromptu
void AlgoriCombine::Arret_du_comptage_CPU()
{ // tout d'abord on appel la méthode générique qui concerne finalement
// que l'algo combiné
Algori::Arret_du_comptage_CPU();
// puis ici il s'agit de faire l'arrêt également de tous les sous algo
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
tab_algo(i)->Arret_du_comptage_CPU();
};
// ------- concernant les algo internes --------
// lecture des algorithmes internes
void AlgoriCombine::Lecture_algo_interne(const bool avec_typeDeCal
,const list <EnumSousTypeCalcul>& soustype
,const list <bool>& avec_soustypeDeCal
,UtilLecture& entreePrinc)
{ // les algos internes sont encadrés par les mots clés:
// liste_algorithmes_a_combiner_ et fin_liste_algorithmes_a_combiner_
// ces mots clés doivent exister et il doit y avoir au moins un algo interne
list_sousTypeCalcul.clear();
list_avec_sousCalcul.clear();
list <list<EnumSousTypeCalcul> >::const_iterator ili=list_sousTypeCalcul.begin();
list <list<bool> >::const_iterator ala=list_avec_sousCalcul.begin();
try
{ entreePrinc.NouvelleDonnee();// on passe la ligne de définition de l'algo combiner
string nom_class_methode("AlgoriCombine::Lecture_algo_interne(..."); // pour info lecture
// on passe le mot clé de début de liste
string mot_cle = "liste_algorithmes_a_combiner_";
bool lec_eff = entreePrinc.Lecture_et_verif_mot_cle(nom_class_methode,mot_cle);
list < Algori * > list_algori_inter; // une liste de travail pour la lecture
// maintenant on va lire chaque algorithme
entreePrinc.NouvelleDonnee();
do
{ // on lit les infos concernant le type de calcul interne
EnumTypeCalcul typeCalcul;bool avec_Calcul;
list<EnumSousTypeCalcul> sousTypeCalcul;
list<bool> avec_sousCalcul;
LectureTypeCalcul(entreePrinc,typeCalcul,avec_Calcul,sousTypeCalcul,avec_sousCalcul);
list_sousTypeCalcul.push_front(sousTypeCalcul);ili=list_sousTypeCalcul.begin();
list_avec_sousCalcul.push_front(avec_sousCalcul);ala=list_avec_sousCalcul.begin();
// du coup : les listes sont rangées : la première -> le dernier algo, etc.
// def de l'algorithme
Algori* algori = Algori::New_Agori
(typeCalcul,avec_Calcul, (*ili),(*ala),entreePrinc);
list_algori_inter.push_back(algori);
}
while (strstr(entreePrinc.tablcar,"fin_liste_algorithmes_a_combiner_")==NULL) ;
// entreePrinc.NouvelleDonnee(); // on passe le mot clé fin_liste_algorithmes_a_combiner_
// maintenant on stocke dans le tableau ceci pour un acces non séquentiel futur
int nb_algo = list_algori_inter.size();
tab_algo.Change_taille(nb_algo);
list < Algori * >::iterator il,ilfin= list_algori_inter.end();
int i=1;
for (il = list_algori_inter.begin();il != ilfin; il++,i++)
tab_algo(i)=(*il);
}
catch (...)
{
cout << "\n *** erreur en lecture algorithme(s) interne(s) "
<< "\n AlgoriCombine::Lecture_algo_interne(.."<<flush;
Sortie(1);
};
// on renseigne la variable: ptalgocombi de la classe Algori pour tous les sous-algo
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
tab_algo(i)->Change_ptalgocombi (this);
};
// sortie des temps cpu cumulées de tous les algos
void AlgoriCombine::AutreSortieTempsCPU(ofstream& sort,const int ) const
{ // on commence par cumuler tous les temps de calcul
Tableau <Temps_CPU_HZpp> lesTsCpu(10); // init
// on passe en revue tous les algorithmes et on cumule les temps cpu
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
tab_algo(i)->Ajout_Temps_CPU_HZpp_to_lesTempsCpu(lesTsCpu);
// on n'ajoute pas les temps de l'algo combiner, car sinon
// on va compter 2 fois certains temps
// en fait les temps de l'algo combiner ne sont pas très exploitable
// dans la forme actuelle, peut-être à améliorer si on veut les temps
// spécifique de l'algo combiner
// puis on affiche comme dans
//Algori::Ecriture_base_info(ofstream& sort,const int cas
/// ----> pour rappel:
// //------- temps cpu -----
// Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1)
// Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2)
// Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3)
// Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4)
// Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5)
// Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6)
// Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7)
// Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8)
// Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9)
// Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10)
// Temps_CPU_HZpp temps_CL; // lesTempsCpu(11)
// Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12)
// Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13)
// Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14)
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
sort << "\n tps_InitAlgo " << lesTsCpu(1);
sort << "\n tps_MiseAJourAlgo "<< lesTsCpu(2);
sort << "\n tps_CalEquilibre "<< lesTsCpu(3);
sort << "\n tps_MatSmLoc "<< lesTsCpu(4);
sort << "\n tps_SmLoc "<< lesTsCpu(5);
sort << "\n tps_ResSystLineaire "<< lesTsCpu(6);
sort << "\n tps_Sauvegarde "<< lesTsCpu(7);
sort << "\n tps_SortieFilCalcul "<< lesTsCpu(8);
sort << "\n tps_contactMatSmLoc "<< lesTsCpu(9);
sort << "\n tps_contactSmLoc "<< lesTsCpu(10);
};
// sortie pour info de la liste des énumérés de tous les sous-algo
list <EnumTypeCalcul> AlgoriCombine::List_Sous_Algo() const
{ list <EnumTypeCalcul> retour;
int nb_algo = tab_algo.Taille();
for (int i=1;i<=nb_algo;i++)
retour.push_back(tab_algo(i)->TypeDeCalcul());
// retour
return retour;
};