mise en place de la gestion des interuptions (d'Herezh) pour l'assemblage des seconds membres

This commit is contained in:
Gérard Rio 2024-03-27 16:19:08 +01:00
parent a05683f958
commit ab330c7860

View file

@ -1799,13 +1799,12 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
// on balaie les éléments nécessaires
list <int >::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 <int >::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 <int >& list_elem_cpu= tab_list_elem_cpu(nbMail); // pour simplifier
// on balaie les éléments nécessaires
list <int >::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 <Coordonnee> 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 <int > >& 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 <int >& list_elem_cpu= tab_list_elem_cpu(nbMail); // pour simplifier
// on balaie les éléments nécessaires
list <int >::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<Noeud *>& 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<Noeud *>& 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