// 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-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 . // // For more information, please consult: . #include "AlgoriCombine.h" #include "MatBand.h" #include //------- décomposition en 3 du calcul d'équilibre ------------- // a priori : InitAlgorithme et FinCalcul ne s'appellent qu'une fois, // par contre : CalEquilibre peut s'appeler plusieurs fois, le résultat sera différent si entre deux calcul // certaines variables ont-été changés // initialisation void AlgoriCombine::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage, Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats) { // INITIALISATION globale tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info // on s'occupe des fonctions nD de pilotage // 1) cas de choix_algo if ((nom_choix_algo.length()) && (choix_algo == NULL)) // cas où on doit récupérer la fonction nD {choix_algo = lesFonctionsnD->Trouve(nom_choix_algo); if (choix_algo->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales {// on vérifie qu'en retour on a un 2 scalaires choix_algo->Valeur_pour_variables_globales(); // pour simplifier if (choix_algo->NbComposante() != 1) {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_choix_algo << " qui permet de faire le choix de l'algo interne a utiliser " << " ne retourne pas 1 scalaire !! a priori ce n'est pas correct "; Sortie(1); }; } else {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_choix_algo << " qui permet de faire le choix de l'algo interne a utiliser " << " utilise des variables autres que globales, ce n'est pas possible ! "; Sortie(1); }; }; // 2) cas de la validation et sauvegarde if ((nom_gestion_sauvegarde.length()) && (gestion_sauvegarde == NULL)) // cas où on doit récupérer la fonction nD {gestion_sauvegarde = lesFonctionsnD->Trouve(nom_gestion_sauvegarde); if (gestion_sauvegarde->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales {// on vérifie qu'en retour on a un scalaire gestion_sauvegarde->Valeur_pour_variables_globales(); // pour simplifier if (gestion_sauvegarde->NbComposante() != 1) {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sauvegarde << " qui permet le pilotage de la sauvegarde " << " ne retourne pas un scalaire unique !! a priori ce n'est pas correct "; Sortie(1); }; } else {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sauvegarde << " qui permet le pilotage de la sauvegarde " << " utilise des variables autres que globales, ce n'est pas possible ! "; Sortie(1); }; }; // 3) gestion de la sortie à convergence de chaque algo if ((nom_gestion_sortie_a_convergence.length()) && (gestion_sortie_a_convergence == NULL)) // cas où on doit récupérer la fonction nD {gestion_sortie_a_convergence = lesFonctionsnD->Trouve(nom_gestion_sortie_a_convergence); if (gestion_sortie_a_convergence->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales {// on vérifie qu'en retour on a un scalaire gestion_sortie_a_convergence->Valeur_pour_variables_globales(); // pour simplifier if (gestion_sortie_a_convergence->NbComposante() != 1) {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sortie_a_convergence << " qui permet de piloter la sortie a convergence de chaque algo " << " ne retourne pas un scalaire unique !! a priori ce n'est pas correct "; Sortie(1); }; } else {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sortie_a_convergence << " qui permet de piloter la sortie a convergence de chaque algo " << " utilise des variables autres que globales, ce n'est pas possible ! "; Sortie(1); }; }; // on passe en revue tous les algorithmes et on les initialise int nb_algo = tab_algo.Taille(); for (int i=1;i<=nb_algo;i++) {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); tab_algo(i)->InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts,resultats); }; // on regarde s'il y a besoin de sauvegarde // explication: cela ce fait ici, car au niveau de chaque sous-algo, l'ouverture en écriture a été gelée // du fait que chaque sous algo n'est pas le maitre, ceci pour éviter une sucession d'ouverture écritures // mais il faut quand même finir par ouvrir en écriture si cela est demandé après toutes les lectures if (this->Active_sauvegarde()) { // on récupère la position de restart lue par le dernier algo // récupération de la position lue par l'algo dans le .BI, changé lors d'un restart par exemple // il s'agit de la sauvegarde par l'algo de la position qu'il a lue en restart debut_increment = tab_algo(nb_algo)->Debut_increment(); //&& (ParaGlob::param->TypeCalcul_maitre() == this->typeCalcul) ) // si le fichier base_info n'est pas en service on l'ouvre entreePrinc->Ouverture_base_info("ecriture"); // dans le cas ou se n'est pas un restart on sauvegarde l'incrément actuel // c'est-à-dire le premier incrément // après s'être positionné au début du fichier if (this->Num_restart() == 0) { (entreePrinc->Sort_BI())->seekp(0); int cas = 1; paraGlob->Ecriture_base_info(*(entreePrinc->Sort_BI()),cas); this->Ecriture_base_info (cas,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage ,charge,lesCondLim,lesContacts,resultats,OrdreVisu::INCRE_0); } else { // sinon on se place dans le fichier à la position du restart // debut_increment a été définit dans algori (classe mère) (entreePrinc->Sort_BI())->seekp(debut_increment); } }; tempsInitialisation.Arret_du_comptage(); // temps cpu }; // mise à jour void AlgoriCombine::MiseAJourAlgo(ParaGlob * paraGlob,LesMaillages * lesMail, LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage, Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats) { // INITIALISATION globale tempsMiseAjourAlgo.Mise_en_route_du_comptage(); // temps cpu Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info // on passe en revue tous les algorithmes et on demande leur mise à jour int nb_algo = tab_algo.Taille(); for (int i=1;i<=nb_algo;i++) {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts,resultats); }; tempsMiseAjourAlgo.Arret_du_comptage(); // temps cpu }; // calcul // si tb_combiner est non null -> un tableau de 3 fonctions // - la première fct dit si on doit valider ou non le calcul à convergence ok, // - la deuxième dit si on doit sortir de la boucle ou non à convergence ok // - la troisième sert d'indicateur: si == un pointeur nulle, cela signifie qu'au début du // sous - algo on part pour le calcul final des positions à t, sinon on part des position à tdt // ==> sert en I/O des sous-algo, chaque sous-algo disant au suivant s'il a valider ou pas // le paramètre est figé pour le premier algo // // si la validation est effectuée, la sauvegarde pour le post-traitement est également effectuée // en fonction de la demande de sauvegard, // sinon pas de sauvegarde pour le post-traitement à moins que l'on a demandé un mode debug // qui lui fonctionne indépendamment void AlgoriCombine::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lescontacts ,Resultats* resultats,Tableau < Fonction_nD* > * ) { tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info int nb_algo = tab_algo.Taille(); Tableau < Fonction_nD* > * tb_combiner = new Tableau < Fonction_nD* >; tb_combiner->Change_taille(3,NULL); // init par défaut // --- mise à jour du numéro de chargement des algos // le numéro de chargement est initialement déterminé par le premier algo icharge = tab_algo(1)->Num_increment(); for (int i=1;i<=nb_algo;i++) tab_algo(i)->Affectation_icharge(icharge); // concernant la troisième fonction qui gère le départ de chaque sous-algo // à partir de X_t ou pas, (*tb_combiner)(3)=NULL; // on part de la position X_t // ensuite ce sont les sous-algos qui modifient le paramètre // en fonction du fait qu'il valide ou pas le calcul // on boucle sur les incréments de charge bool affichage = true; // affichage a priori de la fin des calculs while ( (!charge->Fin(icharge,affichage)) && (charge->Fin(icharge,true)!=2) // si on a dépassé le nombre d'incrément permis on s'arrête dans tous les cas && (charge->Fin(icharge,false)!=3) // idem si on a dépassé le nombre d'essai d'incrément permis // 1er appel avec true: pour affichage et second avec false car c'est déjà affiché && (!pa.EtatSortieEquilibreGlobal()) ) { // l'appel des algos s'effectuent soit successivement si aucune info particulière // soit en fonction du retour de la fonction choix if (choix_algo == NULL) {// cas où on passe les algos successivement dans l'ordre de leurs définitions for (int i=1;i<=nb_algo;i++) {// avant tout chose, on met à jour // //------ debug // cout << "\n ********* debug calequilibre Combiner: " // << " tab_algo(1)->pa.Deltat()= " << tab_algo(1)->pa.Deltat() // << "\n tab_algo(2)->pa.Deltat()= " << tab_algo(2)->pa.Deltat() // << "\n tab_algo(3)->pa.Deltat()= " << tab_algo(3)->pa.Deltat() << flush; // //--- fin debug ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier if (aff_incr) cout << "\n---------------------------------------------------------------------" << "\n >>>> algorithme ("<< i <<"): " << Nom_TypeCalcul(tab_algo(i)->TypeDeCalcul()) << " >>>> " << "\n---------------------------------------------------------------------" << flush; tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor ,lesLoisDeComp,diversStockage,charge,lesCondLim ,lescontacts,resultats ); // on met à jour tb_combiner if (gestion_sortie_a_convergence != NULL) {(*tb_combiner)(2)=gestion_sortie_a_convergence;} else // sinon par défaut {(*tb_combiner)(2)=cst_1; // sortie de boucle à la convergence propre à l'algo }; if (gestion_sauvegarde != NULL) {(*tb_combiner)(1)=gestion_sauvegarde;} else // sinon c'est le dernier algo qui sauvegarde par défaut {if (i != nb_algo) {(*tb_combiner)(1)=cst_0;}// pas de validation else // pour le dernier algo {(*tb_combiner)(1)=cst_1;}; // validation }; // //------ debug // cout << "\n ********* debug calequilibre Combiner: " // << " tab_algo(1)->pa.Deltat()= " << tab_algo(1)->pa.Deltat() // << "\n tab_algo(2)->pa.Deltat()= " << tab_algo(2)->pa.Deltat() // << "\n tab_algo(3)->pa.Deltat()= " << tab_algo(3)->pa.Deltat() << flush; // //--- fin debug // puis on calcul l'équilibre tab_algo(i)->CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor ,lesLoisDeComp,diversStockage,charge,lesCondLim,lescontacts,resultats ,tb_combiner); // //------ debug // cout << "\n ********* debug calequilibre Combiner: apres tab_algo(i)->CalEquilibre " // << " tab_algo(1)->pa.Deltat()= " << tab_algo(1)->pa.Deltat() // << "\n tab_algo(2)->pa.Deltat()= " << tab_algo(2)->pa.Deltat() // << "\n tab_algo(3)->pa.Deltat()= " << tab_algo(3)->pa.Deltat() << flush; // //--- fin debug // s'il y a une fctnD de sauvegarde on garde le numéro du dernier sous-algo qui a sauvegardé // car c'est le seul important pour la sauvegarde if (gestion_sauvegarde != NULL) {if ((bool) gestion_sauvegarde->Valeur_pour_variables_globales()(1)) {nb_dernier_algo_qui_a_fait_une_sauvegarde = i;}; } else // sinon c'est le dernier par défaut qui sauvegarde {nb_dernier_algo_qui_a_fait_une_sauvegarde = nb_algo; }; }; // récup du numéro de chargement icharge = tab_algo(nb_algo)->Num_increment(); // c'est le dernier qui sauvegarde } else // sinon il existe une fonction de choix, on s'en sert { bool sans_changement_increment = true; do {int i = choix_algo->Valeur_pour_variables_globales()(1); if ((i >0)&&(i <= nb_algo)) {// on met à jour ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier if (aff_incr) cout << "\n---------------------------------------------------------------------" << "\n >>>> algorithme ("<< i <<"): " << Nom_TypeCalcul(tab_algo(i)->TypeDeCalcul()) << " >>>> " << "\n---------------------------------------------------------------------" << flush; tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor ,lesLoisDeComp,diversStockage,charge,lesCondLim ,lescontacts,resultats ); // on met à jour tb_combiner if (gestion_sortie_a_convergence != NULL) {(*tb_combiner)(2)=gestion_sortie_a_convergence;} else // sinon par défaut {(*tb_combiner)(2)=cst_1; // sortie de boucle à la convergence propre à l'algo }; if (gestion_sauvegarde != NULL) {(*tb_combiner)(1)=gestion_sauvegarde;} else // sinon c'est le dernier algo qui sauvegarde par défaut {if (i != nb_algo) {(*tb_combiner)(1)=cst_0;}// pas de validation else // pour le dernier algo {(*tb_combiner)(1)=cst_1;}; // validation }; // puis on calcul l'équilibre tab_algo(i)->CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor ,lesLoisDeComp,diversStockage,charge,lesCondLim,lescontacts,resultats ,tb_combiner); // récup du numéro de chargement icharge = tab_algo(i)->Num_increment(); } else {cout << "\n erreur** la fonction de choix d'algo indique l'algo num: "<< i << " qui n'a pas ete defini !! on ne peut pas continuer " << "\n AlgoriCombine::CalEquilibre(..."<Valeur_pour_variables_globales()(1)); // si on a sauvegardé on va sortir de la boucle, on sauvegarde le num d'algo if (!sans_changement_increment) nb_dernier_algo_qui_a_fait_une_sauvegarde = i; } while (sans_changement_increment); }; // --- mise à jour du numéro de chargement pour tous les algos for (int i=1;i<=nb_algo;i++) tab_algo(i)->Affectation_icharge(icharge); }; // fin du while tempsCalEquilibre.Arret_du_comptage(); // temps cpu }; // dernière passe void AlgoriCombine::FinCalcul(ParaGlob * paraGlob,LesMaillages * lesMail,LesReferences* lesRef ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage, Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats) { // fin des calculs Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info // // on passe en revue tous les algorithmes et on demande la fin des calculs // non, sinon on a plusieurs dernières sauvegardes !! // donc on ne sauvegarde la fin que via le dernier sous_algo qui a sauvegardé int nb_algo = tab_algo.Taille(); // for (int i=1;i<=nb_algo;i++) int i=nb_dernier_algo_qui_a_fait_une_sauvegarde; {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); tab_algo(i)->FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts,resultats); }; }; //---- gestion des commndes interactives -------------- // écoute et prise en compte d'une commande interactive // ramène true tant qu'il y a des commandes en cours bool AlgoriCombine::ActionInteractiveAlgo() { cout << "\n commande? "; return false; }; // sortie du schemaXML: en fonction de enu void AlgoriCombine::SchemaXML_Algori(ofstream& sort,const Enum_IO_XML enu) const { switch (enu) { case XML_TYPE_GLOBAUX : { break; } case XML_IO_POINT_INFO : { break; } case XML_IO_POINT_BI : { break; } case XML_IO_ELEMENT_FINI : { break; } case XML_ACTION_INTERACTIVE : {sort << "\n " << "\n" << "\n " << "\n initialisation de l'algo " << "\n " << "\n " << "\n"; sort << "\n" << "\n " << "\n execution de l'ensemble de l'algo, sans l'initialisation et la derniere passe " << "\n " << "\n " << "\n"; sort << "\n" << "\n " << "\n fin de l'algo " << "\n " << "\n " << "\n"; break; } case XML_STRUCTURE_DONNEE : { break; } }; };