From ab330c78604270282dc245980953cf950032c9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Rio?= Date: Wed, 27 Mar 2024 16:19:08 +0100 Subject: [PATCH] mise en place de la gestion des interuptions (d'Herezh) pour l'assemblage des seconds membres --- Algo/AlgoRef/Algori.cc | 270 ++++++++++++++++++++++++++++++----------- 1 file changed, 196 insertions(+), 74 deletions(-) diff --git a/Algo/AlgoRef/Algori.cc b/Algo/AlgoRef/Algori.cc index 283bd9e..e815649 100644 --- a/Algo/AlgoRef/Algori.cc +++ b/Algo/AlgoRef/Algori.cc @@ -1799,13 +1799,12 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin // on balaie les éléments nécessaires list ::const_iterator il,ilfin=list_elem_cpu.end(); for (il = dernier_il;il != ilfin;il++) - { int ne = (*il); - // on récupère un signal du process 0 + { // on récupère un signal du process 0 // on considère qu'il y a eu au moins un passage + tempsRaidSmEner.Arret_du_comptage(); temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu if (reqs1.active()) reqs1.wait(); temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu - tempsRaidSmEner.Arret_du_comptage(); temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu DeuxEntiers num_el_et_mail(gestion_exception,-1); // on transmet les numéros d'élément et de maillage @@ -1926,14 +1925,14 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif - if (ParaGlob::NiveauImpression() >= 10) + { if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage de la matrice de raideur (puissance interne) avant conditions limites"; matglob.Affichage_ecran(entete); entete = " affichage du second membre (puissance interne) avant condition limites "; vglobin.Affichage_ecran(entete); }; if (permet_affichage >3) cout << "\n -- fin calcul second membre et raideur " << flush; - + }; tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu }; // fin du cas sans exception // retour indiquant si oui ou non il y a eu des exceptions @@ -1943,6 +1942,7 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin // calcul du second membre pour tous les maillages ainsi que des énergies totales bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin) {tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu + bool retour = true; // init par défaut // on doit initialiser les temps globaux de loi de comp et de métrique car // on va ajouter ensuite des temps qui eux mêmes globalisent ce qui se passe à chaque pti // Temps_CPU_HZpp tps_zero; // un temps d'initialisation @@ -1965,18 +1965,23 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & mpi::request reqs2; Vecteur deux_faux_entiers(2); bool premier_passage = true; + int proc_en_cours = ParaGlob::Monde()->rank(); + int gestion_exception = 0; // pour la gestion #endif // on gère les exceptions éventuelles en mettant le bloc sous surveillance - try + int nbMailMax = lesMail->NbMaillage(); + int dernier_nbMail=1; // pour la gestion d'erreur + list ::const_iterator dernier_il; // pour la gestion d'erreur + try {// boucle sur les elements int nbMailMax = lesMail->NbMaillage(); #ifndef UTILISATION_MPI // cas d'un calcul mono CPU - for (int nbMail =1; nbMail<= nbMailMax; nbMail++) + for (int nbMail =1; nbMail<= nbMailMax; nbMail++,dernier_nbMail++) {int nemax = lesMail->Nombre_element(nbMail); for (int ne=1; ne<= nemax;ne++) { - #else + #else // cas d'un calcul multi-CPU // on va parcourir les éléments associés au cpu // on récupère la distribution d'éléments concernant le cpu en cours @@ -1989,7 +1994,7 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & {const list & list_elem_cpu= tab_list_elem_cpu(nbMail); // pour simplifier // on balaie les éléments nécessaires list ::const_iterator il,ilfin=list_elem_cpu.end(); - for (il = list_elem_cpu.begin();il != ilfin;il++) + for (il = dernier_il = list_elem_cpu.begin();il != ilfin;il++,dernier_il++) { int ne = (*il); // on récupère un signal du process 0 temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu @@ -2029,15 +2034,14 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & Ass.AssemSM (vglobin,*res,el.TableauDdl(),taN); // du second membre #else // cas d'un calcul parallèle, et CPU != 0 - int num_process = ParaGlob::Monde()->rank(); - if (num_process != 0) + if (proc_en_cours != 0) {tempsSecondMembreEnerg.Arret_du_comptage(); temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu // DeuxEntiers num_el_et_mail(el.Num_elt(),el.Num_maillage()); deux_faux_entiers(1) = (double ) el.Num_elt(); deux_faux_entiers(2) = (double ) el.Num_maillage(); // on transmet les numéros d'élément et de maillage - reqs1 = deux_faux_entiers.Ienvoi_MPI(0, 24); + reqs1 = deux_faux_entiers.Ienvoi_MPI(0, 24111); // reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail); temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu // puis on transmets le vecteur résidu @@ -2046,7 +2050,7 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & reqs2.wait(); temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu temps_transfert_long_matSm.Mise_en_route_du_comptage(); // comptage cpu - reqs2 = res->Ienvoi_MPI(0,25); + reqs2 = res->Ienvoi_MPI(0,25111); temps_transfert_long_matSm.Arret_du_comptage(); // fin comptage cpu tempsSecondMembreEnerg.Mise_en_route_du_comptage(); }; @@ -2083,65 +2087,124 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & } catch (ErrJacobienNegatif_ElemMeca excep) // cas d'un jacobien négatif "a prendre en compte" - { phase_de_convergence = -5; a_converge = false; return false; } - catch (ErrVarJacobienMini_ElemMeca excep) + { + #ifndef UTILISATION_MPI + phase_de_convergence = -5; a_converge = false; retour = false; + #else + gestion_exception = 1; + #endif + } + catch (ErrVarJacobienMini_ElemMeca excep) // cas d'une variation de jacobien trop importante - { phase_de_convergence = -6; a_converge = false; return false; } + { + #ifndef UTILISATION_MPI + phase_de_convergence = -6; a_converge = false; retour = false; + #else + gestion_exception = 2; + #endif + } catch (ErrNonConvergence_loiDeComportement excep) // cas d'une d'une erreur survenue à cause d'une non convergence pour la résolution // d'une loi de comportement incrémentale - { phase_de_convergence = -7; a_converge = false; + { + #ifndef UTILISATION_MPI cout << "\n non convergence sur une loi de comportement "; - return false; + switch (excep.cas) + {case 1: phase_de_convergence = -8; break; + case 0: default : phase_de_convergence = -7; break; + }; + a_converge = false; retour = false; + #else + switch (excep.cas) + {case 1: gestion_exception = 3; break; + case 0: default : gestion_exception = 4; break; + }; + #endif } catch (ErrCalculFct_nD) // cas d'une d'une erreur survenue à cause d'une erreur sur le calcul d'une fct nD // au niveau du chargement - { phase_de_convergence = -10; a_converge = false; + { + #ifndef UTILISATION_MPI + phase_de_convergence = -10; a_converge = false; cout << "\n *** erreur exception genere par une fonction nD utilisee en chargement "; - return false; + retour = false; + #else + gestion_exception = 5; + #endif } catch (ErrSortie) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur - { ErrSortie toto; + { + #ifndef UTILISATION_MPI + tempsSecondMembreEnerg.Arret_du_comptage(); + ErrSortie toto; throw (toto); + #else + gestion_exception = 6; + #endif } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur - { ErrSortieFinale toto; - tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu - throw (toto); - } + { + #ifndef UTILISATION_MPI + tempsSecondMembreEnerg.Arret_du_comptage(); + ErrSortieFinale toto; + throw (toto); + #else + gestion_exception = 7; + #endif + } catch ( ... ) - { if (ParaGlob::NiveauImpression() >= 1) - {cout << "\n warning: exception generee par un element mais dont la prise en compte " - << " n'est pas prevu !, on ne fait rien et on continue le calcul"; - if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::SecondMembreEnerg(.."; - }; - } - // affichage éventuelle du second membre - if (ParaGlob::NiveauImpression() >= 10) - { string entete = " affichage du second membre (puissance interne) avant conditions limites "; - vglobin.Affichage_ecran(entete); - }; - if (permet_affichage >3) cout << "\n -- fin calcul second membre " << flush; -//---- debug -// if (pa.CalVolTotalEntreSurfaceEtPlansRef()) -// { //Tableau vol_total2D_avec_plan_ref; // volume total entre la surface et : yz, xz,xy -// cout << "\n debug Algo::SecondMembreEnerg "; -// cout << "\n vol_total2D_avec_plan_ref " -// << vol_total2D_avec_plan_ref(1) << flush; -// }; -//---- fin debug - - // -- calcul des intégrales éventuelles avec transfert en global - lesMail->Integration(); + { + #ifndef UTILISATION_MPI + if (ParaGlob::NiveauImpression() >= 1) + {cout << "\n warning: exception generee par un element mais dont la prise en compte " + << " n'est pas prevu !, on ne fait rien et on continue le calcul"; + if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::SecondMembreEnerg(.."; + }; + #else + gestion_exception = 8; + #endif + } - tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu - #ifdef UTILISATION_MPI - if (ParaGlob::Monde()->rank() == 0) + + tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu +#ifdef UTILISATION_MPI + // tout d'abord on gère le cas des exceptions + if (proc_en_cours != 0) + {if (gestion_exception != 0) + {// on transmets l'info au proc 0 avec le même protocole que pour un résultat + // on boucle sur tous les derniers éléments qui n'ont pas été calculé + // ceci pour que proc 0 puisse correctement traiter tous les éléments + const Tableau < list >& tab_list_elem_cpu = distribution_CPU_algo.List_element_CPU_en_cours(); + int nb_mail_distrib = tab_list_elem_cpu.Taille(); + for (int nbMail =dernier_nbMail; nbMail<= nb_mail_distrib; nbMail++) + {const list & list_elem_cpu= tab_list_elem_cpu(nbMail); // pour simplifier + // on balaie les éléments nécessaires + list ::const_iterator il,ilfin=list_elem_cpu.end(); + for (il = dernier_il;il != ilfin;il++) + { // on récupère un signal du process 0 + // on considère qu'il y a eu au moins un passage + tempsSecondMembreEnerg.Arret_du_comptage(); + temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu + if (reqs1.active()) reqs1.wait(); + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu + deux_faux_entiers(1) = gestion_exception; + deux_faux_entiers(2) = -1; + // on transmet au proc 0 + reqs1 = deux_faux_entiers.Ienvoi_MPI(0, 24111); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); + }; + }; + }; + }; + + if (proc_en_cours == 0) { tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu // récup du nombre total d'éléments, cumul sur tous les maillages int total_elem = distribution_CPU_algo.NB_total_element(); @@ -2154,7 +2217,7 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu // DeuxEntiers num_el_et_mail; // mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 24, num_el_et_mail); - reqs1 = deux_faux_entiers.Irecup_MPI(mpi::any_source, 24); + reqs1 = deux_faux_entiers.Irecup_MPI(mpi::any_source, 24111); mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu @@ -2164,30 +2227,77 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & // temps_attente.Arret_du_comptage(); // fin comptage cpu int ne = (int) deux_faux_entiers(1); //num_el_et_mail.un; // numero d'identification de l'element int nbMail = (int) deux_faux_entiers(2);//num_el_et_mail.deux; // numéro de maillage - // d'où l'élément - ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); - // récupération des conteneurs ad hoc vecteur et raideur - int source = stat.source(); // récupération du numéro de la source - Vecteur * residu = el.Conteneur_Residu(); - tempsSecondMembreEnerg.Arret_du_comptage(); - temps_transfert_long_matSm.Mise_en_route_du_comptage(); // comptage cpu - mpi::request reqs2 = residu->Irecup_MPI(source, 25); - reqs2.wait(); // on attend que le conteneur soit rempli - temps_transfert_long_matSm.Arret_du_comptage(); // fin comptage cpu - tempsSecondMembreEnerg.Mise_en_route_du_comptage(); - Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el - // --- assemblage - Ass.AssemSM (vglobin,*residu,el.TableauDdl(),taN); // du second membre + if (nbMail > 0) + // cas normal + { + // d'où l'élément + ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); + // récupération des conteneurs ad hoc vecteur et raideur + int source = stat.source(); // récupération du numéro de la source + Vecteur * residu = el.Conteneur_Residu(); + tempsSecondMembreEnerg.Arret_du_comptage(); + temps_transfert_long_matSm.Mise_en_route_du_comptage(); // comptage cpu + mpi::request reqs2 = residu->Irecup_MPI(source, 25111); + reqs2.wait(); // on attend que le conteneur soit rempli + temps_transfert_long_matSm.Arret_du_comptage(); // fin comptage cpu + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); + Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el + // --- assemblage + Ass.AssemSM (vglobin,*residu,el.TableauDdl(),taN); // du second membre + } + else // la suite concerne le cas d'une exception + {// s'il y a une exception fatal, cela va arrêter proc 0 et donc tous les autres + gestion_exception = ne; + switch (gestion_exception) + {case 1: phase_de_convergence = -5; a_converge = false; retour = false; break; + case 2: phase_de_convergence = -6; a_converge = false; retour = false; break; + case 3: phase_de_convergence = -8; retour = false; break; + case 4: phase_de_convergence = -7; retour = false; break; + case 5: phase_de_convergence = -10; a_converge = false; + cout << "\n *** erreur exception genere par une fonction nD utilisee en chargement "; + retour = false; break; + case 6: {tempsRaidSmEner.Arret_du_comptage(); ErrSortie toto; throw (toto);} + case 7: {tempsRaidSmEner.Arret_du_comptage(); ErrSortieFinale toto;; throw (toto);} + case 8: { if (ParaGlob::NiveauImpression() >= 1) + {cout << "\n warning: exception generee par un element mais dont la prise en compte " + << " n'est pas prevu !, on ne fait rien et on continue le calcul"; + if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::SecondMembreEnerg(.."; + };break; + } + default: + cout << "\n erreur en retour d'exception: on a lue gestion_exception = "<< gestion_exception + << " la gestion de ce cas n'existe pas !!! on stop l'execution ..." + << "\n Algori::SecondMembreEnerg(.."; + Sortie(1); + }; // fin de la gestion des différents cas d'exception + // arrivée ici on continue la boucle du while + tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu + }; // on incrémente le nombre d'élément traité nb_elem_deja_calcule++; }; tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu }; - // récupération de toutes les énergies par le cpu 0 - tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu - Algori::Passage_energiesEtVolumes(); - tempsSecondMembreEnerg.Mise_en_route_du_comptage(); - #endif + // à la sortie du calcul on transmets la gestion d'excep + // on transmet à tous les proc l'indicateur calcul_a_effectuer + broadcast(*ParaGlob::Monde(), gestion_exception, 0); + // on vérifie que ce n'est pas une sortie due à une exception + // si c'est ok on continue + if (gestion_exception != 0) + retour = false; + #endif + if(retour) + {tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu + // -- calcul des intégrales éventuelles avec transfert en global + lesMail->Integration(); + + #ifdef UTILISATION_MPI + tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu + // récupération de toutes les énergies par le cpu 0 + Algori::Passage_energiesEtVolumes(); + #endif + + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // -- on transfert en global les énergies internes @@ -2195,10 +2305,22 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & Transfert_ParaGlob_energies_hourglass_bulk_stab(); // idem pour les volumes entre plans Transfert_ParaGlob_volume_entre_plans(); - tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu - // retour indiquant que tout c'est bien passé - return true ; + // affichage éventuelle du second membre + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif + {if (ParaGlob::NiveauImpression() >= 10) + { string entete = " affichage du second membre (puissance interne) avant conditions limites "; + vglobin.Affichage_ecran(entete); + }; + if (permet_affichage >3) cout << "\n -- fin calcul second membre " << flush; + }; + tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu + }; // fin du cas sans exception + + // retour indiquant si oui ou non il y a eu des exceptions + return retour ; }; // Mise à jour de la raideur et du second membre pour le contact