// 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) . // // 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 . // // For more information, please consult: . #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 & soustype ,const list & 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 >::iterator ili=list_sousTypeCalcul.begin(); list >::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 ::const_iterator ili,ili_fin = soustypeDeCalcul->end(); list ::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 ::const_iterator ili,ili_fin = soustypeDeCalcul->end(); list ::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 nom_variables;// les variables non globales -> 0 Tableau enu_variables_globale; // enu globaux -> 0 Tableau 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(ostream& sort,const int& cas) { 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(sort,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(istream& ent,const int& cas,bool choix) { if (cas == 1) {// dimensionnement if (choix) {// cas d'une lecture normale 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(ent,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(ent,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(ent,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 & soustype ,const list & 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 >::const_iterator ili=list_sousTypeCalcul.begin(); list >::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); 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 sousTypeCalcul; list 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(.."<Change_ptalgocombi (this); }; // sortie des temps cpu cumulées de tous les algos void AlgoriCombine::AutreSortieTempsCPU(ostream& sort,const int ) const { // on commence par cumuler tous les temps de calcul Tableau lesTsCpu(18); // 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 ----- // // ainsi en sortie on pourra différencier les temps totaux et les temps partiels // 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) // Temps_CPU_HZpp tempsCalMasse; // lesTempsCpu(17) // Temps_CPU_HZpp tempsCalViscoNum; // lesTempsCpu(18) //#ifdef UTILISATION_MPI // // cas d'un calcul parallèle: // passage des infos entre process // Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(19) // Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(20) // Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(21) // Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(22) // Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(23) // Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(24) // Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(25) // Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(26) // Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(27) // Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(28) // Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(29) // Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(30) 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); sort << "\n tempsCalMasse "<< lesTsCpu(17); sort << "\n tempsCalViscoNum "<< lesTsCpu(18); }; // sortie pour info de la liste des énumérés de tous les sous-algo list AlgoriCombine::List_Sous_Algo() const { list 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; };