From ea11c75ff8085752b0e3d12c3b4f8299fbd38d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Rio?= Date: Sun, 24 Mar 2024 11:43:58 +0100 Subject: [PATCH] =?UTF-8?q?-=20corr=20bug=20affichage=20intempestif=20cont?= =?UTF-8?q?act=20-=20fct=20nD:=20am=C3=A9lioration=20message=20d'erreur=20?= =?UTF-8?q?(arguments),=20et=20en=20fct=20du=20niveau=20g=C3=A9r=C3=A9=20p?= =?UTF-8?q?ar=20une=20fct=20nD=20-=20premi=C3=A8re=20validation=20du=20fct?= =?UTF-8?q?.=20en=20//=20en=20implicite=20statique=20et=20en=20RD,=20=20?= =?UTF-8?q?=20nombreuses=20modifications=20et=20am=C3=A9lioration=20!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gérard Rio --- Algo/AlgoRef/Algori.cc | 825 ++++++++++++++---- Algo/AlgoRef/Algori.h | 32 +- Algo/AlgoRef/Algori2.cc | 26 +- Algo/AlgoRef/Algori4.cc | 284 ++++-- Algo/AlgorithmeCombiner/AlgoriCombine.cc | 64 +- Algo/AlgorithmeCombiner/AlgoriCombine2.cc | 2 +- .../AlgoDynaExplicite/AlgoRungeKutta.cc | 2 +- .../AlgoDynaExplicite/AlgoriDynaExpli2.cc | 2 +- .../AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc | 2 +- .../AlgoDynaExplicite/Algori_chung_lee.cc | 2 +- .../AlgoDynaExplicite/Algori_relax_dyna.cc | 660 +++++++++++--- .../AlgoDynaExplicite/Algori_tchamwa.cc | 2 +- .../AlgoDynaImplicite/AlgoriNewmark2.cc | 2 +- .../AlgoStatiques/AlgoriNonDyna2.cc | 81 +- .../DG_DynaExplicite/AlgoBonelli.cc | 2 +- Chargement/Charge.cc | 24 +- Chargement/Charge2.cc | 57 +- Elements/Element.cc | 79 +- Elements/Element.h | 21 +- Elements/Geometrie/Frontiere/Front.cc | 14 +- Elements/Geometrie/Frontiere/Front.h | 13 + Elements/Mecanique/ElemMeca.cc | 126 +-- Elements/Mecanique/SFE/SfeMembT.cc | 7 + General/Distribution_CPU.cc | 206 ++++- General/Distribution_CPU.h | 4 +- General/herezh.cc | 10 + Maillage/LesMaillages.cc | 21 +- Maillage/LesMaillages.h | 2 +- Maillage/LesMaillages2.cc | 32 +- Maillage/Maillage.cc | 4 +- Maillage/maillage4.cc | 5 + Parametres/EnteteParaGlob.h | 2 +- Parametres/ParaAlgoControle.cc | 40 +- Parametres/ParaAlgoControle.h | 3 + Parametres/banniere.cc | 16 +- Resolin/Resolution_Condi/Condilineaire.cc | 62 +- Resolin/Resolution_Condi/Condilineaire.h | 4 +- Tableaux/Tableau_T.h | 18 +- Util/Courbes/Fonc_scal_combinees_nD.cc | 87 +- Util/Courbes/Fonc_scal_combinees_nD.h | 9 + .../Fonction_expression_litterale_nD.cc | 480 +--------- .../Fonction_expression_litterale_nD.h | 1 + Util/Courbes/Fonction_nD.cc | 217 ++++- Util/Courbes/Fonction_nD.h | 113 +-- comportement/LesLoisDeComp.cc | 3 + contact/ElContact.cc | 127 ++- contact/ElContact.h | 44 +- contact/ElContact_2.cc | 209 +++-- contact/LesContacts.cc | 472 ++++++++-- contact/LesContacts.h | 47 +- contact/LesContacts_2.cc | 4 + contact/LesContacts_3.cc | 281 ++++-- 52 files changed, 3452 insertions(+), 1400 deletions(-) diff --git a/Algo/AlgoRef/Algori.cc b/Algo/AlgoRef/Algori.cc index 23de137..283bd9e 100644 --- a/Algo/AlgoRef/Algori.cc +++ b/Algo/AlgoRef/Algori.cc @@ -149,16 +149,17 @@ Algori::Algori () : // par defaut ,tempsSauvegarde(),tempsSortieFilCalcul(),tempsRaidSmEnerContact() ,tempsSecondMembreEnergContact(),temps_CL(),temps_CLL() ,temps_lois_comportement(),temps_metrique_K_SM(),temps_chargement() - ,temps_rech_contact() + ,temps_rech_contact(),tempsCalMasse(),tempsCalViscoNum() ,ptalgocombi(NULL) #ifndef UTILISATION_MPI - ,lesTempsCpu(16) + ,lesTempsCpu(18) #else - ,lesTempsCpu(28),distribution_CPU_algo() + ,lesTempsCpu(30),distribution_CPU_algo() ,temps_transfert_court_algo(),temps_transfert_long_algo(),temps_attente_algo() ,temps_transfert_court_matSm(),temps_transfert_long_matSm(),temps_attente_matSm() ,temps_transfert_court_charge(),temps_transfert_long_charge(),temps_attente_charge() ,temps_transfert_court_contact(),temps_transfert_long_contact(),temps_attente_contact() + ,inter_transfer(),inter_transfer2() #endif //---------- stockage pour la transmission des grandeurs consultables ----- // ,stock_compteur(GENERIQUE_UNE_GRANDEUR_GLOBALE),val_stock_compteur(NULL) @@ -243,16 +244,17 @@ Algori::Algori (EnumTypeCalcul type,const bool avec_typeDeCal ,tempsSauvegarde(),tempsSortieFilCalcul(),tempsRaidSmEnerContact() ,tempsSecondMembreEnergContact(),temps_CL(),temps_CLL() ,temps_lois_comportement(),temps_metrique_K_SM(),temps_chargement() - ,temps_rech_contact() + ,temps_rech_contact(),tempsCalMasse(),tempsCalViscoNum() ,ptalgocombi(NULL) #ifndef UTILISATION_MPI - ,lesTempsCpu(16) + ,lesTempsCpu(18) #else - ,lesTempsCpu(28),distribution_CPU_algo() + ,lesTempsCpu(30),distribution_CPU_algo() ,temps_transfert_court_algo(),temps_transfert_long_algo(),temps_attente_algo() ,temps_transfert_court_matSm(),temps_transfert_long_matSm(),temps_attente_matSm() ,temps_transfert_court_charge(),temps_transfert_long_charge(),temps_attente_charge() ,temps_transfert_court_contact(),temps_transfert_long_contact(),temps_attente_contact() + ,inter_transfer(),inter_transfer2() #endif //---------- stockage pour la transmission des grandeurs consultables ----- @@ -439,11 +441,12 @@ Algori::Algori (const Algori& algo) : ,temps_CL(algo.temps_CL),temps_CLL(algo.temps_CLL) ,temps_lois_comportement(algo.temps_lois_comportement),temps_metrique_K_SM(algo.temps_metrique_K_SM) ,temps_chargement(algo.temps_chargement),temps_rech_contact(algo.temps_rech_contact) + ,tempsCalMasse(algo.tempsCalMasse),tempsCalViscoNum(algo.tempsCalViscoNum) ,ptalgocombi(NULL) #ifndef UTILISATION_MPI - ,lesTempsCpu(16) + ,lesTempsCpu(18) #else - ,lesTempsCpu(28),distribution_CPU_algo(algo.distribution_CPU_algo) // distribution de charge sur les CPU + ,lesTempsCpu(30),distribution_CPU_algo(algo.distribution_CPU_algo) // distribution de charge sur les CPU ,temps_transfert_court_algo(algo.temps_transfert_court_algo),temps_transfert_long_algo(algo.temps_transfert_long_algo) ,temps_attente_algo(algo.temps_attente_algo) ,temps_transfert_court_matSm(algo.temps_transfert_court_matSm),temps_transfert_long_matSm(algo.temps_transfert_long_matSm) @@ -454,6 +457,7 @@ Algori::Algori (const Algori& algo) : ,temps_transfert_court_contact(algo.temps_transfert_court_contact) ,temps_transfert_long_contact(algo.temps_transfert_long_contact) ,temps_attente_contact(algo.temps_attente_contact) + ,inter_transfer(),inter_transfer2() #endif //---------- stockage pour la transmission des grandeurs consultables ----- @@ -602,37 +606,40 @@ void Algori::Preparation_conteneurs_interne(LesMaillages& lesMail) }; // -- cas des temps cpu - // //------- temps cpu ----- - // Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1) - // Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2) - // Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3) - // Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4) - // Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5) - // Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6) - // Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7) - // Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8) - // Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9) - // Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10) - // Temps_CPU_HZpp temps_CL; // lesTempsCpu(11) - // Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12) - // Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13) - // Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14) - // Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15) - // Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16) - // si calcul //: -// // cas d'un calcul parallèle: // passage des infos entre process -// Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(17) -// Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18) -// Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19) -// Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20) -// Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21) -// Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22) -// Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23) -// Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24) -// Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25) -// Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26) -// Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27) -// Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28) +// //------- temps cpu ----- on garde des temps spécifiques pour chaque algo +// // 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) // Tableau lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties // // via listeVarGlob, mais c'est les variables Temps_CPU_HZpp qui stockent @@ -680,21 +687,23 @@ void Algori::Preparation_conteneurs_interne(LesMaillages& lesMail) listeVarGlob["tpsU_Metriques"]=&lesTempsCpu(14)(1); listeVarGlob["tpsU_chargement"]=&lesTempsCpu(15)(1); listeVarGlob["tpsU_rech_contact"]=&lesTempsCpu(16)(1); + listeVarGlob["tempsCalMasse"]=&lesTempsCpu(17)(1); + listeVarGlob["tempsCalViscoNum"]=&lesTempsCpu(18)(1); #ifdef UTILISATION_MPI // cas d'un calcul parallèle - listeVarGlob["tpsU_transfert_court_inter_cpu_Algo"]=&lesTempsCpu(17)(1); - listeVarGlob["tpsU_attente_inter_cpu_Algo"]=&lesTempsCpu(18)(1); - listeVarGlob["tpsU_transfert_long_inter_cpu_Algo"]=&lesTempsCpu(19)(1); - listeVarGlob["tpsU_transfert_court_inter_cpu_Mat-Smloc"]=&lesTempsCpu(20)(1); - listeVarGlob["tpsU_attente_inter_cpu_Mat-Smloc"]=&lesTempsCpu(21)(1); - listeVarGlob["tpsU_transfert_long_inter_cpu-Mat-Smloc"]=&lesTempsCpu(22)(1); + listeVarGlob["tpsU_transfert_court_inter_cpu_Algo"]=&lesTempsCpu(19)(1); + listeVarGlob["tpsU_attente_inter_cpu_Algo"]=&lesTempsCpu(20)(1); + listeVarGlob["tpsU_transfert_long_inter_cpu_Algo"]=&lesTempsCpu(21)(1); + listeVarGlob["tpsU_transfert_court_inter_cpu_Mat-Smloc"]=&lesTempsCpu(22)(1); + listeVarGlob["tpsU_attente_inter_cpu_Mat-Smloc"]=&lesTempsCpu(23)(1); + listeVarGlob["tpsU_transfert_long_inter_cpu-Mat-Smloc"]=&lesTempsCpu(24)(1); - listeVarGlob["tpsU_transfert_court_inter_cpu_charge"]=&lesTempsCpu(23)(1); - listeVarGlob["tpsU_transfert_long_inter_cpu_charge"]=&lesTempsCpu(24)(1); - listeVarGlob["tpsU_attente_inter_cpu_charge"]=&lesTempsCpu(25)(1); - listeVarGlob["tpsU_transfert_court_inter_cpu_contact"]=&lesTempsCpu(26)(1); - listeVarGlob["tpsU_transfert_long_inter_cpu_contact"]=&lesTempsCpu(27)(1); - listeVarGlob["tpsU_attente_inter_cpu_contact"]=&lesTempsCpu(28)(1); + listeVarGlob["tpsU_transfert_court_inter_cpu_charge"]=&lesTempsCpu(25)(1); + listeVarGlob["tpsU_transfert_long_inter_cpu_charge"]=&lesTempsCpu(26)(1); + listeVarGlob["tpsU_attente_inter_cpu_charge"]=&lesTempsCpu(27)(1); + listeVarGlob["tpsU_transfert_court_inter_cpu_contact"]=&lesTempsCpu(28)(1); + listeVarGlob["tpsU_transfert_long_inter_cpu_contact"]=&lesTempsCpu(29)(1); + listeVarGlob["tpsU_attente_inter_cpu_contact"]=&lesTempsCpu(30)(1); #endif @@ -1534,6 +1543,7 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin ,Mat_abstraite& matglob ) { tempsRaidSmEner.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 @@ -1552,22 +1562,26 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension())); #ifdef UTILISATION_MPI - mpi::request reqs1; - mpi::request reqs2; - mpi::request reqs3; - bool premier_passage = true; + mpi::request reqs1; + mpi::request reqs2; + mpi::request reqs3; + 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 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 - #ifndef UTILISATION_MPI + #ifndef UTILISATION_MPI // cas d'un calcul mono CPU for (int nbMail =1; nbMail<= nbMailMax; 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 @@ -1576,11 +1590,11 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin // aura pas de boucle, (ou plutôt on sortira directement de la boucle // le cas CPU 0 est traité à part int nb_mail_distrib = tab_list_elem_cpu.Taille(); - for (int nbMail =1; nbMail<= nb_mail_distrib; nbMail++) + for (int nbMail =1; nbMail<= nb_mail_distrib; nbMail++,dernier_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 = 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 @@ -1592,7 +1606,7 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin }; temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu - #endif + #endif //calcul de la raideur local et du residu local ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el @@ -1633,8 +1647,7 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin Ass.AssembMatnonSym (matglob,*(resu.raid),el.TableauDdl(),taN); // de la raideur #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) {tempsRaidSmEner.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()); @@ -1667,7 +1680,7 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin // cout << "\n " << *(listeVarGlob["vol_total2D_avec_plan_yz"]) << " " << *(listeVarGlob["vol_total2D_avec_plan_xz"]) // << " " << *(listeVarGlob["vol_total2D_avec_plan_xy"]) << endl; // fin débug - }; + }; // globalisation des temps cpu loi de comp et métrique temps_lois_comportement += el.Temps_lois_comportement(); temps_lois_comportement -= temps_debut_lois_comportement; @@ -1689,70 +1702,124 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin } catch (ErrJacobienNegatif_ElemMeca excep) // cas d'un jacobien négatif "a prendre en compte" - { phase_de_convergence = -5; a_converge = false; return false; } + { + #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; } - catch (ErrNonConvergence_loiDeComportement excep) + { + #ifndef UTILISATION_MPI + phase_de_convergence = -6; a_converge = false; retour = false; + #else + gestion_exception = 2; + #endif + } + catch (ErrNonConvergence_loiDeComportement excep) // cas d'une erreur survenue à cause d'une non convergence pour la résolution // d'une loi de comportement incrémentale - { switch (excep.cas) + { + #ifndef UTILISATION_MPI + switch (excep.cas) {case 1: phase_de_convergence = -8; break; case 0: default : phase_de_convergence = -7; break; }; - a_converge = false; return false; + 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 + tempsRaidSmEner.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; - tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu + { + #ifndef UTILISATION_MPI + tempsRaidSmEner.Arret_du_comptage(); + ErrSortieFinale toto; throw (toto); + #else + gestion_exception = 7; + #endif } catch ( ... ) - { if (ParaGlob::NiveauImpression() >= 1) + { + #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::RaidSmEner(.."; }; - } - // affichage éventuelle de la matrice de raideur et du second membre - 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); - }; - // -- calcul des intégrales éventuelles avec transfert en global - lesMail->Integration(); - // --- debug ------- essai ---- -// cout << "\n *** ener_bulk " << E_bulk; - // --- fin debug ------- essai ---- -// if ((permet_affichage > 6) || (ParaGlob::NiveauImpression() < 10)) -// {string entete = " affichage du second membre (puissance interne) avant condition limites "; -// vglobin.Affiche(); -// }; - if (permet_affichage >3) cout << "\n -- fin calcul second membre et raideur " << flush; + #else + gestion_exception = 8; + #endif + } tempsRaidSmEner.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++) + { int ne = (*il); + // on récupère un signal du process 0 + // on considère qu'il y a eu au moins un passage + 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 + reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + tempsRaidSmEner.Mise_en_route_du_comptage(); + }; + }; + }; + }; + // récupération des grandeurs locales par le proc 0 - if (ParaGlob::Monde()->rank() == 0) - { tempsRaidSmEner.Mise_en_route_du_comptage(); // comptage cpu - // récup du nombre total d'éléments, cumul sur tous les maillages + if (proc_en_cours == 0) + { // récup du nombre total d'éléments, cumul sur tous les maillages int total_elem = distribution_CPU_algo.NB_total_element(); // on va boucler sur les éléments récupérés des différents process // jusqu'au nombre maxi d'élément @@ -1766,71 +1833,111 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu int ne = num_el_et_mail.un; // numero d'identification de l'element int nbMail = 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(); - temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu - mpi::request reqs2 = residu->Irecup_MPI(source, 25); - Mat_pleine* raideur = el.Conteneur_raideur(); - mpi::request reqs3 = raideur->Irecup_MPI(source, 26); - temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + // on regarde s'il s'agit d'une exception + 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(); + mpi::request reqs2 = residu->Irecup_MPI(source, 25); + Mat_pleine* raideur = el.Conteneur_raideur(); + mpi::request reqs3 = raideur->Irecup_MPI(source, 26); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu - temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu - reqs2.wait(); // on attend que le conteneur soit rempli - reqs3.wait(); // on attend que le conteneur soit rempli - temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu + reqs2.wait(); // on attend que le conteneur soit rempli + reqs3.wait(); // on attend que le conteneur soit rempli + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu - Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el - // --- assemblage - Ass.AssemSM (vglobin,*residu,el.TableauDdl(),taN); // du second membre - if (pa.Symetrie_matrice()) - Ass.AssembMatSym (matglob,*raideur,el.TableauDdl(),taN); // de la raideur - else - Ass.AssembMatnonSym (matglob,*raideur,el.TableauDdl(),taN); // de la raideur + tempsRaidSmEner.Mise_en_route_du_comptage(); // comptage cpu + Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el + // --- assemblage + Ass.AssemSM (vglobin,*residu,el.TableauDdl(),taN); // du second membre + if (pa.Symetrie_matrice()) + Ass.AssembMatSym (matglob,*raideur,el.TableauDdl(),taN); // de la raideur + else + Ass.AssembMatnonSym (matglob,*raideur,el.TableauDdl(),taN); // de la raideur + tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu + } + 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::RaidSmEner(.."; + };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::RaidSmEner(.."; + 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++; }; - tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu - // }; - // maintenannt chaque proc i va transmettre au proc 0 les bilans - if (ParaGlob::Monde()->rank() != 0) - { - /* pour info, de plus il faut regarder plus haut le cas des intégralles... - - on part de l'idée que c'est mieux de transmettre petit à petit les grandeurs globales pour quelles suivent le même processus de mise en global - pour chaqu proc i comme pour le proc 0, car l'utilisation de ces grandeurs peut éventuellement être nécessaire tout de suite après ... - - energTotal.Inita(0.); // initialisation des énergies à 0 - energHourglass=0.;energStabiliMembBiel=0.; - volume_total_matiere = 0.; // init - E_bulk = 0.; // init - P_bulk=0.; // init - if (pa.CalVolTotalEntreSurfaceEtPlansRef()) - vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension())); - - */ - } + // à 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) + {tempsRaidSmEner.Mise_en_route_du_comptage(); // comptage cpu + // -- calcul des intégrales éventuelles avec transfert en global + lesMail->Integration(); + + #ifdef UTILISATION_MPI + tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu + // récupération de toutes les énergies par le cpu 0 + Algori::Passage_energiesEtVolumes(); #endif - #ifdef UTILISATION_MPI - tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu - // récupération de toutes les énergies par le cpu 0 - Algori::Passage_energiesEtVolumes(); - tempsRaidSmEner.Mise_en_route_du_comptage(); // fin comptage cpu - #endif - - // -- on transfert en global les énergies internes - Transfert_ParaGlob_energies_internesLoisComp(); - Transfert_ParaGlob_energies_hourglass_bulk_stab(); - // idem pour les volumes entre plans - Transfert_ParaGlob_volume_entre_plans(); - // retour indiquant que tout c'est bien passé - return true ; + tempsRaidSmEner.Mise_en_route_du_comptage(); // fin comptage cpu + // -- on transfert en global les énergies internes + Transfert_ParaGlob_energies_internesLoisComp(); + Transfert_ParaGlob_energies_hourglass_bulk_stab(); + // idem pour les volumes entre plans + Transfert_ParaGlob_volume_entre_plans(); + + // affichage éventuelle de la matrice de raideur et du second membre + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif + 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 + return retour ; }; // calcul du second membre pour tous les maillages ainsi que des énergies totales @@ -2088,6 +2195,7 @@ 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 ; @@ -2105,6 +2213,20 @@ bool Algori::RaidSmEnerContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & v energPenalisation = 0.; if (permet_affichage >3) cout << "\n -- debut calcul second membre et raideur pour le contact " << flush; + #ifdef UTILISATION_MPI + mpi::request reqs1; + mpi::request reqs2; + mpi::request reqs3; + bool premier_passage = true; + + // mise à jour de la liste des contacts pour proc 0: il s'agit des infos minimales + // qui permettent ensuite de faire un assemblage + lesCont->Mise_a_jour_liste_contacts_actif_interProc(); + int proc_en_cours = ParaGlob::Monde()->rank(); + // en // ce sont les proc i>0 qui gèrent les éléments de contact + if (proc_en_cours != 0) + { + #endif // on récupère la liste des éléments de contact LaLIST & listElContact = lesCont->LesElementsDeContact(); LaLIST ::iterator il,ilfin=listElContact.end(); @@ -2121,6 +2243,18 @@ bool Algori::RaidSmEnerContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & v //------ debug // (*il).Affiche(); // ------ fin debug + #ifdef UTILISATION_MPI + // on récupère un signal du process 0 + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + if (premier_passage) {premier_passage = false;} + else // on regarde l'activité , car au début avant le balayage de tous les éléments des tableaux + {if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés + if (reqs2.active()) reqs2.wait(); // car aucun transfert n'a encore été effectué + if (reqs3.active()) reqs3.wait(); // + }; + temps_attente_contact.Arret_du_comptage(); + #endif + ElContact& elcontact = (*il); // pour simplifier Tableau& taN = elcontact.TabNoeud_pour_assemblage(); // tableau de noeuds // calcul effectif de la raideur et résidu locals @@ -2132,6 +2266,7 @@ bool Algori::RaidSmEnerContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & v // (resu.raid)->Affiche1(1,6,1,1,6,1); // (int min_i,int max_i,int pas_i,int min_j,int max_j,int pas_j,int nd) // ------ fin debug + #ifndef UTILISATION_MPI // assemblage // dans le cas où le retour est un pointeur nul, cela signifie qu'il n'y a pas de second membre et raideur calculés if (resu.res != NULL) @@ -2141,6 +2276,36 @@ bool Algori::RaidSmEnerContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & v else Ass.AssembMatnonSym (matglob,*(resu.raid),elcontact.TableauDdlCont(),taN); // de la raideur }; + #else + // cas d'un calcul parallèle, et CPU != 0 + {tempsRaidSmEnerContact.Arret_du_comptage(); + // on va transmettre les infos permettant au proc 0 de récupérer + // l'élément de contact ad hoc et de préparer la place + temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + // on commence par transmettre les infos de l'élément de contact + QuatreEntiers nums; + nums.un = elcontact.Esclave()->Num_Mail(); + nums.deux = elcontact.Esclave()->Num_noeud(); + nums.trois = elcontact.Elfront()->NumUnique(); + if (resu.res != NULL) + {nums.quatre = resu.res->Taille();} + else // sinon resu.res == NULL, on envoie un signal via une taille négative + {nums.quatre = -1;} + + // on transmet les infos permettants de récupérer l'élément de contact + reqs1 = ParaGlob::Monde()->isend(0, 240, nums); + if (resu.res != NULL) + {// puis on transmets le vecteur résidu + reqs2 = resu.res->Ienvoi_MPI(0,250); + //puis la matrice + reqs3 = resu.raid->Ienvoi_MPI(0, 260); + }; + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + tempsRaidSmEnerContact.Mise_en_route_du_comptage(); + }; + + #endif + // globalisation des énergies dues aux frottements energFrottement += elcontact.EnergieFrottement(); energPenalisation += elcontact.EnergiePenalisation(); @@ -2166,7 +2331,14 @@ bool Algori::RaidSmEnerContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & v << " n'est pas prevu !, on ne fait rien et on continue le calcul"; if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::RaidSmEnerContact(.."; }; - } + } + #ifdef UTILISATION_MPI + } // fin du cas des proc i>0 + #endif + + + + // affichage éventuelle de la matrice de raideur et du second membre //------ debug // cout << "\n debug Algori::RaidSmEnerContact "; @@ -2192,6 +2364,103 @@ bool Algori::RaidSmEnerContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & v if (permet_affichage >3) cout << "\n -- fin calcul second membre et raideur pour le contact " << flush; tempsRaidSmEnerContact.Arret_du_comptage(); // temps cpu + +#ifdef UTILISATION_MPI + // récupération des grandeurs locales par le proc 0 + if (ParaGlob::Monde()->rank() == 0) + { tempsRaidSmEnerContact.Mise_en_route_du_comptage(); // comptage cpu + // récup du nombre total d'éléments de contact, cumulé sur tous les maillages + int total_elem_contact = lesCont->Nb_actifs(); + // on va boucler sur les éléments récupérés des différents process +////---debug +//cout << "\n debug Algori::RaidSmEnerContact " +// << "\n total_elem_contact actif = "<irecv(mpi::any_source, 240, nums); + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + temps_attente_contact.Arret_du_comptage(); // fin comptage cpu + int numMailEsclave = nums.un; + int numNoeudEsclave = nums.deux; + int numUnique = nums.trois; + int taille_res = nums.quatre; + // on récupére l'élément de contact + ElContact* elcontact = lesCont->RecupElContactActif + (numMailEsclave,numNoeudEsclave,numUnique); + if (elcontact == NULL ) + {cout << "\n erreur *** en calcul parallele, le proc 0 ne parvient pas a recuperer" + << " l'element de contact pour les infos suivantes: " + << "\n numMailEsclave= "<< numMailEsclave + << " numNoeudEsclave= "<< numNoeudEsclave + << " numUnique= "<< numUnique + << "\n la suite n'est pas possible "; + Sortie(1); + }; + // récupération des conteneurs ad hoc vecteur et raideur + int source = stat.source(); // récupération du numéro de la source + + if (nums.quatre > 0) // s'il est négatif => il n'y a pas eu de résultat venant de l'élément de contact + {// récup uniquement des conteneurs raideurs et résidu (pas forcément remplis, mais de la bonne taille) + Element::ResRaid resRaid = elcontact->Conteneur_ResRaid(); + Vecteur * residu = resRaid.res; + if (residu->Taille() != taille_res ) + {cout << "\n erreur *** en calcul parallele, le proc 0 ne parvient pas a recuperer" + << " la bonne taille pour le résidu de contact avec les infos suivantes: " + << "\n numMailEsclave= "<< numMailEsclave + << " numNoeudEsclave= "<< numNoeudEsclave + << " numUnique= "<< numUnique + << "\n taille_residu transmis : "<Taille() + << "\n ce n'est pas normal ==> erreur " + << "\n on arrete "; + Sortie(1); + }; + + temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + mpi::request reqs2 = residu->Irecup_MPI(source, 250); + Mat_pleine* raideur = resRaid.raid; + mpi::request reqs3 = raideur->Irecup_MPI(source, 260); + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + reqs2.wait(); // on attend que le conteneur soit rempli + reqs3.wait(); // on attend que le conteneur soit rempli + temps_attente_contact.Arret_du_comptage(); // fin comptage cpu + tempsRaidSmEnerContact.Mise_en_route_du_comptage(); // temps cpu + // assemblage + Tableau& taN = elcontact->TabNoeud_pour_assemblage(); // tableau de noeuds + Ass.AssemSM (vglobin,*(residu),elcontact->TableauDdlCont(),taN); // du second membre + if (pa.Symetrie_matrice()) + Ass.AssembMatSym (matglob,*(raideur),elcontact->TableauDdlCont(),taN); // de la raideur + else + Ass.AssembMatnonSym (matglob,*(raideur),elcontact->TableauDdlCont(),taN); // de la raideur + tempsRaidSmEnerContact.Arret_du_comptage(); // fin comptage cpu + }; + // on incrémente le nombre d'élément traité + nb_elem_deja_calcule++; + }; + tempsRaidSmEnerContact.Arret_du_comptage(); // fin comptage cpu + // + }; + + // récupération de toutes les énergies par le cpu 0 + tempsRaidSmEnerContact.Arret_du_comptage(); // fin comptage cpu + Algori::Passage_energiesContact(); + tempsRaidSmEnerContact.Mise_en_route_du_comptage(); +#endif + + tempsRaidSmEnerContact.Mise_en_route_du_comptage(); + // -- on transfert en global les énergies internes + Transfert_ParaGlob_energies_contact(); + tempsRaidSmEnerContact.Arret_du_comptage(); // fin comptage cpu + // retour indiquant que tout c'est bien passé return true ; }; @@ -2205,6 +2474,20 @@ bool Algori::SecondMembreEnergContact(LesContacts * lesCont,Assemblage& Ass,Vect volume_total_matiere = 0.; // init if (permet_affichage >3) cout << "\n -- debut calcul second membre pour le contact " << flush; + #ifdef UTILISATION_MPI + mpi::request reqs1; + mpi::request reqs2; + bool premier_passage = true; + + int proc_en_cours = ParaGlob::Monde()->rank(); + // mise à jour de la liste des contacts pour proc 0: il s'agit des infos minimales + // qui permettent ensuite de faire un assemblage + lesCont->Mise_a_jour_liste_contacts_actif_interProc(); + + // en // ce sont les proc i>0 qui gèrent les éléments de contact + if (proc_en_cours != 0) + { + #endif // on récupère la liste des éléments de contact LaLIST & listElContact = lesCont->LesElementsDeContact(); LaLIST ::iterator il,ilfin=listElContact.end(); @@ -2213,13 +2496,48 @@ bool Algori::SecondMembreEnergContact(LesContacts * lesCont,Assemblage& Ass,Vect {// boucle sur les elements de contact for (il=listElContact.begin();il != ilfin; il++) { if ((*il).Actif()) // on n'intervient que si le contact est actif - { //calcul du residu local + { + #ifdef UTILISATION_MPI + // on récupère un signal du process 0 + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + if (premier_passage) {premier_passage = false;} + else // on regarde l'activité , car au début avant le balayage de tous les éléments des tableaux + {if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés + if (reqs2.active()) reqs2.wait(); // car aucun transfert n'a encore été effectué + }; + temps_attente_contact.Arret_du_comptage(); + #endif + + //calcul du residu local ElContact& elcontact = (*il); // pour simplifier Tableau& taN = elcontact.TabNoeud_pour_assemblage(); // tableau de noeuds //calcul du residu local Vecteur* res = elcontact.SM_charge_contact(); + #ifndef UTILISATION_MPI // assemblage Ass.AssemSM (vglobin,*res,elcontact.TableauDdlCont(),taN); // du second membre + #else + // cas d'un calcul parallèle, et CPU != 0 + {tempsSecondMembreEnergContact.Arret_du_comptage(); + // on va transmettre les infos permettant au proc 0 de récupérer + // l'élément de contact ad hoc et de préparer la place + temps_transfert_long_contact.Mise_en_route_du_comptage(); // comptage cpu + // on commence par transmettre les infos de l'élément de contact + QuatreEntiers nums; + nums.un = elcontact.Esclave()->Num_Mail(); + nums.deux = elcontact.Esclave()->Num_noeud(); + nums.trois = elcontact.Elfront()->NumUnique(); + nums.quatre = res->Taille(); + // on transmet les infos permettants de récupérer l'élément de contact + reqs1 = ParaGlob::Monde()->isend(0, 240, nums); + // puis on transmets le vecteur résidu + reqs2 = res->Ienvoi_MPI(0,250); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + tempsRaidSmEnerContact.Mise_en_route_du_comptage(); + }; + + #endif + // globalisation des énergies dues aux frottements energFrottement += elcontact.EnergieFrottement(); energPenalisation += elcontact.EnergiePenalisation(); @@ -2246,14 +2564,101 @@ bool Algori::SecondMembreEnergContact(LesContacts * lesCont,Assemblage& Ass,Vect if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::SecondMembreEnergContact(.."; }; } - // affichage éventuelle du second membre + + #ifdef UTILISATION_MPI + } // fin du cas des proc i>0 + #endif + + // affichage éventuelle du second membre if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage du second membre uniquement du au contact "; vglobin.Affichage_ecran(entete); }; - - // -- on transfert en global les énergies + + tempsSecondMembreEnergContact.Arret_du_comptage(); // temps cpu + +#ifdef UTILISATION_MPI + // récupération des grandeurs locales par le proc 0 + if (ParaGlob::Monde()->rank() == 0) + { tempsSecondMembreEnergContact.Mise_en_route_du_comptage(); // comptage cpu + // récup du nombre total d'éléments de contact, cumulé sur tous les maillages + int total_elem_contact = lesCont->Nb_actifs(); + // on va boucler sur les éléments récupérés des différents process + // jusqu'au nombre maxi d'élément + int nb_elem_deja_calcule = 0; // init + while (nb_elem_deja_calcule < total_elem_contact) + { // on récupère un résultat de calcul + temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + QuatreEntiers nums; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 240, nums); + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + temps_attente_contact.Arret_du_comptage(); // fin comptage cpu + int numMailEsclave = nums.un; + int numNoeudEsclave = nums.deux; + int numUnique = nums.trois; + int taille_res = nums.quatre; + // on récupére l'élément de contact + ElContact* elcontact = lesCont->RecupElContactActif + (numMailEsclave,numNoeudEsclave,numUnique); + if (elcontact == NULL ) + {cout << "\n erreur *** en calcul parallele, le proc 0 ne parvient pas a recuperer" + << " l'element de contact pour les infos suivantes: " + << "\n numMailEsclave= "<< numMailEsclave + << " numNoeudEsclave= "<< numNoeudEsclave + << " numUnique= "<< numUnique + << "\n la suite n'est pas possible "; + Sortie(1); + }; + // récupération des conteneurs ad hoc vecteur et raideur + int source = stat.source(); // récupération du numéro de la source + + // récup uniquement du conteneur résidu (pas forcément rempli, mais de la bonne taille) + Vecteur* residu = elcontact->Conteneur_Residu(); + + if (residu->Taille() != taille_res ) + {cout << "\n erreur *** en calcul parallele, le proc 0 ne parvient pas a recuperer" + << " la bonne taille pour le résidu de contact avec les infos suivantes: " + << "\n numMailEsclave= "<< numMailEsclave + << " numNoeudEsclave= "<< numNoeudEsclave + << " numUnique= "<< numUnique + << "\n taille_residu transmis : "<Taille() + << "\n ce n'est pas normal ==> erreur " + << "\n on arrete "; + Sortie(1); + }; + + temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + mpi::request reqs2 = residu->Irecup_MPI(source, 250); + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + reqs2.wait(); // on attend que le conteneur soit rempli + temps_attente_contact.Arret_du_comptage(); // fin comptage cpu + tempsSecondMembreEnergContact.Mise_en_route_du_comptage(); // temps cpu + // assemblage + Tableau& taN = elcontact->TabNoeud_pour_assemblage(); // tableau de noeuds + Ass.AssemSM (vglobin,*(residu),elcontact->TableauDdlCont(),taN); // du second membre + tempsSecondMembreEnergContact.Arret_du_comptage(); // fin comptage cpu + // on incrémente le nombre d'élément traité + nb_elem_deja_calcule++; + }; + tempsSecondMembreEnergContact.Arret_du_comptage(); // fin comptage cpu + // + }; + + // récupération de toutes les énergies par le cpu 0 + tempsSecondMembreEnergContact.Arret_du_comptage(); // fin comptage cpu + Algori::Passage_energiesContact(); + tempsSecondMembreEnergContact.Mise_en_route_du_comptage(); +#endif + + tempsSecondMembreEnergContact.Mise_en_route_du_comptage(); + // -- on transfert en global les énergies internes Transfert_ParaGlob_energies_contact(); + tempsSecondMembreEnergContact.Arret_du_comptage(); // fin comptage cpu // affichage éventuelle de la force maxi de contact lesCont->Forces_contact_maxi(aff_iteration); @@ -2279,7 +2684,15 @@ Tableau Algori::Choix_matriciel (int nbddl,Tableau & tab_matglob,LesMaillages * lesMail ,LesReferences* lesRef,const Nb_assemb& nb_casAssemb,LesCondLim* lesCondLim , LesContacts* lescontacts ) - { // tout d'abord le choix de la matrice de stockage + { + // on s'occupe tout d'abord du contact (extérieur à la boucle éventuelle sur + // les matrices ) + int demicontact=0,totalcontact=0,cumulecontact=0; + bool largeur_bande_contact_sup_1 = false; // init + if (lescontacts != NULL) + lescontacts->Largeur_Bande(demicontact,totalcontact,nb_casAssemb,cumulecontact); + + // tout d'abord le choix de la matrice de stockage Tableau tab_enu_matrice_sec; // init tab_enu_matrice_sec.Init_from_list(pa.Type_matrice_secondaire()); @@ -2429,9 +2842,10 @@ Tableau Algori::Choix_matriciel cout << "\n raideur: largeur de bande initiale pour les elements (en ddl) " << total << " "; if (lescontacts!= NULL) {// calcul de la largeur de bande effective en tenant compte du contact - int demic=0,totalc=0,cumule=0; + int demic=demicontact,totalc=totalcontact,cumule=cumulecontact; // on n'intervient que si la largeur en noeud augmente - if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) +// if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) + if (largeur_bande_contact_sup_1) {totalc = std::min(totalc,nbddl); demic = std::min(demic,nbddl); cumule = std::min(cumule,nbddl); @@ -2529,9 +2943,10 @@ Tableau Algori::Choix_matriciel cout << "\n raideur: largeur de bande initiale pour les elements (en ddl) " << total << " "; if (lescontacts!= NULL) {// calcul de la largeur de bande effective en tenant compte du contact - int demic=0,totalc=0,cumule=0; + int demic=demicontact,totalc=totalcontact,cumule=cumulecontact; // on n'intervient que si la largeur en noeud augmente - if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) +// if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) + if (largeur_bande_contact_sup_1) {totalc = std::min(totalc,2*nbddl-1); demic = std::min(demic,nbddl); cumule = std::min(cumule,nbddl); @@ -2696,11 +3111,19 @@ void Algori::Mise_a_jour_Choix_matriciel_contact , LesContacts* lescontacts ,int niveau_substitution ,TroisEntiers* nouvelle_largeur_imposee) { - #ifdef UTILISATION_MPI - // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées - if (ParaGlob::Monde()->rank() != 0) - return ; - #endif + // on s'occupe tout d'abord du contact (extérieur à la boucle éventuelle sur + // les matrices ) + int demicontact=0,totalcontact=0,cumulecontact=0; + bool largeur_bande_contact_sup_1 = false; // init + if (lescontacts != NULL) + largeur_bande_contact_sup_1 = lescontacts->Largeur_Bande(demicontact,totalcontact,nb_casAssemb,cumulecontact); + + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + // la suite ne concerne que le proc 0 qui gère la résolution globale + if (proc_en_cours == 0) + { + #endif // tout d'abord le choix de la matrice de stockage Tableau tab_enu_matrice_sec; // init @@ -2764,11 +3187,12 @@ void Algori::Mise_a_jour_Choix_matriciel_contact ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n)); int ancien_demi = matglob->Nb_colonne(); // calcul de la largeur de bande effective en tenant compte du contact - int demic=0,totalc=0,cumule=0; + int demic=demicontact,totalc=totalcontact,cumule=cumulecontact; int demi = parstock.demi; // init if (nouvelle_largeur_imposee == NULL) // cas où il faut calculer {// on n'intervient que si la largeur en noeud augmente - if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) +// if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) + if (largeur_bande_contact_sup_1) {// la mise à jour dépend du type de contact if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation // on doit augmenter la lb en fonction de cumule, si la largeur en noeud est différente @@ -2833,11 +3257,12 @@ void Algori::Mise_a_jour_Choix_matriciel_contact ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n)); //int demi = matglob->Nb_colonne(); // calcul de la largeur de bande effective en tenant compte du contact - int demic=0,totalc=0,cumule=0; + int demic=demicontact,totalc=totalcontact,cumule=cumulecontact; int total = parstock.total; // init if (nouvelle_largeur_imposee == NULL) // cas où il faut calculer {// on n'intervient que si la largeur en noeud augmente - if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) +// if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) + if (largeur_bande_contact_sup_1) {// la mise à jour dépend du type de contact if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation // on doit augmenter la lb en fonction de cumule @@ -2921,6 +3346,11 @@ void Algori::Mise_a_jour_Choix_matriciel_contact cout << "\n stockage raideur " << enumatrice << " taille (entiers) :" << matglob->Place() << endl; }; + #ifdef UTILISATION_MPI + }; // fin du cas proc 0 + #endif + + }; // choix de la matrice de la matrice de masse globale @@ -3387,12 +3817,6 @@ Mat_abstraite* Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite (int nbddl,Mat_abstraite* mat_mass,LesMaillages * lesMail,LesReferences* lesRef ,const Nb_assemb& nb_casAssemb, LesContacts* lescontacts) { - #ifdef UTILISATION_MPI - // cas d'un calcul //, seule la matrice du CPU 0 est concernée - if (ParaGlob::Monde()->rank() != 0) - return NULL; - #endif - //// préparation pour le cas particulier : pa.ContactType() == 1 // int contact_type_1_et_maitre_deformable = false; @@ -3412,7 +3836,19 @@ Mat_abstraite* Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite // il n'y a rien n'a faire {return NULL;} else // sinon on statut en fonction du type existant de matrice - { // en fait il n'y a que deux cas très différents: + { // .. on va utiliser des infos de contact, on va en préliminaire + // .. récupérer ces infos + int demicontact=0,totalcontact=0,cumulecontact=0; + bool largeur_bande_contact_sup_1 = lescontacts->Largeur_Bande(demicontact,totalcontact,nb_casAssemb,cumulecontact); + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + // la suite ne concerne que le proc 0 qui gère la résolution globale + if (proc_en_cours != 0) + {return NULL;} // retour par défaut + // pour le proc 0 on continue + #endif + + // en fait il n'y a que deux cas très différents: // soit on est en diagonal, et on doit peut-être passer dans un autre type // de stockage // soit ce n'est pas du diagonal, et on regarde s'il faut agrandir @@ -3434,12 +3870,13 @@ Mat_abstraite* Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite parstock.nbass = nb_casAssemb; parstock.demi = parstock.total = 1; // tout est diagonal - int demic=0,totalc=0,cumule=0; + int demic=demicontact,totalc=totalcontact,cumule=cumulecontact; int demi=0,total=0; // int ancien_lb = mat_mass->Nb_colonne(); //-- dans tous les cas, à minima il faut passer en tridiagonale - if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) +// if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) + if (largeur_bande_contact_sup_1) { demi = 1 + cumule; // c'est donc toute la largeur hors diag que l'on ajoute total = 1 + 2 * cumule; } @@ -3617,10 +4054,11 @@ Mat_abstraite* Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n)); int ancien_demi = mat_mass->Nb_colonne(); // calcul de la largeur de bande effective en tenant compte du contact - int demic=0,totalc=0,cumule=0; + int demic=demicontact,totalc=totalcontact,cumule=cumulecontact; int demi = parstock.demi; // init // on n'intervient que si la largeur en noeud augmente - if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) +// if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) + if (largeur_bande_contact_sup_1) {// la mise à jour dépend du type de contact if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation // on doit augmenter la lb en fonction de cumule, si la largeur en noeud est différente @@ -3679,10 +4117,11 @@ Mat_abstraite* Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n)); //int demi = matglob->Nb_colonne(); // calcul de la largeur de bande effective en tenant compte du contact - int demic=0,totalc=0,cumule=0; + int demic=demicontact,totalc=totalcontact,cumule=cumulecontact; int total = parstock.total; // init // on n'intervient que si la largeur en noeud augmente - if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) +// if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule)) + if (largeur_bande_contact_sup_1) {// la mise à jour dépend du type de contact if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation // on doit augmenter la lb en fonction de cumule @@ -3770,6 +4209,8 @@ Mat_abstraite* Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite if (change_stockage) {return mat_mass;} else {return NULL;}; + + }; // calcul la matrice de masse @@ -3778,7 +4219,8 @@ void Algori::Cal_matrice_masse(LesMaillages * lesMail,Assemblage& Ass ,Mat_abstraite& mat_mass ,const DiversStockage* divStoc,LesReferences* lesRef ,const Enum_ddl & N_ddl ,LesFonctions_nD* lesFonctionsnD) -{ bool use_diagonale = false; // par défaut on n'utilise pas de stockage diagonal +{ tempsCalMasse.Mise_en_route_du_comptage(); + bool use_diagonale = false; // par défaut on n'utilise pas de stockage diagonal if ( (mat_mass.Type_matrice() == DIAGONALE) || (pa.Type_calcul_masse() == MASSE_DIAG_COEF_EGAUX) || (pa.Type_calcul_masse() == MASSE_DIAG_COEF_VAR) @@ -3861,6 +4303,7 @@ void Algori::Cal_matrice_masse(LesMaillages * lesMail,Assemblage& Ass { string entete = " affichage de la matrice masse "; mat_mass.Affichage_ecran(entete); }; + tempsCalMasse.Arret_du_comptage(); }; @@ -3876,7 +4319,7 @@ void Algori::Ajout_masses_ponctuelles(LesMaillages * lesMail,Assemblage& Ass,Mat if (ParaGlob::Monde()->rank() != 0) return ; #endif - + tempsCalMasse.Mise_en_route_du_comptage(); // prise en compte de masses ponctuelles int dima = ParaGlob::Dimension(); // dans le cas où on est en axisymétrie il faut diminuer de 1 @@ -4033,7 +4476,7 @@ void Algori::Ajout_masses_ponctuelles(LesMaillages * lesMail,Assemblage& Ass,Mat }; }; // ---- fin cas des masses concentrées ----- - + tempsCalMasse.Arret_du_comptage(); }; // définition de la matrice de viscosité numérique, dans le cas d'une approximation @@ -4050,7 +4493,7 @@ Mat_abstraite* Algori::Cal_mat_visqueux_num_expli(const Mat_abstraite& mat_mass, if (ParaGlob::Monde()->rank() != 0) return mat_C_pt; #endif - + tempsCalViscoNum.Mise_en_route_du_comptage(); // on regarde s'il ne faut pas redimentionner la matrice: // si inadéquation: on supprime la matrice C existante if (inita) @@ -4151,6 +4594,8 @@ Mat_abstraite* Algori::Cal_mat_visqueux_num_expli(const Mat_abstraite& mat_mass, break; // dans les autres cas on ne fait rien }; + + tempsCalViscoNum.Arret_du_comptage(); return mat_C_pt; // retour de la matrice }; @@ -4164,7 +4609,7 @@ void Algori::CalculEnContinuMatriceViscositeCritique(const Mat_abstraite& mat_ma if (ParaGlob::Monde()->rank() != 0) return ; #endif - + tempsCalViscoNum.Mise_en_route_du_comptage(); // ---- on commence par calculer (omega_0)^2 qui représente la plus basse fréquence double omega02=0.; // init switch (opt_cal_C_critique) @@ -4283,7 +4728,7 @@ void Algori::CalculEnContinuMatriceViscositeCritique(const Mat_abstraite& mat_ma mat_C_pt = mat_mass; mat_C_pt *= viscosite * ampli_visco; - + tempsCalViscoNum.Arret_du_comptage(); }; @@ -4297,7 +4742,7 @@ void Algori::Cal_mat_visqueux_num_stat(Mat_abstraite& mat_glob,Vecteur& forces_v if (ParaGlob::Monde()->rank() != 0) return ; #endif - + tempsCalViscoNum.Mise_en_route_du_comptage(); // le fonctionnement n'est pas identique au cas explicite switch (pa.Amort_visco_artificielle()) {case 1 : // cas d'un amortissement de Rayleigh classique @@ -4338,7 +4783,7 @@ void Algori::Cal_mat_visqueux_num_stat(Mat_abstraite& mat_glob,Vecteur& forces_v << pa.Amort_visco_artificielle() << " celui-ci n'est pas disponible en statique, on n'en tient pas compte ! " << flush; }; - + tempsCalViscoNum.Arret_du_comptage(); }; diff --git a/Algo/AlgoRef/Algori.h b/Algo/AlgoRef/Algori.h index d0b5448..d21c859 100644 --- a/Algo/AlgoRef/Algori.h +++ b/Algo/AlgoRef/Algori.h @@ -739,20 +739,26 @@ class Algori 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(17) - Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18) - Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19) - Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20) - Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21) - Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22) - Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23) - Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24) - Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25) - Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26) - Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27) - Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28) + 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) + + // des conteneurs de passage utilisés par Algori::Gestion_stockage_et_renumerotation_avec_contact + Vecteur inter_transfer; // un conteneur de transfert Algori::RaidSmEnerContact + Vecteur inter_transfer2; // un conteneur de transfert pour ConnectionCLL de contact #endif Tableau lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties @@ -1303,6 +1309,8 @@ class Algori // cas d'un calcul parallèle, passage des énergies, volumes // a priori utilisée dans le calcul de raideur et second membres void Passage_energiesEtVolumes(); + // passage des énergies liées au contact + void Passage_energiesContact(); #endif diff --git a/Algo/AlgoRef/Algori2.cc b/Algo/AlgoRef/Algori2.cc index 4046428..f93b089 100644 --- a/Algo/AlgoRef/Algori2.cc +++ b/Algo/AlgoRef/Algori2.cc @@ -36,9 +36,13 @@ #include "ReferenceNE.h" #include "ReferenceAF.h" +#include "ExceptionsElemMeca.h" +#include "ExceptionsLoiComp.h" +#include "TypeQuelconqueParticulier.h" #include "AlgoriCombine.h" // pour la sortie base_info + // cas eventuel d'un démarrage à partir de base_info // si inc_voulu est négatif cela signifie que l'on est déjà positionné sur un // incrément voulu et qu'il faut simplement faire la lecture des infos @@ -1025,6 +1029,10 @@ void Algori::LectureCommandeVisu(ParaGlob * paraGlob,LesMaillages * lesMaillages return; } // écriture de l'en-tête + #ifdef UTILISATION_MPI + // cas d'un calcul //, seul le CPU 0 affiche + if (ParaGlob::Monde()->rank() == 0) + #endif if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2)) cout << "\n ======== lecture du fichier de commande de visualisation ========\n"; // -- on définit l'ensemble des incréments possibles, ceci sont stocké dans .BI @@ -1176,6 +1184,10 @@ void Algori::LectureCommandeVisu(ParaGlob * paraGlob,LesMaillages * lesMaillages // avertissement de la fin de lecture du fichier de commande // if (ParaGlob::NiveauImpression() >= 0) + #ifdef UTILISATION_MPI + // cas d'un calcul //, pour l'instant seul le CPU 0 affiche + if (ParaGlob::Monde()->rank() == 0) + #endif if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2)) cout << "\n ======== fin de la lecture du fichier de commande de visualisation ========\n"; // visualisation en fonction de l'activité des différents types de sortie @@ -1429,6 +1441,10 @@ void Algori::VisuAuFilDuCalcul(ParaGlob * paraGlob,LesMaillages * lesMaillages,L << "\n VisuAuFilDuCalcul(..."; return; } + #ifdef UTILISATION_MPI + // cas d'un calcul //, seul le CPU 0 affiche + if (ParaGlob::Monde()->rank() == 0) + #endif // écriture de l'en-tête if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 1)) || (permet_affichage > 2)) {cout << "\n ======== lecture du fichier de commande " @@ -1575,6 +1591,10 @@ void Algori::VisuAuFilDuCalcul(ParaGlob * paraGlob,LesMaillages * lesMaillages,L } // avertissement de la fin de lecture du fichier de commande // if (ParaGlob::NiveauImpression() >= 2) + #ifdef UTILISATION_MPI + // cas d'un calcul //, pour l'instant seul le CPU 0 affiche + if (ParaGlob::Monde()->rank() == 0) + #endif if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n ======== fin de la lecture du fichier de commande de visualisation ========\n"; // initialisation de la sortie vrml (fichier) si la sortie vrml est valide @@ -1882,6 +1902,8 @@ void Algori::Ecriture_base_info sort << "\n tps_SortieFilCalcul "<< tempsSortieFilCalcul; sort << "\n tps_contactMatSmLoc "<< tempsRaidSmEnerContact; sort << "\n tps_contactSmLoc "<< tempsSecondMembreEnergContact; + sort << "\n tempsCalMasse "<< tempsCalMasse; + sort << "\n tempsCalViscoNum "<< tempsCalViscoNum; } else {ptalgocombi->AutreSortieTempsCPU(sort,cas); }; @@ -2084,7 +2106,9 @@ void Algori::Lecture_base_info(ifstream& ent,const int cas) ent >> nom1 >> tempsSortieFilCalcul; ent >> nom1 >> tempsRaidSmEnerContact; ent >> nom1 >> tempsSecondMembreEnergContact; - + ent >> nom1 >> tempsCalMasse; + ent >> nom1 >> tempsCalViscoNum; + // --- b) parties extérieures à l'algo ent >> nom1 >> temps_CL; ent >> nom1 >> temps_CLL; diff --git a/Algo/AlgoRef/Algori4.cc b/Algo/AlgoRef/Algori4.cc index 6808737..74e9f0c 100644 --- a/Algo/AlgoRef/Algori4.cc +++ b/Algo/AlgoRef/Algori4.cc @@ -405,35 +405,39 @@ void Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(L }; // //------- temps cpu ----- -// Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1) -// Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2) -// Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3) -// Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4) -// Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5) -// Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6) -// Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7) -// Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8) -// Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9) -// Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10) -// Temps_CPU_HZpp temps_CL; // lesTempsCpu(11) -// Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12) -// Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13) -// Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14) -// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15) -// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16) -// si calcul // -//Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(17) -//Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18) -//Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19) -//Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20) -//Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21) -//Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22) -//Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23) -//Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24) -//Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25) -//Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26) -//Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27) -//Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28) +// // 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) // // Tableau lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties @@ -489,29 +493,31 @@ void Algori::Temps_CPU_HZpp_to_lesTempsCpu lesTempsCpu(15)(1)= temps_chargement.Temps_CPU_User(); temps_rech_contact = contact.Temps_cpu_Contact(); lesTempsCpu(16)(1)= temps_rech_contact.Temps_CPU_User(); + lesTempsCpu(17)(1)= tempsCalMasse.Temps_CPU_User(); + lesTempsCpu(18)(1)= tempsCalViscoNum.Temps_CPU_User(); #ifdef UTILISATION_MPI // cas des temps de l'algorithme - lesTempsCpu(17)(1)= temps_transfert_court_algo.Temps_CPU_User(); - lesTempsCpu(18)(1)= temps_transfert_long_algo.Temps_CPU_User(); - lesTempsCpu(19)(1)= temps_attente_algo.Temps_CPU_User(); + lesTempsCpu(19)(1)= temps_transfert_court_algo.Temps_CPU_User(); + lesTempsCpu(20)(1)= temps_transfert_long_algo.Temps_CPU_User(); + lesTempsCpu(21)(1)= temps_attente_algo.Temps_CPU_User(); // des mat et SM locaux - lesTempsCpu(20)(1)= temps_transfert_court_matSm.Temps_CPU_User(); - lesTempsCpu(21)(1)= temps_transfert_long_matSm.Temps_CPU_User(); - lesTempsCpu(22)(1)= temps_attente_matSm.Temps_CPU_User(); + lesTempsCpu(22)(1)= temps_transfert_court_matSm.Temps_CPU_User(); + lesTempsCpu(23)(1)= temps_transfert_long_matSm.Temps_CPU_User(); + lesTempsCpu(24)(1)= temps_attente_matSm.Temps_CPU_User(); // du chargement temps_transfert_court_charge = charge.Temps_transfert_court(); - lesTempsCpu(23)(1)= temps_transfert_court_charge.Temps_CPU_User(); + lesTempsCpu(25)(1)= temps_transfert_court_charge.Temps_CPU_User(); temps_transfert_long_charge = charge.Temps_transfert_long(); - lesTempsCpu(24)(1)= temps_transfert_long_charge.Temps_CPU_User(); + lesTempsCpu(26)(1)= temps_transfert_long_charge.Temps_CPU_User(); temps_attente_charge = charge.Temps_attente(); - lesTempsCpu(25)(1)= temps_attente_charge.Temps_CPU_User(); + lesTempsCpu(27)(1)= temps_attente_charge.Temps_CPU_User(); // du contact temps_transfert_court_contact = contact.Temps_transfert_court(); - lesTempsCpu(26)(1)= temps_transfert_court_contact.Temps_CPU_User(); + lesTempsCpu(28)(1)= temps_transfert_court_contact.Temps_CPU_User(); temps_transfert_long_contact = contact.Temps_transfert_long(); - lesTempsCpu(27)(1)= temps_transfert_long_contact.Temps_CPU_User(); + lesTempsCpu(29)(1)= temps_transfert_long_contact.Temps_CPU_User(); temps_attente_contact = contact.Temps_attente(); - lesTempsCpu(28)(1)= temps_attente_contact.Temps_CPU_User(); + lesTempsCpu(30)(1)= temps_attente_contact.Temps_CPU_User(); #endif }; @@ -522,9 +528,9 @@ void Algori::Temps_CPU_HZpp_to_lesTempsCpu Tableau & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau & lesTsCpu) { // test éventuel de la taille du tableau #ifdef MISE_AU_POINT - if (lesTsCpu.Taille() != 10) + if (lesTsCpu.Taille() != 18) {cout << "\n erreur de dim de tableau: dim lesTsCpu= " << lesTsCpu.Taille() - << " au lieu de 10 !! " + << " au lieu de 18 !! " << "\n Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(... " ; Sortie(1); }; @@ -541,19 +547,21 @@ Tableau & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau < lesTsCpu(8) += tempsSortieFilCalcul; // conversion de long long en double lesTsCpu(9) += tempsRaidSmEnerContact; // conversion de long long en double lesTsCpu(10) += tempsSecondMembreEnergContact; // conversion de long long en double + lesTsCpu(17) += tempsCalMasse; // conversion de long long en double + lesTsCpu(18) += tempsCalViscoNum; // conversion de long long en double #ifdef UTILISATION_MPI - lesTsCpu(17) += temps_transfert_court_algo; - lesTsCpu(18) += temps_transfert_long_algo; - lesTsCpu(19) += temps_attente_algo; - lesTsCpu(20) += temps_transfert_court_matSm; - lesTsCpu(21) += temps_transfert_long_matSm; - lesTsCpu(22) += temps_attente_matSm; - lesTsCpu(23) += temps_transfert_court_charge; - lesTsCpu(24) += temps_transfert_long_charge; - lesTsCpu(25) += temps_attente_charge; - lesTsCpu(26) += temps_transfert_court_contact; - lesTsCpu(27) += temps_transfert_long_contact; - lesTsCpu(28) += temps_attente_contact; + lesTsCpu(19) += temps_transfert_court_algo; + lesTsCpu(20) += temps_transfert_long_algo; + lesTsCpu(21) += temps_attente_algo; + lesTsCpu(22) += temps_transfert_court_matSm; + lesTsCpu(23) += temps_transfert_long_matSm; + lesTsCpu(24) += temps_attente_matSm; + lesTsCpu(25) += temps_transfert_court_charge; + lesTsCpu(26) += temps_transfert_long_charge; + lesTsCpu(27) += temps_attente_charge; + lesTsCpu(28) += temps_transfert_court_contact; + lesTsCpu(29) += temps_transfert_long_contact; + lesTsCpu(30) += temps_attente_contact; #endif // retour return lesTsCpu; @@ -579,6 +587,8 @@ void Algori::Arret_du_comptage_CPU() temps_metrique_K_SM.Arret_du_comptage(); temps_chargement.Arret_du_comptage(); temps_rech_contact.Arret_du_comptage(); + tempsCalMasse.Arret_du_comptage(); + tempsCalViscoNum.Arret_du_comptage(); #ifdef UTILISATION_MPI temps_transfert_court_algo.Arret_du_comptage(); temps_transfert_long_algo.Arret_du_comptage(); @@ -700,6 +710,14 @@ void Algori::Sortie_temps_cpu(const LesCondLim& lesCondLim << ".("<< std::setw(nbdigit) << (100*temps_CLL.Temps_CPU_User()/total_cpu) << " % ) " << temps_CLL.Temps_CPU_User_milli() ; + sort_cpu << "\n tempsCalMasse " + << ".("<< std::setw(nbdigit) << (100*tempsCalMasse.Temps_CPU_User()/total_cpu) << " % ) " + << tempsCalMasse.Temps_CPU_User_milli() + ; + sort_cpu << "\n tempsCalViscoNum " + << ".("<< std::setw(nbdigit) << (100*tempsCalViscoNum.Temps_CPU_User()/total_cpu) << " % ) " + << tempsCalViscoNum.Temps_CPU_User_milli() + ; sort_cpu << "\n tps_ResSystLineaire " << "("<< std::setw(nbdigit) << (100*tempsResolSystemLineaire.Temps_CPU_User()/total_cpu) << " % ) " @@ -979,36 +997,82 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul ,Tableau & tab_mato,const Nb_assemb& nb_casAssemb ,LesContacts* lescontacts,int niveau_substitution) { - #ifdef UTILISATION_MPI - // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées - // donc s'il s'agit d'un CPU différent, on revient immédiatement - if (ParaGlob::Monde()->rank() != 0) - return false; - #endif + bool retour = false; // init pas de changement a priori au niveau des matrices + // récup des connexions entre noeud dues aux contacts + list & listCondLine= lescontacts->ConnectionCLL(); + int taille_listCondLine=listCondLine.size(); // init + + #ifdef UTILISATION_MPI + // il faut que tous les proc effectuent la renumérotation, il faut donc transmettre les conditions linéaires de contact + int proc_en_cours = ParaGlob::Monde()->rank(); + // seule le proc 0 a récupérer la liste complète des conditions linéaires + int taille_conteneur=0; // init + temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu + if (proc_en_cours == 0) + { //transmission au cpu i >0 + // pour cela on va utiliser un conteneur intermédiaire + // on calcul la taille nécessaire pour le conteneur (a découper éventuellement ??) + taille_conteneur=0; + list ::iterator il,ilfin = listCondLine.end(); + for (il = listCondLine.begin();il != ilfin;il++) + taille_conteneur += (*il).Taille_Pack(); + inter_transfer2.Change_taille(taille_conteneur); // le conteneur + // on rempli le conteneur + int rang = 1; // init + for (il = listCondLine.begin();il != ilfin;il++) + rang = (*il).Pack_vecteur(inter_transfer2,rang); + }; + // on transfert + broadcast(*ParaGlob::Monde(), taille_conteneur, 0); + if (proc_en_cours != 0) + inter_transfer2.Change_taille(taille_conteneur); + // le proc 0 transfert le tableau + inter_transfer2.Broadcast(0); + if (proc_en_cours != 0) + {// l'objectif ici est de récupérer les conditions linéaires + // pour chaque cpu i>0 + listCondLine.clear();// + // on va remplir la liste des conditions limites + int rang = 1; // init + while (rang != 0) + { Condilineaire condi; // une condition intermédiaire + rang = condi.UnPack_vecteur(*lesMail,inter_transfer2,rang, + &LesMaillages::Noeud_LesMaille); + listCondLine.push_back(condi); + }; + // on met à jour la taille de la liste, car utilisée ensuite dans des tests + taille_listCondLine=listCondLine.size(); + }; + temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu + #endif TroisEntiers nevez_largeurs; - bool retour = false; // init pas de changement a priori au niveau des matrices if (premier_calcul) {// si demandé, renumérotation en fonction des éléments en contact if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation()) { // récup des connexions entre noeud dues aux contacts - list & listCondLine= lescontacts->ConnectionCLL(); - if (listCondLine.size() > 0) //cas où il faut en tenir compte - {// récup des connexions entre noeuds dues aux CLL externes + if (taille_listCondLine > 0) //cas où il faut en tenir compte + {bool calcul_ok = false; // init + // récup des connexions entre noeuds dues aux CLL externes Tableau > tabCLL(lesCondLim->ConnectionCLL(lesMail,lesRef)); int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); // tabCLL(tailtabCLL+1) = listCondLine; // ajout de la partie contact Tableau & tabCLL_contact = tabCLL(tailtabCLL+1); // pour simplifier - tabCLL_contact.Change_taille(listCondLine.size()); + tabCLL_contact.Change_taille(taille_listCondLine); list ::iterator il,ilfin = listCondLine.end(); int i=1; for (il = listCondLine.begin();il != ilfin;il++,i++) tabCLL_contact(i) = (*il); + #ifdef UTILISATION_MPI + // seule le proc 0 affiche + if (proc_en_cours == 0) + #endif if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation en tenant compte des elements de contact "; + // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage - bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); + calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation {//lesMail->MiseAJourPointeurAssemblage(nb_casAssemb);// mise a jour des pointeurs d'assemblage // il faut regarder un peu partout: élément, frontière etc @@ -1036,9 +1100,9 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul {if (nouvelle_situation_contact) {if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation()) { // récup des connexions entre noeud dues aux contacts - list & listCondLine= lescontacts->ConnectionCLL(); - if (listCondLine.size() > 0) //cas où il faut en tenir compte - {// récup des connexions entre noeuds dues aux CLL externes: comme les cll ont été mises à jour + if (taille_listCondLine > 0) //cas où il faut en tenir compte + { bool calcul_ok = false; // init + // récup des connexions entre noeuds dues aux CLL externes: comme les cll ont été mises à jour // on récupère directement le tableau Tableau > tabCLL(lesCondLim->Tab_CLinApplique()); int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); @@ -1049,10 +1113,14 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul int i=1; for (il = listCondLine.begin();il != ilfin;il++,i++) tabCLL_contact(i) = (*il); + #ifdef UTILISATION_MPI + // seule le proc 0 affiche + if (proc_en_cours == 0) + #endif if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation en tenant compte d'un changement de contact "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage - bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); + calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation { // on met à jour le tableau indice pour LesContacts @@ -1078,8 +1146,9 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul else {retour = false; }; }; //-- fin du cas si ce n'est pas un premier calcul - // retour - return retour; + + // retour + return retour; // correct uniquement pour le proc 0, les autres procs ne s'en servent pas à priori }; @@ -1440,7 +1509,8 @@ Tableau Algori::New_tous_les_Algo // cas d'un calcul parallèle, passage des énergies, volumes // a priori utilisée dans le calcul de raideur et second membres void Algori::Passage_energiesEtVolumes() - { mpi::request reqs1; + { tempsRaidSmEner.Mise_en_route_du_comptage(); // fin comptage cpu + mpi::request reqs1; bool premier_passage = true; // récupération de toutes les énergies par le cpu 0 @@ -1457,6 +1527,7 @@ Tableau Algori::New_tous_les_Algo dim_tav_double += vol_total2D_avec_plan_ref(i).Dimension(); Vecteur v_val_inter(8+dim_tav_double); int num_process = ParaGlob::Monde()->rank(); + tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu if (num_process != 0) {temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu //on rempli le vecteur de passage @@ -1531,6 +1602,71 @@ Tableau Algori::New_tous_les_Algo // ////------------- fin debug -------- }; + + // passage des énergies liées au contact + void Algori::Passage_energiesContact() + { mpi::request reqs1; + bool premier_passage = true; + + // récupération de toutes les énergies par le cpu 0 + // on dit à tous les process d'attendre sauf le master + + // on crée un vecteur intermédiaire pour le passage d'information + Vecteur v_val_inter(4); + int num_process = ParaGlob::Monde()->rank(); + if (num_process != 0) + {temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + //on rempli le vecteur de passage + v_val_inter(1) =energFrottement.EnergieElastique(); + v_val_inter(2) =energFrottement.DissipationPlastique(); + v_val_inter(3) =energFrottement.DissipationVisqueuse(); + v_val_inter(4)=energPenalisation; +// //------------- debug -------- +// cout << "\n debug Algori::Passage_energiesContact() num_process= "<< num_process; +// cout << "\n v_val_inter= "<size(); + for (int i=1;i lesTsCpu(10); // init + Tableau lesTsCpu(18); // init // on passe en revue tous les algorithmes et on cumule les temps cpu int nb_algo = tab_algo.Taille(); @@ -909,32 +909,40 @@ void AlgoriCombine::AutreSortieTempsCPU(ofstream& sort,const int ) const //Algori::Ecriture_base_info(ofstream& sort,const int cas /// ----> pour rappel: // //------- temps cpu ----- - // Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1) - // Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2) - // Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3) - // Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4) - // Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5) - // Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6) - // Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7) - // Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8) - // Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9) - // Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10) - // Temps_CPU_HZpp temps_CL; // lesTempsCpu(11) - // Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12) - // Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13) - // Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14) - // Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15) - // Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16) - // cas d'un calcul parallèle: // passage des infos entre process -// Temps_CPU_HZpp temps_transfert_court ; // lesTempsCpu(17) -// Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(18) -// Temps_CPU_HZpp temps_attente ; // lesTempsCpu(19) -// Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(20) -// Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(21) -// Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(22) -// Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(23) -// Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(24) -// Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(25) +// // 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); @@ -945,6 +953,8 @@ void AlgoriCombine::AutreSortieTempsCPU(ofstream& sort,const int ) const 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); }; diff --git a/Algo/AlgorithmeCombiner/AlgoriCombine2.cc b/Algo/AlgorithmeCombiner/AlgoriCombine2.cc index 2cfc186..0e6dfea 100755 --- a/Algo/AlgorithmeCombiner/AlgoriCombine2.cc +++ b/Algo/AlgorithmeCombiner/AlgoriCombine2.cc @@ -51,7 +51,7 @@ void AlgoriCombine::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc index 63e61fa..514127f 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc @@ -961,7 +961,7 @@ void AlgoriRungeKutta::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc index ebc3523..d6f10c0 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc @@ -803,7 +803,7 @@ void AlgoriDynaExpli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc index 2d38395..e1ff6bd 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc @@ -294,7 +294,7 @@ void AlgoriDynaExpli_zhai::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * les #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc index e76fd5f..46c1b31 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc @@ -283,7 +283,7 @@ void Algori_chung_lee::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc index 6dda520..5509b50 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc @@ -1306,16 +1306,17 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage, - Charge* charge,LesCondLim* lesCondLim,LesContacts* lescontacts + Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats) { // INITIALISATION globale tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(RELAX_DYNA); // transfert info #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); tempsInitialisation.Arret_du_comptage(); // temps cpu temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); @@ -1361,7 +1362,7 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // dans le cas où l'on calcul des contraintes et/ou déformation et/ou un estimateur d'erreur // à chaque incrément, initialisation tenuXVG.Change_taille(3);tenuXVG(1)=X1;tenuXVG(2)=V1;tenuXVG(3)=GAMMA1; - prepa_avec_remont = Algori::InitRemont(lesMail,lesRef,diversStockage,charge,lesCondLim,lescontacts,resultats); + prepa_avec_remont = Algori::InitRemont(lesMail,lesRef,diversStockage,charge,lesCondLim,lesContacts,resultats); if ( prepa_avec_remont)// remise enservice des ddl du pab {lesMail->Inactive_ddl(); lesMail->Active_un_type_ddl_particulier(X1);}; // dans le cas de l'algorithme de relaxation dynamique, le temps est normalement imposé à 1., donc n'intervient pas @@ -1481,12 +1482,12 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, { // definition des elements de frontiere, ces elements sont utilises pour le contact lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_t); // // initialisation des zones de contacts éventuelles - lescontacts->Init_contact(*lesMail,*lesRef,lesFonctionsnD); + lesContacts->Init_contact(*lesMail,*lesRef,lesFonctionsnD); // verification qu'il n'y a pas de contact avant le premier increment de charge - lescontacts->Verification(); + lesContacts->Verification(); // definition des elements de contact eventuels // et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact) - lescontacts->DefElemCont(0.); // au début le déplacement des noeuds est nul + lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul if (pa.ContactType() == 4) // cas particulier du type 4 de contact où on utilise les forces internes {// def d'un type générique, utilisé pour le transfert des forces internes, vers les conteneurs noeuds Coordonnee coor(ParaGlob::Dimension()); // un type coordonnee typique @@ -1506,7 +1507,7 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // ouverture de base info entreePrinc->Ouverture_base_info("lecture"); this->Lecture_base_info(cas ,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage - ,charge,lesCondLim,lescontacts,resultats,(this->Num_restart())); + ,charge,lesCondLim,lesContacts,resultats,(this->Num_restart())); icharge = this->Num_restart();//+1; // récup du pas de temps, proposé par l'utilisateur, initialisation et vérif / pas critique this->Gestion_pas_de_temps(true,lesMail,2); // 2 signifie cas courant @@ -1555,7 +1556,7 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, 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); + ,charge,lesCondLim,lesContacts,resultats,OrdreVisu::INCRE_0); } else { // sinon on se place dans le fichier à la position du restart @@ -1582,20 +1583,20 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // ici le numéro d'assemblage est celui de X car on projette bien sur des vitesses virtuelles c-a-d ddl X*. #ifdef UTILISATION_MPI // seule le process 0 s'occupe de la sortie - if (ParaGlob::Monde()->rank() == 0) + if (proc_en_cours == 0) #endif if (ParaGlob::NiveauImpression() > 2) cout << "\n matrice masse principale: "; mat_masse = Choix_matrice_masse(nbddl_X,mat_masse,lesMail,lesRef - ,Ass1.Nb_cas_assemb(),lescontacts,lesCondLim); + ,Ass1.Nb_cas_assemb(),lesContacts,lesCondLim); #ifdef UTILISATION_MPI // seule le process 0 s'occupe de la sortie - if (ParaGlob::Monde()->rank() == 0) + if (proc_en_cours == 0) #endif if (ParaGlob::NiveauImpression() > 2) cout << "\n matrice masse secondaire: "; mat_masse_sauve = Choix_matrice_masse(nbddl_X,mat_masse_sauve,lesMail,lesRef - ,Ass1.Nb_cas_assemb(),lescontacts,lesCondLim); + ,Ass1.Nb_cas_assemb(),lesContacts,lesCondLim); // choix de la résolution if (mat_masse->Type_matrice() == DIAGONALE) // dans le cas d'une matrice diagonale on force la résolution directe quelque soit l'entrée @@ -1670,7 +1671,7 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // ---- initialisation des sauvegardes sur matrice et second membre // ce qui ne correspond à rien ici normalement lesCondLim->InitSauve(Ass3.Nb_cas_assemb()); - // + // lesCondLim->ImposeConLimtdt(lesMail,lesRef,*mat_masse,vglobaal,Ass3.Nb_cas_assemb() ,cas_combi_ddl,vglob_stat); // puis on prépare (si besoin est en fonction du type de matrice) la résolution @@ -1754,7 +1755,7 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // mise à jour au cas où Algori::MiseAJourAlgoMere(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp,diversStockage - ,charge,lesCondLim,lescontacts,resultats); + ,charge,lesCondLim,lesContacts,resultats); tempsInitialisation.Arret_du_comptage(); // temps cpu }; @@ -1766,7 +1767,7 @@ void AlgoriRelaxDyna::MiseAJourAlgo ,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage - ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lescontacts + ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats ) { // INITIALISATION globale @@ -1784,7 +1785,7 @@ void AlgoriRelaxDyna::MiseAJourAlgo // mise à jour au cas où Algori::MiseAJourAlgoMere(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp - ,diversStockage,charge,lesCondLim,lescontacts,resultats); + ,diversStockage,charge,lesCondLim,lesContacts,resultats); // init indicateur Transfert_ParaGlob_AMOR_CINET_VISQUEUX(); tempsMiseAjourAlgo.Arret_du_comptage(); // temps cpu @@ -1803,7 +1804,7 @@ void AlgoriRelaxDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage - ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lescontacts + ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats,Tableau < Fonction_nD* > * tb_combiner) { tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu @@ -1811,7 +1812,9 @@ void AlgoriRelaxDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail // on vérifie que le pas de temps est correcte: on propose le deltat actuel qui sera modifié s'il n'est pas bon double deltat_actuel = pa.Deltat(); pa.Modif_Detat_dans_borne(deltat_actuel); - +#ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); +#endif // récup des entités Assemblage& Ass1 = *Ass1_; @@ -1932,7 +1935,7 @@ Vecteur V_ext(F_int_tdt); if (arret_pilotage) break; // pilotage -> arret du calcul, on sort du switch #ifdef UTILISATION_MPI // seule le process 0 s'occupe de la sortie - if (ParaGlob::Monde()->rank() == 0) + if (proc_en_cours == 0) { #endif // affichage de l'increment de charge @@ -1976,12 +1979,12 @@ Vecteur V_ext(F_int_tdt); if (pa.ContactType()) // traitement différent lors du premier incément calculé (premier passage) puis des passages courants { if (premier_calcul) { // ici delta_X est nulle au premier passage ... on laisse quand même par cohérence avec les autres algo - lescontacts->DefElemCont(delta_X.Max_val_abs()); + lesContacts->DefElemCont(delta_X.Max_val_abs()); } // au début il n'y a pas de déplacement à priori else - { lescontacts->SuppressionDefinitiveElemInactif(); // on supprime les éléments inactifs testés à l'incr prec dans Actualisation() -// lescontacts->Nouveau(lesMail->Max_var_dep_t_a_tdt()); // on rajoute éventuellement de nouveau élément de contact - lescontacts->Nouveau(delta_X.Max_val_abs()); // idem mais je pense plus rapide + { lesContacts->SuppressionDefinitiveElemInactif(); // on supprime les éléments inactifs testés à l'incr prec dans Actualisation() +// lesContacts->Nouveau(lesMail->Max_var_dep_t_a_tdt()); // on rajoute éventuellement de nouveau élément de contact + lesContacts->Nouveau(delta_X.Max_val_abs()); // idem mais je pense plus rapide }; }; }; @@ -1990,7 +1993,7 @@ Vecteur V_ext(F_int_tdt); { if (arret_pilotage) break; // pilotage -> arret du calcul #ifdef UTILISATION_MPI // seule le process 0 s'occupe de la sortie - if (ParaGlob::Monde()->rank() == 0) + if (proc_en_cours == 0) #endif cout << "\n=============================================================================" << "\n ....... re-analyse du contact ........ " @@ -2014,7 +2017,7 @@ Vecteur V_ext(F_int_tdt); lesLoisDeComp->MiseAJour_umat_nbincr(icharge); // init pour les lois Umat éventuelles // mise à jour éventuelle de la matrice de raideur en fonction de l'existence du contact et du type de modèle de contact // if (pa.ContactType()) -// Mise_a_jour_Choix_matriciel_contact(mato,Ass.Nb_cas_assemb(),lescontacts); +// Mise_a_jour_Choix_matriciel_contact(mato,Ass.Nb_cas_assemb(),lesContacts); // --- récupération (initialisation) des ddl position, vitesse et accélération // récupe X_t initiale @@ -2111,9 +2114,10 @@ Vecteur V_ext(F_int_tdt); // affichage ou non de l'itération bool aff_iteration = (pa.freq_affich_iter() > 0) ? (aff_incr && (compteur % pa.freq_affich_iter()==0) &&(compteur!=0)) : false ; +// (aff_incr && (compteur % pa.freq_affich_iter()==0) ) : false ; #ifdef UTILISATION_MPI // seule le process 0 s'occupe de la sortie - if (ParaGlob::Monde()->rank() != 0) aff_iteration=false; + if (proc_en_cours != 0) aff_iteration=false; #endif /* // --- imposition des ddls bloqués @@ -2208,12 +2212,16 @@ Vecteur V_ext(F_int_tdt); // lesMail->Vect_glob_vers_local(TEMPS_t,GAMMA1,acceleration_t,GAMMA1); lesLoisDeComp->MiseAJour_umat_nbiter(compteur); // init pour les lois Umat éventuelles -/* //debug ------ + //debug ------ +// #ifdef UTILISATION_MPI +// if (proc_en_cours == 0) // cas d'un calcul //, seule la matrice du CPU 0 est concernée +// #endif // { cout << "\n ***1 AlgoriRelaxDyna::CalEquilibre( "; -// lesMail->Noeud_LesMaille(1,483).Affiche(); +// cout << "\n X_tdt= "; X_tdt.Affiche(); +//// lesMail->Noeud_LesMaille(1,483).Affiche(); // cout << endl ; // }; -////fin debug ------ */ +//fin debug ------ // mise en place des conditions linéaires lesCondLim->MiseAJour_condilineaire_tdt (pa.Multiplicateur(),lesMail,charge->Increment_de_Temps(),lesRef,charge->Temps_courant() @@ -2227,11 +2235,11 @@ Vecteur V_ext(F_int_tdt); // il faut mettre le contact ici, car il utilise le déplacement de t à tdt { lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_tdt); //s'il n'y a pas if (premier_calcul) - { lescontacts->DefElemCont(delta_X.Max_val_abs()); + { lesContacts->DefElemCont(delta_X.Max_val_abs()); premier_calcul=false;} // au début il n'y a pas de déplacement à priori, on prend 2. * le delta noeud mini else - { lescontacts->SuppressionDefinitiveElemInactif(); // on supprime les éléments inactifs testés à l'incr prec dans Actualisation() - lescontacts->Nouveau(delta_X.Max_val_abs()); // idem mais je pense plus rapide + { lesContacts->SuppressionDefinitiveElemInactif(); // on supprime les éléments inactifs testés à l'incr prec dans Actualisation() + lesContacts->Nouveau(delta_X.Max_val_abs()); // idem mais je pense plus rapide }; }; }; @@ -2241,14 +2249,14 @@ Vecteur V_ext(F_int_tdt); // quand un noeud glisse d'une facette sur une voisine, peut changer la position du noeud // qui est projeté sur la facette dans le cas de l'algorithme cinématique if (((compteur != 0)&&(pa.ContactType()))&&(compteur_demarrage > 0)) - { lescontacts->Actualisation(0); // en particulier: pour le type 4 on a projection + { lesContacts->Actualisation(0); // en particulier: pour le type 4 on a projection // des noeuds sur les facettes maîtres // mise à jour éventuelle des répercussions du contact sur les noeuds en contact - AlgoriRelaxDyna::Repercussion_algo_sur_cinematique(lescontacts,X_tdt,vitesse_tdt); + AlgoriRelaxDyna::Repercussion_algo_sur_cinematique(lesContacts,X_tdt,vitesse_tdt); // lesMail->Vect_loc_vers_glob(TEMPS_tdt,X1,X_tdt,X1); // lesMail->Vect_loc_vers_glob(TEMPS_tdt,V1,vitesse_tdt,V1); // mise à jour éventuelle de la matrice de raideur en fonction du contact -// Mise_a_jour_Choix_matriciel_contact(mato,Ass.Nb_cas_assemb(),lescontacts); +// Mise_a_jour_Choix_matriciel_contact(mato,Ass.Nb_cas_assemb(),lesContacts); }; // -+-+ sinon l'actualisation du contact s'effectue à la fin de l'itération (un peu plus loin) @@ -2291,7 +2299,7 @@ Vecteur V_ext(F_int_tdt); // calcul des reactions de contact éventuelles (contact et frottement) if ((pa.ContactType())&&(compteur_demarrage > 0)) // et des énergies développées pendant le contact {// dans le cas où le calcul est inexploitable (pb dans le calcul) arrêt de la boucle - if (!SecondMembreEnergContact(lescontacts,Ass1,vcontact,aff_iteration)) break; + if (!SecondMembreEnergContact(lesContacts,Ass1,vcontact,aff_iteration)) break; }; F_ext_tdt_prec = F_ext_tdt; // sauvegarde des valeurs de l'itération précédente @@ -2308,31 +2316,23 @@ Vecteur V_ext(F_int_tdt); // on utilise le volume de chaque élément, donc il doit avoir été calculé // -- ** ce qui est le cas au moment du calcul des forces internes // sauf en MPI - #ifdef UTILISATION_MPI - // seule le process 0 s'occupe du calcul de la masse - if (ParaGlob::Monde()->rank() == 0) - { - #endif CalculEnContinuMatriceMasse (relax_vit_acce,lesMail,Ass1,compteur - ,diversStockage,lesRef,X1,premier_calcul,lescontacts + ,diversStockage,lesRef,X1,premier_calcul,lesContacts ,force_recalcul_masse,lesFonctionsnD); - #ifdef UTILISATION_MPI - }; - #endif // calcul des reactions de contact pour les noeuds esclaves // dans le repere absolu ( pour la sortie des infos sur le contact) // et test s'il y a decollement de noeud en contact (pour les contacts actifs) - // mais ici, il n'y a pas de modification des éléments de contact (elles ont été faites dans lescontacts->Actualisation()) + // mais ici, il n'y a pas de modification des éléments de contact (elles ont été faites dans lesContacts->Actualisation()) bool decol=false; // création et init de decol if ((pa.ContactType())&&(compteur_demarrage > 0)) - lescontacts->CalculReaction(vglobin,decol,Ass1.Nb_cas_assemb(),aff_iteration); + lesContacts->CalculReaction(vglobin,decol,Ass1.Nb_cas_assemb(),aff_iteration); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) list *listCondLine = NULL; // init donc sans élément if (((pa.ContactType()==1) || (pa.ContactType()==3))&&(compteur_demarrage > 0)) - listCondLine = &(lescontacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // -- dans le cas d'un amortissement visqueux critique ou // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée @@ -2357,6 +2357,9 @@ Vecteur V_ext(F_int_tdt); /* else { mat_C_pt->Initialise(0.);}; // if (typeCalRelaxation == 2) // CalculEnContinuMatriceViscositeCritique(*mat_masse_sauve,*mat_C_pt,delta_X,vitesse_tdt); */ + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) // cas d'un calcul //, seule la matrice du CPU 0 est concernée + #endif vglobaal -= mat_C_pt->Prod_mat_vec(vitesse_t,forces_vis_num); }; @@ -2386,9 +2389,25 @@ Vecteur V_ext(F_int_tdt); // sauvegarde des reactions aux ddl bloque (uniquement pour les Xi) // lesCondLim->ReacApresCHrepere(vglobin,lesMail,lesRef,Ass3.Nb_cas_assemb(),cas_combi_ddl); +////---- debug +//#ifdef UTILISATION_MPI +// if (proc_en_cours == 0) // cas d'un calcul //, seule la matrice du CPU 0 est concernée +//#endif +//{cout << "\n debug algo relax: mat_masse avec CL"; +// mat_masse->Affiche(); +//} +////--- fin debug // mise en place des conditions limites sur la matrice masse et le second membre lesCondLim->ImposeConLimtdt(lesMail,lesRef,*mat_masse,vglobaal ,Ass3.Nb_cas_assemb(),cas_combi_ddl,vglob_stat); +////---- debug +//#ifdef UTILISATION_MPI +// if (proc_en_cours == 0) // cas d'un calcul //, seule la matrice du CPU 0 est concernée +//#endif +//{cout << "\n debug algo relax: mat_masse après CL"; +// mat_masse->Affiche(); +//} +////--- fin debug // puis on prépare (si besoin est en fonction du type de matrice) la résolution // s'il n'y a pas de condition linéaire et pas de chg de repère, // on peut déjà inverser par exemple la matrice masse @@ -2409,7 +2428,7 @@ Vecteur V_ext(F_int_tdt); bool demande_de_break=false; // pour gestion du break en tenant compte ou non du MPI #ifdef UTILISATION_MPI // seule le process 0 s'occupe de la convergence - if (ParaGlob::Monde()->rank() == 0) + if (proc_en_cours == 0) { #endif // examen de la convergence si nécessaire, utilisant le résidu @@ -2483,7 +2502,7 @@ Vecteur V_ext(F_int_tdt); // 4 ---- calcul des nouvelles accélérations #ifdef UTILISATION_MPI // seule le process 0 fait la résolution globale - if (ParaGlob::Monde()->rank() == 0) + if (proc_en_cours == 0) { #endif // resolution simple (fonction du type de matrice) @@ -2523,9 +2542,12 @@ Vecteur V_ext(F_int_tdt); // ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process acceleration_tdt.Broadcast(0); //// debug -//cout << "\n debug algo relax " -// << " barriere après transfert acceleration_tdt , proc= "<< ParaGlob::Monde()->rank() -// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush; +// if (proc_en_cours == 0) // cas d'un calcul //, seule la matrice du CPU 0 est concernée +// {cout << "\n debug algo relax " +// << " barriere après transfert acceleration_tdt , proc= "<< ParaGlob::Monde()->rank() +// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush; +// cout << "\n acceleration_tdt ";acceleration_tdt.Affiche(); +// }; //// fin debug @@ -2537,8 +2559,13 @@ Vecteur V_ext(F_int_tdt); // << acceleration_tdt << flush; // // fin debug #else -// // debug -// cout << "\n debug algo relax " +//// // debug +// {cout << "\n debug algo relax " +// << " barriere après transfert acceleration_tdt " +// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush; +// cout << "\n acceleration_tdt ";acceleration_tdt.Affiche(); +// }; +//// cout << "\n debug algo relax " // << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage << " acceleration: "; // acceleration_tdt.Affiche(); cout << flush; // // fin debug @@ -2546,7 +2573,7 @@ Vecteur V_ext(F_int_tdt); // effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée lesCondLim->EffMarque(); - if (pa.ContactType()) lescontacts->EffMarque(); + if (pa.ContactType()) lesContacts->EffMarque(); // -- calcul de la vitesse exacte à t+dt selon le schéma DFC avec un delta t =1. vitesse_tdt = vitesse_t + 0.5 * (acceleration_t+acceleration_tdt); @@ -2563,9 +2590,9 @@ Vecteur V_ext(F_int_tdt); // dans le cas ou la recherche de nouveaux contacts est effectuée à chaque itération if (((type_activation_contact== 1) && (pa.ContactType()))&&(compteur_demarrage > 0)) { // actualisation des éléments de contact et éventuellement inactivation d'éléments - lescontacts->Actualisation(0); // si on n'a plus de projection + lesContacts->Actualisation(0); // si on n'a plus de projection // on inactive les éléments de contact qui se relache: testé soit via la réaction - lescontacts->RelachementNoeudcolle(); // ou via la sortie d'une zone d'accostage (dépend de l'algo) + lesContacts->RelachementNoeudcolle(); // ou via la sortie d'une zone d'accostage (dépend de l'algo) }; if (compteur_demarrage != -1) @@ -2614,7 +2641,7 @@ Vecteur V_ext(F_int_tdt); // visualisation éventuelle au fil du calcul: essentiellement la déformée tempsCalEquilibre.Arret_du_comptage(); // on arrête le compteur pour la sortie VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge - ,lesCondLim,lescontacts,resultats,type_incre,(icharge*1000000+compteur)); + ,lesCondLim,lesContacts,resultats,type_incre,(icharge*1000000+compteur)); // on remet les choses dans l'ordre initial tempsCalEquilibre.Mise_en_route_du_comptage(); // on remet en route le compteur lesMail->Vect_glob_vers_local(TEMPS_t,X1,save_X_t,X1); @@ -2634,7 +2661,7 @@ Vecteur V_ext(F_int_tdt); // effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée // car ici on n'est pas passé par cette endroit si l'on a convergé lesCondLim->EffMarque(); - if (pa.ContactType()) lescontacts->EffMarque(); + if (pa.ContactType()) lesContacts->EffMarque(); // mise à jour des indicateurs contrôlés par le tableau: *tb_combiner if (tb_combiner != NULL) // cas d'un contrôle via des fonctions nD @@ -2667,7 +2694,7 @@ Vecteur V_ext(F_int_tdt); { // cas ou on a réussi à trouver un incrément sauvegardé adoc = maintenant icharge int cas=2; this->Lecture_base_info(cas ,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage - ,charge,lesCondLim,lescontacts,resultats,icharge); + ,charge,lesCondLim,lesContacts,resultats,icharge); // comme les conditions limites cinématiques peuvent être différentes en restart // on libére toutes les CL imposées éventuelles lesMail->Libere_Ddl_representatifs_des_physiques(LIBRE); @@ -2693,13 +2720,16 @@ Vecteur V_ext(F_int_tdt); else {// --- sinon calcul correcte pas_de_convergence_pour_l_instant = 0; + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if ((ParaGlob::NiveauImpression() > 0)&&(compteur_demarrage > 0)) cout << " \n ... convergence en " << compteur << " iterations "<< endl ; // traitement du contact dans le cas où son activation n'a pas été faite à chaque itération if ((pa.ContactType()) && (type_activation_contact != 1)) - { lescontacts->Actualisation(0); // actualisation du contact en fonction du dernier incrément + { lesContacts->Actualisation(0); // actualisation du contact en fonction du dernier incrément // mise à jour éventuelle de la matrice de raideur en fonction du contact -// Mise_a_jour_Choix_matriciel_contact(mato,Ass.Nb_cas_assemb(),lescontacts); +// Mise_a_jour_Choix_matriciel_contact(mato,Ass.Nb_cas_assemb(),lesContacts); // réexamen du contact pour voir s'il n'y a pas de nouveau element de contact // en fait on fera au plus deux passages supplémentaire, sinon la boucle peut être infini, // à la fin du second passage, on regarde s'il y a décollement, si oui on relâche et on refait un passage @@ -2707,7 +2737,7 @@ Vecteur V_ext(F_int_tdt); //I)-------------- //cout << "\n avant test: indicCycleContact= " << indicCycleContact << endl; if (indicCycleContact == 0 ) - { if (lescontacts->Nouveau(lesMail->Max_var_dep_t_a_tdt())) + { if (lesContacts->Nouveau(lesMail->Max_var_dep_t_a_tdt())) {indicCycleContact=1;} // on a de nouveau contact on refait le deuxième cycle else // sinon, on n'a pas de nouveau contact, on regarde s'il y a du relachement @@ -2719,7 +2749,7 @@ Vecteur V_ext(F_int_tdt); {indicCycleContact=0;}; // pas de newcontact, ni de relachement donc c'est ok //II)--------------- if (indicCycleContact == 2) - { if (lescontacts->RelachementNoeudcolle()) + { if (lesContacts->RelachementNoeudcolle()) {indicCycleContact=3;} // pour une dernière boucle d'équilibre else {indicCycleContact=0;};// pas de relachement donc ok @@ -2748,11 +2778,11 @@ Vecteur V_ext(F_int_tdt); if (validation_calcul) {// actualisation des ddl et des grandeurs actives de t+dt vers t lesMail->TdtversT(); - lescontacts->TdtversT(); + lesContacts->TdtversT(); // cas du calcul des énergies, passage des grandeurs de tdt à t if (compteur_demarrage != -1) Algori::TdtversT(); // actualisation des éléments de contact et éventuellement suppression - if (pa.ContactType()) lescontacts->Actualisation(0); // des éléments qui ne sont plus en contact + if (pa.ContactType()) lesContacts->Actualisation(0); // des éléments qui ne sont plus en contact if (compteur_demarrage != -1) {// on valide l'activité des conditions limites et condition linéaires lesCondLim->Validation_blocage (lesRef,charge->Temps_courant()); @@ -2781,12 +2811,12 @@ Vecteur V_ext(F_int_tdt); tempsCalEquilibre.Arret_du_comptage(); // on arrête le compteur pour la sortie // sauvegarde de l'incrément si nécessaire Ecriture_base_info(2,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge - ,lesCondLim,lescontacts,resultats,type_incre,icharge); + ,lesCondLim,lesContacts,resultats,type_incre,icharge); // enregistrement du num d'incrément et du temps correspondant list_incre_temps_calculer.push_front(Entier_et_Double(icharge,pa.Variables_de_temps().TempsCourant())); // visualisation éventuelle au fil du calcul VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge - ,lesCondLim,lescontacts,resultats,type_incre,icharge); + ,lesCondLim,lesContacts,resultats,type_incre,icharge); tempsCalEquilibre.Mise_en_route_du_comptage(); // on remet en route le compteur }; }; //- fin de la condition if (compteur_demarrage != -1) @@ -2874,16 +2904,16 @@ void AlgoriRelaxDyna::FinCalcul(ParaGlob * paraGlob,LesMaillages * lesMail, LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage, - Charge* charge,LesCondLim* lesCondLim,LesContacts* lescontacts + Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats) { // passage finale dans le cas d'une visualisation au fil du calcul Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(RELAX_DYNA); // transfert info type_incre = OrdreVisu::DERNIER_INCRE; VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge - ,lesCondLim,lescontacts,resultats,type_incre,icharge); + ,lesCondLim,lesContacts,resultats,type_incre,icharge); // sauvegarde de l'incrément si nécessaire Ecriture_base_info(2,lesMail,lesRef,lesCourbes1D,lesFonctionsnD - ,lesLoisDeComp,diversStockage,charge,lesCondLim,lescontacts + ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts ,resultats,type_incre,icharge); // enregistrement du num d'incrément et du temps correspondant list_incre_temps_calculer.push_front(Entier_et_Double(icharge,pa.Variables_de_temps().TempsCourant())); @@ -2894,7 +2924,7 @@ void AlgoriRelaxDyna::InitCalculMatriceMasse(LesMaillages * lesMail ,Mat_abstraite& mat_mass,Assemblage& Ass ,Mat_abstraite& mat_mass_sauve ,LesFonctions_nD* lesFonctionsnD) - { + {tempsCalMasse.Mise_en_route_du_comptage(); switch (type_calcul_mass) { case 1: // cas historique {// on définit un vecteur de dimension le nombre de noeud = celui de mat_mass / dim @@ -2929,6 +2959,7 @@ void AlgoriRelaxDyna::InitCalculMatriceMasse(LesMaillages * lesMail Sortie(1); }; }; + tempsCalMasse.Arret_du_comptage(); }; @@ -2936,9 +2967,9 @@ void AlgoriRelaxDyna::InitCalculMatriceMasse(LesMaillages * lesMail void AlgoriRelaxDyna::CalculMatriceMasse (const int& relax_vit_acce,LesMaillages * lesMail,Assemblage& Ass , int compteur, const DiversStockage* divStoc,LesReferences* lesRef - ,const Enum_ddl & N_ddl ,LesContacts* lescontacts + ,const Enum_ddl & N_ddl ,LesContacts* lesContacts ,LesFonctions_nD* lesFonctionsnD) -{ +{ tempsCalMasse.Mise_en_route_du_comptage(); int dima = ParaGlob::Dimension(); // dans le cas où on est en axisymétrie il faut diminuer de 1 if (ParaGlob::AxiSymetrie()) @@ -2946,6 +2977,7 @@ void AlgoriRelaxDyna::CalculMatriceMasse int nbddl_X = mat_masse->Nb_ligne(); int nbNoe = nbddl_X / dima; #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); // seule le process 0 s'occupe du calcul de la masse // et celui-ci ne peut pas être le type historique : 1, car le volume de chaque élément // n'est pas dispo (il est dispo dans les processus != 0) @@ -3008,8 +3040,18 @@ void AlgoriRelaxDyna::CalculMatriceMasse break; } case 2: // ---cas ou on utilise la matrice de raideur réelle - // **** le calcul effectif de la matrice masse se fait ici - {mat_masse->Initialise(0.); + // **** le calcul effectif de la matrice masse se fait ici + { + #ifdef UTILISATION_MPI + // 1) partie classique pour K et sm + { + mpi::request reqs1; + mpi::request reqs2; + mpi::request reqs3; + bool premier_passage = true; + + #endif + mat_masse->Initialise(0.); v_mass.Change_taille(nbddl_X); v_mass.Zero(); // idem: v_mass1 un vecteur intermédiaire de calcul if ( ((casMass_relax > 3) && (casMass_relax < 6)) //4-5 cas où on a besoin de deux assemblages @@ -3020,13 +3062,43 @@ void AlgoriRelaxDyna::CalculMatriceMasse matglob->Initialise(0.); // boucle sur les elements - int nbMailMax = lesMail->NbMaillage(); - for (int nbMail =1; nbMail<= nbMailMax; nbMail++) - { int nemax = lesMail->Nombre_element(nbMail); - for (int ne=1; ne<= nemax;ne++) - { //calcul de la raideur local et du residu local + #ifndef UTILISATION_MPI + int nbMailMax = lesMail->NbMaillage(); + // cas d'un calcul mono CPU + for (int nbMail =1; nbMail<= nbMailMax; nbMail++) + {int nemax = lesMail->Nombre_element(nbMail); + for (int ne=1; ne<= nemax;ne++) + { + #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 + const Tableau < list >& tab_list_elem_cpu = distribution_CPU_algo.List_element_CPU_en_cours(); + // la taille est identique à nbMailMax, sauf si c'est le cpu 0, là le tableau est vide et il n'y + // aura pas de boucle, (ou plutôt on sortira directement de la boucle + // le cas CPU 0 est traité à part + int nb_mail_distrib = tab_list_elem_cpu.Taille(); + for (int nbMail =1; 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 = list_elem_cpu.begin();il != ilfin;il++) + { int ne = (*il); + // on récupère un signal du process 0 + tempsCalMasse.Arret_du_comptage(); + temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu + if (premier_passage) {premier_passage = false;} + else // on attend que les transferts soient finis + {reqs1.wait(); + reqs2.wait(); + reqs3.wait(); + }; + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + tempsCalMasse.Mise_en_route_du_comptage(); + + #endif + //calcul de la raideur local et du residu local ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element - Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el ////------- debug --- // if (ne == 15) // cout << "\n debug AlgoriRelaxDyna::CalculMatriceMasse( "; @@ -3039,8 +3111,9 @@ void AlgoriRelaxDyna::CalculMatriceMasse //cout << "\n debug AlgoriRelaxDyna::CalculMatriceMasse( "; //resu.raid->Affiche();cout << endl; ////------ fin debug ----- - - // assemblage + #ifndef UTILISATION_MPI + {// assemblage + Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el if (casMass_relax < 2) // 0 1 : on ne retient que la diagonale { Ass.AssembDiagonale (v_mass,*(resu.raid),el.TableauDdl(),taN);} else if (casMass_relax < 6) // sinon c'est la somme des valeurs absolues de la ligne @@ -3061,26 +3134,143 @@ void AlgoriRelaxDyna::CalculMatriceMasse // cas où on fait un deuxième assemblages if ((casMass_relax > 3) && (casMass_relax < 6)) //4-5 { Ass.AssembDiagonale (v_mass1,*(resu.raid),el.TableauDdl(),taN);}; + }; ////------- debug --- //{cout << "\n debug AlgoriRelaxDyna::CalculMatriceMasse( "; // cout << "\n -- info vecteur masse diagonale sur la raideur uniquement -- "; // Coordonnee3 moy=v_mass.MinMaxMoy(true); //}; ////------ fin debug ----- - }; - }; + #else + // cas d'un calcul parallèle, et CPU != 0 + int num_process = ParaGlob::Monde()->rank(); + if (num_process != 0) + {tempsCalMasse.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()); + // on transmet les numéros d'élément et de maillage + reqs1 = ParaGlob::Monde()->isend(0, 2401, num_el_et_mail); + // puis on transmets le vecteur résidu + reqs2 = resu.res->Ienvoi_MPI(0,2501); + //puis la matrice + reqs3 = resu.raid->Ienvoi_MPI(0, 2601); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + tempsCalMasse.Mise_en_route_du_comptage(); + }; + + #endif + + }; // fin boucle sur les éléments + };// fin boucle sur les maillages - if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 5 )) || (permet_affichage > 2)) - {// on affiche les min max du vecteur - cout << "\n -- info vecteur masse diagonale sur la raideur uniquement -- "; - Coordonnee3 moy=v_mass.MinMaxMoy(true); - }; + + #ifdef UTILISATION_MPI + // récupération des grandeurs locales par le proc 0 + if (ParaGlob::Monde()->rank() == 0) + { // récup du nombre total d'éléments, cumul sur tous les maillages + int total_elem = distribution_CPU_algo.NB_total_element(); + // on va boucler sur les éléments récupérés des différents process + // jusqu'au nombre maxi d'élément + int nb_elem_deja_calcule = 0; // init + while (nb_elem_deja_calcule < total_elem) + { // on récupère un résultat de calcul + tempsCalMasse.Arret_du_comptage(); + 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, 2401, num_el_et_mail); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu + int ne = num_el_et_mail.un; // numero d'identification de l'element + int nbMail = 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(); + mpi::request reqs2 = residu->Irecup_MPI(source, 2501); + Mat_pleine* raideur = el.Conteneur_raideur(); + mpi::request reqs3 = raideur->Irecup_MPI(source, 2601); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + + temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu + reqs2.wait(); // on attend que le conteneur soit rempli + reqs3.wait(); // on attend que le conteneur soit rempli + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + + tempsCalMasse.Mise_en_route_du_comptage(); // comptage cpu + + // assemblage + Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el + if (casMass_relax < 2) // 0 1 : on ne retient que la diagonale + { Ass.AssembDiagonale (v_mass,*raideur,el.TableauDdl(),taN);} + else if (casMass_relax < 6) // sinon c'est la somme des valeurs absolues de la ligne + { Ass.AssembDiagoMajorValPropre (v_mass,*raideur,el.TableauDdl(),taN);} + // maintenant on s'occupe du cas où on utilise une matrice de raideur complète assemblée + else if ((casMass_relax > 5) && (casMass_relax < 10)) + {if (pa.Symetrie_matrice()) + Ass.AssembMatSym (*matglob,*raideur,el.TableauDdl(),taN); // de la raideur + else + Ass.AssembMatnonSym (*matglob,*raideur,el.TableauDdl(),taN); // de la raideur + } + else + { cout << "\n *** attention le cas casMass_relax = " << casMass_relax + << " n'est pas encore pris en compte !! se plaindre !! "; + Sortie(1); + }; + + // cas où on fait un deuxième assemblages + if ((casMass_relax > 3) && (casMass_relax < 6)) //4-5 + { Ass.AssembDiagonale (v_mass1,*raideur,el.TableauDdl(),taN);}; + tempsCalMasse.Arret_du_comptage(); // fin comptage cpu + // on incrémente le nombre d'élément traité + nb_elem_deja_calcule++; + }; + // + }; + }; // fin partie classique K sm + #endif + + if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 5 )) || (permet_affichage > 2)) + {// on affiche les min max du vecteur + cout << "\n -- info vecteur masse diagonale sur la raideur uniquement -- "; + Coordonnee3 moy=v_mass.MinMaxMoy(true); + }; + + + tempsCalMasse.Mise_en_route_du_comptage(); +////----- debug +//cout << "\n debug AlgoriRelaxDyna::CalculMatriceMasse "; +//{ string entete = " affichage de la matrice masse avant prise en compte du contact "; +// cout << "\n " << entete; +// v_mass.Affiche(); +// cout << endl; +//}; +////---fin debug + // prise en compte éventuelle de la raideur des éléments de contact if (pa.ContactType()) // et des énergies développées pendant le contact - {// on récupère la liste des éléments de contact - LaLIST & listElContact = lescontacts->LesElementsDeContact(); + { + #ifdef UTILISATION_MPI + // 2) partie contact dont seuls les proc != 0 savent calculer Kloc et smloc + mpi::request reqs1; + mpi::request reqs2; + mpi::request reqs3; + bool premier_passage = true; + // mise à jour de la liste des contacts pour proc 0: il s'agit des infos minimales + // qui permettent ensuite de faire un assemblage + lesContacts->Mise_a_jour_liste_contacts_actif_interProc(); + int proc_en_cours = ParaGlob::Monde()->rank(); + // en // ce sont les proc i>0 qui gèrent les éléments de contact + if (proc_en_cours != 0) + { + #endif + // on récupère la liste des éléments de contact + LaLIST & listElContact = lesContacts->LesElementsDeContact(); LaLIST ::iterator il,ilfin=listElContact.end(); // on gère les exceptions éventuelles en mettant le bloc sous surveillance try @@ -3088,14 +3278,30 @@ void AlgoriRelaxDyna::CalculMatriceMasse for (il=listElContact.begin();il != ilfin; il++) { if ((*il).Actif()) // on n'intervient que si le contact est actif - {//calcul de la raideur locale et du residu local + { + #ifdef UTILISATION_MPI + // on récupère un signal du process 0 + tempsCalMasse.Arret_du_comptage(); + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + if (premier_passage) {premier_passage = false;} + else // on regarde l'activité , car au début avant le balayage de tous les éléments des tableaux + {if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés + if (reqs2.active()) reqs2.wait(); // car aucun transfert n'a encore été effectué + if (reqs3.active()) reqs3.wait(); // + }; + temps_attente_contact.Arret_du_comptage(); + tempsCalMasse.Mise_en_route_du_comptage(); + #endif + + //calcul de la raideur locale et du residu local ElContact& elcontact = (*il); // pour simplifier - Tableau& taN = elcontact.TabNoeud_pour_assemblage(); // tableau de noeuds // calcul effectif de la raideur et résidu locals Element::ResRaid resu = elcontact.SM_K_charge_contact(); // cout << "numéro =" << ne << endl; // (resu.res)->Affiche(); // (resu.raid)->Affiche(); //1,8,1,1,8,1); + #ifndef UTILISATION_MPI + Tableau& taN = elcontact.TabNoeud_pour_assemblage(); // tableau de noeuds // assemblage // dans le cas où le retour est un pointeur nul, cela signifie qu'il n'y a pas de second membre et raideur calculés if (resu.res != NULL) @@ -3103,7 +3309,17 @@ void AlgoriRelaxDyna::CalculMatriceMasse { Ass.AssembDiagonale (v_mass,*(resu.raid),elcontact.TableauDdlCont(),taN);} else if ((casMass_relax > 1) && (casMass_relax < 6)) // sinon c'est la somme // des valeurs absolues de la ligne - { Ass.AssembDiagoMajorValPropre (v_mass,*(resu.raid),elcontact.TableauDdlCont(),taN);} + { Ass.AssembDiagoMajorValPropre (v_mass,*(resu.raid),elcontact.TableauDdlCont(),taN); +////--debug +//cout << "\n debug AlgoriRelaxDyna::CalculMatriceMasse "; +////string entete = " affichage de la matrice masse avant prise en compte du contact "; +//// cout << "\n " << entete; +//cout << "\n el contact: "; elcontact.Affiche(1); +//cout <<"\n *(resu.raid)= ";(resu.raid)->Affiche(); +//// v_mass.Affiche(); +// cout << endl; +////--- fin debug + } else { cout << "\n *** attention le cas du contact avec le casMass_relax = " << casMass_relax << " (c-a-d entre 6 a 9) " @@ -3115,6 +3331,33 @@ void AlgoriRelaxDyna::CalculMatriceMasse if ((casMass_relax > 3) && (casMass_relax < 6)) //4-5 { Ass.AssembDiagonale (v_mass1,*(resu.raid),elcontact.TableauDdlCont(),taN);}; }; + #else + // cas d'un calcul parallèle, et CPU != 0 + {// on va transmettre les infos permettant au proc 0 de récupérer + // l'élément de contact ad hoc et de préparer la place + tempsCalMasse.Arret_du_comptage(); + temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + // on commence par transmettre les infos de l'élément de contact + QuatreEntiers nums; + nums.un = elcontact.Esclave()->Num_Mail(); + nums.deux = elcontact.Esclave()->Num_noeud(); + nums.trois = elcontact.Elfront()->NumUnique(); + nums.quatre = resu.res->Taille(); + if (resu.res == NULL) + // il n'y a rien de calculé, donc on définit un indicateur ad hoc + nums.quatre = -1; // ici une taille négative + // on transmet les infos permettants de récupérer l'élément de contact + reqs1 = ParaGlob::Monde()->isend(0, 2400, nums); + // puis on transmets éventuellement le vecteur résidu et raideur + if (resu.res != NULL) + {reqs2 = resu.res->Ienvoi_MPI(0,2500); + //puis la matrice + reqs3 = resu.raid->Ienvoi_MPI(0, 2600); + }; + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + tempsCalMasse.Mise_en_route_du_comptage(); + }; + #endif }; //-- fin du test sur l'activité }; //-- fin de la boucle sur les éléments de contact } //-- fin du try @@ -3132,8 +3375,133 @@ void AlgoriRelaxDyna::CalculMatriceMasse if (ParaGlob::NiveauImpression() >= 4) cout << "\n AlgoriRelaxDyna::CalculMatriceMasse(.."; }; }; + #ifdef UTILISATION_MPI + }; // fin du cas des proc i>0 + #endif + + #ifdef UTILISATION_MPI + // cas du proc 0 + // récupération des grandeurs locales par le proc 0 + if (ParaGlob::Monde()->rank() == 0) + { // récup du nombre total d'éléments de contact, cumulé sur tous les maillages + int total_elem_contact = lesContacts->Nb_actifs(); + // on va boucler sur les éléments récupérés des différents process + // jusqu'au nombre maxi d'élément + int nb_elem_deja_calcule = 0; // init + while (nb_elem_deja_calcule < total_elem_contact) + { // on récupère un résultat de calcul + tempsCalMasse.Arret_du_comptage(); + temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + QuatreEntiers nums; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 2400, nums); + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + temps_attente_contact.Arret_du_comptage(); // fin comptage cpu + int numMailEsclave = nums.un; + int numNoeudEsclave = nums.deux; + int numUnique = nums.trois; + int taille_res = nums.quatre; + // on ne continue que si la taille n'est pas négative + if (taille_res > 0) + {// on récupére l'élément de contact + ElContact* elcontact = lesContacts->RecupElContactActif + (numMailEsclave,numNoeudEsclave,numUnique); + if (elcontact == NULL ) + {cout << "\n erreur *** en calcul parallele, le proc 0 ne parvient pas a recuperer" + << " l'element de contact pour les infos suivantes: " + << "\n numMailEsclave= "<< numMailEsclave + << " numNoeudEsclave= "<< numNoeudEsclave + << " numUnique= "<< numUnique + << "\n la suite n'est pas possible "; + Sortie(1); + }; + // récupération des conteneurs ad hoc vecteur et raideur + int source = stat.source(); // récupération du numéro de la source + + // récup uniquement des conteneurs raideurs et résidu (pas forcément remplis, mais de la bonne taille) + Element::ResRaid resRaid = elcontact->Conteneur_ResRaid(); + Vecteur * residu = resRaid.res; + if (residu->Taille() != taille_res ) + {cout << "\n erreur *** en calcul parallele, le proc 0 ne parvient pas a recuperer" + << " la bonne taille pour le résidu de contact avec les infos suivantes: " + << "\n numMailEsclave= "<< numMailEsclave + << " numNoeudEsclave= "<< numNoeudEsclave + << " numUnique= "<< numUnique + << "\n taille_residu transmis : "<Taille() + << "\n ce n'est pas normal ==> erreur " + << "\n on arrete "; + Sortie(1); + }; + + temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu + mpi::request reqs2 = residu->Irecup_MPI(source, 2500); + Mat_pleine* raideur = resRaid.raid; + mpi::request reqs3 = raideur->Irecup_MPI(source, 2600); + temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu + + temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu + reqs2.wait(); // on attend que le conteneur soit rempli + reqs3.wait(); // on attend que le conteneur soit rempli + temps_attente_contact.Arret_du_comptage(); // fin comptage cpu + tempsCalMasse.Mise_en_route_du_comptage(); + // assemblage + Tableau& taN = elcontact->TabNoeud_pour_assemblage(); // tableau de noeuds + if (casMass_relax < 2) // 0 1 : on ne retient que la diagonale + { Ass.AssembDiagonale (v_mass,*(raideur),elcontact->TableauDdlCont(),taN);} + else if ((casMass_relax > 1) && (casMass_relax < 6)) // sinon c'est la somme + // des valeurs absolues de la ligne + { Ass.AssembDiagoMajorValPropre (v_mass,*(raideur),elcontact->TableauDdlCont(),taN); +////--debug +//cout << "\n debug AlgoriRelaxDyna::CalculMatriceMasse "; +////string entete = " affichage de la matrice masse avant prise en compte du contact "; +//// cout << "\n " << entete; +//cout << "\n el contact: "; elcontact->Affiche(1); +//cout <<"\n *(resu.raid)= ";raideur->Affiche(); +//// v_mass.Affiche(); +// cout << endl; +////--- fin debug + + } + else + { cout << "\n *** attention le cas du contact avec le casMass_relax = " << casMass_relax + << " (c-a-d entre 6 a 9) " + << " n'est pas encore pris en compte !! se plaindre !! " + << " \n --> cas de la prise en compte de la raideur des elements de contact "; + Sortie(1); + }; + // cas où on fait un deuxième assemblages + if ((casMass_relax > 3) && (casMass_relax < 6)) //4-5 + { Ass.AssembDiagonale (v_mass1,*(raideur),elcontact->TableauDdlCont(),taN);}; + }; + // on incrémente le nombre d'élément traité + nb_elem_deja_calcule++; + }; + }; + #endif + + }; // fin du test: if (pa.ContactType()) - +////----- debug +//#ifdef UTILISATION_MPI +// // la suite ne concerne que le proc 0 +// if (proc_en_cours == 0) +//#endif +//cout << "\n debug AlgoriRelaxDyna::CalculMatriceMasse "; +//{ string entete = " affichage de la matrice masse après prise en compte du contact "; +// cout << "\n " << entete; +// v_mass.Affiche(); +// cout << endl; +//}; +////---fin debug + + #ifdef UTILISATION_MPI + // la suite ne concerne que le proc 0 + if (proc_en_cours == 0) + { + #endif + if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 5 )) || (permet_affichage > 2)) {// on affiche les min max du vecteur cout << "\n -- info vecteur masse diagonale sur la raideur + contact -- "; @@ -3216,14 +3584,17 @@ void AlgoriRelaxDyna::CalculMatriceMasse }; //v_mass.Affiche(); - if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 5 )) || (permet_affichage > 2)) - {// on affiche les min max du vecteur - cout << "\n -- info matrice masse finale -- "; - Coordonnee3 moy=mat_masse->MinMaxMoy(true); - }; + if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 5 )) || (permet_affichage > 2)) + {// on affiche les min max du vecteur + cout << "\n -- info matrice masse finale -- "; + Coordonnee3 moy=mat_masse->MinMaxMoy(true); + }; + #ifdef UTILISATION_MPI + }; + #endif + break; + } // fin du case 2: - break; - }; default: { cout << "\n **** erreur le cas type_calcul_mass= " << type_calcul_mass << "\n pour l'instant n'est pas implante " @@ -3232,6 +3603,11 @@ void AlgoriRelaxDyna::CalculMatriceMasse }; }; +#ifdef UTILISATION_MPI + // la suite concerne seulement le process 0 + if (proc_en_cours == 0) + { +#endif // prise en compte de masses ponctuelles // ---- cas des masses concentrées ----- Algori::Ajout_masses_ponctuelles(lesMail,Ass,(*mat_masse),divStoc,lesRef,N_ddl,lesFonctionsnD); @@ -3263,7 +3639,10 @@ void AlgoriRelaxDyna::CalculMatriceMasse <<" a une masse nulle en coordonnee " << coor ; } }; - + #ifdef UTILISATION_MPI + }; + #endif + tempsCalMasse.Arret_du_comptage(); }; @@ -3275,13 +3654,19 @@ void AlgoriRelaxDyna::CalculEnContinuMatriceMasse (const int& relax_vit_acce,LesMaillages * lesMail,Assemblage& Ass , int compteur, const DiversStockage* divStoc,LesReferences* lesRef ,const Enum_ddl & N_ddl - ,bool premier_calcul,LesContacts* lescontacts + ,bool premier_calcul,LesContacts* lesContacts ,bool & force_recalcul_masse,LesFonctions_nD* lesFonctionsnD) { // on regarde en fonction de option_recalcul_mass et des parametres associés éventuels s'il faut calculer la matrice masse bool calcul_a_effectuer = false; - double epsilon = 0.; // --- étude des différents cas de contrôle du recalcul de masse --- int option_recalcul_mass_en_cours = option_recalcul_mass(1); + double epsilon = 0.; +#ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + // partie uniquement dédiée au proc 0 + if (proc_en_cours == 0) + { +#endif // init principal (convient s'il n'y a pas d'option spécifique visqueuse if (fct_nD_option_recalcul_mass(1) != NULL) {option_recalcul_mass_en_cours = (fct_nD_option_recalcul_mass(1)->Valeur_pour_variables_globales())(1); @@ -3370,7 +3755,10 @@ void AlgoriRelaxDyna::CalculEnContinuMatriceMasse }; break; }; - +#ifdef UTILISATION_MPI + }; +#endif + // dans le cas ou on est à la première itération, le contact est updaté et // on peut statuer s'il y a un pb avec des conditions linéaires de contact if (((compteur <= 1 )&&(pa.ContactType()==1))) @@ -3378,8 +3766,14 @@ void AlgoriRelaxDyna::CalculEnContinuMatriceMasse // retourne un pointeur sur la nouvelle matrice, s'il y a eu une modification // l'ancienne est supprimée // sinon retour d'un pointeur NULL + // en // tous les proc doivent passer ici Mat_abstraite* mat_inter = Mise_a_jour_type_et_taille_matrice_masse_en_explicite - (delta_X.Taille(),mat_masse,lesMail,lesRef,(Ass.Nb_cas_assemb()).n,lescontacts); + (delta_X.Taille(),mat_masse,lesMail,lesRef,(Ass.Nb_cas_assemb()).n,lesContacts); +#ifdef UTILISATION_MPI +// partie uniquement dédiée au proc 0 +if (proc_en_cours == 0) + { +#endif if (mat_inter != NULL) { mat_masse = mat_inter; // c'est le nouveau stockage // il faut dans ce cas également changer le stockage de la copie @@ -3393,18 +3787,38 @@ void AlgoriRelaxDyna::CalculEnContinuMatriceMasse mat_masse_sauve = mat_masse->NouvelElement(); // création d'un nouvel élément identique calcul_a_effectuer=true; } +#ifdef UTILISATION_MPI + }; +#endif }; +#ifdef UTILISATION_MPI +// partie uniquement dédiée au proc 0 +if (proc_en_cours == 0) + { +#endif // on prend en compte un cas de forçage éventuel if (force_recalcul_masse) {calcul_a_effectuer = true; force_recalcul_masse = false; }; +#ifdef UTILISATION_MPI + }; + // on transmet à tous les proc l'indicateur calcul_a_effectuer + broadcast(*ParaGlob::Monde(), calcul_a_effectuer, 0); +#endif + // on calcul la matrice masse si nécessaire if (calcul_a_effectuer) - { CalculMatriceMasse(relax_vit_acce,lesMail,Ass,compteur,divStoc - ,lesRef,N_ddl,lescontacts,lesFonctionsnD); + { // en // tous les proc doivent passer ici + CalculMatriceMasse(relax_vit_acce,lesMail,Ass,compteur,divStoc + ,lesRef,N_ddl,lesContacts,lesFonctionsnD); +#ifdef UTILISATION_MPI +// partie uniquement dédiée au proc 0 +if (proc_en_cours == 0) + { +#endif // ici on va quand même éviter d'avoir des masses nulles sur la diagonale // on commence par calculer la valeur moyenne Coordonnee3 moy=mat_masse->MinMaxMoy((ParaGlob::NiveauImpression() > 3)); @@ -3440,24 +3854,40 @@ void AlgoriRelaxDyna::CalculEnContinuMatriceMasse }; }; *mat_masse_sauve = *mat_masse; +#ifdef UTILISATION_MPI + } +#endif } - else { *mat_masse = *mat_masse_sauve ;}; // on reprend l'ancienne sans les CL, si on n'a rien calculé + else + { +#ifdef UTILISATION_MPI + if (proc_en_cours == 0) // partie uniquement dédiée au proc 0 +#endif + *mat_masse = *mat_masse_sauve ;}; // on reprend l'ancienne sans les CL, si on n'a rien calculé +#ifdef UTILISATION_MPI +// partie uniquement dédiée au proc 0 +if (proc_en_cours == 0) + { +#endif // info si voulu, dans le cas où option_recalcul_mass_en_cours ==-1 c'est un calcul à chaque itération donc on n'affiche rien if ((calcul_a_effectuer && (ParaGlob::NiveauImpression() > 2)) && (option_recalcul_mass_en_cours != -1)) { if (option_recalcul_mass_en_cours != 4) { cout << "\n recalcul de la pseudo-masse (type: "<< option_recalcul_mass_en_cours <<") "; } else { cout << "\n recalcul de la pseudo-masse; epsilon=" << epsilon << endl ; }; }; - // affichage éventuelle de la matrice de masse - if (ParaGlob::NiveauImpression() >= 10) + if (ParaGlob::NiveauImpression() >= 10) +//cout << "\n debug AlgoriRelaxDyna::CalculEnContinuMatriceMasse "; { string entete = " affichage de la matrice masse utilisee en relaxation dynamique"; cout << "\n " << entete; mat_masse->Affiche(); cout << endl; }; +#ifdef UTILISATION_MPI + }; +#endif }; diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc index b884611..395e0e2 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc @@ -872,7 +872,7 @@ void AlgoriTchamwa::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc b/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc index 7082d48..32acfb7 100644 --- a/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc +++ b/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc @@ -50,7 +50,7 @@ void AlgoriNewmark::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc b/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc index 9f72329..0278725 100644 --- a/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc +++ b/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc @@ -51,7 +51,7 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); tempsInitialisation.Arret_du_comptage(); // temps cpu temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); @@ -71,8 +71,6 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, //cout << endl; ////-------- fin debug - - // avant toute chose, au cas où l'algo interviendrait après un autre algo // on inactive tous les ddl existants lesMail->Inactive_ddl(); @@ -139,7 +137,8 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, int nbddl_X = lesMail->NbTotalDdlActifs(); // nb total de ddl // choix de la matrice de raideur du système linéaire (calcul éventuellement d'une largeur de bande ad oc) - Choix_matriciel(nbddl_X,tab_mato,lesMail,lesRef,Ass.Nb_cas_assemb(),lesCondLim); + // ici, au niveau init, on démarre sans contact, son action sera ensuite rajoutée + Choix_matriciel(nbddl_X,tab_mato,lesMail,lesRef,Ass.Nb_cas_assemb(),lesCondLim,NULL); matglob = tab_mato(1); // par défaut c'est la première matrice // dans le cas où l'on veut également utiliser du Newton modifié, on definit la matrice de sauvegarde if (deb_newton_modifie >= 0) @@ -242,7 +241,7 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // initi boucle sur les increments de charge icharge = 0; - + // definition des elements de frontiere, ces elements sont utilises pour le contact lesMail->CreeElemFront(); // calcul éventuel des normales aux noeuds -> init des normales pour t=0 @@ -274,6 +273,31 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // definition des elements de contact eventuels // et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact) bool nevez_contact = lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul + +// #ifdef UTILISATION_MPI +// if (ParaGlob::Monde()->rank() == 0) +// { cout << "\n debug AlgoriNonDyna::InitAlgorithme fin transitoire proc 0"; +// cout << "\n taper une lettre pour stopper "; +// string toto; +// cin >> toto; +// int nb_process = ParaGlob::Monde()->size(); +// for (int i=1;isend(i, 100, std::string("redemarrage")); +// }; +// Sortie(1); +// } +// else +// { cout << "\n debug AlgoriNonDyna::InitAlgorithme fin transitoire proc " << ParaGlob::Monde()->rank(); +// // on attend le message de redémarrage du proc 0 +// std::string msg; +// ParaGlob::Monde()->recv(0, 100, msg); +// Sortie(1); +// }; +// #endif + + + int niveau_substitution = 0; // on intervient sur toutes les matrices bool premier_calcul = true; // mise à jour éventuelle de la matrice de raideur en fonction du contact @@ -719,7 +743,10 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail //--fin-debug // affichage ou non de l'itération bool aff_iteration = (pa.freq_affich_iter() > 0) ? - (aff_incr && (compteur % pa.freq_affich_iter()==0) &&(compteur!=0)) : false ; + (aff_incr && (compteur % pa.freq_affich_iter()==0) &&(compteur!=0)) + : (pa.freq_affich_iter() < 0) ? // dans le cas < 0 on affiche également l'itération 0 + (aff_incr && (compteur % pa.freq_affich_iter()==0)) + :false ; // utilisation d'un comportement tangent simplifié si nécessaire if (compteur <= pa.Init_comp_tangent_simple() ) lesLoisDeComp->Loi_simplifie(true); @@ -732,6 +759,12 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail if (pa.ContactType()) { int niveau_substitution = 0; // on intervient sur toutes les matrices bool a_changer = lescontacts->Actualisation(1); + #ifdef UTILISATION_MPI + // if faut que tous les proc aient le résultat final qui peut être différent pour chaque proc + // due au fait que chaque proc ne traite pas les mêmes éléments de contact + broadcast(*ParaGlob::Monde(), a_changer, 0); + #endif + // mise à jour éventuelle des matrices de raideur en fonction du contact if (a_changer) {//bool changement_sur_matrice = @@ -824,8 +857,14 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail // calcul des maxi des puissances internes maxPuissInt = vglobin.Max_val_abs(); +////------- debug +//#ifdef UTILISATION_MPI +// // cas d'un calcul //, pour l'instant seul le CPU 0 sont concerné +// if (ParaGlob::Monde()->rank() == 0) +//#endif //cout << "\n debug AlgoNonDyna::CalEquilibre: maxPuissInt => "< "; vglobex.Affiche(); +////cout << "\n debug AlgoNonDyna::CalEquilibre: vglobex => "; vglobex.Affiche(); +////------- debug +// #ifdef UTILISATION_MPI +// // cas d'un calcul //, pour l'instant seul le CPU 0 sont concerné +// if (ParaGlob::Monde()->rank() == 0) +// #endif +// { cout << "\n debug AlgoriNonDyna::CalEquilibre"; +// cout << "\n debug AlgoNonDyna::CalEquilibre: maxPuissext sans contact => "< "; vcontact.Affiche(); + +// //------- debug +// #ifdef UTILISATION_MPI +// // cas d'un calcul //, pour l'instant seul le CPU 0 sont concerné +// if (ParaGlob::Monde()->rank() == 0) +// #endif +// { cout << "\n debug AlgoriNonDyna::CalEquilibre"; +// cout << "\n max forces de contact " << vcontact.Max_val_abs(); +// }; +// //--- fin debug + // on globalise tout pour les forces externes généralisées #ifdef UTILISATION_MPI temps_transfert_long_algo.Mise_en_route_du_comptage(); // comptage cpu @@ -1034,6 +1093,14 @@ decol = false; // pour debugger }; residu_final = vglobaal; // sauvegarde pour le post-traitement +////------- debug +//cout << "\n debug AlgoriNonDyna::CalEquilibre"; +// { string entete = " affichage de la matrice de raideur (puissance interne) avant resolution"; +// tab_mato(1)->Affichage_ecran(entete); +// entete = " affichage du second membre (puissance interne) avant resolution "; +// residu_final.Affichage_ecran(entete); +// }; +////--- fin debug try {// ici sol en fait = vecglob qui est ecrase par la resolution sol = &(tab_mato(niveau_substitution)->Resol_systID diff --git a/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc b/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc index 4071fab..85dea8d 100644 --- a/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc +++ b/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc @@ -650,7 +650,7 @@ void AlgoBonelli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, #ifdef UTILISATION_MPI // calcul de l'équilibrage initiale par le cpu 0 if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) - {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); + {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() ,distribution_CPU_algo.Tab_indique_CPU_en_cours() diff --git a/Chargement/Charge.cc b/Chargement/Charge.cc index dbd5c15..dc131b2 100644 --- a/Chargement/Charge.cc +++ b/Chargement/Charge.cc @@ -219,7 +219,7 @@ Charge::Charge () : // constructeur par defaut tabV_transfert.Change_taille(taille_passage); tabMat_transfert.Change_taille(taille_passage); tab_six_faux_entiers.Change_taille(taille_passage); - for (int i=1;i<=taille_passage;i++)tab_six_faux_entiers(i).Change_taille(6); + for (int i=1;i<=taille_passage;i++) tab_six_faux_entiers(i).Change_taille(6); #endif } @@ -1355,11 +1355,11 @@ void Charge::Transfert_SM(bool& premier_passage, // on transmet les numéros d'élément et de maillage etc. reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + // puis on transmets le vecteur résidu sauf si tyfront est négatif if (tyfront > 0) - {temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu - reqs2 = SM_transfert.Ienvoi_MPI(0,35); - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + {reqs2 = SM_transfert.Ienvoi_MPI(0,35); // // debug // cout << "\n debug Charge::Transfert_SM( proc= "<< ParaGlob::Monde()->rank() // << " six_faux_entiers= " << six_faux_entiers @@ -1371,6 +1371,7 @@ void Charge::Transfert_SM(bool& premier_passage, index_transfert++; if (index_transfert > taille_tableau) // on fait une permutation circulaire index_transfert = 1;// on revient au premier élément des tableaux de transfert + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu }; // transfert du second membre "SM_transfert" et de la matrice "MAT_transfert" et mise à jour @@ -1406,7 +1407,8 @@ void Charge::Transfert_MatSm(bool& premier_passage, six_faux_entiers(3) = (double) tyfront; six_faux_entiers(4) = (double) num_front; six_faux_entiers(5) = (double) SM_transfert.Taille(); - six_faux_entiers(6) = (double) index_transfert; + int indique_matrice = (MAT_transfert != NULL); + six_faux_entiers(6) = (double) indique_matrice; // on transmet les numéros d'élément et de maillage etc. reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); // // debug @@ -1415,12 +1417,15 @@ void Charge::Transfert_MatSm(bool& premier_passage, // << " SM_transfert= " << SM_transfert << flush; // // fin debug temps_transfert_court.Arret_du_comptage(); // fin comptage cpu - // puis on transmets le vecteur résidu temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu - reqs2 = SM_transfert.Ienvoi_MPI(0,35); - // puis on transmets éventuellementla matrice de raideur - if (MAT_transfert != NULL) + + // puis on transmets le vecteur résidu sauf si tyfront est négatif + if (tyfront > 0) + {reqs2 = SM_transfert.Ienvoi_MPI(0,35); + // puis on transmets éventuellementla matrice de raideur + if (MAT_transfert != NULL) reqs3 = MAT_transfert->Ienvoi_MPI(0,36); + }; // ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore // en transfert vers le proc 0 index_transfert++; @@ -1429,6 +1434,7 @@ void Charge::Transfert_MatSm(bool& premier_passage, temps_transfert_long.Arret_du_comptage(); // fin comptage cpu }; + #endif diff --git a/Chargement/Charge2.cc b/Chargement/Charge2.cc index 08cf539..ca37bac 100644 --- a/Chargement/Charge2.cc +++ b/Chargement/Charge2.cc @@ -354,7 +354,7 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid #ifdef UTILISATION_MPI // on définit les conteneurs de passage d'info int proc_en_cours = ParaGlob::Monde()->rank(); - int index_transfert; // index pour incrémenter dans les tableaux + int index_transfert = 1; // index pour incrémenter dans les tableaux bool premier_passage = true; if (proc_en_cours != 0) @@ -467,8 +467,6 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; #ifdef UTILISATION_MPI - // appel du calcul du second membre correspondant à la charge de type pression - // appel du calcul du second membre correspondant à la charge surfacique Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier int num_face = ref.NumeroFA(ns); SM_transfert = elem.SM_charge_surfacique_E_tdt(vforce,pt_fonct,num_face,pa); @@ -1388,6 +1386,10 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // le signe - indique une fin // appel du transfert et mise à jour de l'index des tableaux Vecteur& SM_transfert = tabV_transfert(index_transfert); // ne sert pas ici + // il faut que le vecteur ne soit pas vide, s'il a une taille nulle on modifie arbitrairement + // c'est le cas qui arrive s'il n'y a aucun chargement + if (SM_transfert.Taille() == 0) + SM_transfert.Change_taille(1); // le vecteur ne sert pas ici Transfert_SM(premier_passage,tyfront, 0,SM_transfert, index_transfert,0,0 @@ -1540,11 +1542,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid retour = false; }; temps_cpu_chargement.Arret_du_comptage(); -#ifdef UTILISATION_MPI - temps_attente.Mise_en_route_du_comptage(); - ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process - temps_attente.Arret_du_comptage(); -#endif +//#ifdef UTILISATION_MPI +// temps_attente.Mise_en_route_du_comptage(); +// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process +// temps_attente.Arret_du_comptage(); +//#endif return retour; }; @@ -1886,13 +1888,12 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid #ifdef UTILISATION_MPI // on définit les conteneurs de passage d'info int proc_en_cours = ParaGlob::Monde()->rank(); - int index_transfert; // index pour incrémenter dans les tableaux + int index_transfert = 1; // index pour incrémenter dans les tableaux bool premier_passage = true; if (proc_en_cours != 0) { #endif - // $$$--- cas des forces surfaciques ---$$$ // il y a une implication éventuelle sur la raideur int tabsurfactaille = tabFsurfac.Taille(); @@ -2003,8 +2004,7 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid Element::ResRaid resu = elem.SMR_charge_surfacique_I(vforce,pt_fonct,ref.NumeroFA(ns),pa); #ifdef UTILISATION_MPI - // appel du calcul du second membre correspondant à la charge de type pression - // appel du calcul du second membre correspondant à la charge surfacique + // transfert Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); Mat_pleine* pt_MAT = NULL; @@ -2143,8 +2143,6 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid Element::ResRaid resu = elem.SMR_charge_pression_I(press_ac,pt_fonct,ref.NumeroFA(ns),pa); #ifdef UTILISATION_MPI - // appel du calcul du second membre correspondant à la charge de type pression - // appel du calcul du second membre correspondant à la charge surfacique Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); Mat_pleine* pt_MAT = NULL; @@ -2170,6 +2168,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid pt_MAT,index_transfert, num_mail,num_elem ); +// //-------debug +// cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< ParaGlob::Monde()->rank() +// << "\n SM= " << SM_transfert << flush; +// cout << "\n mat= "<<*pt_MAT; +// //-------fin debug temps_cpu_chargement.Mise_en_route_du_comptage(); } }; @@ -2186,6 +2189,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); +// //-------debug +// cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid " +// << "\n SM= " << *(resu.res) << flush; +// cout << "\n mat= "<<*(resu.raid); +// //-------fin debug } #endif }; @@ -2307,8 +2315,6 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid #ifdef UTILISATION_MPI - // appel du calcul du second membre correspondant à la charge de type pression - // appel du calcul du second membre correspondant à la charge surfacique Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); Mat_pleine* pt_MAT = NULL; @@ -3024,6 +3030,10 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // le signe - indique une fin // appel du transfert et mise à jour de l'index des tableaux Vecteur& SM_transfert = tabV_transfert(index_transfert); // ne sert pas ici + // il faut que le vecteur ne soit pas vide, s'il a une taille nulle on modifie arbitrairement + // c'est le cas qui arrive s'il n'y a aucun chargement + if (SM_transfert.Taille() == 0) + SM_transfert.Change_taille(1); // le vecteur ne sert pas ici Transfert_SM(premier_passage,tyfront, 0,SM_transfert, index_transfert,0,0 @@ -3058,7 +3068,7 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid tyfront = (int) six_faux_entiers(3); num_front = (int) six_faux_entiers(4); taille_SM = (int) six_faux_entiers(5); - index_transfert = six_faux_entiers(6); + int indique_matrice = (int) six_faux_entiers(6); source = stat.source(); ////-------debug @@ -3071,19 +3081,24 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid {Element& elem = lesMail->Element_LesMaille(nbMail,ne); // def de SM et MAT avec la bonne dimension SM_transfert.Change_taille(taille_SM); - if (MAT_transfert.Nb_ligne () != taille_SM) + if (indique_matrice) + if (MAT_transfert.Nb_ligne () != taille_SM) MAT_transfert.Initialise(taille_SM,taille_SM); // récupération des conteneurs ad hoc vecteur et raideur temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu reqs2 = SM_transfert.Irecup_MPI(source, 35); reqs2.wait(); // on attend que le conteneur soit rempli - // idem pour la matrice - reqs3 = MAT_transfert.Irecup_MPI(source,36); + // idem pour la matrice éventuelle + if (indique_matrice) + {reqs3 = MAT_transfert.Irecup_MPI(source,36); + reqs3.wait(); + } temps_transfert_long.Arret_du_comptage(); // fin comptage cpu ////-------debug //cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< ParaGlob::Monde()->rank() -// << " SM= " << SM << flush; +// << "\n SM= " << SM_transfert << flush; +//cout << "\n mat= "< distance mini entre noeuds extrèmes -// en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface -// en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol -// cas = 3: 1D idem cas 2, 2D: distance mini noeud arrête opposée, 3D: distance mini noeud face opposé double Element::LongueurGeometrique_mini(int cas) const { double longueur=0.; // valeur de retour switch (cas) @@ -843,6 +839,81 @@ double Element::LongueurGeometrique_mini(int cas) const //cout << " longueur= "<< longueur << endl; return longueur; }; + +// ramène la coordonnée maxi dans la direction i de l'ensemble des noeuds de l'élément +// à l'instant tdt, ou t ou t=0 en fonction de temps +double Element::Maxi_xi_noeud(int i_dir, Enum_dure temps) + {double maxi_xi =0; // init + int nbne = tab_noeud.Taille(); // récup du nombre de noeud + switch (temps) + { case TEMPS_0: + {for (int i=1;i<= nbne;i++) + { double xi = tab_noeud(i)->Coord0()(i_dir); + if (maxi_xi < xi) maxi_xi = xi; + }; + break; + } + case TEMPS_t: + {for (int i=1;i<= nbne;i++) + { double xi = tab_noeud(i)->Coord1()(i_dir); + if (maxi_xi < xi) maxi_xi = xi; + }; + break; + } + case TEMPS_tdt: + {for (int i=1;i<= nbne;i++) + { double xi = tab_noeud(i)->Coord2()(i_dir); + if (maxi_xi < xi) maxi_xi = xi; + }; + break; + } + }; + return maxi_xi; + }; + + +// calcul d'une longueur géométrique caractéristique représentative de l'élément +// cas = 1: correspond à la distance moyenne entre deux noeuds coins de l'élément +// cas = 2: dans le cas 1D -> distance moyenne entre noeuds extrèmes +// en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface +// en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol +double Element::LongueurGeometrique_caracteristique(int cas) const + { double longueur=0.; // valeur de retour + switch (cas) + { case 1: + { int nbne = tab_noeud.Taille(); // récup du nombre de noeud + if (nbne > 1) // si on a qu'un seul noeud, on ne peut rien calculer + { // tout d'abord l'objectif est de déterminer la distance moyenne entre les différents noeuds + // initialisation de la distance entre les deux noeuds + double dist = 0.; + int nb_dist = 0; // init + if (tab_noeud(1)->ExisteCoord1()) + {// cas où les coordonnées à t sont définies + for (int i=1;i<= nbne;i++) + // on itère sur les noeuds restants + for (int j=i+1;j<= nbne;j++,nb_dist++) + dist += (tab_noeud(i)->Coord1() - tab_noeud(j)->Coord1()).Norme(); + } + else + {// cas où seules les coordonnées à 0 sont définit + for (int i=1;i<= nbne;i++) + // on itère sur les noeuds restants + for (int j=i+1;j<= nbne;j++,nb_dist++) + dist += (tab_noeud(i)->Coord0() - tab_noeud(j)->Coord0()).Norme(); + }; + longueur = dist / nb_dist; + }; + break; + } + default : + cout << "\nErreur : cas:" << cas <<" non encore traite !\n" + << "Element::LongueurGeometrique_caracteristique(int cas) ) \n"; + Sortie(1); + }; +//cout << " longueur= "<< longueur << endl; + return longueur; + }; + // calcul le volume entre l'élément (=surface2D) et les plans de ref: yz, xz, xy, dans cet ordre // valable uniquement pour les éléments 2D dans un espace 3D, ramène une dim nulle sinon diff --git a/Elements/Element.h b/Elements/Element.h index 889e33a..8de3faa 100644 --- a/Elements/Element.h +++ b/Elements/Element.h @@ -335,14 +335,23 @@ class Element // ramene l'element geometrique virtual ElemGeomC0& ElementGeometrique() const =0; // ramene l'element geometrique en constant - virtual const ElemGeomC0& ElementGeometrique_const() const =0; + virtual const ElemGeomC0& ElementGeometrique_const() const =0; + // calcul d'une longueur géométrique mini représentative de l'élément // cas = 1: correspond à la distance mini entre deux noeuds coins de l'élément - // cas = 2: dans le cas 1D -> distance mini entre noeuds extrèmes - // en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface - // en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol - // cas = 3: 1D idem cas 2, 2D: distance mini noeud arrête opposée, 3D: distance mini noeud face opposé - double LongueurGeometrique_mini(int cas) const; + double LongueurGeometrique_mini(int cas) const; + + // ramène la coordonnée maxi dans la direction i de l'ensemble des noeuds de l'élément + // à l'instant tdt, ou t ou t=0 en fonction de temps + double Maxi_xi_noeud(int i, Enum_dure temps); + + // calcul d'une longueur géométrique moyenne représentative de l'élément + // cas = 1: correspond à la distance moyenne entre deux noeuds coins de l'élément + // cas = 2: dans le cas 1D -> distance moyenne entre noeuds extrèmes + // en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface + // en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol + double LongueurGeometrique_caracteristique(int cas) const; + // récupération du volume de l'élément (qui doit avoir été calculé dans une des classes dérivées // par exemple en mécanique via un calcul explicite ou implicite d'équilibre mécanique // pour un élément 3D: le volume au sens classique diff --git a/Elements/Geometrie/Frontiere/Front.cc b/Elements/Geometrie/Frontiere/Front.cc index 59c82fe..f0f0a13 100644 --- a/Elements/Geometrie/Frontiere/Front.cc +++ b/Elements/Geometrie/Frontiere/Front.cc @@ -34,12 +34,18 @@ // constructeur //par defaut Front::Front() : - boite_Front(),num_frontiere(0),elem(NULL) + boite_Front(),num_frontiere(0),elem(NULL),angle_mort(0) +#ifdef UTILISATION_MPI + ,num_unique(0) +#endif {ptEl = NULL; tabmitoyen=NULL; }; // normal Front::Front ( const ElFrontiere& el, Element * pt, int num_front ,int ang_mort) : boite_Front(ParaGlob::Dimension()),num_frontiere(num_front) ,angle_mort(ang_mort) +#ifdef UTILISATION_MPI + ,num_unique(0) +#endif ,elem(el.NevezElemFront()) { ptEl =(Element *) pt; tabmitoyen=NULL; @@ -53,6 +59,9 @@ Front::Front ( const ElFrontiere& el, Element * pt, int num_front ,int ang_mort Front::Front ( const Front& a) : boite_Front(a.boite_Front),num_frontiere(a.num_frontiere) ,elem(a.elem->NevezElemFront()),angle_mort(a.angle_mort) +#ifdef UTILISATION_MPI + ,num_unique(a.num_unique) +#endif { ptEl = (Element *) a.ptEl; if (a.tabmitoyen != NULL) { int tabtaille = (a.tabmitoyen)->Taille(); @@ -146,6 +155,9 @@ Front& Front::operator = ( const Front& a) boite_Front = a.boite_Front; // angle mort angle_mort = a.angle_mort; +#ifdef UTILISATION_MPI + num_unique = a.num_unique; +#endif return *this; }; diff --git a/Elements/Geometrie/Frontiere/Front.h b/Elements/Geometrie/Frontiere/Front.h index f80b510..c043abb 100644 --- a/Elements/Geometrie/Frontiere/Front.h +++ b/Elements/Geometrie/Frontiere/Front.h @@ -180,6 +180,13 @@ class Front int Angle_mort() const {return angle_mort;}; // changement de l'indicateur d'angle mort void Change_angle_mort(int new_angle_mort) {angle_mort= new_angle_mort;}; + + #ifdef UTILISATION_MPI + // cas d'un calcul parallèle: // passage des infos entre process + int NumUnique() const {return num_unique;}; // s'il est attribué (c-a-d != 0) donne un numéro unique de référencement + // est mis à jour et utilisé par les classes appelantes + void ChangeNumUnique(int num) {num_unique = num;}; + #endif // test si la position d'un point est du bon cote ( c-a-d hors matiere) ou non // si le point est sur la surface, ramène false @@ -215,6 +222,12 @@ class Front int angle_mort; // indicateur par défaut = 0, ==1 s'il s'agit d'un front // qui est construit pour représenter un angle mort + + #ifdef UTILISATION_MPI + // cas d'un calcul parallèle: // passage des infos entre process + int num_unique; // s'il est attribué (c-a-d != 0) donne un numéro de référencement + // est mis à jour et utilisé par les classes appelantes + #endif // fonctions internes static double prop_mini; // mini proportion à ajouter à l'encombrement diff --git a/Elements/Mecanique/ElemMeca.cc b/Elements/Mecanique/ElemMeca.cc index 3564c94..4084402 100644 --- a/Elements/Mecanique/ElemMeca.cc +++ b/Elements/Mecanique/ElemMeca.cc @@ -756,6 +756,17 @@ int ElemMeca::Interne(Enum_dure temps,const Coordonnee& M,Coordonnee* coor_local Sortie(1); }; #endif +////----- debug +//if ((Num_elt() == 3) && (Num_maillage() == 2)) +// {cout << "\n debug ElemMeca::Interne(..."; +// Tableau& tan = Tab_noeud(); +// +// for (int i = 1;i<= tan.Taille();i++) +// {cout << " noeud ("<Coord2().Affiche(); +// }; +// }; +////---- fin debug // la methode consiste tout d'abord a calculer les coordonnees locales correspondants // a M. Pour cela on utilise un processus iteratif // ---- 1 :init de la recherche @@ -860,56 +871,64 @@ int ElemMeca::Interne(Enum_dure temps,const Coordonnee& M,Coordonnee* coor_local {retour = 2;} // !-! à l'erreur près, le point est sur la frontière else {retour = 1;}; // !-! point à l'intérieur } - else {return 0;}; // !-! point à l'extérieur -> retour directe - // --- cas particuliers --- - // -- dans le cas où "retour" est différent de 0, on regarde les cas particuliers - switch (dim_glob) - {case 3: - {switch (dim_loc) - { case 3: break; // cas pas de pb - case 2: // cas des "coques ou plaques" on regarde si le point est réellement à l'intérieur (+- 1/2 épaisseur) - { double epaisseur = Epaisseurs(temps,theta); - A = (met->*PointM) (tab_noeud,ph_i); // le point projeté sur la surface de l'élément - AM = M-A; double delta_hauteur = 0.5 * epaisseur - AM.Norme(); - if (Dabs(delta_hauteur) <= prec_tehetai_interne) - {retour = 2;} // !-! à l'erreur près, le point est sur la frontière - else if (delta_hauteur < 0.) - {retour = 0;} // !-! point externe - else {retour = 1;}; // !-! point à l'intérieur - break; - } - default: - cout << " \n *** erreur : cas non implemente pour l'instant " - << " dim_glob= " << dim_glob << " dim_loc= " << dim_loc - << "\n ElemMeca::Interne(... "; - Sortie(1); - };// -- fin du switch dim_loc pour dim_glob=3 - break; - } // fin dim_glob=3 - case 2: - {switch (dim_loc) - {case 2: break; // pas de pb - case 1: case 3: // cas des poutres et volume (pb non consistance) pour l'instant non traité - // donc on laisse aller à la valeur par défaut - default: - cout << " \n *** erreur : cas non implemente pour l'instant " - << " dim_glob= " << dim_glob << " dim_loc= " << dim_loc - << "\n ElemMeca::Interne(... "; - Sortie(1); - };// -- fin du switch dim_loc pour dim_glob=3 - break; - } // fin dim_glob=2 - case 1: // la dimension locale est forcément 1, et pas de pb - {break; - } - default: // default pour le switch sur di_glob - cout << " \n *** erreur : cas non implemente pour l'instant " - << " dim_glob= " << dim_glob << " dim_loc= " << dim_loc - << "\n ElemMeca::Interne(... "; - Sortie(1); - break; - }; // -- fin du switch sur dim_glob - // retour + else {retour = 0;}; // !-! point à l'extérieur -> retour directe + if (!retour) + {// --- cas particuliers --- + // -- dans le cas où "retour" est différent de 0, on regarde les cas particuliers + switch (dim_glob) + {case 3: + {switch (dim_loc) + { case 3: break; // cas pas de pb + case 2: // cas des "coques ou plaques" on regarde si le point est réellement à l'intérieur (+- 1/2 épaisseur) + { double epaisseur = Epaisseurs(temps,theta); + A = (met->*PointM) (tab_noeud,ph_i); // le point projeté sur la surface de l'élément + AM = M-A; double delta_hauteur = 0.5 * epaisseur - AM.Norme(); + if (Dabs(delta_hauteur) <= prec_tehetai_interne) + {retour = 2;} // !-! à l'erreur près, le point est sur la frontière + else if (delta_hauteur < 0.) + {retour = 0;} // !-! point externe + else {retour = 1;}; // !-! point à l'intérieur + break; + } + default: + cout << " \n *** erreur : cas non implemente pour l'instant " + << " dim_glob= " << dim_glob << " dim_loc= " << dim_loc + << "\n ElemMeca::Interne(... "; + Sortie(1); + };// -- fin du switch dim_loc pour dim_glob=3 + break; + } // fin dim_glob=3 + case 2: + {switch (dim_loc) + {case 2: break; // pas de pb + case 1: case 3: // cas des poutres et volume (pb non consistance) pour l'instant non traité + // donc on laisse aller à la valeur par défaut + default: + cout << " \n *** erreur : cas non implemente pour l'instant " + << " dim_glob= " << dim_glob << " dim_loc= " << dim_loc + << "\n ElemMeca::Interne(... "; + Sortie(1); + };// -- fin du switch dim_loc pour dim_glob=3 + break; + } // fin dim_glob=2 + case 1: // la dimension locale est forcément 1, et pas de pb + {break; + } + default: // default pour le switch sur di_glob + cout << " \n *** erreur : cas non implemente pour l'instant " + << " dim_glob= " << dim_glob << " dim_loc= " << dim_loc + << "\n ElemMeca::Interne(... "; + Sortie(1); + break; + }; // -- fin du switch sur dim_glob + }; +// //----- debug +// if ((Num_elt() == 3) && (Num_maillage() == 2)) +// {cout << "\n debug ElemMeca::Interne(...)"; +// cout << " retour = "<rank() != 0) + #endif if (ParaGlob::NiveauImpression() > 9) { cout << "\n Raideur et second membre locaux: ? (o/n) "; string rep(" "); // procédure de lecture avec prise en charge d'un retour chariot @@ -1163,6 +1185,10 @@ void ElemMeca::Cal_implicit (DdlElement & tab_ddl else {Cal_implicit_StabMembBiel(-1,*ex_final, nbint,volume,NULL);} ; }; #ifdef MISE_AU_POINT + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() != 0) + #endif + if (ParaGlob::NiveauImpression() > 9) { if ((type_stabHourglass)||(pt_StabMembBiel != NULL)) {cout << "\n apres stabilisation: Raideur et second membre locaux: ? (o/n) "; string rep(" "); diff --git a/Elements/Mecanique/SFE/SfeMembT.cc b/Elements/Mecanique/SFE/SfeMembT.cc index 669817e..ca05cac 100644 --- a/Elements/Mecanique/SFE/SfeMembT.cc +++ b/Elements/Mecanique/SFE/SfeMembT.cc @@ -980,6 +980,10 @@ if ((*residu)(jloc) > 10.) }; // fin boucle sur les points d'intégration #ifdef MISE_AU_POINT +#ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) +#endif + if (ParaGlob::NiveauImpression() > 9) { cout << "\n Raideur et second membre locaux: ? (o/n) "; string rep(" "); // procédure de lecture avec prise en charge d'un retour chariot @@ -1009,6 +1013,9 @@ if ((*residu)(jloc) > 10.) (-1,*ex_final, nbtotsurf,volume,unefois->doCoMemb->noeud_a_prendre_en_compte);} ; }; #ifdef MISE_AU_POINT +#ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) +#endif if (ParaGlob::NiveauImpression() > 9) { if ((type_stabHourglass)||(pt_StabMembBiel != NULL)) {cout << "\n apres stabilisation: Raideur et second membre locaux: ? (o/n) "; string rep(" "); diff --git a/General/Distribution_CPU.cc b/General/Distribution_CPU.cc index 981b813..c457cd0 100755 --- a/General/Distribution_CPU.cc +++ b/General/Distribution_CPU.cc @@ -36,7 +36,7 @@ namespace mpi = boost::mpi; // constructeur par défaut Distribution_CPU::Distribution_CPU(): tab_list_maillage_element(),tab_indic() - ,total_elem(0) + ,total_elem(0),total_elem_maitre(0) ,tab_vide_list_maillage_element() ,tab_list_maillage_noeud(),tab_indic_noeud() ,total_noeud(0) @@ -46,7 +46,8 @@ Distribution_CPU::Distribution_CPU(): // constructeur de copie Distribution_CPU::Distribution_CPU (const Distribution_CPU& a): tab_list_maillage_element(a.tab_list_maillage_element) - ,tab_indic(a.tab_indic),total_elem(a.total_elem) + ,tab_indic(a.tab_indic) + ,total_elem(a.total_elem),total_elem_maitre(a.total_elem_maitre) ,tab_vide_list_maillage_element() ,tab_list_maillage_noeud(a.tab_list_maillage_noeud) ,tab_indic_noeud(a.tab_indic_noeud),total_noeud(a.total_noeud) @@ -54,7 +55,7 @@ Distribution_CPU::Distribution_CPU (const Distribution_CPU& a): {}; // calcul de l'équilibrage initiale -void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMaillages) +void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMaillages, LesContacts * lesContacts) { if (ParaGlob::Monde()->rank() == 0) { // on équilibre sur tous les cpu excepté le maître, qui lui ne calcule pas @@ -104,6 +105,7 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai int nb_elem_un_cpu = total_elem/nb_proc_calcul; // arrondi inférieur // on adapte le tableau de liste tab_list_maillage_element.Change_taille(nb_proc_calcul); + tab_list_maillage_noeud.Change_taille(nb_proc_calcul); for (int iproc =1;iproc <= nb_proc_calcul; iproc++) {tab_list_maillage_element(iproc).Change_taille(nb_mail); tab_list_maillage_noeud(iproc).Change_taille(nb_mail); @@ -112,40 +114,170 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai tab_list_maillage_noeud(iproc)(imail).clear(); }; }; - // on parcours tous les éléments et on remplit les tableaux - int iproc = 1; // le num du proc en cours - int nb_ele_enreg_iproc = 1; // init le nombre d'élément enregistré pour le proc - for (int imail=1;imail<=nb_mail;imail++) - { - int nb_ele = lesMaillages->Nombre_element(imail); - {list * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init - list * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init - // de la liste courante - for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++) - { li_maillage_element->push_back(ile); - tab_indic(iproc)(imail)(ile)=true; // on signale - // idem pour les noeuds - Element& ele = lesMaillages->Element_LesMaille(imail,ile); - Tableau& tab_N = ele.Tab_noeud(); - int nb_N = tab_N.Taille(); - for (int ne =1;ne<=nb_N;ne++) - {int num_noeud = tab_N(ne)->Num_noeud(); - tab_indic_noeud(iproc)(imail)(num_noeud)=true; - li_maillage_noeud->push_back(num_noeud); - }; - // on regarde s'il faut changer de cpu - // si c'est le dernier cpu, on ne change pas -> pour éviter - // les pb d'arrondi - if ((nb_ele_enreg_iproc > nb_elem_un_cpu) - && (iproc < nb_proc_calcul) ) - {iproc++; - nb_ele_enreg_iproc=1; // reinit du compteur - li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée - li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); - }; - }; - }; - }; + + // on différencie le cas sans et avec contact + // dans le cas sans contact on parcours linéairement tous les maillages successivement + int nb_mail_Esclave = lesMaillages->NbEsclave(); // def du nombre de maillages esclaves + + // si aucun esclave + if (nb_mail_Esclave==0) + {// on parcours tous les éléments et on remplit les tableaux + int iproc = 1; // le num du proc en cours + int nb_ele_enreg_iproc = 1; // init le nombre d'élément enregistré pour le proc + for (int imail=1;imail<=nb_mail;imail++) + { + int nb_ele = lesMaillages->Nombre_element(imail); + {list * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init + list * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init + // de la liste courante + for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++) + { li_maillage_element->push_back(ile); + tab_indic(iproc)(imail)(ile)=true; // on signale + // idem pour les noeuds + Element& ele = lesMaillages->Element_LesMaille(imail,ile); + Tableau& tab_N = ele.Tab_noeud(); + int nb_N = tab_N.Taille(); + for (int ne =1;ne<=nb_N;ne++) + {int num_noeud = tab_N(ne)->Num_noeud(); + tab_indic_noeud(iproc)(imail)(num_noeud)=true; + li_maillage_noeud->push_back(num_noeud); + }; + // on regarde s'il faut changer de cpu + // si c'est le dernier cpu, on ne change pas -> pour éviter + // les pb d'arrondi + if ((nb_ele_enreg_iproc > nb_elem_un_cpu) + && (iproc < nb_proc_calcul) ) + {iproc++; + nb_ele_enreg_iproc=1; // reinit du compteur + li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée + li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); + }; + }; + }; + }; + } + else // cas où on a des maillages maîtres particuliers donc du contact + {// l'idée est de tout d'abord, ventiler les éléments des maillages maîtres ou en autocontact + // de manière à l'exécution qu'il y ait une ventilation: + // 1) de la recherche du contact + // 2) potentiellement (si contact il y a) d'élément de contact + int iproc = 1; // le num du proc en cours + // on va calculer le nb d'éléments maitres (environ) qui doivent être attribué à chaque cpu + int nbmailautocontact = lesContacts->NbmailAutoContact(); +// int nbmailMaitre = nb_mail-(nb_mail_Esclave-nbmailautocontact); // def du nombre de maillage maitres + // ce sont les derniers maillages + total_elem_maitre = 0; // init + for (int i=1+nb_mail_Esclave-nbmailautocontact;i<=nb_mail;i++) + {int nb_elem_mail = lesMaillages->Nombre_element(i); + total_elem_maitre += nb_elem_mail; + }; + int nb_elem_maitre_un_cpu = total_elem_maitre/nb_proc_calcul; // arrondi inférieur +// // --- debug +// cout << "\n *** debug Distribution_CPU::Calcul_Equilibrage_initiale" +// << "\n total_elem_maitre= "<< total_elem_maitre +// << " nb_elem_maitre_un_cpu= "<< nb_elem_maitre_un_cpu; +// //--- fin debug + // on distribue en parcourant les maillages maîtres + int nb_ele_enreg_iproc = 1; // init le nombre d'élément enregistré pour le proc + for (int imail=1+nb_mail_Esclave-nbmailautocontact;imail<=nb_mail;imail++) + { + int nb_ele = lesMaillages->Nombre_element(imail); + {list * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init + list * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init + // de la liste courante + for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++) + { li_maillage_element->push_back(ile); + tab_indic(iproc)(imail)(ile)=true; // on signale + // idem pour les noeuds + Element& ele = lesMaillages->Element_LesMaille(imail,ile); + Tableau& tab_N = ele.Tab_noeud(); + int nb_N = tab_N.Taille(); + for (int ne =1;ne<=nb_N;ne++) + {int num_noeud = tab_N(ne)->Num_noeud(); + tab_indic_noeud(iproc)(imail)(num_noeud)=true; + li_maillage_noeud->push_back(num_noeud); + }; + // on regarde s'il faut changer de cpu + // si c'est le dernier cpu, on ne change pas -> pour éviter + // les pb d'arrondi + if ((nb_ele_enreg_iproc > nb_elem_maitre_un_cpu) + && (iproc < nb_proc_calcul) ) + {iproc++; + nb_ele_enreg_iproc=1; // reinit du compteur + li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée + li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); + }; + }; + }; + }; +//// --- debug +//cout << "\n *** debug Distribution_CPU::Calcul_Equilibrage_initiale"; +//cout << "\n 1) elements maitres pour chaque proc : "; +//for (int iproc = 1;iproc <= nb_proc_calcul; iproc++) +// {for (int imail=1+nb_mail_Esclave-nbmailautocontact;imail<=nb_mail;imail++) +// {list * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init +// list ::iterator il,ilfin = li_maillage_element->end(); +// for (il = li_maillage_element->begin();il != ilfin; il++) +// cout << "\n proc("< * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init +// list ::iterator il,ilfin = li_maillage_element->end(); +// for (il = li_maillage_element->begin();il != ilfin; il++) +// cout << "\n proc("< > > tab_indic; int total_elem ; // nombre total d'éléments cumulé sur tous les maillages + int total_elem_maitre; // nombre total d'éléments maitres cumulé sur tous les maillages; // tab_list_maillage_noeud(i)(j) contient la liste // pour le maillage j des num associés au cpu i diff --git a/General/herezh.cc b/General/herezh.cc index 79c1b19..9055159 100644 --- a/General/herezh.cc +++ b/General/herezh.cc @@ -437,6 +437,16 @@ try #endif +//#ifdef UTILISATION_MPI +// if (world.rank() == 0) +// { cout << "\n debug Herezh.cc fin transitoire de lecture proc 0"; +// cout << "\n taper une lettre pour stopper "; +// string toto; +// cin >> toto; +// Sortie(1); +// }; +//#endif + do { projet.Calcul(); // 2- calcul diff --git a/Maillage/LesMaillages.cc b/Maillage/LesMaillages.cc index c27a3f1..a5a2999 100644 --- a/Maillage/LesMaillages.cc +++ b/Maillage/LesMaillages.cc @@ -3361,10 +3361,23 @@ Ddl LesMaillages::NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage, double& return noe.Ddl_noeud_t(a.Const_Enu()); }; -// creation des elements frontiere // creation des elements frontiere: cela n'a lieu qu'une seule fois // si les frontières existent déjà, --> aucune action, --> ramène 0 // sinon il y a réellement création, et --> ramène 1 +// NB: il s'agit ici des frontière minimales permettant de représenter toute la frontière +// Ainsi: +// en 1D on retrouve: +// - des points uniquement +// en 2D on retrouve : +// - des segments dans le cas d'une surface (les noeuds sont exclus car intégrés aux lignes) +// - points et segment pour les lignes +// en 2D axi, on retrouve : +// - des segments dans le cas d'une surface (les noeuds sont exclus car intégrés aux lignes) +// - points et segment pour les lignes +// en 3D, on retrouve +// - des faces pour les éléments volumique (noeuds et lignes sont exclus) +// - une face et des lignes pour les éléments 2D (pas de noeuds) + int LesMaillages::CreeElemFront() { int retour = 0; @@ -3414,10 +3427,16 @@ int LesMaillages::CreeElemFront() // ramene le tableau des noeuds des frontières des maillages esclaves Tableau < Tableau *> LesMaillages::Tab_noeud_frontiere_esclave() { Tableau < Tableau *> ret(domEsclave); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if ((domEsclave)&&(ParaGlob::NiveauImpression()>2)) cout << "\n >>>> Information maillages : "; for (int i=1;i<=domEsclave;i++) {ret(i) = tt_noeud_front(i); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (ParaGlob::NiveauImpression()>2) cout << "\n il y a "<Taille() << " noeuds esclaves possible sur front. du maillage " << i ; diff --git a/Maillage/LesMaillages.h b/Maillage/LesMaillages.h index 2a8ec5b..fdb1fb9 100644 --- a/Maillage/LesMaillages.h +++ b/Maillage/LesMaillages.h @@ -647,7 +647,7 @@ class LesMaillages int CreeElemFront(); // ramene le nombre de maillage esclave - inline int NbEsclave() { return domEsclave;}; + inline int NbEsclave() const { return domEsclave;}; // ramene le tableau des list des elements frontiere minimales (cf. explication dans CreeElemFront()) inline Tableau *>& ListFrontiere() { return listFrontiere;}; // ramene un tableau des noeuds des frontières des maillages esclaves diff --git a/Maillage/LesMaillages2.cc b/Maillage/LesMaillages2.cc index 95d158c..12947e7 100644 --- a/Maillage/LesMaillages2.cc +++ b/Maillage/LesMaillages2.cc @@ -2179,7 +2179,7 @@ void LesMaillages::Integration() // }; }; - // maintenant il s'agit d'alimenter les grandeurs globales + // maintenant il s'agit d'alimenter les grandeurs globales (du proc i en //) // on récupère le pointeur correspondant à la grandeur correspondant au nom // de référence @@ -2206,14 +2206,15 @@ void LesMaillages::Integration() TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); *(gr_quelc->Grandeur_pointee()) = *(g_TG); - #ifdef UTILISATION_MPI + #ifdef UTILISATION_MPI }; - #endif + #endif }; - // même chose pour les intégrales en volume et en temps - int taill1 = ref_integ_vol_t.Taille(); - for (int rang_integ =1;rang_integ<= taill1;rang_integ++) - if (ref_integ_vol_t(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas + + // même chose pour les intégrales en volume et en temps + int taill1 = ref_integ_vol_t.Taille(); + for (int rang_integ =1;rang_integ<= taill1;rang_integ++) + if (ref_integ_vol_t(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas // l'intégrale stockée reste fixe pendant le calcul { const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol_t(rang_integ)); // initialisation du conteneur relatif à chaque ref @@ -2258,7 +2259,7 @@ void LesMaillages::Integration() // }; // }; }; - // maintenant il s'agit d'alimenter les grandeurs globales + // maintenant il s'agit d'alimenter les grandeurs globales (des proc i en //) // on récupère le pointeur correspondant à la grandeur correspondant au nom // de référence @@ -2285,11 +2286,16 @@ void LesMaillages::Integration() // on l'affecte TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); *(gr_quelc->Grandeur_pointee()) = *(g_TG); - #ifdef UTILISATION_MPI - }; - #endif + #ifdef UTILISATION_MPI + }; + #endif }; + + #ifdef UTILISATION_MPI + // on ne continue que s'il y a quelque chose à transmettre + if (taill_v != 0) + { if (ParaGlob::Monde()->rank() != 0) {temps_serialisation.Mise_en_route_du_comptage(); // comptage cpu // on va transmettre au proc 0 les résultats pour que celui-ci globalise les informations @@ -2325,7 +2331,7 @@ void LesMaillages::Integration() temps_serialisation.Arret_du_comptage(); // fin comptage cpu temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu // 4) transfert sans attente au proc 0 - mpi::request reqs1 = ParaGlob::Monde()->isend(0, 50, v_integ); + mpi::request reqs1 = v_integ.Ienvoi_MPI(0,50); temps_transfert_long.Arret_du_comptage(); // comptage cpu } else // cas du proc 0 @@ -2472,7 +2478,7 @@ void LesMaillages::Integration() }; temps_serialisation.Arret_du_comptage(); // fin comptage cpu } - + }; // fin cu cas (taill_v != 0) #endif diff --git a/Maillage/Maillage.cc b/Maillage/Maillage.cc index 752e604..658efd5 100755 --- a/Maillage/Maillage.cc +++ b/Maillage/Maillage.cc @@ -2007,7 +2007,7 @@ pour le calcul des frontières donc on met en stand by pour l'instant, si pas de - // definition des elements mitoyens aux elements de frontiere + // definition des elements frontières mitoyens aux elements de frontiere MitoyenFront(); // ==== définition du tableau des noeuds frontières ===== // 1) on définit un tableau de numéro de noeuds qui sont utilisés @@ -2736,7 +2736,7 @@ Tableau Maillage::Taille_boiteMail() //========================== fonction protegee ============================= -// definition des elements mitoyens aux elements de frontiere +// definition des elements frontières mitoyens aux elements de frontiere // à la fin du programme tous les éléments mitoyens sont stocké dant les éléments front // la manip est de créer des éléments frontières aux éléments frontières existant // ensuite deux éléments sont mitoyens s'il ont la même frontière diff --git a/Maillage/maillage4.cc b/Maillage/maillage4.cc index 9f1963f..b06993b 100644 --- a/Maillage/maillage4.cc +++ b/Maillage/maillage4.cc @@ -1804,6 +1804,11 @@ void Maillage::AffichageNoeudNonReferencer() { //if (ParaGlob::NiveauImpression() > 2) // cout << "\n print nodes which are not referred in the mesh " // << nomDuMaillage << endl; + #ifdef UTILISATION_MPI + // cas d'un calcul //, seul le CPU 0 affiche + if (ParaGlob::Monde()->rank() != 0) + return ; + #endif // on commence par chercher les noeuds non référencés int taille_tabnoeud=tab_noeud.Taille(); Tableau non_referencer(taille_tabnoeud,true); diff --git a/Parametres/EnteteParaGlob.h b/Parametres/EnteteParaGlob.h index a857a3d..2adb26e 100644 --- a/Parametres/EnteteParaGlob.h +++ b/Parametres/EnteteParaGlob.h @@ -41,7 +41,7 @@ EnumLangue ParaGlob::langueHZ = FRANCAIS; // langue utilisée pour les entrées sorties int ParaGlob::nbComposantesTenseur = 1; // nombre de composantes par defaut a 1 int ParaGlob::nivImpression = 2; // niveau d'impression - string ParaGlob::nbVersion = "7.023" ; // numéro de version du logiciel + string ParaGlob::nbVersion = "7.028" ; // numéro de version du logiciel string ParaGlob::NbVersionsurfichier = ""; // numéro de version lue en entrée fichier int ParaGlob::nb_diggit_double_calcul= 17; // nombre de chiffre significatifs utilisé pour // l'affichage des double précision pour l'archivage diff --git a/Parametres/ParaAlgoControle.cc b/Parametres/ParaAlgoControle.cc index a44d0ea..bcd1700 100755 --- a/Parametres/ParaAlgoControle.cc +++ b/Parametres/ParaAlgoControle.cc @@ -201,6 +201,7 @@ ParaAlgoControle::ParaAlgoControle() : nbDecolAutorise = 1; // nb de fois un noeud décolle pour n'être plus considéré en contact typeDeDecolement = 0; // type par défaut sur la réaction nb_glissant = 1; // par défaut il n'y a pas de moyenne glissante + nb_change_frontiere_max = 4; // nb de changement maxi de frontière niveau_commentaire_lescontacts = 0; // par défaut c'est le général qui commande fct_niveau_commentaire_lescontacts = "_";// pas de fonction par défaut @@ -316,7 +317,8 @@ ParaAlgoControle::ParaAlgoControle(const ParaAlgoControle& p) : force_tangentielle_noeud_maxi(p.force_tangentielle_noeud_maxi), fct_nD_force_tangentielle_noeud_maxi(p.fct_nD_force_tangentielle_noeud_maxi), nb_boucle_newton_position_frontiere(p.nb_boucle_newton_position_frontiere), - nbDecolAutorise(p.nbDecolAutorise),typeDeDecolement(p.typeDeDecolement),nb_glissant(p.nb_glissant), + nbDecolAutorise(p.nbDecolAutorise),typeDeDecolement(p.typeDeDecolement), + nb_glissant(p.nb_glissant),nb_change_frontiere_max(p.nb_change_frontiere_max), niveau_commentaire_lescontacts(p.niveau_commentaire_lescontacts), fct_niveau_commentaire_lescontacts(p.fct_niveau_commentaire_lescontacts), niveau_commentaire_contact(p.niveau_commentaire_contact), @@ -429,7 +431,8 @@ ParaAlgoControle& ParaAlgoControle::operator= (const ParaAlgoControle& p) fct_nD_force_tangentielle_noeud_maxi = p.fct_nD_force_tangentielle_noeud_maxi; nb_boucle_newton_position_frontiere = p.nb_boucle_newton_position_frontiere; - nbDecolAutorise = p.nbDecolAutorise; typeDeDecolement = p.typeDeDecolement; nb_glissant = p.nb_glissant; + nbDecolAutorise = p.nbDecolAutorise; typeDeDecolement = p.typeDeDecolement; + nb_glissant = p.nb_glissant;nb_change_frontiere_max = p.nb_change_frontiere_max; niveau_commentaire_lescontacts = p.niveau_commentaire_lescontacts; fct_niveau_commentaire_lescontacts = p.fct_niveau_commentaire_lescontacts; @@ -1110,6 +1113,9 @@ void ParaAlgoControle::Lecture_paraAlgoControle(UtilLecture & entreePrinc) {typeDeDecolement= (int) entreePrinc.lect_avec_const_double_utilisateur("TYPE_DE_DECOLLEMENT ");} else if (nom == "NB_MOY_GLISSANT") {nb_glissant= (int) entreePrinc.lect_avec_const_double_utilisateur("NB_MOY_GLISSANT ");} + else if (nom == "NB_CHANGE_FRONTIERE_MAX") + {nb_change_frontiere_max = (int) entreePrinc.lect_avec_const_double_utilisateur("NB_CHANGE_FRONTIERE_MAX ");} + else if (nom == "NIVEAU_COMMENTAIRE_LESCONTACTS") {if (strstr(entreePrinc.tablcar,"FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACTS")!=NULL) {*(entreePrinc.entree) >> nom_inter >> fct_niveau_commentaire_lescontacts; @@ -1133,7 +1139,7 @@ void ParaAlgoControle::Lecture_paraAlgoControle(UtilLecture & entreePrinc) else if (nom == "OPTIMISATION_NUMEROTATION") {optimisation_numerotation= (int) entreePrinc.lect_avec_const_double_utilisateur("OPTIMISATION_NUMEROTATION ");} else - { cout << "\n ** erreur en lecture des parametres de contact" << nom; + { cout << "\n ** erreur en lecture des parametres de contact: " << nom; entreePrinc.MessageBuffer ("** lecture des parametres des parametres de contact **"); Affiche(); @@ -1470,6 +1476,8 @@ void ParaAlgoControle::Ecriture_base_info_Para sort << "NB_DECOLLEMENT_MAXI " << nbDecolAutorise << "\n"; sort << "TYPE_DE_DECOLLEMENT " << typeDeDecolement << "\n"; sort << "NB_MOY_GLISSANT " << nb_glissant << "\n"; + sort << "NB_CHANGE_FRONTIERE_MAX " << nb_glissant << "\n"; + sort << "NIVEAU_COMMENTAIRE_LESCONTACTS "<< niveau_commentaire_lescontacts << "FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACT"<< fct_niveau_commentaire_lescontacts << "\n"; sort << "NIVEAU_COMMENTAIRE_CONTACT "<< niveau_commentaire_contact @@ -1682,6 +1690,8 @@ void ParaAlgoControle::Lecture_base_info_Para(ifstream& ent,const int cas) ent >> toto >> nbDecolAutorise ; ent >> toto >> typeDeDecolement ; ent >> toto >> nb_glissant ; + ent >> toto >> nb_glissant ; + ent >> toto >> niveau_commentaire_lescontacts >> toto >> fct_niveau_commentaire_lescontacts; ent >> toto >> niveau_commentaire_contact >> toto >> fct_niveau_commentaire_contact; ent >> toto >> optimisation_numerotation; @@ -1890,6 +1900,8 @@ void ParaAlgoControle::Affiche() const cout << "NB_DECOLLEMENT_MAXI " << nbDecolAutorise << "\n"; cout << "TYPE_DE_DECOLLEMENT " << typeDeDecolement << "\n"; cout << "NB_MOY_GLISSANT " << nb_glissant << "\n"; + cout << "NB_CHANGE_FRONTIERE_MAX " << nb_glissant << "\n"; + cout << "NIVEAU_COMMENTAIRE_LESCONTACTS " << niveau_commentaire_lescontacts << "FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACTS"<< fct_niveau_commentaire_lescontacts << "\n"; cout << "NIVEAU_COMMENTAIRE_CONTACT " << niveau_commentaire_contact @@ -2540,7 +2552,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc) << "\n#--------------------------- " << "\n# PARAMETRE | VALEUR | " << "\n#--------------------------- "; - Tableau tab_modif(37,false); // indique qu'est-ce qui a été modifié + Tableau tab_modif(38,false); // indique qu'est-ce qui a été modifié //On va proposer un menu string repa=" "; cout << "\n --- controle generaux ------ "; @@ -2585,16 +2597,17 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc) << "\n (34) FCT_ND_FORCE_TANGENTIELLE_NOEUD_MAXI " << "\n (35) FCT_ND_NIVEAU_COMMENTAIRE_CONTACT " << "\n (36) FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACTS " - << "\n (37 ou h ou ? ) informations " + << "\n (37) NB_CHANGE_FRONTIERE_MAX " + << "\n (38 ou h ou ? ) informations " << "\n "; repa = lect_return_defaut(false,"f"); if ((Minuscules(repa) == "f") || (Minuscules(repa) == "0"))// sortie directe break; int numa = ChangeEntier(repa); - if (repa == "?") numa = 37; + if (repa == "?") numa = 38; - if (!((numa >= 0)&&(numa<=37))) - { cout << "\n Erreur on attendait un entier entre 0 et 37 !!, " + if (!((numa >= 0)&&(numa<=38))) + { cout << "\n Erreur on attendait un entier entre 0 et 38 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; }; @@ -2606,7 +2619,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc) switch (numa) { case 0: // sortie { break;} // normalement cela a déjà été filtré avant - case 6: case 8: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 25: + case 6: case 8: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 25: case 37: { cout << "\n nouvelle valeur (un entier ) ? "; string_inter= lect_chaine();cout << " valeur lue ="< à la taille de v // dans ce cas ramène 0 int Condilineaire::Pack_vecteur(Vecteur& v,int rang) const - { // le tableau de pointeurs + { + +////debug Condilineaire::Pack_vecteur +//{ int rang_inter = rang; +// cout << "\n debug Condilineaire::Pack_vecteur "; +// // le tableau de pointeurs +// int taille_pt = pt.Taille(); +// cout << "\n taille_pt "<NouvelleDonnee(); // lecture d'une nouvelle ligne } while (strstr(entreePrinc->tablcar,"fin_fcts_interne_fonction_combinee_")==0); // on passe à la ligne suivante - entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne + // on lit sans tenir compte des < éventuelles + {entreePrinc->NouvelleDonneeSansInf();}; // on met en tableau int tai = li_Fi.size(); Fi.Change_taille(tai); @@ -1053,7 +1068,8 @@ Tableau & Fonc_scal_combinees_nD::Valeur_FnD_interne(Tableau * int tail_enu = enu_variables_globale_int.Taille(); // les variables globales - for (int i=1;i<= tail_enu;i++,i_fval_int++) + int index_glob=1; // init + for (int i=1;i<= tail_enu;i++,i_fval_int++,index_glob++) {// on récupère le pointeur correspondant à la grandeur const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale_int(i))); TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); @@ -1107,10 +1123,12 @@ Tableau & Fonc_scal_combinees_nD::Valeur_FnD_interne(Tableau * this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1); }; }; + // on remplit également le tableau de stockage + x_glob(index_glob)=tab_fVal_int(i_fval_int); }; // idem pour les variables globales indiçées par des strings int tail_nom = nom_variables_globales_int.Taille(); // idem avec des noms - for (int i=1;i<= tail_nom;i++,i_fval_int++) + for (int i=1;i<= tail_nom;i++,i_fval_int++,index_glob++) {// on récupère le pointeur correspondant à la grandeur const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales_int(i))); TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); @@ -1217,6 +1235,8 @@ Tableau & Fonc_scal_combinees_nD::Valeur_FnD_interne(Tableau * this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1); }; }; + // on remplit également le tableau de stockage + x_glob(index_glob)=tab_fVal_int(i_fval_int); }; // appel de la fonction maître @@ -2055,6 +2075,63 @@ void Fonc_scal_combinees_nD::Init_fonction_analytique() +// affichage des arguments xi internes en supprimant les redondances, +// utilisée par les fonctions dérivées +// tab_ret: le retour qui a été calculé par la fonction +// decal: donne le nombre de blanc à insérer avant l'affichage +// niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage +void Fonc_scal_combinees_nD::Affiche_interne_valeurs_et_arguments + (int& decal,const Tableau * xi,const Tableau & tab_ret,int niveau) const +{int decal_initial = decal; +//--- debug +//if (nom_ref == "fct_reso_valPropre_coef_B_MAT_1") +// {cout << " debug ";//Fonc_scal_combinees_nD::Affiche_interne_valeurs_et_arguments"; +// int toto; +// cin >> toto; +// } + +//--- fin debug + if (niveau > 3) + {Fonction_nD::Affiche_interne_valeurs_et_arguments(decal,xi,tab_ret,niveau); + decal++; // +=2; // on décale pour le cas de fct emboitée +// if (permet_affichage > 4) +// {cout << "\n";SortBlanc(decal);cout << " --- fonction composee : Fonc_scal_combinees_nD : nom_ref= " << nom_ref; +// cout << "\n";SortBlanc(decal);cout << " 1) -- vue d'ensemble des variables: --- ";}; + if ((niveau > 5) && (niveau < 8)) + // --- les variables dans l'ensemble + { cout << "\n";SortBlanc(decal);cout << " --- fonction composee : Fonc_scal_combinees_nD : nom_ref= " << nom_ref; + // maintenant on s'intéresse à chaque fonction membre + cout << " >>>> fct membres dont le retour sert d'argument: --- "; + int tail = Fi.Taille(); + for (int i=1; i<= tail; i++) + { decal++; // 2; + Fi(i)->Affiche_interne_valeurs_et_arguments(decal,&tab_fVal_Fi(i),tab_ret_Fi(i),niveau); + decal--;// -= 2; +// cout << "\n";SortBlanc(decal);cout << " retour fct (" <NomFonction() << ") qui sert d'argument: "; +// int nb_val = tab_ret_Fi(i).Taille(); +// for (int j=1;j<=nb_val;j++) +// cout << " val("<Affiche_interne_valeurs_et_arguments(decal,&tab_fVal_Fi(i),tab_ret_Fi(i),8); + decal = decal_deb; + }; + + }; + }; + decal = decal_initial; // retour au décalage initiale +}; + + + diff --git a/Util/Courbes/Fonc_scal_combinees_nD.h b/Util/Courbes/Fonc_scal_combinees_nD.h index 9730d59..22533d8 100755 --- a/Util/Courbes/Fonc_scal_combinees_nD.h +++ b/Util/Courbes/Fonc_scal_combinees_nD.h @@ -265,6 +265,15 @@ class Fonc_scal_combinees_nD : public Fonction_nD // sont des grandeurs globales virtual Tableau & Valeur_pour_variables_globales_interne(); + // affichage des arguments xi internes en supprimant les redondances, + // utilisée par les fonctions dérivées + // tab_ret: le retour qui a été calculé par la fonction + // decal: donne le nombre de blanc à insérer avant l'affichage + // niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage + virtual void Affiche_interne_valeurs_et_arguments + (int& decal, const Tableau * xi,const Tableau & tab_ret,int niveau) const; + + }; /// @} // end of group diff --git a/Util/Courbes/Fonction_expression_litterale_nD.cc b/Util/Courbes/Fonction_expression_litterale_nD.cc index 32711a0..4d411e8 100755 --- a/Util/Courbes/Fonction_expression_litterale_nD.cc +++ b/Util/Courbes/Fonction_expression_litterale_nD.cc @@ -124,7 +124,7 @@ Fonction_nD& Fonction_expression_litterale_nD::operator= (const Fonction_nD& elt return *this; }; - // affichage de la courbe + // affichage de la fonction void Fonction_expression_litterale_nD::Affiche(int niveau) const { cout << " Fonction_expression_litterale_nD " << nom_ref ; cout << " \n arguments= " << nom_variables @@ -450,6 +450,7 @@ void Fonction_expression_litterale_nD::Info_commande_Fonctions_nD(UtilLecture & }; // calcul des valeurs de la fonction, retour d'un tableau de scalaires +// pas d'affichage sauf s'il y a une erreur Tableau & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau * xi) { int i_in_xi=1; // indice pour se déplacer dans xi // int i_in_tab_coor=1;// indice pour se déplacer dans tab_coor @@ -471,10 +472,8 @@ Tableau & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau int tail_enu = enu_variables_globale.Taille(); // les variables globales int tail_nom = nom_variables_globales.Taille(); // idem avec des noms #ifdef MISE_AU_POINT -// if (tab_fVal.Taille() != (taille_xi+taille_totale_coor+tail_enu)) if (tab_fVal.Taille() != (taille_xi+tail_enu+tail_nom)) { cout << "\n *** pb de dimensions d'argument non coherentes !! " -// << " taille_xi+taille_totale_coor "<Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - } - catch(...) - { cout << "\n ** erreur dans l'appel de la fonction " - << nom_ref << " d'expression " << expression_fonction; - cout << " verifier la presence des grandeurs globales voulues " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."<Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif - // on parcours les variables globales - int taille = enu_variables_globale.Taille(); - for (int i=1;i<= taille;i++,i_fval++) - {// on récupère le pointeur correspondant à la grandeur - const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i))); - TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); - switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()) - { case TYPE_SIMPLE: - { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) - {case PARTICULIER_SCALAIRE_ENTIER: - {Grandeur_scalaire_entier& gr - = *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurEntier()); - break; - } - case PARTICULIER_SCALAIRE_DOUBLE: - {Grandeur_scalaire_double& gr - = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurDouble()); - break; - } - case PARTICULIER_DDL_ETENDU: - {Grandeur_Ddl_etendu& gr - = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - } - - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - }; - }; - // 3) idem pour les globaux en nom c-a-d typées sous forme de string - if (tail_nom>0) - { - // en debug on vérifie que les grandeurs globales sont présentent - #ifdef MISE_AU_POINT - try - { for (int i=1;i<= tail_nom;i++) - {// on récupère le pointeur correspondant à la grandeur - const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i))); - if (pointe == NULL) - { cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! " - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas disponible, on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."<Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - } - catch(...) - { cout << "\n ** erreur dans l'appel de la fonction " - << nom_ref << " d'expression " << expression_fonction; - cout << " verifier la presence des grandeurs globales voulues " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."<Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif - // on parcours les variables globales - int taille = nom_variables_globales.Taille(); - for (int i=1;i<= taille;i++,i_fval++) - {// on récupère le pointeur correspondant à la grandeur - const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i))); - TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); - switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()) - { case TYPE_SIMPLE: - { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) - {case PARTICULIER_SCALAIRE_ENTIER: - {Grandeur_scalaire_entier& gr - = *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurEntier()); - break; - } - case PARTICULIER_SCALAIRE_DOUBLE: - {Grandeur_scalaire_double& gr - = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurDouble()); - break; - } - case PARTICULIER_DDL_ETENDU: - {Grandeur_Ddl_etendu& gr - = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - break; - } - case PARTICULIER_VECTEUR_NOMMER: - {Grandeur_Vecteur_Nommer& gr - = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - #ifdef MISE_AU_POINT - // on vérifie qu'une seule grandeur est stockée - if (gr.NbMaxiNumeroOrdre() > 1) - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en " - << " compte pour l'intant, on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - } - - break; - } - case TABLEAU_T: // valable uniquement pour les vecteur nommer - // dans ce cas on n'utilise pour l'instant que la première valeur - { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) - { case PARTICULIER_VECTEUR_NOMMER: - {Grandeur_Vecteur_Nommer& gr - = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - #ifdef MISE_AU_POINT - // on vérifie qu'une seule grandeur est stockée - if (gr.NbMaxiNumeroOrdre() > 1) - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en " - << " compte pour l'intant, on ne peut pas continuer " - << "\n grandeur= "<Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - } - - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - }; - }; -*/ - // on peut maintenant appeler la fonction int nNum; double * v = p.Eval(nNum); @@ -774,7 +543,6 @@ Tableau & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau cout <<"\n >>> arbre d'appel : fonction this : "; this->Affiche(5); cout << endl; -// p.Eval(nNum); // on génère une interruption ce qui permettra de dépiler les appels ErrCalculFct_nD toto;throw (toto);Sortie(1); }; @@ -818,251 +586,8 @@ Tableau & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau // sont toutes des grandeurs globales: pour l'instant que pour des variables scalaires Tableau & Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne() { - -/* // en debug on vérifie que les grandeurs globales sont présentent - #ifdef MISE_AU_POINT - try - { // on vérifie tout d'abord que toutes les variables sont globales - if (nom_variables.Taille() != 0) - { cout << "\n ** erreur dans l'appel de la fonction " - << nom_ref << " d'expression " << expression_fonction; - cout << " toutes les variables ne sont pas globales !! " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<Affiche(); - // on génère une interruption ce qui permettra de dépiler les appels - ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - // maintenant on vérifie la présence des variables globales - int taille = enu_variables_globale.Taille(); - for (int i=1;i<= taille;i++) - {// on récupère le pointeur correspondant à la grandeur - const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i))); - if (pointe == NULL) - { cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! " - << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) - << ", n'est pas disponible, on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<Affiche(); - // on génère une interruption ce qui permettra de dépiler les appels - ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - } - catch(...) - { cout << "\n ** erreur dans l'appel de la fonction " - << nom_ref << " d'expression " << expression_fonction; - cout << " verifier la presence des grandeurs globales voulues " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<Affiche(); - // on génère une interruption ce qui permettra de dépiler les appels - ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif - // idem pour les grandeurs indicées avec des string - #ifdef MISE_AU_POINT - try - { int tail_nom = nom_variables_globales.Taille(); - for (int i=1;i<= tail_nom;i++) - {// on récupère le pointeur correspondant à la grandeur - const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i))); - if (pointe == NULL) - { cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! " - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas disponible, on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - } - catch(...) - { cout << "\n ** erreur dans l'appel de la fonction " - << nom_ref << " d'expression " << expression_fonction; - cout << " verifier la presence des grandeurs globales voulues " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<Affiche(); - // on génère une interruption ce qui permettra de dépiler les appels - ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif -*/ - // arrivée ici toutes les grandeurs existent try { -/* // on parcours les variables globales - int i_fval=1; // indice pour se déplacer dans plusieurs boucles - int taille = enu_variables_globale.Taille(); - for (int i=1;i<= taille;i++,i_fval++) - {// on récupère le pointeur correspondant à la grandeur - const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i))); - TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); - switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()) - { case TYPE_SIMPLE: - { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) - {case PARTICULIER_SCALAIRE_ENTIER: - {Grandeur_scalaire_entier& gr - = *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurEntier()); - break; - } - case PARTICULIER_SCALAIRE_DOUBLE: - {Grandeur_scalaire_double& gr - = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurDouble()); - break; - } - case PARTICULIER_DDL_ETENDU: - {Grandeur_Ddl_etendu& gr - = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - } - - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - }; - // idem mais typées sous forme de string - {// on parcours les variables globales - int taille = nom_variables_globales.Taille(); - for (int i=1;i<= taille;i++,i_fval++) - {// on récupère le pointeur correspondant à la grandeur - const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i))); - TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); - switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()) - { case TYPE_SIMPLE: - { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) - {case PARTICULIER_SCALAIRE_ENTIER: - {Grandeur_scalaire_entier& gr - = *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurEntier()); - break; - } - case PARTICULIER_SCALAIRE_DOUBLE: - {Grandeur_scalaire_double& gr - = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = *(gr.ConteneurDouble()); - break; - } - case PARTICULIER_DDL_ETENDU: - {Grandeur_Ddl_etendu& gr - = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - break; - } - case PARTICULIER_VECTEUR_NOMMER: - {Grandeur_Vecteur_Nommer& gr - = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - #ifdef MISE_AU_POINT - // on vérifie qu'une seule grandeur est stockée - if (gr.NbMaxiNumeroOrdre() > 1) - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en " - << " compte pour l'intant, on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - } - - break; - } - case TABLEAU_T: // valable uniquement pour les vecteur nommer - // dans ce cas on n'utilise pour l'instant que la première valeur - { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) - { case PARTICULIER_VECTEUR_NOMMER: - {Grandeur_Vecteur_Nommer& gr - = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier - tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1)); - #ifdef MISE_AU_POINT - // on vérifie qu'une seule grandeur est stockée - if (gr.NbMaxiNumeroOrdre() > 1) - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en " - << " compte pour l'intant, on ne peut pas continuer " - << "\n grandeur= "<Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - #endif - break; - } - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - } - - break; - } - - default: - { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction - << " la variable globale "<< nom_variables_globales(i) - << ", n'est pas prise en compte actuellement , on ne peut pas continuer " - << "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..." - <Affiche();ErrCalculFct_nD toto;throw (toto); - Sortie(1); - }; - }; - }; - }; -*/ // on récupère les grandeurs globales Fonction_nD::Recup_Grandeurs_globales(); // on affecte les grandeurs @@ -1097,7 +622,6 @@ Tableau & Fonction_expression_litterale_nD::Valeur_pour_variables_globa cout <<"\n >>> arbre d'appel : fonction this : "; this->Affiche(5); cout << endl; -// p.Eval(nNum); // on génère une interruption ce qui permettra de dépiler les appels this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1); }; diff --git a/Util/Courbes/Fonction_expression_litterale_nD.h b/Util/Courbes/Fonction_expression_litterale_nD.h index 93cc568..7c089d5 100755 --- a/Util/Courbes/Fonction_expression_litterale_nD.h +++ b/Util/Courbes/Fonction_expression_litterale_nD.h @@ -164,6 +164,7 @@ class Fonction_expression_litterale_nD : public Fonction_nD // METHODES PROTEGEES : // calcul des valeurs de la fonction, retour d'un tableau de scalaires + // pas d'affichage sauf s'il y a une erreur virtual Tableau & Valeur_FnD_interne(Tableau * xi); // calcul des valeurs de la fonction, dans le cas où les variables diff --git a/Util/Courbes/Fonction_nD.cc b/Util/Courbes/Fonction_nD.cc index f33adc5..a7dd27f 100755 --- a/Util/Courbes/Fonction_nD.cc +++ b/Util/Courbes/Fonction_nD.cc @@ -38,6 +38,8 @@ #include "Fonction_expression_litterale_nD.h" #include "Fonction_externe_nD.h" #include "MotCle.h" +#include "CharUtil.h" + // CONSTRUCTEURS : // par défaut @@ -887,7 +889,8 @@ void Fonction_nD::Construction_index_conteneurs_evoluees() posi_ddl_enum(i)=position; // maintenant il faut récupérer la position = l'indice, de l'enu dans le tenseur // erreur : 18 mars 2023 Deuxentiers_enu deux = IJind(ddl_de_service.Enum(),dim); - Deuxentiers_enu deux = IJind(ddenumetendu.Enum(),dim); + // on considère qu'il s'agit de composantes de tenseur en absolu + Deuxentiers_enu deux = IJind(ddenumetendu.Enum(),ParaGlob::NbCompTens()); ind_tens(i) = deux; break; } @@ -1122,11 +1125,12 @@ Tableau & Fonction_nD::Vers_tab_double(Tableau & di di(num_variable) = (*(*tens_ddl_enum)(j))(k,l); #ifdef MISE_AU_POINT if (permet_affichage > 9) - cout << "\n num_variable= "< li_inter; // init + nom_variables.Init_list(li_inter); // on remplit la liste + li_inter.sort(); // ordonne la liste + li_inter.unique(); // supprime les redondances + // affichage + list ::iterator il,ilfin=li_inter.end(); + for (il = li_inter.begin();il != ilfin; il++) + cout << (*il) << " "; + }; + if (niveau > 1) { // les énumérés globaux éventuels int taille_enu_variables_globale= enu_variables_globale.Taille(); if (taille_enu_variables_globale != 0) - { cout << "\n enumeres_globaux:_taille " << enu_variables_globale.Taille(); + { cout << "\n enumeres_globaux: (nb total avec redondance= "<< enu_variables_globale.Taille()<<") " ; // << enu_variables_globale.Taille(); for (int i=1;i<= taille_enu_variables_globale;i++) - cout << " " << Nom_GrandeurGlobale(enu_variables_globale(i)); + {// on regarde si un élément de même type à déjà été affiché + int posi = enu_variables_globale.Contient(enu_variables_globale(i),i-1); + if (posi == 0) + cout << " " << Nom_GrandeurGlobale(enu_variables_globale(i)); + }; }; // les noms de variables globales éventuelles int taille_nom_variables_globales= nom_variables_globales.Taille(); if (taille_nom_variables_globales != 0) - { cout << "\n noms_variables_globales:_taille " << nom_variables_globales.Taille(); + { cout << "\n noms_variables_globales: (nb total avec redondance= "<< nom_variables_globales.Taille()<<") " ;// << nom_variables_globales.Taille(); for (int i=1;i<= taille_nom_variables_globales;i++) - cout << " " << nom_variables_globales(i); + {// on regarde si un élément de même type à déjà été affiché + int posi = nom_variables_globales.Contient(nom_variables_globales(i),i-1); + if (posi == 0) + cout << " " << nom_variables_globales(i); + }; }; // enu étendu équivalent aux variables non globales int taille_tab_enu_etendu= tab_enu_etendu.Taille(); if (taille_tab_enu_etendu != 0) - { cout << "\n enum_etendu_locaux:_taille " << tab_enu_etendu.Taille(); + { cout << "\n enum_etendu_locaux equivalent : (nb total avec redondance= "<< taille_tab_enu_etendu<<") " ; // << taille_tab_enu_etendu; + // l'objectif est d'afficher le tableau tab_enu_etendu + // du fait qu'il peut y avoir (due aux fct internes) une redondance + // on fait une manip pour n'afficher qu'un seul exemplaire + for (int i=1;i<= taille_tab_enu_etendu;i++) - {cout << " " << tab_enu_etendu(i).Nom_plein(); - int j = posi_ddl_enum(i); - switch (type_des_variables(i)) - {case 1: cout << " type scalaire: valeur actuelle= " - << val_ddl_enum(j) ; - break; - case 2: cout << " type coordonnees: valeur actuelle= " - << coor_ddl_enum(j)(num_dans_coor(j)); - break; - case 3: cout << " type tenseur: valeur actuelle= " - << (*tens_ddl_enum(j))(ind_tens(j).i,ind_tens(j).j) ; - break; - default: cout << "\n type non reconnue= " << type_des_variables(i) - << "\n Fonction_nD::Affiche_interne( "; - Sortie(1); - }; + {// on regarde si un élément de même type à déjà été affiché + int posi = tab_enu_etendu.Contient(tab_enu_etendu(i),i-1); + if ((posi == 0) + || ((posi !=0)&&(posi_ddl_enum(i) != posi_ddl_enum(posi))) + ) + {cout << " " << tab_enu_etendu(i).Nom_plein(); + int j = posi_ddl_enum(i); + switch (type_des_variables(i)) + {case 1: cout << " type scalaire: valeur actuelle= " + << val_ddl_enum(j) ; + break; + case 2: cout << " type coordonnees: valeur actuelle= " + << coor_ddl_enum(j)(num_dans_coor(j)); + break; + case 3: cout << " type tenseur: valeur actuelle= " + << (*tens_ddl_enum(j))(ind_tens(j).i,ind_tens(j).j) ; + break; + default: cout << "\n type non reconnue= " << type_des_variables(i) + << "\n Fonction_nD::Affiche_interne( "; + Sortie(1); + }; + }; }; // bilan des variables évoluées cout << "\n il y a: " @@ -1461,7 +1498,7 @@ void Fonction_nD::Affiche_interne(int niveau) const // grandeurs quelconques équivalentes aux variables non globales int taille_tab_enu_quelconque= tab_enu_quelconque.Taille(); if (taille_tab_enu_quelconque != 0) - { cout << "\n enum_quelconque:_taille " << tab_enu_quelconque.Taille() + { cout << "\n enum_quelconque (equivalent aux variables non globales):_taille " << tab_enu_quelconque.Taille() << "\n liste: "; for (int i=1;i<= taille_tab_enu_quelconque;i++) cout << NomTypeQuelconque(tab_enu_quelconque(i)) << ", "; @@ -1632,11 +1669,13 @@ void Fonction_nD::Lecture_variables(string& nom_lu,UtilLecture * entreePrinc) nom_variables.Init_list(list_de_variables); bool lecture_effective = false; // init - while (( (strstr(entreePrinc->tablcar,"un_argument=")==0) - && (strstr(entreePrinc->tablcar,"deb_list_var_")==0) - ) - || (nom_lu == "un_argument=") - || (nom_lu == "deb_list_var_") + while ( ( (strstr(entreePrinc->tablcar,"un_argument=")!=0) + || (strstr(entreePrinc->tablcar,"deb_list_var_")!=0) + || (nom_lu == "un_argument=") + || (nom_lu == "deb_list_var_") + ) + && (nom_lu != "fin_list_var_") +// || (lecture_effective) ) { // si on a un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur @@ -1687,7 +1726,7 @@ void Fonction_nD::Lecture_variables(string& nom_lu,UtilLecture * entreePrinc) Sortie(1); }; - + lecture_effective = false; // on réinit // cas de la lecture d'une variable if(nom_lu == "un_argument=") {*(entreePrinc->entree) >> nom_lu; @@ -1699,6 +1738,27 @@ void Fonction_nD::Lecture_variables(string& nom_lu,UtilLecture * entreePrinc) { list_de_variables_nom_globales.push_back(nom_lu);} else // sinon ce n'est pas une grandeur globale {list_de_variables.push_back(nom_lu);}; + // on gère le fait que l'on peut être à la fin de la ligne + if ((entreePrinc->entree)->rdstate() == 0) + {} // lecture normale on ne fait rien + #ifdef ENLINUX + else if ((entreePrinc->entree)->fail()) + // on a atteind la fin de la ligne et on appelle un nouvel enregistrement + { // on lira sans tenir compte des < éventuelles + entreePrinc->NouvelleDonneeSansInf(); + } + #else + else if ((entreePrinc->entree)->eof()) + // la lecture est bonne mais on a atteind la fin de la ligne + { entreePrinc->NouvelleDonneeSansInf(); + } + #endif + else // cas d'une erreur de lecture + { cout << "\n erreur de lecture inconnue "; + entreePrinc->MessageBuffer("** erreur3 des parametres d'une fonction nD **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; // on signale que la lecture a été effective lecture_effective = true; } @@ -2047,6 +2107,97 @@ void Fonction_nD::Recup_Grandeurs_globales() }; +// affichage des arguments xi internes en supprimant les redondances, +// utilisée par les fonctions dérivées +// tab_ret: le retour qui a été calculé par la fonction +// decal: donne le nombre de blanc à insérer avant l'affichage +// niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage +void Fonction_nD::Affiche_interne_valeurs_et_arguments + (int& decal,const Tableau * xi,const Tableau & tab_ret,int niveau) const + { int taille_nom_variables = nom_variables.Taille(); + int taille_enu_variables_globale= enu_variables_globale.Taille(); + int taille_nom_variables_globales= nom_variables_globales.Taille(); + + #ifdef MISE_AU_POINT + // vérif de démarrage + if (xi == NULL) + { if (taille_nom_variables != 0) + {cout << "\n *** erreur d'appel de fonction nD, on ne devrait pas avoir de variables autre que globales !! " + << "\n Fonction_nD::Affiche_interne_valeurs_arguments(..."; + Affiche(2); + Sortie(1); + }; + } + else + { if (xi->Taille() != taille_nom_variables) + {cout << "\n *** erreur d'appel de fonction nD, le nombre d'arguments ("<< xi->Taille() + <<") n'est pas coherent avec les arguments lues (avec redondance) !! " + << "\n Fonction_nD::Affiche_interne_valeurs_arguments(..."; + Affiche(2); + Sortie(1); + }; + + }; + #endif + + if (niveau > 3) + { + if (niveau < 8) + {cout << "\n";SortBlanc(decal);cout << " --- fonction: "< 4) + if (taille_nom_variables > 0) + {cout << "\n";SortBlanc(decal);cout << " les_variables_lues: " ;// nom_variables + // l'objectif est d'afficher le tableau nom_variables et les valeurs correspondantes + for (int i = 1; i<= taille_nom_variables;i++) + {// on regarde si un élément de même type à déjà été affiché + int posi = nom_variables.Contient(nom_variables(i),i-1); + if (posi == 0) // pas encore affiché, on l'affiche + cout << " " << nom_variables(i) << " = " << (*xi)(i); + }; + }; + + if (niveau > 6) + {// les énumérés globaux éventuels + if (taille_enu_variables_globale != 0) + { cout << "\n";SortBlanc(decal);cout << " enumeres_globaux: "; // << enu_variables_globale.Taille(); + for (int i=1;i<= taille_enu_variables_globale;i++) + {// on regarde si un élément de même type à déjà été affiché + int posi = enu_variables_globale.Contient(enu_variables_globale(i),i-1); + if (posi == 0) + cout << " " << Nom_GrandeurGlobale(enu_variables_globale(i)) + << " = " << x_glob(i); + }; + }; + // les noms de variables globales éventuelles + if (taille_nom_variables_globales != 0) + { cout << "\n";SortBlanc(decal);cout << " noms_variables_globales: ";// << nom_variables_globales.Taille(); + for (int i=1;i<= taille_nom_variables_globales;i++) + {// on regarde si un élément de même type à déjà été affiché + int posi = nom_variables_globales.Contient(nom_variables_globales(i),i-1); + if (posi == 0) + cout << " " << nom_variables_globales(i) + << " = " << x_glob(i+taille_enu_variables_globale); + }; + }; + }; + SortBlanc(decal);cout << " ==>> retour fonction: "; + int nb_val = tab_ret.Taille(); + for (int i=1;i<=nb_val;i++) + cout << " val("<"; + int nb_val = tab_ret.Taille(); + for (int i=1;i<=nb_val;i++) + cout << " val("< & Valeur_FnD_tab_scalaire(Tableau * val_double) {try - { -// #ifdef MISE_AU_POINT - if (permet_affichage > 4) - { - cout << "\n fonction: "< 5) - {cout << "\n parametres d'appel: "; - int nb_var = val_double->Taille(); - for (int j=1;j<=nb_var;j++) - { cout << " para("< & inter = Valeur_FnD_interne(val_double); - cout << "\n retour fonction: "; - int nb_val = inter.Taille(); - for (int i=1;i<=nb_val;i++) - cout << " val("< & inter = Valeur_FnD_interne(val_double); + int decal = 0; + Affiche_interne_valeurs_et_arguments(decal,val_double,inter,permet_affichage); + return inter; } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie @@ -330,25 +315,12 @@ class Fonction_nD {try { Vers_tab_double(t_inter_double,val_ddl_enum,coor_ddl_enum,tens_ddl_enum ,tqi,t_num_ordre); -// #ifdef MISE_AU_POINT - if (permet_affichage > 4) - {cout << "\n fonction: "< 5) - {cout << "\n parametres d'appel: "; - int nb_var = t_inter_double.Taille(); - for (int j=1;j<=nb_var;j++) - { cout << " para("< & inter = Valeur_FnD_interne(&t_inter_double); - cout << "\n retour fonction: "; - int nb_val = inter.Taille(); - for (int i=1;i<=nb_val;i++) - cout << " val("< & inter = Valeur_FnD_interne(&t_inter_double); + int decal = 0; + Affiche_interne_valeurs_et_arguments(decal,&t_inter_double,inter,permet_affichage); + return inter; } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie @@ -417,25 +389,12 @@ class Fonction_nD { if (equivalence_nom_enu_etendu_et_enu_quelconque) { try {Vers_tab_double(t_inter_double,val_ddl_enum,li_evolue_scalaire,li_evoluee_non_scalaire,tqi,t_num_ordre); -// #ifdef MISE_AU_POINT - if (permet_affichage > 4) - {cout << "\n fonction: "< 5) - {cout << "\n parametres d'appel: "; - int nb_var = t_inter_double.Taille(); - for (int j=1;j<=nb_var;j++) - { cout << " para("< & inter = Valeur_FnD_interne(&t_inter_double); - cout << "\n retour fonction: "; - int nb_val = inter.Taille(); - for (int i=1;i<=nb_val;i++) - cout << " val("< & inter = Valeur_FnD_interne(&t_inter_double); + int decal = 0; + Affiche_interne_valeurs_et_arguments(decal,&t_inter_double,inter,permet_affichage); + return inter; } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie @@ -485,19 +444,12 @@ class Fonction_nD Tableau & Valeur_pour_variables_globales() { try { -// #ifdef MISE_AU_POINT - if (permet_affichage > 4) - {cout << "\n fonction: "< & inter = Valeur_pour_variables_globales_interne(); - cout << "\n retour fonction: "; - int nb_val = inter.Taille(); - for (int i=1;i<=nb_val;i++) - cout << " val("< & inter = Valeur_pour_variables_globales_interne(); + int decal = 0; // init + Affiche_interne_valeurs_et_arguments(decal,NULL,inter,permet_affichage); + return inter; } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie @@ -518,7 +470,15 @@ class Fonction_nD // elles sont mises en public, pour pouvoir être appelées par les classes dérivées // sans avoir à déclarer en friend les classes dérivées, sinon cela fait une boucle // sans fin, d'où la solution choisit pour éviter ce pb - + + // affichage des arguments xi internes en supprimant les redondances, + // utilisée par les fonctions dérivées + // tab_ret: le retour qui a été calculé par la fonction + // decal: donne le nombre de blanc à insérer avant l'affichage + // niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage + virtual void Affiche_interne_valeurs_et_arguments + (int& decal, const Tableau * xi,const Tableau & tab_ret,int niveau) const; + // calcul des valeurs de la fonction, retour d'un tableau de scalaires virtual Tableau & Valeur_FnD_interne(Tableau * val_ddl_enum) = 0; @@ -554,7 +514,8 @@ class Fonction_nD // ramène le type de la Fonction EnumFonction_nD Type_Fonction() const { return typeFonction;}; - + // recup du niveau d'affichage + int Permet_affichage() const {return permet_affichage;}; protected : @@ -751,7 +712,7 @@ class Fonction_nD // méthode utilisée par les classes dérivées, pour transférer les infos qui sont // gérées au niveau de Fonction_nD - Fonction_nD& Transfert_info(const Fonction_nD& elt); + void Transfert_info(const Fonction_nD& elt); // affichage des données internes, utilisée par les fonctions dérivées // niveau donne le degré d'affichage @@ -785,7 +746,7 @@ class Fonction_nD // affichage des variables de la fonction, dépend du niveau d'impression void Affichage_variables() const; - + // récupération des valeurs des variables globales et stockage dans le tableau // interne x_glob void Recup_Grandeurs_globales(); diff --git a/comportement/LesLoisDeComp.cc b/comportement/LesLoisDeComp.cc index 7d37a05..d9e95a8 100644 --- a/comportement/LesLoisDeComp.cc +++ b/comportement/LesLoisDeComp.cc @@ -530,6 +530,9 @@ void LesLoisDeComp::LecMateriaux(UtilLecture& entreePrinc,LesReferences& entreePrinc.NouvelleDonnee(); // prepa du flot de lecture pt->LectureDonneesParticulieres (&entreePrinc,lesCourbes1D,lesFonctionsnD); // on enregistre et on signale si la loi est inutilisée via un warning + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank()==0) // seule le proc 0 afficher + #endif if (!ex && (ParaGlob::NiveauImpression()>1)) { cout << "\n Warning, le nom de materiau = " << st1 << " , ne correspond pas a une" diff --git a/contact/ElContact.cc b/contact/ElContact.cc index a5af13e..19e3980 100644 --- a/contact/ElContact.cc +++ b/contact/ElContact.cc @@ -451,13 +451,14 @@ ElContact::ElContact ( const Front * elf, const Noeud * noe, Fct_nD_contact & fc // pour stocker les info specifique aux intersections et tangence // par contre les info generique (noeuds etc) sont identiques Construction_TabNoeud(); // on construit le tableau de noeud global + tabNoeud_t = tabNoeud; // init tabForce_cont.Change_taille(tabNoeud.Taille()-1); tabForce_cont_t.Change_taille(tabNoeud.Taille()-1); }; // de copie ElContact::ElContact ( const ElContact & a): - tabNoeud(),tabNoeud_t() + tabNoeud(a.tabNoeud),tabNoeud_t(a.tabNoeud_t) ,Mtdt(a.Mtdt),Mt(a.Mt),M_noeud_tdt_avant_projection(a.M_noeud_tdt_avant_projection) ,phi_theta_0(a.phi_theta_0) ,force_contact(a.force_contact),tabForce_cont(a.tabForce_cont) @@ -496,7 +497,7 @@ ElContact::ElContact ( const ElContact & a): // on cree un nouvelle element generique frontiere identique // pour stocker les info specifique aux intersections et tangence // par contre les info generique (noeuds etc) sont identiques - Construction_TabNoeud(); // on construit le tableau de noeud global +// non, car normalement toutes les initialisation on déjà été faites dans "a" Construction_TabNoeud(); // on construit le tableau de noeud global }; // DESTRUCTEUR : ElContact::~ElContact () @@ -504,7 +505,45 @@ ElContact::~ElContact () }; // METHODES PUBLIQUES : +// affectation de toute les donnees +ElContact& ElContact::operator = ( const ElContact& a) + { tabNoeud=a.tabNoeud;tabNoeud_t=a.tabNoeud_t; + Mtdt=a.Mtdt;Mt=a.Mt;M_noeud_tdt_avant_projection=a.M_noeud_tdt_avant_projection; + phi_theta_0=a.phi_theta_0; + force_contact=a.force_contact;tabForce_cont=a.tabForce_cont; + force_contact_t=a.force_contact_t;tabForce_cont_t=a.tabForce_cont_t; + F_N_max=a.F_N_max;F_T_max=a.F_T_max; + F_N_max_t=a.F_N_max_t;F_T_max_t=a.F_T_max_t; + ddlElement_assemblage=a.ddlElement_assemblage; + raideur=a.raideur;residu=a.residu; + energie_penalisation=a.energie_penalisation; + energie_frottement=a.energie_frottement; + num_zone_contact=a.num_zone_contact;normale_lisser=a.normale_lisser; + nb_decol_t=a.nb_decol_t;nb_decol_tdt=a.nb_decol_tdt; + gap_t=a.gap_t;gap_tdt=a.gap_tdt;nb_pene_t=a.nb_pene_t;nb_pene_tdt=a.nb_pene_tdt; + dep_T_t=a.dep_T_t;dep_T_tdt=a.dep_T_tdt; + mult_pene_t=a.mult_pene_t;mult_pene_tdt=a.mult_pene_tdt; + mult_tang_t=a.mult_tang_t;mult_tang_tdt=a.mult_tang_tdt; + actif=a.actif;type_trajectoire_t=a.type_trajectoire_t; + type_trajectoire_tdt=a.type_trajectoire_tdt; + cas_solide=a.cas_solide;cas_collant=a.cas_collant;nb_change_frontiere=a.nb_change_frontiere; + tabNoeud_pour_assemblage=a.tabNoeud_pour_assemblage;tab_posi_esclave=a.tab_posi_esclave; + nb_posi_esclave_stocker_t=a.nb_posi_esclave_stocker_t;nb_posi_esclave_stocker_tdt=a.nb_posi_esclave_stocker_tdt; + indice_stockage_glissant_t=a.indice_stockage_glissant_t;indice_stockage_glissant_tdt=a.indice_stockage_glissant_t; + penalisation=a.penalisation;penalisation_tangentielle=a.penalisation_tangentielle; + penalisation_t=a.penalisation_t;penalisation_tangentielle_t=a.penalisation_tangentielle_t; + // utilisation éventuelle de fonction nD + fct_nD_contact=a.fct_nD_contact; + N=a.N;dep_tangentiel=a.dep_tangentiel; + // pour le contact 4, pour le calcul de la pénalisation avec une moyenne glissante + val_penal=a.val_penal;pt_dans_val_penal=a.pt_dans_val_penal; + noeud = a.noeud;noeud_t = noeud; + elfront = new Front(*(a.Elfront())); + elfront_t=elfront; + return *this; + }; + // affichage à l'écran des informations liées au contact // cas = 0 : affichage en fonction du niveau de commentaire voulu // cas = 1 : affichage minimal nécessaire pour repérer l'élément @@ -717,16 +756,48 @@ bool ElContact::Contact( bool init) int dim = noeud->Dimension(); Plan pl(dim); Droite dr(dim); int indic; // def des variables de tangence N = Calcul_Normale(dim,pl,dr,indic); + int permet_affiche = Permet_affichage(); // la seule chose que l'on peut faire pour valider le fait qu'il y a contact ou pas // c'est de tester si le noeud est à l'intérieur de l'élément d'angle mort ou pas // c'est plus long qu'un test de surface mais il n'y a pas vraiment d'autre solution int cas = elfront->PtEI()->Interne_tdt(noeud->Coord2()); - if (Permet_affichage() > 5) + if (permet_affiche > 5) {cout << "\n -- ElContact::Contact: "; cout << " Interne_tdt ? cas= " << cas <<", "; this->Affiche(1); }; - return cas; // si != 0 le point est interne + // retour : =0 le point est externe, =1 le point est interne , + // = 2 le point est sur la frontière à la précision près + if (cas == 0) + return cas; + // sinon on continue à tester + // on déclare le noeud pas en contact si la distance entre le noeud et la frontière est trop grande: + double dmax = ParaGlob::param->ParaAlgoControleActifs().DistanceMaxiAuPtProjete(); + // pour cela il nous faut le point d'impact + // calcul de la trajectoire a utiliser + Coordonnee V = Trajectoire(test); + Coordonnee M1(dim); + if (init) + {M1 = Intersection(V,true); + } + else + {M1 = Intersection(V,false);}; + // dans le cas ou M1 a une dimension nulle, signifie qu'il n'y a pas d'intersection, + // on peut alors dire qu'il ne peut pas y avoir contact donc retour + if (M1.Dimension() == 0) + return false; + // on regarde la distance d'impact + double d_MM1 = (M1-noeud->Coord2()).Norme(); + if (permet_affiche > 6) + {cout << " intersection= ";M1.Affiche(); + cout << " d_MM1= "<> nb_change_frontiere: " << nb_change_frontiere @@ -1861,6 +1932,13 @@ int ElContact::Actualisation() { int ta_taille_et1 = 1+ta->Taille(); for (int i=1; i < ta_taille_et1; i++) { + #ifdef UTILISATION_MPI + // dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu + Element & elem11 = *((*ta)(i)->PtEI()); // l'element qui contiend la frontiere + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(elem11.Num_maillage(),elem11.Num_elt_const()) ) + { + #endif if (Permet_affichage() > 5) cout << "\n >> test de l'element voisin "<PtEI()->Interne_tdt(noeud->Coord2()); @@ -1891,6 +1969,12 @@ int ElContact::Actualisation() // on commence par sauvegarder (*ta)(i) en créant une copie Front* newelfront = new Front(*((*ta)(i))); +////----- debug +//if (newelfront->NumUnique()==0) +// {cout << "\ndebug Elcontact::Actualisation , ***** NumUnique est nulle !! erreur "; +// cout << "\n (*ta)(i)->Unique() = "<<(*ta)(i)->NumUnique(); +// } +////----- fin debug // Libere(); // on supprime le elfront actuel, donc le tableau ta // on ne peut pas supprimer le elfront, car il est également pointé par elfront_t // du coup ce sera fait dans la méthode ElContact::TdtversT() @@ -1906,6 +1990,9 @@ int ElContact::Actualisation() }; if (intersec == 2) break; + #ifdef UTILISATION_MPI + }; + #endif }; }; } @@ -1946,12 +2033,12 @@ int ElContact::Actualisation() // int contactType = ElContact::Recup_et_mise_a_jour_type_contact(); if ((elfro.InSurf(extra_in_surface)) - || (nb_change_frontiere > nb_change_frontiere_max) // pour limiter les flip-flop + || (nb_change_frontiere > abs(nb_change_frontiere_max)) // pour limiter les flip-flop ) // l'intersection est ok pour l'element // cote droite : contrairement a Intersection() , on oblige ici éventuellement en fonction du modèle de contact // le point a etre sur la surface, car a priori il y a toujours contact - { intersec = 1; + { if (nb_change_frontiere_max > 0) intersec = 1; else { intersec = 0;}; } else // l'intersection est en dehors de la surface ou courbe maitre, on essaie une projection sur @@ -1961,6 +2048,14 @@ int ElContact::Actualisation() if (ta != NULL) // cas où il y a des éléments voisins ! {for (int i=1; i<= ta->Taille(); i++) { bool mitoyen_valider = false; + + #ifdef UTILISATION_MPI + // dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu + Element & elem11 = *((*ta)(i)->PtEI()); // l'element qui contiend la frontiere + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(elem11.Num_maillage(),elem11.Num_elt_const()) ) + { + #endif if (Permet_affichage() > 5) cout << "\n >> test de l'element voisin "< 2) + if (Permet_affichage() > 3) {cout << "\n change front. du noeud "<< noeud->Num_noeud() <<" mail= " << noeud->Num_Mail() << " == "; elfront->Affiche(1); @@ -2037,6 +2136,14 @@ int ElContact::Actualisation() // on commence par sauvegarder (*ta)(i) Front* newelfront = new Front(*((*ta)(i))); + +// //----- debug +// if (newelfront->NumUnique()==0) +// {cout << "\ndebug Elcontact::Actualisation , ***** NumUnique est nulle !! erreur 2 "; +// cout << "\n (*ta)(i)->Unique() = "<<(*ta)(i)->NumUnique(); +// } +// //----- fin debug + // Libere(); // on supprime le elfront actuel, donc le tableau ta // on ne peut pas supprimer le elfront, car il est également pointé par elfront_t // du coup ce sera fait dans la méthode ElContact::TdtversT() diff --git a/contact/ElContact.h b/contact/ElContact.h index 3fa102f..24b772c 100644 --- a/contact/ElContact.h +++ b/contact/ElContact.h @@ -171,15 +171,18 @@ class ElContact // du fait éventuel qu'il peut-être collant ou pas ElContact ( const Front * elfront, const Noeud * noeud, Fct_nD_contact & fct_contact_, int collant = 0); // de copie - ElContact ( const ElContact & a); + ElContact ( const ElContact & a); // DESTRUCTEUR : ~ElContact (); // METHODES PUBLIQUES : - // test d'egalite sur les éléments originaux : - // l'élément de frontière front, le noeud esclave, même zone de contact - inline bool MemeOrigine( const ElContact& a) const + // affectation de toute les donnees + ElContact& operator = ( const ElContact& a); + + // test d'egalite sur les éléments originaux : + // l'élément de frontière front, le noeud esclave, même zone de contact + inline bool MemeOrigine( const ElContact& a) const { if ( (this->elfront->MemeOrigine(*a.Elfront())) && (this->noeud->Num_noeud() == a.Const_Esclave()->Num_noeud()) && (this->noeud->Num_Mail() == a.Const_Esclave()->Num_Mail()) @@ -347,6 +350,11 @@ class ElContact virtual Vecteur* SM_charge_contact(); // -> implicite, virtual Element::ResRaid SM_K_charge_contact(); + // récup uniquement des conteneurs raideurs et résidu (pas forcément remplis, mais de la bonne taille) + Element::ResRaid Conteneur_ResRaid(); + // récup uniquement du conteneur résidu (pas forcément rempli, mais de la bonne taille) + Vecteur* Conteneur_Residu(); + // récupération des énergies intégrées sur l'éléments, résultants d'un précédent calcul // explicite, ou implicite: // 1- il s'agit ici de l'énergie développée par le frottement glissant ou pas @@ -398,7 +406,28 @@ class ElContact void Lec_base_info_ElContact(ifstream& ent); void Ecri_base_info_ElContact(ofstream& sort); - +#ifdef UTILISATION_MPI // spécifique au calcul parallèle + // stockage dans un unique vecteur, des infos à partir de l'indice rang inclus + // correspond à une sérialisation des infos + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + // niveau: == 1 -> niveau minimum de sauvegarde, concerne uniquement la structure de l'élément + int Pack_vecteur(int niveau, Vecteur& v,int rang) const; + // taille du conteneur actuel de la condition linéaire + // dépend du niveau de sauvegarde + int Taille_Pack(int niveau) const; + // modification des infos à partir de l'indice rang inclus en fonction du vecteur passé en paramètre + // correspond à une désérialisation + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + // on passe un pointeur de fonctions qui ramène un noeud en fonction d'un numéro de maillage et d'un + // numéro de noeud, ceci pour éviter de passer toute l'instance de la classe Les_maillages + // niveau: == 1 -> niveau minimum de sauvegarde, concerne uniquement la structure de l'élément + + template int UnPack_vecteur(T& instance,int niveau,const Vecteur& v,int rang, + Noeud & (T::*Ptfonc) (int num_mail,int num_noeud) const ); +#endif + protected : // VARIABLES PROTEGEES : int actif; // un indicateur, disant si le contact est actif ou pas @@ -543,4 +572,9 @@ protected : }; /// @} // end of group +// pour faire de l'inline: nécessaire avec les templates +// on n'inclut que les méthodes templates +#include "ElContact_3.cc" +#define ElContact_deja_inclus + #endif diff --git a/contact/ElContact_2.cc b/contact/ElContact_2.cc index 5e64b3a..19e7d4f 100755 --- a/contact/ElContact_2.cc +++ b/contact/ElContact_2.cc @@ -1437,6 +1437,35 @@ Element::ResRaid ElContact::SM_K_charge_contact() return el; }; + +// récup uniquement des conteneurs raideurs et résidu (pas forcément remplis, mais de la bonne taille) +Element::ResRaid ElContact::Conteneur_ResRaid() + { Mise_a_jour_ddlelement_cas_solide_assemblage(); // mise à jour de ddl element et de cas_solide + // def de quelques dimensions pour simplifier + int dima = ParaGlob::Dimension(); + int tab_taille = tabNoeud.Taille(); + int nbddl = ddlElement_assemblage->NbDdl(); + // récup d'une place pour le résidu local et mise à jour de list_SM éventuellement + RecupPlaceResidu(nbddl); + // idem pour la raideur + RecupPlaceRaideur(nbddl); + // préparation du retour + Element::ResRaid el; + el.res = residu; + el.raid = raideur; + return el; + }; +// récup uniquement du conteneur résidu (pas forcément rempli, mais de la bonne taille) +Vecteur* ElContact::Conteneur_Residu() + {Mise_a_jour_ddlelement_cas_solide_assemblage(); // mise à jour de ddl element et de cas_solide + // def de quelques dimensions pour simplifier + int dima = ParaGlob::Dimension(); + int tab_taille = tabNoeud.Taille(); + int nbddl = ddlElement_assemblage->NbDdl(); + // récup d'une place pour le résidu local et mise à jour de list_SM éventuellement + RecupPlaceResidu(nbddl); + return residu; + }; //================================= methodes privées =========================== @@ -1936,7 +1965,7 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact case 2: case 3: case 4: case 5: case 6: case 7: case 8:// calcul du type ls-dyna avec la compressibilité du maître { // on choisit en fonction de la géométrie si il existe une compressibilité ElFrontiere* elfrontiere = elfront->Eleme(); // pour simplifier l'écriture - const Element * elem = elfront->PtEI(); // idem + Element * elem = elfront->PtEI(); // idem if (((const ElemMeca*) elem)->CompressibiliteMoyenne() > 0.) { switch (elfrontiere->Type_geom_front()) { case SURFACE: @@ -1954,6 +1983,8 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact } else // sinon c'est bon {facteur = surf*surf/volume;} + if (Permet_affichage() > 4) + cout << "\n SURFACE d'un volume: facteur = "<< facteur; } else if (elem->ElementGeometrie(X1).Dimension()==2) { // cas d'une surface frontière d'un élément coque ou plaque @@ -1969,25 +2000,47 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact } else // sinon c'est bon {facteur = surf/maxdiag;} + if (Permet_affichage() > 4) + cout << "\n SURFACE d'une coque ou plaque: facteur = "<< facteur; }; break; // pour mémoire pour la suite POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM - //******** partie en construction - case LIGNE: // --- on traite les cas particuliers des éléments d'angle mort if (elfront->Angle_mort()) - { // il n'y a pas de notion de surface de contact et l'idée est de récupérer - // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément - // on retient une expression simple - double longueur = elem->LongueurGeometrique_mini(1); - facteur = longueur; - //%%%% essai %%%% - longueur = elem->LongueurGeometrique_mini(1); - double volume = elem->Volume(); - facteur = volume / (longueur * longueur); - //%%%% fin essai %%%% + { +// il n'y a pas de notion de surface de contact et l'idée est de récupérer +// // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément +// // on retient une expression simple +// double longueur = elem->LongueurGeometrique_caracteristique(1); +// facteur = longueur; +// if (Permet_affichage() > 4) +// cout << "\n angle mort: facteur1 = "<< facteur; +// //%%%% essai %%%% +// longueur = elem->LongueurGeometrique_caracteristique(1); +// double volume = elem->Volume(); +// facteur = volume / (longueur * longueur); +// if (Permet_affichage() > 4) +// cout << "\n angle mort: facteur2 = "<< facteur; +// +// //%%%% fin essai %%%% + + double longueur = elem->LongueurGeometrique_caracteristique(1); + double volume = elem->Volume(); + if (Dabs(volume) <= ConstMath::pasmalpetit) + { if (Permet_affichage() > 1) + cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage " + << elem->Num_maillage() << " est nul, on utilise le max de diagonal "; + if (Permet_affichage() > 4) + cout << "\n ElContact::CalFactPenal()"; + facteur = elfrontiere->MaxDiagonale_tdt(); + } + else // sinon c'est bon + {facteur = volume/longueur/longueur;}; + if (Permet_affichage() > 4) + cout << "\n LIGNE angle mort: facteur = "<< facteur; + } else {// --- cas d'un élément de contact autre que d'angle mort @@ -1997,7 +2050,7 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact if (elem->ElementGeometrie(X1).Dimension()==2) // élément 2D en axi donc 3D en réalité { // récup de la longueur de la frontière - double longueur = elfrontiere->LongueurApprox(); + // double longueur = elfrontiere->LongueurApprox(); // on calcul la surface associée // M_impact(1) = x donc = le rayon car on est axi autour de y //// double surf = longueur * M_impact(1) * ConstMath::Pi * 2.; @@ -2005,19 +2058,49 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact // donc il ne faut pas tenir compte du point d'impact ?? sinon par exemple si le point est au centre // M_impact(1) = 0 et on n'a pas de surf !! // mais plus généralement, le pt d'impact ne doit pas interférer à mon avis - double surf = longueur * ConstMath::Pi * 2.; + // 3 fevr 2023 : c'est incohérent, car surf n'a pas la dimension d'une surface + // du coup avec le volume qui est vraiment de dim 3 on aura une grandeur non cohérente + // par rapport à la formule de base double surf = longueur * ConstMath::Pi * 2.; + // du coup on va utiliser la surface de l'élément + #ifdef MISE_AU_POINT + if (!(elem->SurfExiste(1))) + {cout << "\n *** erreur la surface l'element axi " << elem->Num_elt_const() << " du maillage " + << elem->Num_maillage() << " n'est pas disponible, on stop "; + Sortie(1); + }; + #endif + // on récupère la surface de l'élément qui a créé la frontière - double volume = elem->Volume(); - if (Dabs(volume) <= ConstMath::pasmalpetit) - { if (Permet_affichage() > 1) - cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage " - << elem->Num_maillage() << " est nul, on utilise le max de diagonal "; - if (Permet_affichage() > 4) - cout << "\n ElContact::CalFactPenal()"; - facteur = elfrontiere->MaxDiagonale_tdt(); - } - else // sinon c'est bon - {facteur = surf*surf/volume;} + ElFrontiere* const elfro_elem = elem->Frontiere_surfacique(1,false); + double surf = elfro_elem->SurfaceApprox(); // là on a bien la surface approximative de l'élément de surface axi + double longueur = elfrontiere->MaxDiagonale_tdt(); + facteur = surf / longueur; + // comme on est en axisymétrie, la force résultante doit-être multipliée par la circonférence du point d'application + // pour être cohérente avec les forces internes de réaction des éléments maîtres, qui eux sont relatives à des volumes + // pour maximiser la force: on utilise la coordonnée x maxi des noeuds de l'élément maître, et on évite la coordonnée x du point + // d'impact qui est nulle pour le centre par exemple + double maxi_x1 = elem->Maxi_xi_noeud(1, TEMPS_t);// on se contente de la valeur à t, car il s'agit d'une approximation et cela évite l'instabilité + facteur *= maxi_x1 * ConstMath::Pi * 2.; // on se contente de la valeur à t, car il s'agit d'une approximation et cela évite l'instabilité + +// +// +// +// double volume = elem->Volume(); // là il s'agit du volume totale +// if (Dabs(volume) <= ConstMath::pasmalpetit) +// { if (Permet_affichage() > 1) +// cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage " +// << elem->Num_maillage() << " est nul, on utilise le max de diagonal "; +// if (Permet_affichage() > 4) +// cout << "\n ElContact::CalFactPenal()"; +// facteur = elfrontiere->MaxDiagonale_tdt(); +// } +// else // sinon c'est bon +// {facteur = surf*surf/volume;} + + if (Permet_affichage() > 4) + cout << "\n LIGNE en axi: facteur = "<< facteur + << ", surface= " << surf <<", longueur= " << longueur; + } else // sinon ce n'est pas pris en charge {cout << "\n *** erreur: cas non pris en charge pour l'instant: " @@ -2028,17 +2111,9 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact }; } else if (elem->ElementGeometrie(X1).Dimension()==3) - // cas d'une ligne frontière d'un élément coque ou plaque - { - // il faut finir la fonction ElFrontiere::LongueurApprox() - // cf le laïus qui est écrit dans la méthode - - - double surf = elfrontiere->SurfaceApprox(); + // cas d'une ligne frontière d'un élément volumique + { double longueur = elem->LongueurGeometrique_caracteristique(1); double volume = elem->Volume(); - - // virtual double EpaisseurMoyenne(Enum_dure ) - if (Dabs(volume) <= ConstMath::pasmalpetit) { if (Permet_affichage() > 1) cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage " @@ -2048,11 +2123,13 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact facteur = elfrontiere->MaxDiagonale_tdt(); } else // sinon c'est bon - {facteur = surf*surf/volume;} + {facteur = volume/longueur/longueur;} + if (Permet_affichage() > 4) + cout << "\n LIGNE d'un volume: facteur = "<< facteur; } else if (elem->ElementGeometrie(X1).Dimension()==2) // cas d'une ligne frontière d'une plaque - { double longueur = elfrontiere->LongueurApprox(); + { double longueur = elfrontiere->LongueurApprox(); double epais = 0.; // init if (!ParaGlob::AxiSymetrie()) // si on n'est pas en axi {epais = ((ElemMeca*) elem)->EpaisseurMoyenne(TEMPS_tdt );} @@ -2060,24 +2137,43 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact {epais = 1.;}; double surf = elem->Volume() / epais; facteur = surf/longueur; + if (Permet_affichage() > 4) + cout << "\n LIGNE d'une plaque: facteur = "<< facteur; }; }; break; - - //******** fin partie en construction case POINT_G: // --- on traite les cas particuliers des éléments d'angle mort if (elfront->Angle_mort()) - { // il n'y a pas de notion de surface de contact et l'idée est de récupérer - // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément - // on retient une expression simple - double longueur = elem->LongueurGeometrique_mini(1); - facteur = longueur; - //%%%% essai %%%% - longueur = elem->LongueurGeometrique_mini(1); - double volume = elem->Volume(); - facteur = volume / (longueur * longueur); - //%%%% fin essai %%%% + { +// // il n'y a pas de notion de surface de contact et l'idée est de récupérer +// // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément +// // on retient une expression simple +// double longueur = elem->LongueurGeometrique_caracteristique(1); +// facteur = longueur; +// if (Permet_affichage() > 4) +// cout << "\n angle mort: facteur1 = "<< facteur; +// //%%%% essai %%%% +// double volume = elem->Volume(); +// facteur = volume / (longueur * longueur); +// //%%%% fin essai %%%% +// if (Permet_affichage() > 4) +// cout << "\n angle mort: facteur2 = "<< facteur; + double longueur = elem->LongueurGeometrique_caracteristique(1); + double volume = elem->Volume(); + if (Dabs(volume) <= ConstMath::pasmalpetit) + { if (Permet_affichage() > 1) + cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage " + << elem->Num_maillage() << " est nul, on utilise le max de diagonal "; + if (Permet_affichage() > 4) + cout << "\n ElContact::CalFactPenal()"; + facteur = elfrontiere->MaxDiagonale_tdt(); + } + else // sinon c'est bon + {facteur = volume/longueur/longueur;}; + if (Permet_affichage() > 4) + cout << "\n POINT_G angle mort: facteur = "<< facteur + << ", volume = " << volume << ", longueur = " << longueur; } else { // --- cas d'un élément de contact autre que d'angle mort @@ -2088,9 +2184,12 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact {// on veut calculer Ke * Ae * Ae / vol , comme on est dans le cas d'une barre // vol = long * section, et Ae = section , du coup: // Ke * Ae * Ae / vol = Ke * vol / (long * long) avec long = la longueur de l'élément - double longueur = elem->LongueurGeometrique_mini(1); + double longueur = elem->LongueurGeometrique_caracteristique(1); double volume = elem->Volume(); facteur = volume / (longueur * longueur); + if (Permet_affichage() > 4) + cout << "\n POINT_G en dim espace 1D: facteur = "<< facteur + << ", volume = " << volume << ", longueur = " << longueur; } else {cout << "\n *** erreur: cas non pris en charge pour l'instant: " @@ -2411,10 +2510,10 @@ double ElContact::CalFactPenalTangentiel(const double& dep_T,double & d_beta_dep { // il n'y a pas de notion de surface de contact et l'idée est de récupérer // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément // on retient une expression simple - double longueur = elem->LongueurGeometrique_mini(1); + double longueur = elem->LongueurGeometrique_caracteristique(1); facteur = longueur; //%%%% essai %%%% - longueur = elem->LongueurGeometrique_mini(1); + longueur = elem->LongueurGeometrique_caracteristique(1); double volume = elem->Volume(); facteur = volume / (longueur * longueur); //%%%% fin essai %%%% @@ -2495,7 +2594,7 @@ double ElContact::CalFactPenalTangentiel(const double& dep_T,double & d_beta_dep { // il n'y a pas de notion de surface de contact et l'idée est de récupérer // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément // on retient une expression simple - double longueur = elem->LongueurGeometrique_mini(1); + double longueur = elem->LongueurGeometrique_caracteristique(1); facteur = longueur; } else @@ -2507,7 +2606,7 @@ double ElContact::CalFactPenalTangentiel(const double& dep_T,double & d_beta_dep {// on veut calculer Ke * Ae * Ae / vol , comme on est dans le cas d'une barre // vol = long * section, et Ae = section , du coup: // Ke * Ae * Ae / vol = Ke * vol / (long * long) avec long = la longueur de l'élément - double longueur = elem->LongueurGeometrique_mini(1); + double longueur = elem->LongueurGeometrique_caracteristique(1); double volume = elem->Volume(); facteur = volume / (longueur * longueur); } diff --git a/contact/LesContacts.cc b/contact/LesContacts.cc index e82eb47..d3f3ee4 100644 --- a/contact/LesContacts.cc +++ b/contact/LesContacts.cc @@ -34,8 +34,6 @@ #include "ReferenceAF.h" #include "CharUtil.h" -#include "Enum_TypeQuelconque.h" -#include "TypeQuelconqueParticulier.h" // --------------- variables statiques --------- @@ -119,9 +117,13 @@ bool LesContacts::ReactCont::operator != (const LesContacts::ReactCont& a) LesContacts::LesContacts () : listCoLin(),tabReacCont(),listContact()//,numtesN() ,sauve_lesFonctionsnD(NULL),fct_nD_contact() + ,fct_niveau_commentaire(NULL),li_pour_noeuds_element(),gr_pour_noeud(NULL),gr_pour_elem(NULL) ,listContact_nouveau_tatdt(),listContact_efface_tatdt() ,nom_ref_zone_contact(),lissage_de_la_normale() ,t_listFront(),nb_mail_Esclave(),nbmailautocontact(0),nbmailMaitre() +#ifdef UTILISATION_MPI + ,pointe_t_listFront(),v_interProc_contact_actif() +#endif ,tesctotal(),tesN_encontact() ,tesN_collant() ,nb_contact_actif(0),indice(),cont_solide_defor(),liQ_en_sortie() @@ -131,15 +133,26 @@ LesContacts::LesContacts () : ,temps_transfert_court(),temps_transfert_long(),temps_attente() ,inter_transfer(),inter_transfer2(),lesMaille(NULL) #endif - {}; + {// pour une sortie spécifique noeud et ou element + Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques + li_pour_noeuds_element.push_front(TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier)); + gr_pour_noeud = ((Grandeur_scalaire_entier*) (*li_pour_noeuds_element.begin()).Grandeur_pointee()); + li_pour_noeuds_element.push_front(TypeQuelconque(NUM_ELEMENT,EPS11,grand_courant_entier)); + gr_pour_elem = ((Grandeur_scalaire_entier*) (*li_pour_noeuds_element.begin()).Grandeur_pointee()); +}; // constructeur de copie LesContacts::LesContacts (const LesContacts& a): listCoLin(a.listCoLin),tabReacCont(a.tabReacCont) ,sauve_lesFonctionsnD(a.sauve_lesFonctionsnD),fct_nD_contact(a.fct_nD_contact) + ,fct_niveau_commentaire(a.fct_niveau_commentaire),li_pour_noeuds_element(a.li_pour_noeuds_element) + ,gr_pour_noeud(a.gr_pour_noeud),gr_pour_elem(a.gr_pour_elem) ,listContact(a.listContact)//,numtesN(a.numtesN) ,listContact_nouveau_tatdt(a.listContact_nouveau_tatdt),listContact_efface_tatdt(a.listContact_efface_tatdt) ,nom_ref_zone_contact(a.nom_ref_zone_contact),lissage_de_la_normale(a.lissage_de_la_normale) ,t_listFront(a.t_listFront),nb_mail_Esclave(a.nb_mail_Esclave),nbmailautocontact(a.nbmailautocontact) +#ifdef UTILISATION_MPI + ,pointe_t_listFront(),v_interProc_contact_actif() +#endif ,nbmailMaitre(a.nbmailMaitre),tesctotal(a.tesctotal),tesN_encontact(a.tesN_encontact) ,tesN_collant(a.tesN_collant) ,nb_contact_actif(a.nb_contact_actif),indice(a.indice),cont_solide_defor(a.cont_solide_defor) @@ -150,7 +163,29 @@ LesContacts::LesContacts (const LesContacts& a): ,temps_transfert_long(a.temps_transfert_long),temps_attente(a.temps_attente) ,inter_transfer(),inter_transfer2(),lesMaille(NULL) #endif - {}; + {// on réaffecte les pointeurs pour la sortie spécifique noeud et ou element + list ::iterator ili = li_pour_noeuds_element.begin(); + gr_pour_elem = ((Grandeur_scalaire_entier*) (*ili).Grandeur_pointee()); + ili++; + gr_pour_noeud = ((Grandeur_scalaire_entier*) (*ili).Grandeur_pointee()); +#ifdef UTILISATION_MPI + // on redéfini le tableau pointe_t_listFront() et la numérotation unique dans les fronts stockés + pointe_t_listFront.Change_taille(a.pointe_t_listFront.Taille()); + int nb_zone = MaX(1,nom_ref_zone_contact.size()); + int inum = 1; + for (int i=1;i<=nbmailMaitre;i++) + { for (int j=1;j<=nb_zone;j++) + { LaLIST_io & list_fronta = (t_listFront(i)(j)); // pour simplifier + LaLIST_io ::iterator il,ilfin = list_fronta.end(); + for (il = list_fronta.begin();il != ilfin; il++,inum++) + {pointe_t_listFront(inum) = &(*il); + (*il).ChangeNumUnique(inum); + }; + }; + }; +#endif + + }; // DESTRUCTEUR : LesContacts::~LesContacts () { }; @@ -179,13 +214,13 @@ void LesContacts::Init_contact(LesMaillages& lesMail int niveau_commentaire_lescontacts = Permet_affichage(); // on met à jour le niveau de commentaire dans les éléments de contact ElContact::Mise_a_jour_niveau_commentaire(); - if (niveau_commentaire_lescontacts > 4) #ifdef UTILISATION_MPI // on sauvegarde un pointeur sur les maillages lesMaille = &lesMail; if (ParaGlob::Monde()->rank() == 0) #endif + if (niveau_commentaire_lescontacts > 4) cout << "\n -- LesContacts::Init_contact: "; Creation_Fct_nD_contact(); // récupération des fonctions de pilotage éventuelles @@ -551,17 +586,55 @@ void LesContacts::Init_contact(LesMaillages& lesMail // on définit et on ajoute les fronts des angles morts ElementAngleMort(lesMail); - - // Pour diminuer le temps de recherche, et aussi les messages on va constituer une liste des éléments - // qui contiennent les frontières + + // il faut mettre à jour les mitoyens des Front: c-a-d il faut que les mitoyens + // soient eux-même des fronts de t_listFront int nb_zone = MaX(1,nom_ref_zone_contact.size()); - liste_elemens_front.clear(); // init de la liste for (int i=1;i<=nbmailMaitre;i++) { for (int j=1;j<=nb_zone;j++) { LaLIST_io & list_fronta = (t_listFront(i)(j)); // pour simplifier LaLIST ::iterator iM,iMfin=list_fronta.end(); for (iM = list_fronta.begin();iM != iMfin; iM++) // boucle sur les frontières enregistrées - liste_elemens_front.push_back((*iM).PtEI()); + {Front & fronta = (*iM); // pour simplifier + const Tableau * ta = fronta.TabMitoyen(); // récup des mitoyens + if (ta != NULL) // cas où il y a des éléments voisins ! + { const Tableau & taa = *ta; // pour simplifier + int ta_taille = ta->Taille(); + Tableau inter(ta_taille);// un tableau inter de travail + for (int i=1; i <= ta_taille; i++) + // on récupère l'élément ad hoc + {Front* froon = Front_de_meme_origine(taa(i),j); + if (froon != NULL) + {inter(i)=froon;} + else // sinon c'est un pb pour la suite + {cout << "\n *** erreur dans la definition des mitoyens pour l'initialisation des frontieres de contact " + << " on n'a pas trouve dans la zone de contact une frontiere adequate : arret "; + Sortie(1); + }; + }; + // on peut maintenant remplacer le tableau de mitoyen + fronta.DefMitoyen(inter); + }; + }; + }; + }; + + // Pour diminuer le temps de recherche, et aussi les messages on va constituer une liste des éléments + // qui contiennent les frontières + liste_elemens_front.clear(); // init de la liste + #ifdef UTILISATION_MPI + int nb_total_front=0; // permet ensuite de dimensionner le tableau pointe_t_listFront + #endif + for (int i=1;i<=nbmailMaitre;i++) + { for (int j=1;j<=nb_zone;j++) + { LaLIST_io & list_fronta = (t_listFront(i)(j)); // pour simplifier + LaLIST ::iterator iM,iMfin=list_fronta.end(); + for (iM = list_fronta.begin();iM != iMfin; iM++) // boucle sur les frontières enregistrées + {liste_elemens_front.push_back((*iM).PtEI()); + #ifdef UTILISATION_MPI + nb_total_front++; + #endif + }; }; }; // on ordonne la liste puis on supprime les doublons @@ -585,6 +658,52 @@ void LesContacts::Init_contact(LesMaillages& lesMail // } //} ////-- fin debug + + #ifdef UTILISATION_MPI + // on défini le tableau pointe_t_listFront et on définit le numéro associé unique dans les fronts + pointe_t_listFront.Change_taille(nb_total_front); + int inum = 1; + for (int i=1;i<=nbmailMaitre;i++) + { for (int j=1;j<=nb_zone;j++) + { LaLIST_io & list_fronta = (t_listFront(i)(j)); // pour simplifier + LaLIST_io ::iterator il,ilfin = list_fronta.end(); + for (il = list_fronta.begin();il != ilfin; il++,inum++) + {pointe_t_listFront(inum) = &(*il); + (*il).ChangeNumUnique(inum); + }; + }; + }; +// //--- debug +// {cout << "\n debug : LesContacts::Init_contact "; +// for (int i=1;i<=nbmailMaitre;i++) +// { for (int j=1;j<=nb_zone;j++) +// { LaLIST_io & list_fronta = (t_listFront(i)(j)); // pour simplifier +// LaLIST_io ::iterator il,ilfin = list_fronta.end(); +// for (il = list_fronta.begin();il != ilfin; il++) +// {if ((*il).NumUnique() == 0) +// cout << "\n debug : LesContacts::Init_contact " +// << " ***** erreur numunique == 0 !!" ; +// // maintenant on s'occupe des mitoyens +// {Front & fronta = (*il); // pour simplifier +// const Tableau * ta = fronta.TabMitoyen(); // récup des mitoyens +// if (ta != NULL) // cas où il y a des éléments voisins ! +// { const Tableau & taa = *ta; // pour simplifier +// int ta_taille = ta->Taille(); +// for (int i=1; i <= ta_taille; i++) +// {if (taa(i)->NumUnique() == 0) +// cout << "\n debug : LesContacts::Init_contact " +// << " ***** erreur dans les mitoyens : numunique == 0 !!" ; +// }; +// }; +// }; +// +// }; +// }; +// }; +// } +// //-- fin debug + #endif + tempsContact.Arret_du_comptage(); // fin cpu }; @@ -651,7 +770,7 @@ void LesContacts::Verification() if ((elem.Interne_t(pt_esc)==1) && (niveau_commentaire_lescontacts >= 3)) { cout << "\n attention, noeud esclave dans elem. " << "avant incre. 1 charge"; - if (niveau_commentaire_lescontacts > 2) + if (niveau_commentaire_lescontacts > 3) cout << "\n LesContacts::Verification(..)"; int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); cout << "\n -> noeud " << tesc(inesc)->Num_noeud() << " du maillage " << tesc(inesc)->Num_Mail() @@ -676,6 +795,8 @@ void LesContacts::Verification() // cette méthode est utilisée au début du calcul, ensuite c'est Nouveau() // qui prend le relais // ramène true s'il y a effectivement création d'élément de contact +// en parallèle seules les proc i>0 définissent des éléments de contact +// le proc 0 ne fait rien, il récupère le retour et fait le bilan bool LesContacts::DefElemCont(double dep_max) { tempsContact.Mise_en_route_du_comptage(); // def deb compt @@ -706,7 +827,11 @@ bool LesContacts::DefElemCont(double dep_max) int nb_zone = MaX(1,nom_ref_zone_contact.size()); double dist_max = Dabs(ParaGlob::param->ParaAlgoControleActifs().DistanceMaxiAuPtProjete()); - + #ifdef UTILISATION_MPI + if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact + { + #endif + // on va iterer sur les noeuds esclaves pour savoir s'ils ont une trajectoire // qui cree un contact avec les elements maitres, ou l'inverse, c-a-d s'ils sont // dans de la matiere @@ -811,6 +936,10 @@ bool LesContacts::DefElemCont(double dep_max) ElContact elcont(&(*iM),tesc(inesc),fct_nD_contact,tesN_col(inesc)); elcont.Num_zone_contact()=j_zone; // affectation du numéro de zone elcont.Change_lissage_normale(lissage_de_la_normale(j_zone)); // affectation du lissage + #ifdef UTILISATION_MPI + // on attribue au front de l'élément de contact, le numéro unique utilisable pour le tableau pointe_t_listFront + elcont.Elfront()->ChangeNumUnique((*iM).NumUnique()); + #endif // calcul du contact, et translation (éventuelle) du noeud sur la surface si le contact existe bool init_inter = true; // on est en phase d'initialisation // //--- debug @@ -825,7 +954,7 @@ bool LesContacts::DefElemCont(double dep_max) #else cout << "\n" #endif - << " recherche du contact entre noeud " << elcont.Esclave()->Num_noeud() + << " recherche du contact entre noeud " << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() << " et frontiere " << (*iM).Num_frontiere() << " de l'element " << elem.Num_elt() << " du maillage " @@ -885,7 +1014,7 @@ bool LesContacts::DefElemCont(double dep_max) #else cout << "\n" #endif - << "\ncontact entre noeud " ; + << "contact entre noeud " ; if (tesN_col(inesc)) cout << " collant "; cout << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() @@ -930,7 +1059,7 @@ bool LesContacts::DefElemCont(double dep_max) listContact_nouveau_tatdt.push_front(listContact.begin()); tesN_encontact_ii[noee].push_front(listContact.begin()); // on n'intervient pas sur tesN_encontact, car ça ne change pas - if (niveau_commentaire_lescontacts > 2) + if (niveau_commentaire_lescontacts > 3) { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours @@ -938,7 +1067,7 @@ bool LesContacts::DefElemCont(double dep_max) cout << "\n" #endif << " --- changement d'element en contact ---"; - cout << "\ncontact entre noeud " ; + cout << "contact entre noeud " ; if (tesN_col(inesc)) cout << " collant "; cout << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() @@ -965,8 +1094,19 @@ bool LesContacts::DefElemCont(double dep_max) }; //-- fin du test if (!tesN_encontact(intot)(n_noee)) }; //-- fin de la boucle sur inesc }; //-- fin de la boucle sur les zones + + #ifdef UTILISATION_MPI + }; // fin du cas des proc i > 0 + #endif + // retour + #ifdef UTILISATION_MPI + if (proc_en_cours != 0) + { + if (niveau_commentaire_lescontacts > 4) // ==> LesContacts:: + #else if (niveau_commentaire_lescontacts > 2) // ==> LesContacts:: + #endif { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours @@ -980,6 +1120,53 @@ bool LesContacts::DefElemCont(double dep_max) cout <<", "<isend(0, 61, inter_entiers); + // on attend pas + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les infos + tempsContact.Arret_du_comptage(); // fin cpu + int nb_contact=0;int nb_new_contact = 0;int nb_efface_contact = 0; // que l'on va cumuler + + int nb_proc_terminer = 0; // permettra de terminer + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) + { // on récupère un résultat de cpu i + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + QuatreEntiers inter_entiers; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 61, inter_entiers ); + reqs1.wait(); // on attend que le conteneur soit rempli + // on cumule + nb_contact += inter_entiers.deux; + nb_new_contact += inter_entiers.trois; + nb_efface_contact += inter_entiers.quatre; + + if (inter_entiers.un) // si un seul des retour s est bon on passe à true + retour = true; + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + }; + + if (niveau_commentaire_lescontacts > 2) // ==> LesContacts:: + {cout << "\n apres Def Elem Cont: "<< nb_contact << " elem contact "; + if ( nb_new_contact) + cout <<", "<< nb_new_contact << " nouveau(x) "; + if (nb_efface_contact) + cout <<", "< li_pour_noeuds; // pour une sortie spécifique noeud - Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques - li_pour_noeuds.push_front(TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier)); - Grandeur_scalaire_entier& gr_pour_noeud - = *((Grandeur_scalaire_entier*) (*li_pour_noeuds.begin()).Grandeur_pointee()); - list li_pour_elcont; // pour une sortie spécifique élément finis - li_pour_elcont.push_front(TypeQuelconque(NUM_ELEMENT,EPS11,grand_courant_entier)); +////--- debug +//cout << "\n debug LesContacts::Nouveau "<< " niveau_commentaire_lescontacts = "<< niveau_commentaire_lescontacts<< flush; +////--- fin debug +// list li_pour_noeuds; // pour une sortie spécifique noeud +// Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques +// li_pour_noeuds.push_front(TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier)); +// Grandeur_scalaire_entier& gr_pour_noeud +// = *((Grandeur_scalaire_entier*) (*li_pour_noeuds.begin()).Grandeur_pointee()); +// list li_pour_elcont; // pour une sortie spécifique élément finis +// li_pour_elcont.push_front(TypeQuelconque(NUM_ELEMENT,EPS11,grand_courant_entier)); #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); #endif int nb_zone = MaX(1,nom_ref_zone_contact.size()); - + bool retour = false; // init du retour + // on sauvegarde la liste au départ int taille_list_contact_nouveau_au_debut = listContact_nouveau_tatdt.size(); @@ -1017,6 +1208,11 @@ bool LesContacts::Nouveau(double dep_max) cout << "\n" #endif << " -- LesContacts::Nouveau: temps= " << ParaGlob::Variables_de_temps().TempsCourant(); + #ifdef UTILISATION_MPI + if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact + { + #endif + // on montre les noeuds actuellement en contact if (Permet_affichage() > 4) { @@ -1035,8 +1231,9 @@ bool LesContacts::Nouveau(double dep_max) for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves {Noeud* no = tesc(inesc); int n_noee = no->Num_noeud(); - (*gr_pour_noeud.ConteneurEntier()) = n_noee; // pour l'affichage - if (Permet_affichage(&li_pour_noeuds) > 5) + *(gr_pour_noeud->ConteneurEntier()) = n_noee; // pour l'affichage + *(gr_pour_elem->ConteneurEntier()) = 0; //pas d'élément ici + if (Permet_affichage(&li_pour_noeuds_element) > 5) { int num_mail_noe_esclave = no->Num_Mail(); // if (no->Num_noeud()==495) @@ -1124,8 +1321,9 @@ bool LesContacts::Nouveau(double dep_max) if ((*iE).Contact()) { // on valide si le contact est ok (*iE).Met_actif(); - (*gr_pour_noeud.ConteneurEntier()) = (*iE).Esclave()->Num_noeud(); - if (Permet_affichage(&li_pour_noeuds) > 3) + *(gr_pour_noeud->ConteneurEntier()) = (*iE).Esclave()->Num_noeud(); + *(gr_pour_elem->ConteneurEntier()) = (*iE).Elfront()->PtEI()->Num_elt(); + if (Permet_affichage(&li_pour_noeuds_element) > 3) { cout << "\n reactivation (dans LesContacts::Nouveau) contact: "; (*iiE).Affiche(1); cout << endl; }; @@ -1136,8 +1334,9 @@ bool LesContacts::Nouveau(double dep_max) Noeud* noe_esclave = (*iiE).Esclave(); int num_mail_esclave = noe_esclave->Num_Mail(); int num_noeud = noe_esclave->Num_noeud(); - (*gr_pour_noeud.ConteneurEntier()) = num_noeud; - if (Permet_affichage(&li_pour_noeuds) > 3) + *(gr_pour_noeud->ConteneurEntier()) = num_noeud; + *(gr_pour_elem->ConteneurEntier()) = (*iE).Elfront()->PtEI()->Num_elt(); + if (Permet_affichage(&li_pour_noeuds_element) > 3) { cout << "\n effacement contact (dans LesContacts::Nouveau): "; (*iiE).Affiche(1);cout << endl; }; @@ -1164,7 +1363,7 @@ bool LesContacts::Nouveau(double dep_max) // on va iterer sur les noeuds esclaves pour savoir s'ils ont une trajectoire // qui cree un contact avec les elements maitres, ou l'inverse, c-a-d s'ils sont // dans de la matiere - bool retour = false; // init du retour + retour = false; // init du retour LaLIST_io ::iterator iM,iMfin; LaLIST ::iterator icont_inter; // sert pour la recherche de doublon list ::iterator inumtesN; // " " " @@ -1210,8 +1409,9 @@ bool LesContacts::Nouveau(double dep_max) nb_contact = list_tesN.size(); }; - (*gr_pour_noeud.ConteneurEntier()) = n_noee; - if (Permet_affichage(&li_pour_noeuds) > 6) + *(gr_pour_noeud->ConteneurEntier()) = n_noee; + *(gr_pour_elem->ConteneurEntier()) = 0; // pas de numéro d'élément à prendre en compte pour la visu + if (Permet_affichage(&li_pour_noeuds_element) > 6) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours @@ -1220,7 +1420,7 @@ bool LesContacts::Nouveau(double dep_max) #endif << " (re) examen eventuel : contact du noeud " << n_noee << " du maillage " << num_mail_noe_esclave; cout << " coord2= "; no->Coord2().Affiche_1(cout); - if (Permet_affichage(&li_pour_noeuds) > 7) + if (Permet_affichage(&li_pour_noeuds_element) > 7) {cout << " num_mail_dans_contact = " << num_mail_noe_esclave <<" inesc(num N local)= " << inesc << "\n tesN_encontact= " << nb_contact << " contacts enregistres"; @@ -1252,7 +1452,8 @@ bool LesContacts::Nouveau(double dep_max) // ce n'est peut-être pas un pb, mais il faudra peut-être avoir le niveau de zone en plus dans tesN_encontact ?? // cout << endl; }; - + // on ne continue que si le noeud n'est pas entièrement bloqué + // si c'est le cas .... à finir ! { Coordonnee pt_esc = no->Coord2(); // position du noeud esclave // maintenant on regarde les frontieres maitres @@ -1297,8 +1498,9 @@ bool LesContacts::Nouveau(double dep_max) Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere Front& elfront = (*iM); - (*gr_pour_noeud.ConteneurEntier()) = no->Num_noeud(); - if (Permet_affichage(&li_pour_noeuds) > 7) + *(gr_pour_noeud->ConteneurEntier()) = no->Num_noeud(); + *(gr_pour_elem->ConteneurEntier()) = elem.Num_elt(); + if (Permet_affichage(&li_pour_noeuds_element) > 7) {// --- sortie d'info pour vérifier l'appartenance à la boite ou non #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours @@ -1322,7 +1524,7 @@ bool LesContacts::Nouveau(double dep_max) break; // on arrête la boucle si on trouve l'élément parmi ceux contenant le noeud }; - if (Permet_affichage(&li_pour_noeuds) > 6) + if (Permet_affichage(&li_pour_noeuds_element) > 6) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours @@ -1357,8 +1559,9 @@ bool LesContacts::Nouveau(double dep_max) // break;}; // }; */ - (*gr_pour_noeud.ConteneurEntier()) = n_noee; - if (Permet_affichage(&li_pour_noeuds) > 7) + *(gr_pour_noeud->ConteneurEntier()) = n_noee; + *(gr_pour_elem->ConteneurEntier()) = 0; // pas de filtre sur les nb elem + if (Permet_affichage(&li_pour_noeuds_element) > 7) {cout << "\n liste des contacts sur le noeud " << n_noee << " qui est prevu en effacement sur l'increment " ; LaLIST ::iterator ila,ilafin=listContact_efface_tatdt.end(); @@ -1407,6 +1610,10 @@ bool LesContacts::Nouveau(double dep_max) { ElContact elcont(&(*iM),tesc(inesc),fct_nD_contact); elcont.Num_zone_contact()=j_zone; // affectation du numéro de zone elcont.Change_lissage_normale(lissage_de_la_normale(j_zone)); // affectation du lissage + #ifdef UTILISATION_MPI + // on attribue au front de l'élément de contact, le numéro unique utilisable pour le tableau pointe_t_listFront + elcont.Elfront()->ChangeNumUnique((*iM).NumUnique()); + #endif // vérification que l'on a bien les frontières bien connectées if ((niveau_commentaire_lescontacts > 5) @@ -1421,7 +1628,8 @@ bool LesContacts::Nouveau(double dep_max) << ", type: " << Nom_type_geom(elfront->Eleme_const()->Type_geom_front()) << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage " << elfront->PtEI()->Num_maillage() ; - if (Permet_affichage(&li_pour_noeuds) > 7) + *(gr_pour_elem->ConteneurEntier()) = elfront->PtEI()->Num_elt(); + if (Permet_affichage(&li_pour_noeuds_element) > 7) elcont.Affiche(); }; @@ -1500,14 +1708,20 @@ bool LesContacts::Nouveau(double dep_max) };// -- boucle sur inesc }// -- fin de la boucle sur les zones for (int j=1;j<= nb_zone;j++) };// -- boucle sur intot - if (niveau_commentaire_lescontacts > 3) + + #ifdef UTILISATION_MPI + // affichage pour les proc != 0 + if (niveau_commentaire_lescontacts > 4) + #else + if (niveau_commentaire_lescontacts > 3) // ==> LesContacts:: + #endif { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n " #endif - << " en fin de au debut de LesContacts::Nouveau: bilan: "<< listContact.size() << " elem(s) contact "; + << " en fin de LesContacts::Nouveau: bilan: "<< listContact.size() << " elem(s) contact "; if ( listContact_nouveau_tatdt.size()) cout <<", "<< (listContact_nouveau_tatdt.size()-taille_list_contact_nouveau_au_debut) << " nouveau(x) "; @@ -1537,6 +1751,58 @@ bool LesContacts::Nouveau(double dep_max) #endif << " <== fin LesContacts::Nouveau " ; }; + #ifdef UTILISATION_MPI + }; // fin de la recherche de nouveaux contact pour proc != 0 + + #endif + + #ifdef UTILISATION_MPI + if (proc_en_cours != 0) // on transmet à proc 0 + {temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + + // pour cela on va utiliser un conteneur intermédiaire + QuatreEntiers inter_entiers(retour,listContact.size(),listContact_nouveau_tatdt.size(),listContact_efface_tatdt.size()); + // on transmet les infos au proc 0 + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 62, inter_entiers); + // on attend pas + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les infos + tempsContact.Arret_du_comptage(); // fin cpu + int nb_contact=0;int nb_new_contact = 0;int nb_efface_contact = 0; // que l'on va cumuler + + int nb_proc_terminer = 0; // permettra de terminer + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) + { // on récupère un résultat de cpu i + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + QuatreEntiers inter_entiers; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 62, inter_entiers ); + reqs1.wait(); // on attend que le conteneur soit rempli + // on cumule + nb_contact += inter_entiers.deux; + nb_new_contact += inter_entiers.trois; + nb_efface_contact += inter_entiers.quatre; + + if (inter_entiers.un) // si un seul des retour s est bon on passe à true + retour = true; + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + }; + + if (retour) + if (niveau_commentaire_lescontacts > 3) // ==> LesContacts:: + {cout << "\n en fin de LesContacts::Nouveau: bilan: "<< nb_contact << " elem(s) contact "; + if ( nb_new_contact) + cout <<", "<< nb_new_contact << " nouveau(x) "; + if (nb_efface_contact) + cout <<", "<::iterator iE ; -// list ::iterator iden = numtesN.begin(); - // on met .end(), car cette borne peut changer au gré des suppressions for (iE = listContact.begin(); iE != listContact.end(); iE++)//,iden++) {if (!((*iE).Actif()) // on intervient si le contact est déclaré inactif && ((*iE).Collant()) // et si c'est collant: ce n'est pas normal, on le remet actif @@ -1628,20 +1893,46 @@ bool LesContacts::SuppressionDefinitiveElemInactif() // c'est que l'élément est actif, donc cela ne sert à rien de le réactiver ???? ceci dit cela ne génère pas une erreur a priori else {/*(*iE).Met_actif();*/}; // on valide l'activation }; - // info - if (niveau_commentaire_lescontacts > 2) - { if (nb_effacement) - { - #ifdef UTILISATION_MPI - cout << "\n proc " << proc_en_cours - #else - cout << "\n" - #endif - << " sup: "<< nb_effacement << " effacement(s) definitif(s) de contact "; + // info + if (niveau_commentaire_lescontacts > 2) + { if (nb_effacement) + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " sup: "<< nb_effacement << " effacement(s) definitif(s) de contact "; + }; + }; + if ((niveau_commentaire_lescontacts > 6) && (nb_effacement==0)) + cout << " aucun effacement "; + + #ifdef UTILISATION_MPI + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 610, change); + // on attend pas + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les infos + tempsContact.Arret_du_comptage(); // fin cpu + int nb_proc_terminer = 0; // permettra de terminer + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) + { // on récupère un résultat de cpu i + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + bool change_i; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 610, change_i ); + reqs1.wait(); // on attend que le conteneur soit rempli + if (change_i) // si un seul des retour s est bon on passe à true + change = true; + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur }; - }; - if ((niveau_commentaire_lescontacts > 6) && (nb_effacement==0)) - cout << " aucun effacement "; + + }; + // il faut que tous les proc aient le retour global, car le retour sert dans l'algo général + broadcast(*ParaGlob::Monde(), change, 0); + #endif tempsContact.Arret_du_comptage(); // fin cpu // retour du tableau @@ -1654,9 +1945,13 @@ bool LesContacts::RelachementNoeudcolle() { tempsContact.Mise_en_route_du_comptage(); // def deb compt int niveau_commentaire_lescontacts = Permet_affichage(); - #ifdef UTILISATION_MPI - int proc_en_cours = ParaGlob::Monde()->rank(); - #endif + + bool change = false; +#ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact + { +#endif if (niveau_commentaire_lescontacts > 4) #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours @@ -1664,8 +1959,7 @@ bool LesContacts::RelachementNoeudcolle() cout << "\n" #endif << " -- LesContacts::RelachementNoeudcolle(): "; - bool change = false; -// return change; //------- pour le débug +// return change; //------- pour le débug LaLIST ::iterator iE ; // list ::iterator iden = numtesN.begin(); // on met .end(), car cette borne peut changer au gré des suppression @@ -1700,7 +1994,32 @@ bool LesContacts::RelachementNoeudcolle() }; if ((!change)&& (niveau_commentaire_lescontacts > 6)) cout << " aucun noeud relache "; - + #ifdef UTILISATION_MPI + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 6100, change); + // on attend pas + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les infos + tempsContact.Arret_du_comptage(); // fin cpu + int nb_proc_terminer = 0; // permettra de terminer + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) + { // on récupère un résultat de cpu i + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + bool change_i; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 6100, change_i ); + reqs1.wait(); // on attend que le conteneur soit rempli + if (change_i) // si un seul des retour s est bon on passe à true + change = true; + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + }; + + }; + // il faut que tous les proc aient le retour global, car le retour sert dans l'algo général + broadcast(*ParaGlob::Monde(), change, 0); + #endif + tempsContact.Arret_du_comptage(); // fin cpu // retour return change; @@ -1765,7 +2084,6 @@ list & LesContacts::ConditionLin(const Nb_assemb& casAssemb) listCoLin.clear();// Change_taille(nb_contact_actif); while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront { // on récupère un résultat de cpu i - int taille_transfert; mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 40, taille_transfert); mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli @@ -1942,6 +2260,8 @@ else // cas du cpu 0 tempsContact.Arret_du_comptage(); }; }; + // il faut que tous les proc aient le retour global, car le retour sert dans l'algo général + broadcast(*ParaGlob::Monde(), retour, 0); #endif // retour de l'indicateur @@ -2206,6 +2526,10 @@ bool LesContacts::Actualisation(int choix) }; }; #endif + #ifdef UTILISATION_MPI + // il faut que tous les proc aient le retour global, car le retour sert dans l'algo général + broadcast(*ParaGlob::Monde(), retour, 0); + #endif // retour tempsContact.Arret_du_comptage(); // fin cpu @@ -2455,13 +2779,9 @@ void LesContacts::CalculReaction(Vecteur& residu,bool& decol,const Nb_assemb& ca }; }; // affichage éventuelle de la force maxi de contact - #ifdef UTILISATION_MPI - if (proc_en_cours == 0) - #endif - {Forces_contact_maxi(affiche); - // idem pour les gap N et T - Gap_contact_maxi(affiche); - }; + Forces_contact_maxi(affiche); + // idem pour les gap N et T + Gap_contact_maxi(affiche); tempsContact.Arret_du_comptage(); // fin cpu }; diff --git a/contact/LesContacts.h b/contact/LesContacts.h index 9fd987e..4e1cb44 100644 --- a/contact/LesContacts.h +++ b/contact/LesContacts.h @@ -64,6 +64,9 @@ #include "Basiques.h" #include "TypeQuelconque.h" #include "Temps_CPU_HZpp.h" +#include "Enum_TypeQuelconque.h" +#include "TypeQuelconqueParticulier.h" + #include #ifdef UTILISATION_MPI #include @@ -94,6 +97,10 @@ class LesContacts ~LesContacts (); // METHODES PUBLIQUES : + + // ramène le nombre de maillages esclaves en auto contact, donc qui joue le rôle esclave et maître, ou maillages mixte: dépend de la manière dont les zones de contact ont été + // est définit en lecture des données + int NbmailAutoContact() const {return nbmailautocontact;}; // ramène la liste des éléments de contact LaLIST & LesElementsDeContact() {return listContact;}; @@ -261,6 +268,9 @@ class LesContacts void TdtversT(); // actualisation des ddl et des grandeurs actives de t vers tdt void TversTdt(); + + // ramène le nombre de contacts actifs actuel + int Nb_actifs() const {return nb_contact_actif;}; //------- temps cpu ----- // retourne temps cumulé pour imposer les CL imposées @@ -271,6 +281,19 @@ class LesContacts const Temps_CPU_HZpp& Temps_transfert_court() const {return temps_transfert_court;} ; const Temps_CPU_HZpp& Temps_transfert_long() const {return temps_transfert_long;} ; const Temps_CPU_HZpp& Temps_attente() const {return temps_attente;} ; + // mise à jour list contact pour proc 0: il s'agit des infos minimales + void Mise_a_jour_liste_contacts_actif_interProc(); + // on définit une méthode qui permet de retrouver un élément à partir d'infos minimales + ElContact* RecupElContactActif( int num_mailEsclave, int num_noeudEsclave, int numUnique) + {LaLIST ::iterator ili,ilifin = listContact.end(); + for (ili = listContact.begin();ili != ilifin;ili++) + if ( ((*ili).Esclave()->Num_Mail() == num_mailEsclave) + && ((*ili).Esclave()->Num_noeud() == num_noeudEsclave) + && ((*ili).Elfront()->NumUnique() == numUnique) + ) + return (&(*ili)); + return NULL; + } ; #endif //----- lecture écriture de restart ----- @@ -326,7 +349,7 @@ class LesContacts // li si non nulle permet d'indiquer spécifiquement quelle grandeur on veut // sortir int Permet_affichage(list * li = NULL ) const - { int niveau_commentaire_lescontacts; + { int niveau_commentaire_lescontacts = ParaGlob::param->ParaAlgoControleActifs().Niveau_commentaire_LesContact(); return( (fct_niveau_commentaire == NULL) ? (niveau_commentaire_lescontacts == 0) ? ParaGlob::NiveauImpression() : niveau_commentaire_lescontacts : Valeur_fct_nD_LesContacts(fct_niveau_commentaire, li @@ -375,6 +398,9 @@ class LesContacts static Tableau tqi_const_fct_nD_niveau_commentaire; static Tableau < TypeQuelconque * > tqi_fct_nD_niveau_commentaire; static Tableau t_num_ordre_fct_nD_niveau_commentaire; + list li_pour_noeuds_element; // pour une sortie spécifique noeud et ou élément fini contenant la frontière + Grandeur_scalaire_entier* gr_pour_noeud; // contient le numéro de noeud esclave éventuel + Grandeur_scalaire_entier* gr_pour_elem; // contient le numéro éventuel de l'élément fini contenant la frontière // -- fin partie affichage éventuellement piloté @@ -421,6 +447,17 @@ class LesContacts // ** mais uniquement un numéro locale d'ordre // ** mais on a: les éléments de frontière de t_listFront(i) font partie du maillage // i + (nb_mail_Esclave-nbmailautocontact) + #ifdef UTILISATION_MPI + // cas d'un calcul parallèle: // passage des infos entre process + Tableau pointe_t_listFront; // pointe_t_listFront(i_num) permet de repérer un élément unique + // dans t_listFront + // à l'inverse, chaque Front stocke son numéro i_num + // pointe_t_listFront est défini dans LesContacts::Init_contact + Vecteur v_interProc_contact_actif; // conteneur de travail utilisé pour le passage d'infos + // entre proc , par la méthode Mise_a_jour_liste_contacts_actif_interProc() + #endif + + // les noeuds esclaves potentiels Tableau < Tableau < Tableau < Noeud*> > > tesctotal; @@ -535,7 +572,13 @@ class LesContacts return (&(*ili)); return NULL; } ; - + + // recherche dans les Front enregistrés de la zone , c-a-d dans t_listFront(i)(zone) + // un Front de même origine , c-a-d sans les mitoyens + // si aucun résultat retourne NULL + // sinon ramène l'élément de t_listFront de même origine + Front* Front_de_meme_origine(Front* fro, int zone) const; + // init éventuel du pilotage par fct nD du niveau de commentaire void Init_fct_niveau_commentaire(); // définition des conteneurs des TypeQuelconque pour fct nD de LesContacts diff --git a/contact/LesContacts_2.cc b/contact/LesContacts_2.cc index 4684613..050184f 100755 --- a/contact/LesContacts_2.cc +++ b/contact/LesContacts_2.cc @@ -176,6 +176,10 @@ void LesContacts::Lec_base_info_LesContacts(ifstream& ent // mis à jour du numéro de zone courant.Num_zone_contact() = num_zone; courant.Change_lissage_normale(lissage_de_la_normale(num_zone)); // affectation du lissage + #ifdef UTILISATION_MPI + // on attribue au front de l'élément de contact, le numéro unique utilisable pour le tableau pointe_t_listFront + courant.Elfront()->ChangeNumUnique(froant->NumUnique()); + #endif // sauvegarde si l'élément de contact n'existe pas déjà ElContact* test_existance= Element_contact_deja_present(courant); if (test_existance == NULL) diff --git a/contact/LesContacts_3.cc b/contact/LesContacts_3.cc index aa85360..6eb9a98 100755 --- a/contact/LesContacts_3.cc +++ b/contact/LesContacts_3.cc @@ -98,24 +98,32 @@ void LesContacts::TversTdt() Noeud* no = elc.Esclave(); int n_noee = no->Num_noeud(); int num_mail_noe_esclave = no->Num_Mail(); - #ifdef MISE_AU_POINT - if (Element_contact_deja_present(*al)) - { - #ifdef UTILISATION_MPI - cout << "\n proc " << proc_en_cours - #else - cout << "\n" - #endif - << "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal " - << (*al).Esclave()->Num_noeud() - << " du maillage " << (*al).Esclave()->Num_Mail() - << " la suite n'est pas possible " - << " LesContacts::TversTdt(.. \n"; - tempsContact.Arret_du_comptage(); // fin cpu - Sortie(1); - }; - #endif - listContact.push_front(*al); + + // je supprime le test suivant, car on pourrait peut-être avoir en début d'incrément précédent, + // deux elements de contact avec le même noeud esclave mais pas la même frontière + // qui ensuite à cause d'un changement de frontière, deviennent identique -> un des deux est inactivé + // mais il y en a deux identiques. + // du coup si on revient en arrière c'est de ne pas tenir compte du doublon et s'il y a besoin, au niveau de Nouveau + // on aura une création d'un nouvel élément +// #ifdef MISE_AU_POINT +// if (Element_contact_deja_present(*al)) +// { +// #ifdef UTILISATION_MPI +// cout << "\n proc " << proc_en_cours +// #else +// cout << "\n" +// #endif +// << "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal " +// << (*al).Esclave()->Num_noeud() +// << " du maillage " << (*al).Esclave()->Num_Mail() +// << " la suite n'est pas possible " +// << " LesContacts::TversTdt(.. \n"; +// tempsContact.Arret_du_comptage(); // fin cpu +// Sortie(1); +// }; +// #endif + if (!(Element_contact_deja_present(*al))) + listContact.push_front(*al); // on met à jour le tableau tesN_encontact #ifdef MISE_AU_POINT if (tesN_encontact(num_mail_noe_esclave).find(no) @@ -188,7 +196,7 @@ double LesContacts::Pas_de_temps_ideal() #ifdef UTILISATION_MPI temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va transmettre au cpu 0 - mpi::request reqs1 = ParaGlob::Monde()->isend(0, 56, delta_optimal); + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 48, delta_optimal); // on attend pas temps_transfert_court.Arret_du_comptage(); // fin comptage cpu } @@ -200,12 +208,14 @@ double LesContacts::Pas_de_temps_ideal() { // on récupère un résultat de cpu i temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu double dtelem_optimal ; - mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 56, dtelem_optimal ); + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 48, dtelem_optimal ); reqs1.wait(); // on attend que le conteneur soit rempli delta_optimal = MiN(delta_optimal, dtelem_optimal); nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur }; }; + // il faut que tous les proc aient le retour global, car le retour sert dans l'algo général + broadcast(*ParaGlob::Monde(), delta_optimal, 0); #endif return delta_optimal; @@ -1033,11 +1043,11 @@ list & LesContacts::ConnectionCLL() int rang = 1; // init for (il = t_connectionCLL.begin();il != ilfin;il++) rang = (*il).Pack_vecteur(inter_transfer2,rang); - temps_attente.Arret_du_comptage(); // on transfert mpi::request reqs1 = ParaGlob::Monde()->isend(0, 42, taille_conteneur); - - mpi::request reqs2 = inter_transfer2.Ienvoi_MPI(0,43); + // si la taille du conteneur est nulle, on ne le transfert pas + if (taille_conteneur > 0) + mpi::request reqs2 = inter_transfer2.Ienvoi_MPI(0,43); // on attend pas temps_transfert_long.Arret_du_comptage(); // fin comptage cpu } @@ -1053,19 +1063,22 @@ list & LesContacts::ConnectionCLL() int taille_transfert; mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 42, taille_transfert); mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli - inter_transfer2.Change_taille(taille_transfert); // le conteneur - int source = stat.source(); // récupération du numéro de la source - // on récupère - mpi::request reqs2 = inter_transfer2.Irecup_MPI(source, 43); - reqs2.wait(); // on attend que le conteneur soit rempli nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur - // on va remplir la liste des conditions limites - int rang = 1; // init - while (rang != 0) - { Condilineaire condi; // une condition intermédiaire - rang = condi.UnPack_vecteur(*lesMaille,inter_transfer2,rang, + // si la taille == 0, il n'y a rien à faire + if (taille_transfert > 0) + {inter_transfer2.Change_taille(taille_transfert); // le conteneur + int source = stat.source(); // récupération du numéro de la source + // on récupère + mpi::request reqs2 = inter_transfer2.Irecup_MPI(source, 43); + reqs2.wait(); // on attend que le conteneur soit rempli + // on va remplir la liste des conditions limites + int rang = 1; // init + while (rang != 0) + { Condilineaire condi; // une condition intermédiaire + rang = condi.UnPack_vecteur(*lesMaille,inter_transfer2,rang, &LesMaillages::Noeud_LesMaille); - t_connectionCLL.push_back(condi); + t_connectionCLL.push_back(condi); + }; }; }; temps_transfert_long.Arret_du_comptage(); @@ -1483,7 +1496,7 @@ DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche) if ((affiche && (ParaGlob::NiveauImpression() > 2)) || (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact ) - { cout << "\n F_N => [" << retour_min.un << " : " << retour_max.un << "]" + { cout << "\n contact: reaction ==> F_N => [" << retour_min.un << " : " << retour_max.un << "]" << ", F_T max = " << retour_max.deux; }; if (niveau_commentaire_lescontacts > 6) @@ -1516,11 +1529,13 @@ DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche) #ifdef UTILISATION_MPI temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va transmettre au cpu 0 - Vecteur v_inter(2);v_inter(1) = retour.un; v_inter(2) = retour.deux; + Vecteur v_inter(3); + v_inter(1) = retour_max.un; v_inter(2) = retour_max.deux; + v_inter(3) = retour_min.un; // envoi - v_inter.Ienvoi_MPI(0,66); + v_inter.Ienvoi_MPI(0,49); // on attend pas - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu } else // cas du cpu 0 {// l'objectif ici est de récupérer les infos @@ -1529,22 +1544,26 @@ DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche) while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront { // on récupère un résultat de cpu i temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu - Vecteur v_inter(2); - mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 66); + Vecteur v_inter(3); + mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 49); reqs1.wait(); // on attend que le conteneur soit rempli - if (Dabs(v_inter(1)) > Dabs(retour.un) ) - {retour.un = v_inter(1);}; - if (Dabs(v_inter(2)) > Dabs(retour.deux) ) - {retour.deux = v_inter(2); + if (v_inter(1) > retour_max.un) + {retour_max.un = v_inter(1);}; + if (v_inter(2) > retour_max.deux) + {retour_max.deux = v_inter(2); }; + if (v_inter(3) < retour_min.un) + {retour_min.un = v_inter(3);}; temps_transfert_court.Arret_du_comptage(); // fin comptage cpu nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur }; if ((affiche && (ParaGlob::NiveauImpression() > 2)) || (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact ) - cout << "\n contact: reaction ==> |F_N max| " << Dabs(retour_min.un) << " |F_T max| " << DabsMaX(retour_min.deux,retour_max.deux); +// cout << "\n contact: reaction ==> |F_N max| = " << Dabs(retour_min.un) << " |F_T max| = " << DabsMaX(retour_min.deux,retour_max.deux); + cout << "\n contact: reaction ==> F_N => [" << retour_min.un << " : " << retour_max.un << "]" + << ", F_T max = " << retour_max.deux; }; #endif @@ -1612,11 +1631,12 @@ DeuxDoubles LesContacts::Gap_contact_maxi(bool affiche) #ifdef UTILISATION_MPI temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va transmettre au cpu 0 - Vecteur v_inter(2);v_inter(1) = retour.un; v_inter(2) = retour.deux; + Vecteur v_inter(4);v_inter(1) = retour_max.un; v_inter(2) = retour_max.deux; + v_inter(3) = retour_min.un;v_inter(4) = retour_min.deux; // envoi - v_inter.Ienvoi_MPI(0,67); + v_inter.Ienvoi_MPI(0,60); // on attend pas - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu } else // cas du cpu 0 {// l'objectif ici est de récupérer les infos @@ -1625,15 +1645,19 @@ DeuxDoubles LesContacts::Gap_contact_maxi(bool affiche) while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront { // on récupère un résultat de cpu i temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu - Vecteur v_inter(2); - mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 67); + Vecteur v_inter(4); + mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 60); reqs1.wait(); // on attend que le conteneur soit rempli - if (Dabs(v_inter(1)) > Dabs(retour.un) ) - {retour.un = v_inter(1);}; - if (Dabs(v_inter(2)) > Dabs(retour.deux) ) - {retour.deux = v_inter(2); + if (v_inter(1) > retour_max.un) + {retour_max.un = v_inter(1);}; + if (v_inter(2) > retour_max.deux) + {retour_max.deux = v_inter(2); }; + if (v_inter(3) < retour_min.un) + {retour_min.un = v_inter(3);}; + if (v_inter(4) < retour_min.deux) + {retour_min.deux = v_inter(4);}; temps_transfert_court.Arret_du_comptage(); // fin comptage cpu nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur }; @@ -1909,6 +1933,10 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) {int i_noe = (*ih); // le num du noeud maître que l'on va tester Tableau ttn(1); ttn(1)= &(lesMail.Noeud_LesMaille(jf,i_noe)); // récup du pointeur de noeud +////------ debug +//if (ttn(1)->Num_noeud() == 37 ) +// cout << "\n debug LesContacts::ElementAngleMort(..."; +//// fin debug // récup de la liste pour le noeud i_noe, des éléments qui contient ce noeud : construite avec Init_contact const List_io < Element* >& liel = (*indice(jf))(i_noe); @@ -1944,7 +1972,10 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie()); if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE))) {continuer = false;} - // b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence + // b) si on est en axi et qu'il s'agit d'un élément surface, là c'est bon + else if (ParaGlob::AxiSymetrie() && (enu_type_geom_ele == SURFACE)) + {continuer = true;} + // c) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence else if ((ParaGlob::Dimension() == 3) && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE)) ) @@ -2118,7 +2149,10 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie()); if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE))) {continuer = false;} - // b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence + // b) si on est en axi et qu'il s'agit d'un élément surface, là c'est bon + else if (ParaGlob::AxiSymetrie() && (enu_type_geom_ele == SURFACE)) + {continuer = true;} + // c) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence else if ((ParaGlob::Dimension() == 3) && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE)) ) @@ -2456,7 +2490,6 @@ void LesContacts::Init_fct_niveau_commentaire() tqii(i) = tqi(i); }; - // calcul d'une fonction nD relative à des données de LesContacts double LesContacts::Valeur_fct_nD_LesContacts (Fonction_nD * pt_fonct,list* li @@ -2558,6 +2591,140 @@ double LesContacts::Valeur_fct_nD_LesContacts // on récupère le premier élément du tableau uniquement return tab_val(1); }; + + +// recherche dans les Front enregistrés de la zone , c-a-d dans t_listFront(i)(zone) +// un Front de même origine , c-a-d sans les mitoyens +// si aucun résultat retourne NULL +// sinon ramène l'élément de t_listFront de même origine +Front* LesContacts::Front_de_meme_origine(Front* fro, int zone) const +{ // on récupère le num de maillage associé + // récup du numero du maillage rattache + int numMail = fro->NumMail(); + int i = numMail - (nb_mail_Esclave-nbmailautocontact); + + // on va balayer dans la zone de contact + LaLIST_io & list_fronta = (t_listFront(i)(zone)); // pour simplifier + LaLIST_io ::iterator il,ilfin = list_fronta.end(); + for (il = list_fronta.begin();il != ilfin; il++) + if ((*il).MemeOrigine(*fro)) + return &((*il)); + // arrivée ici, cela veut dire que l'on n'a rien trouvé + return NULL; + + // la liste des éléments frontières succeptibles d'entrer en contact + // ces Front (qui contiennent que des pointeurs sauf une boite d'encombrement) + // sont différents de ceux des maillages, et sont donc stocké en interne +// Tableau < Tableau < LaLIST_io > > t_listFront; + // t_listFront(i)(j)(k) : maillage maître (i) + // zone de contact (j) + // (K) = kième frontière (dans l'ordre de la liste) + // ** pour le tableaux t_listFront, le numéros dit de maillage, n'est pas le numéro + // ** intrinsèque de maillage (telle que ceux associés aux noeuds et éléments) + // ** mais uniquement un numéro locale d'ordre + // ** mais on a: les éléments de frontière de t_listFront(i) font partie du maillage + // i + (nb_mail_Esclave-nbmailautocontact) + +}; + + +#ifdef UTILISATION_MPI + // mise à jour list contact pour proc 0: + // il s'agit des infos minimales + void LesContacts::Mise_a_jour_liste_contacts_actif_interProc() + { temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + // on va se servir d'un conteneur intermédiaire + union double_int + { double x; + int n[2]; + } ; + double_int xinter; + + int proc_en_cours = ParaGlob::Monde()->rank(); + if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact + // on boucle sur les elements de contact du proc i pour les transmettres à proc 0 + { int nb_contact_actif = Calcul_Nb_contact_actif(); + // on a besoin de 8 entiers pour repérer un élément de contact, on va transmettre + // un vecteur contenant ces infos +////---debug +//cout << "\n LesContacts::Mise_a_jour_liste_contacts_actif_interProc " +// << " proc "<< proc_en_cours << ", nb_contact= "<< listContact.size(); +////--fin debug + v_interProc_contact_actif.Change_taille(4*nb_contact_actif); + int rang=1; // init + LaLIST ::iterator il,ilfin = listContact.end(); + for (il = listContact.begin();il != ilfin; il++) + if ((*il).Actif()) + {xinter.n[0] = (*il).Actif(); xinter.n[1] = (*il).Cas_solide(); + v_interProc_contact_actif(rang) = xinter.x;rang++; + xinter.n[0] = (*il).Esclave()->Num_Mail(); xinter.n[1] = (*il).Esclave()->Num_noeud(); + v_interProc_contact_actif(rang) = xinter.x;rang++; + xinter.n[0] = (*il).Elfront()->NumUnique(); xinter.n[1] = (*il).Const_Num_zone_contact(); + v_interProc_contact_actif(rang) = xinter.x;rang++; + xinter.n[0] = (*il).Lissage_normale(); xinter.n[1] = (*il).Collant(); + v_interProc_contact_actif(rang) = xinter.x;rang++; + }; + // on transmet à proc 0 + // tout d'abord la taille + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 63, 4*nb_contact_actif); + // puis le conteneur + mpi::request reqs2 = v_interProc_contact_actif.Ienvoi_MPI(0,64); + } + else + // cas du proc 0 + { int nb_proc_terminer = 0; // permettra de terminer + // on supprime la liste existante car: + // - si on teste l'existance d'un élément à chaque ajout => il faut parcourir la liste qui peut être longue + // - il faut y adjoindre une méthode pour supprimer les éléments qui ont été supprimés par un proc + // => c'est plus simple de repartir d'une liste vide, + listContact.clear(); // init + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) + { // on récupère un résultat de cpu i + int taille_transfert; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 63, taille_transfert); + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + v_interProc_contact_actif.Change_taille(taille_transfert); // le conteneur + int source = stat.source(); // récupération du numéro de la source + // on récupère + mpi::request reqs2 = v_interProc_contact_actif.Irecup_MPI(source, 64); + reqs2.wait(); // on attend que le conteneur soit rempli + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + // on va remplir la liste des contacts actifs + int rang = 1; // init + while (rang < taille_transfert+1) + { // récup des infos pour le contact + xinter.x = v_interProc_contact_actif(rang);rang++; + int actif = xinter.n[0]; int casSolide = xinter.n[1]; + xinter.x = v_interProc_contact_actif(rang);rang++; + int num_mail = xinter.n[0]; int num_noeud = xinter.n[1]; + xinter.x = v_interProc_contact_actif(rang);rang++; + int numUnique = xinter.n[0]; int numZoneContact = xinter.n[1]; + xinter.x = v_interProc_contact_actif(rang);rang++; + int lissageNormale = xinter.n[0]; int collant = xinter.n[1]; + + // on crée un élément de contact + ElContact elcont(pointe_t_listFront(numUnique) + ,&(lesMaille->Noeud_LesMaille(num_mail,num_noeud)) + ,fct_nD_contact,collant); + elcont.Num_zone_contact()=numZoneContact; // affectation du numéro de zone + elcont.Change_lissage_normale(lissageNormale); // affectation du lissage + if (actif) elcont.Met_actif(); + else elcont.Met_Inactif(); + listContact.push_front(elcont); + }; + }; +// //---debug +// cout << "\n LesContacts::Mise_a_jour_liste_contacts_actif_interProc " +// << " proc "<< proc_en_cours << ", nb_contact= "<< listContact.size(); +// //--fin debug + Calcul_Nb_contact_actif(); // mise à jour + }; + temps_transfert_long.Arret_du_comptage(); + }; + +#endif + +