From ce2d011450496d62ea081cc532b4269a7f8bd98f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Rio?= Date: Sun, 3 Sep 2023 10:10:17 +0200 Subject: [PATCH] =?UTF-8?q?-=20mise=20en=20place=20calcul=20parall=C3=A8le?= =?UTF-8?q?=20(MPI)=20dans=20algo=20RD=20-=20idem=20pour=20le=20calcul=20d?= =?UTF-8?q?es=20second=20membres=20(Algori)=20-=20idem=20pour=20le=20charg?= =?UTF-8?q?ement=20pression=20en=20explicite=20-=20tests=20ok=20pour=20cal?= =?UTF-8?q?cul=20MPI=20en=20RD=20avec=20pression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Algo/AlgoRef/Algori.cc | 338 +++++++++++---- Algo/AlgoRef/Algori.h | 22 +- Algo/AlgoRef/Algori2.cc | 30 +- Algo/AlgoRef/Algori3.cc | 61 ++- Algo/AlgoRef/Algori4.cc | 226 ++++++++-- Algo/AlgorithmeCombiner/AlgoriCombine.cc | 12 +- Algo/AlgorithmeCombiner/AlgoriCombine2.cc | 18 +- .../AlgoDynaExplicite/AlgoRungeKutta.cc | 3 +- .../AlgoDynaExplicite/AlgoriDynaExpli2.cc | 3 +- .../AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc | 3 +- .../AlgoDynaExplicite/Algori_chung_lee.cc | 3 +- .../AlgoDynaExplicite/Algori_relax_dyna.cc | 157 ++++++- .../AlgoDynaExplicite/Algori_tchamwa.cc | 3 +- .../AlgoDynaImplicite/AlgoriNewmark2.cc | 3 +- .../AlgoStatiques/AlgoriNonDyna2.cc | 17 +- .../DG_DynaExplicite/AlgoBonelli.cc | 3 +- Chargement/Charge.cc | 4 + Chargement/Charge.h | 14 + Chargement/Charge2.cc | 385 ++++++++++++++++- General/Distribution_CPU.cc | 38 +- General/Distribution_CPU.h | 7 + General/herezh.cc | 26 +- Maillage/LesMaillages.cc | 2 +- Maillage/Maillage.h | 2 +- Parametres/EnteteParaGlob.h | 2 +- Parametres/ParaGlob.h | 17 +- TypeBase/Basiques.cc | 165 +++++++- TypeBase/Basiques.h | 390 +++++++++++++++++- TypeBase/List_io.h | 2 +- contact/LesContacts.cc | 13 +- contact/LesContacts.h | 25 +- contact/LesContacts_3.cc | 4 +- 32 files changed, 1744 insertions(+), 254 deletions(-) diff --git a/Algo/AlgoRef/Algori.cc b/Algo/AlgoRef/Algori.cc index 898d7dd..1c786c5 100644 --- a/Algo/AlgoRef/Algori.cc +++ b/Algo/AlgoRef/Algori.cc @@ -154,8 +154,11 @@ Algori::Algori () : // par defaut #ifndef UTILISATION_MPI ,lesTempsCpu(16) #else - ,lesTempsCpu(19),distribution_CPU_algo() - ,temps_transfert_court(),temps_transfert_long(),temps_attente() + ,lesTempsCpu(28),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() #endif //---------- stockage pour la transmission des grandeurs consultables ----- // ,stock_compteur(GENERIQUE_UNE_GRANDEUR_GLOBALE),val_stock_compteur(NULL) @@ -245,8 +248,11 @@ Algori::Algori (EnumTypeCalcul type,const bool avec_typeDeCal #ifndef UTILISATION_MPI ,lesTempsCpu(16) #else - ,lesTempsCpu(19),distribution_CPU_algo() - ,temps_transfert_court(),temps_transfert_long(),temps_attente() + ,lesTempsCpu(28),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() #endif //---------- stockage pour la transmission des grandeurs consultables ----- @@ -437,9 +443,17 @@ Algori::Algori (const Algori& algo) : #ifndef UTILISATION_MPI ,lesTempsCpu(16) #else - ,lesTempsCpu(18),distribution_CPU_algo(algo.distribution_CPU_algo) // distribution de charge sur les CPU - ,temps_transfert_court(algo.temps_transfert_court),temps_transfert_long(algo.temps_transfert_long) - ,temps_attente(algo.temps_attente) + ,lesTempsCpu(28),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) + ,temps_attente_matSm(algo.temps_attente_matSm) + ,temps_transfert_court_charge(algo.temps_transfert_court_charge) + ,temps_transfert_long_charge(algo.temps_transfert_long_charge) + ,temps_attente_charge(algo.temps_attente_charge) + ,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) #endif //---------- stockage pour la transmission des grandeurs consultables ----- @@ -606,9 +620,19 @@ void Algori::Preparation_conteneurs_interne(LesMaillages& lesMail) // Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15) // Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16) // si calcul //: - // Temps_CPU_HZpp temps_transfert_court; // lesTempsCpu(17) - // Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(19) - // Temps_CPU_HZpp temps_attente ; // lesTempsCpu(18) +// // 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) // 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 @@ -658,8 +682,20 @@ void Algori::Preparation_conteneurs_interne(LesMaillages& lesMail) listeVarGlob["tpsU_rech_contact"]=&lesTempsCpu(16)(1); #ifdef UTILISATION_MPI // cas d'un calcul parallèle - listeVarGlob["tpsU_transfert_inter_cpu"]=&lesTempsCpu(17)(1); - listeVarGlob["tpsU_attente_inter_cpu"]=&lesTempsCpu(18)(1); + 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_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); + #endif // cas des vecteurs globaux @@ -1513,9 +1549,8 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin E_bulk = 0.; // init P_bulk=0.; // init if (pa.CalVolTotalEntreSurfaceEtPlansRef()) - {vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension())); + vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension())); - }; #ifdef UTILISATION_MPI mpi::request reqs1; mpi::request reqs2; @@ -1523,9 +1558,9 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin bool premier_passage = true; #endif // on gère les exceptions éventuelles en mettant le bloc sous surveillance - try + int nbMailMax = lesMail->NbMaillage(); + try {// boucle sur les elements - int nbMailMax = lesMail->NbMaillage(); #ifndef UTILISATION_MPI // cas d'un calcul mono CPU for (int nbMail =1; nbMail<= nbMailMax; nbMail++) @@ -1536,7 +1571,7 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin // 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(); + 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 @@ -1548,14 +1583,14 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin for (il = list_elem_cpu.begin();il != ilfin;il++) { int ne = (*il); // on récupère un signal du process 0 - temps_attente.Mise_en_route_du_comptage(); // comptage cpu + 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.Arret_du_comptage(); // fin comptage cpu + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu #endif //calcul de la raideur local et du residu local @@ -1596,6 +1631,24 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin Ass.AssembMatSym (matglob,*(resu.raid),el.TableauDdl(),taN); // de la raideur else 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) + {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()); + // on transmet les numéros d'élément et de maillage + reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail); + // puis on transmets le vecteur résidu + reqs2 = resu.res->Ienvoi_MPI(0,25); + //puis la matrice + reqs3 = resu.raid->Ienvoi_MPI(0, 26); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + tempsRaidSmEner.Mise_en_route_du_comptage(); + }; + + #endif // globalisation des énergies energTotal += el.EnergieTotaleElement(); energHourglass += el.Energie_Hourglass(); @@ -1608,31 +1661,13 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin { const Coordonnee& volPlan = el.VolumePlan(); if (volPlan.Dimension()) vol_total2D_avec_plan_ref(nbMail) += volPlan; -//--- debug -// cout << "\n calcul des volumes balayés"; -// vol_total2D_avec_plan_ref.Affiche(); -// cout << "\n " << *(listeVarGlob["vol_total2D_avec_plan_yz"]) << " " << *(listeVarGlob["vol_total2D_avec_plan_xz"]) -// << " " << *(listeVarGlob["vol_total2D_avec_plan_xy"]) << endl; -// fin débug - }; - #else - // cas d'un calcul parallèle, et CPU != 0 - int num_process = ParaGlob::Monde()->rank(); - if (num_process != 0) - {tempsRaidSmEner.Arret_du_comptage(); - temps_transfert_court.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, 24, num_el_et_mail); - // puis on transmets le vecteur résidu - reqs2 = resu.res->Ienvoi_MPI(0,25); - //puis la matrice - reqs3 = resu.raid->Ienvoi_MPI(0, 26); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu - tempsRaidSmEner.Mise_en_route_du_comptage(); - }; - - #endif + //--- debug + // cout << "\n calcul des volumes balayés"; + // vol_total2D_avec_plan_ref.Affiche(); + // 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; @@ -1701,11 +1736,6 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin entete = " affichage du second membre (puissance interne) avant condition limites "; vglobin.Affichage_ecran(entete); }; - // -- 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(); // -- calcul des intégrales éventuelles avec transfert en global lesMail->Integration(); // --- debug ------- essai ---- @@ -1718,9 +1748,6 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin if (permet_affichage >3) cout << "\n -- fin calcul second membre et raideur " << flush; tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu - // --- debug ------- essai ---- -// cout << "\temps cpu raid SM energ " << tempsRaidSmEner; - // --- fin debug ------- essai ---- #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) { tempsRaidSmEner.Mise_en_route_du_comptage(); // comptage cpu @@ -1731,13 +1758,13 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin int nb_elem_deja_calcule = 0; // init while (nb_elem_deja_calcule < total_elem) { // on récupère un résultat de calcul - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu DeuxEntiers num_el_et_mail; mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 24, num_el_et_mail); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu - temps_attente.Mise_en_route_du_comptage(); // comptage cpu + 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.Arret_du_comptage(); // fin comptage cpu + temps_attente_matSm.Arret_du_comptage(); // fin 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 @@ -1745,16 +1772,16 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin // 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.Mise_en_route_du_comptage(); // comptage cpu + 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.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu - temps_attente.Mise_en_route_du_comptage(); // 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.Arret_du_comptage(); // fin comptage cpu + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el // --- assemblage @@ -1767,18 +1794,21 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin nb_elem_deja_calcule++; }; tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu - } -// else -// {// on récupère le dernier signal du process 0 -//// std::string msg; -//// ParaGlob::Monde()->recv(0, 12, msg); -// // synchronisation ici de tous les process -// ParaGlob::Monde()->barrier(); -// }; - // synchronisation ici de tous les process -// ParaGlob::Monde()->barrier(); - + }; #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 ; }; @@ -1802,16 +1832,61 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & volume_total_matiere = 0.; // init if (pa.CalVolTotalEntreSurfaceEtPlansRef()) vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension())); + + #ifdef UTILISATION_MPI + mpi::request reqs1; + mpi::request reqs2; + Vecteur deux_faux_entiers(2); + bool premier_passage = true; + #endif // on gère les exceptions éventuelles en mettant le bloc sous surveillance try - {for (int nbMail =1; nbMail<= lesMail->NbMaillage(); nbMail++) - for (int ne=1; ne<= lesMail->Nombre_element(nbMail);ne++) - { //calcul du residu local + {// boucle sur les elements + int nbMailMax = lesMail->NbMaillage(); + #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 + // 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 + temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu + if (premier_passage) {premier_passage = false;} + else // on attend que le premier transfert soit fini + {reqs1.wait(); + }; + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + + #endif + //calcul du residu local ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el Temps_CPU_HZpp temps_debut_lois_comportement=el.Temps_lois_comportement(); // init Temps_CPU_HZpp temps_debut_metrique_K_SM = el.Temps_metrique_K_SM(); // init Vecteur* res = el.CalculResidu_tdt(pa); +////--- debug +//cout << "\n debug .... Algori::SecondMembreEnerg( " +// << "\n CPU= "<< ParaGlob::Monde()->rank(); +// // vecteur résidu +//cout << "\n res = " << *res ; +// +////--- fin debug + ////--- debug //if (res->Max_val_abs() > 10) // { cout << "\n debug .... Algori::SecondMembreEnerg( " @@ -1821,28 +1896,63 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & // }; // ////--- fin debug - + #ifndef UTILISATION_MPI + // --- assemblage et calcul de grandeur globale, pour mono-CPU // assemblage Ass.AssemSM (vglobin,*res,el.TableauDdl(),taN); // du second membre + #else + // cas d'un calcul parallèle, et CPU != 0 + int num_process = ParaGlob::Monde()->rank(); + if (num_process != 0) + {tempsSecondMembreEnerg.Arret_du_comptage(); + temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu +// DeuxEntiers num_el_et_mail(el.Num_elt(),el.Num_maillage()); + deux_faux_entiers(1) = (double ) el.Num_elt(); + deux_faux_entiers(2) = (double ) el.Num_maillage(); + // on transmet les numéros d'élément et de maillage + reqs1 = deux_faux_entiers.Ienvoi_MPI(0, 24); +// reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail); + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + // puis on transmets le vecteur résidu + temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu + if (!premier_passage) + reqs2.wait(); + temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu + temps_transfert_long_matSm.Mise_en_route_du_comptage(); // comptage cpu + reqs2 = res->Ienvoi_MPI(0,25); + temps_transfert_long_matSm.Arret_du_comptage(); // fin comptage cpu + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); + }; + + #endif +////--- debug +// { cout << "\n debug .... Algori::SecondMembreEnerg( "; +// // on recalcule pour le debug le vecteur résidu +// cout << "\n second membre local = " << (*res); +//// res = el.CalculResidu_tdt(pa); +// }; + +//--- fin debug // globalisation des énergies - energTotal += el.EnergieTotaleElement(); + energTotal += el.EnergieTotaleElement(); energHourglass += el.Energie_Hourglass(); energStabiliMembBiel += el.Energie_stab_membBiel(); E_bulk += el.Energie_Bulk(); P_bulk += el.Puissance_Bulk(); // globalisation des volumes - volume_total_matiere += el.Volume(); + volume_total_matiere += el.Volume(); + if (pa.CalVolTotalEntreSurfaceEtPlansRef()) + { const Coordonnee& volPlan = el.VolumePlan(); + if (volPlan.Dimension()) + vol_total2D_avec_plan_ref(nbMail) += volPlan; + }; // globalisation des temps cpu loi de comp et métrique temps_lois_comportement += el.Temps_lois_comportement(); temps_lois_comportement -= temps_debut_lois_comportement; temps_metrique_K_SM += el.Temps_metrique_K_SM(); temps_metrique_K_SM -= temps_debut_metrique_K_SM; - if (pa.CalVolTotalEntreSurfaceEtPlansRef()) - { const Coordonnee& volPlan = el.VolumePlan(); - if (volPlan.Dimension()) - vol_total2D_avec_plan_ref(nbMail) += volPlan; - }; - }; + }; + }; } catch (ErrJacobienNegatif_ElemMeca excep) // cas d'un jacobien négatif "a prendre en compte" @@ -1890,10 +2000,6 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin.Affichage_ecran(entete); }; if (permet_affichage >3) cout << "\n -- fin calcul second membre " << flush; - // -- on transfert en global les énergies internes - Transfert_ParaGlob_energies_internesLoisComp(); - Transfert_ParaGlob_energies_hourglass_bulk_stab(); - // idem pour les volumes entre plans //---- debug // if (pa.CalVolTotalEntreSurfaceEtPlansRef()) // { //Tableau vol_total2D_avec_plan_ref; // volume total entre la surface et : yz, xz,xy @@ -1902,13 +2008,67 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & // << vol_total2D_avec_plan_ref(1) << flush; // }; //---- fin debug - Transfert_ParaGlob_volume_entre_plans(); // -- calcul des intégrales éventuelles avec transfert en global lesMail->Integration(); tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu - + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + { tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu + // récup du nombre total d'éléments, cumul sur tous les maillages + int total_elem = distribution_CPU_algo.NB_total_element(); + // 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) + { tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu + // on récupère un résultat de calcul + temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu +// DeuxEntiers num_el_et_mail; +// mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 24, num_el_et_mail); + reqs1 = deux_faux_entiers.Irecup_MPI(mpi::any_source, 24); + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu + +// temps_attente.Mise_en_route_du_comptage(); // comptage cpu +// mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli +// temps_attente.Arret_du_comptage(); // fin comptage cpu + int ne = (int) deux_faux_entiers(1); //num_el_et_mail.un; // numero d'identification de l'element + int nbMail = (int) deux_faux_entiers(2);//num_el_et_mail.deux; // numéro de maillage + // d'où l'élément + ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); + // récupération des conteneurs ad hoc vecteur et raideur + int source = stat.source(); // récupération du numéro de la source + Vecteur * residu = el.Conteneur_Residu(); + tempsSecondMembreEnerg.Arret_du_comptage(); + temps_transfert_long_matSm.Mise_en_route_du_comptage(); // comptage cpu + mpi::request reqs2 = residu->Irecup_MPI(source, 25); + reqs2.wait(); // on attend que le conteneur soit rempli + temps_transfert_long_matSm.Arret_du_comptage(); // fin comptage cpu + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); + Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el + // --- assemblage + Ass.AssemSM (vglobin,*residu,el.TableauDdl(),taN); // du second membre + // on incrémente le nombre d'élément traité + nb_elem_deja_calcule++; + }; + tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu + }; + // récupération de toutes les énergies par le cpu 0 + tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu + Algori::Passage_energiesEtVolumes(); + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); + #endif + + tempsSecondMembreEnerg.Mise_en_route_du_comptage(); + // -- 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 ; }; diff --git a/Algo/AlgoRef/Algori.h b/Algo/AlgoRef/Algori.h index 972252a..d0b5448 100644 --- a/Algo/AlgoRef/Algori.h +++ b/Algo/AlgoRef/Algori.h @@ -741,9 +741,18 @@ class Algori Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16) #ifdef UTILISATION_MPI // 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(19) - Temps_CPU_HZpp temps_attente ; // lesTempsCpu(18) + 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) #endif Tableau lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties @@ -1289,6 +1298,13 @@ class Algori }; }; + + #ifdef UTILISATION_MPI + // 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(); + #endif + }; /// @} // end of group diff --git a/Algo/AlgoRef/Algori2.cc b/Algo/AlgoRef/Algori2.cc index b48032d..4046428 100644 --- a/Algo/AlgoRef/Algori2.cc +++ b/Algo/AlgoRef/Algori2.cc @@ -1893,9 +1893,18 @@ void Algori::Ecriture_base_info sort << "\n tps_chargement "<< temps_chargement; sort << "\n tps_rech_contact "<< temps_rech_contact; #ifdef UTILISATION_MPI - sort << "\n tps_transfert_court_proc "<< temps_transfert_court; - sort << "\n tps_transfert_long_proc "<< temps_transfert_long; - sort << "\n tps_attente_proc "<< temps_attente; + sort << "\n tps_transfert_court_Algo "<< temps_transfert_court_algo; + sort << "\n tps_transfert_long_Algo "<< temps_transfert_long_algo; + sort << "\n tps_attente_Algo "<< temps_attente_algo; + sort << "\n tps_transfert_court_matSm "<< temps_transfert_court_matSm; + sort << "\n tps_transfert_long_matSm "<< temps_transfert_long_matSm; + sort << "\n tps_attente_matSm "<< temps_attente_matSm; + sort << "\n tps_transfert_court_charge "<< temps_transfert_court_charge; + sort << "\n tps_transfert_long_charge "<< temps_transfert_long_charge; + sort << "\n tps_attente_charge "<< temps_attente_charge; + sort << "\n tps_transfert_court_contact "<< temps_transfert_court_contact; + sort << "\n tps_transfert_long_contact "<< temps_transfert_long_contact; + sort << "\n tps_attente_contact "<< temps_attente_contact; #endif // ----- écriture éventuelle des paramètres de l'algorithme et informations particulières @@ -2084,9 +2093,18 @@ void Algori::Lecture_base_info(ifstream& ent,const int cas) ent >> nom1 >> temps_chargement; ent >> nom1 >> temps_rech_contact; #ifdef UTILISATION_MPI - ent >> nom1 >> temps_transfert_court; - ent >> nom1 >> temps_transfert_long; - ent >> nom1 >> temps_attente; + ent >> nom1 >> temps_transfert_court_algo; + ent >> nom1 >> temps_transfert_long_algo; + ent >> nom1 >> temps_attente_algo; + ent >> nom1 >> temps_transfert_court_matSm; + ent >> nom1 >> temps_transfert_long_matSm; + ent >> nom1 >> temps_attente_matSm; + ent >> nom1 >> temps_transfert_court_charge; + ent >> nom1 >> temps_transfert_long_charge; + ent >> nom1 >> temps_attente_charge; + ent >> nom1 >> temps_transfert_court_contact; + ent >> nom1 >> temps_transfert_long_contact; + ent >> nom1 >> temps_attente_contact; #endif // --- lecture éventuelle des paramètres de l'algorithme diff --git a/Algo/AlgoRef/Algori3.cc b/Algo/AlgoRef/Algori3.cc index 1a4a768..6ce38db 100644 --- a/Algo/AlgoRef/Algori3.cc +++ b/Algo/AlgoRef/Algori3.cc @@ -1194,7 +1194,13 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_ cout << "\n >>> changement de inter_nb_entre_relax de " << old_valeur << " en ==> "<< inter_nb_entre_relax; }; - +// #ifdef UTILISATION_MPI +// // debug +// cout << "\n debug Algori::AmortissementCinetique N: " << icharge +// << " debut, proc= "<< ParaGlob::Monde()->rank() << flush; +// // fin debug +// #endif + // // dans le cas où l'on veut un amortissement individuel aux noeuds, on appelle la méthode spécifique // int relax_vit_individuel = 0; // if (amortissement_cinetique_au_noeud && !relax_vit) @@ -1202,6 +1208,7 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_ //*** je ne comprends pas le test que j'ai mis ici: abscon !! 16 oct 2018 // on ne continue que s'il n'y a pas d'amortissement cinétique en route + bool relaxation_effectuee = false; // initialisation if (!((icharge > nb_deb_test_amort_cinetique_noe) && amortissement_cinetique_au_noeud)) // ---- non la suite n'est pas bonne et converge beaucoup moins bien !! // je le remplace : on test si on est en amortissement cinétique, et que le nombre d'itérations @@ -1224,7 +1231,6 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_ // si > 0 : indique que la procédure est active, et que, de manière consécutive, indique // le nombre de fois où il y a eu baisse - bool relaxation_effectuee = false; // initialisation bool relaxation_reactive = false; // " if ((amortissement_cinetique)&&(icharge != 0) && (icharge > nb_deb_test_amort_cinetique)) { // on regarde si l'énergie cinétique a déjà été calculée, sinon on la calcule @@ -1326,6 +1332,7 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_ && (nb_depuis_derniere_relax >= inter_nb_entre_relax)) { // cas ou on met en place l'amortissement V.Zero();relaxation_effectuee=true; + nb_depuis_derniere_relax = 0; dernier_pic = pic_E_cint_t; // on sauvegarde if (taille_moyenne_glissante != 1) // on remet tout à 0 @@ -1387,7 +1394,7 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_ // on tente d'afficher que si l'amortissement a effectivement eu lieu // if (relax_vit && pa.AfficheIncrEnergie()) if (relaxation_effectuee) - if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2)) + {if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2)) {cout << "\n N:" << icharge << " relaxation cinetique effectuee " << " pic_E_cint_t("< lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties @@ -481,14 +490,34 @@ void Algori::Temps_CPU_HZpp_to_lesTempsCpu temps_rech_contact = contact.Temps_cpu_Contact(); lesTempsCpu(16)(1)= temps_rech_contact.Temps_CPU_User(); #ifdef UTILISATION_MPI - lesTempsCpu(17)(1)= temps_transfert_court.Temps_CPU_User(); - lesTempsCpu(19)(1)= temps_transfert_long.Temps_CPU_User(); - lesTempsCpu(18)(1)= temps_attente.Temps_CPU_User(); + // 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(); + // 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(); + // du chargement + temps_transfert_court_charge = charge.Temps_transfert_court(); + lesTempsCpu(23)(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(); + temps_attente_charge = charge.Temps_attente(); + lesTempsCpu(25)(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(); + temps_transfert_long_contact = contact.Temps_transfert_long(); + lesTempsCpu(27)(1)= temps_transfert_long_contact.Temps_CPU_User(); + temps_attente_contact = contact.Temps_attente(); + lesTempsCpu(28)(1)= temps_attente_contact.Temps_CPU_User(); #endif }; // idem la méthode de transfert si-dessus mais concerne uniquement les temps internes à l'algo +// utilisé par l'algo combiné // ajoute au tableau passé en paramètre, les temps de l'algo Tableau & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau & lesTsCpu) { // test éventuel de la taille du tableau @@ -513,9 +542,18 @@ Tableau & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau < lesTsCpu(9) += tempsRaidSmEnerContact; // conversion de long long en double lesTsCpu(10) += tempsSecondMembreEnergContact; // conversion de long long en double #ifdef UTILISATION_MPI - lesTsCpu(17) += temps_transfert_court; - lesTsCpu(19) += temps_transfert_long; - lesTsCpu(18) += temps_attente; + 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; #endif // retour return lesTsCpu; @@ -542,9 +580,18 @@ void Algori::Arret_du_comptage_CPU() temps_chargement.Arret_du_comptage(); temps_rech_contact.Arret_du_comptage(); #ifdef UTILISATION_MPI - temps_transfert_court.Arret_du_comptage(); - temps_transfert_long.Arret_du_comptage(); - temps_attente.Arret_du_comptage(); + temps_transfert_court_algo.Arret_du_comptage(); + temps_transfert_long_algo.Arret_du_comptage(); + temps_attente_algo.Arret_du_comptage(); + temps_transfert_court_matSm.Arret_du_comptage(); + temps_transfert_long_matSm.Arret_du_comptage(); + temps_attente_matSm.Arret_du_comptage(); + temps_transfert_court_charge.Arret_du_comptage(); + temps_transfert_long_charge.Arret_du_comptage(); + temps_attente_charge.Arret_du_comptage(); + temps_transfert_court_contact.Arret_du_comptage(); + temps_transfert_long_contact.Arret_du_comptage(); + temps_attente_contact.Arret_du_comptage(); #endif }; @@ -667,17 +714,54 @@ void Algori::Sortie_temps_cpu(const LesCondLim& lesCondLim << tempsSortieFilCalcul.Temps_CPU_User_milli() ; #ifdef UTILISATION_MPI - sort_cpu << "\n tps__transfert_cour_inter_cpu " - << "("<< std::setw(nbdigit) << (100*temps_transfert_court.Temps_CPU_User()/total_cpu) << " % ) " - << temps_transfert_court.Temps_CPU_User_milli() + sort_cpu << "\n --------- dialogue inter cpu --------- "; + sort_cpu << "\n tps__transfert_court_Algo " + << "("<< std::setw(nbdigit) << (100*temps_transfert_court_algo.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_court_algo.Temps_CPU_User_milli() ; - sort_cpu << "\n tps__transfert_long_inter_cpu " - << "("<< std::setw(nbdigit) << (100*temps_transfert_long.Temps_CPU_User()/total_cpu) << " % ) " - << temps_transfert_long.Temps_CPU_User_milli() + sort_cpu << "\n tps__transfert_long_Algo " + << "("<< std::setw(nbdigit) << (100*temps_transfert_long_algo.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_long_algo.Temps_CPU_User_milli() ; - sort_cpu << "\n tps__attente_inter_cpu " - << "("<< std::setw(nbdigit) << (100*temps_attente.Temps_CPU_User()/total_cpu) << " % ) " - << temps_attente.Temps_CPU_User_milli() + sort_cpu << "\n tps__attente_Algo " + << "("<< std::setw(nbdigit) << (100*temps_attente_algo.Temps_CPU_User()/total_cpu) << " % ) " + << temps_attente_algo.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__transfert_court-Mat-Smloc " + << "("<< std::setw(nbdigit) << (100*temps_transfert_court_matSm.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_court_matSm.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__transfert_long-Mat-Smloc " + << "("<< std::setw(nbdigit) << (100*temps_transfert_long_matSm.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_long_matSm.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__attente-Mat-Smloc " + << "("<< std::setw(nbdigit) << (100*temps_attente_matSm.Temps_CPU_User()/total_cpu) << " % ) " + << temps_attente_matSm.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__transfert_court_charge " + << "("<< std::setw(nbdigit) << (100*temps_transfert_court_charge.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_court_charge.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__transfert_long_charge " + << "("<< std::setw(nbdigit) << (100*temps_transfert_long_charge.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_long_charge.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__attente_charge " + << "("<< std::setw(nbdigit) << (100*temps_attente_charge.Temps_CPU_User()/total_cpu) << " % ) " + << temps_attente_charge.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__transfert_court_contact " + << "("<< std::setw(nbdigit) << (100*temps_transfert_court_contact.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_court_contact.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__transfert_long_contact " + << "("<< std::setw(nbdigit) << (100*temps_transfert_long_contact.Temps_CPU_User()/total_cpu) << " % ) " + << temps_transfert_long_contact.Temps_CPU_User_milli() + ; + sort_cpu << "\n tps__attente_contact " + << "("<< std::setw(nbdigit) << (100*temps_attente_contact.Temps_CPU_User()/total_cpu) << " % ) " + << temps_attente_contact.Temps_CPU_User_milli() ; #endif sort_cpu << "\n"; @@ -1247,7 +1331,7 @@ Tableau Algori::New_tous_les_Algo {// seule le process 0 a fait la résolution globale // il gère seul également la convergence, mais il doit tenir au courant les autres process // on utilise un std::array pour passer en une fois les infos - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu std::array indic_convergence = {phase_de_convergence,nombre_de_bonnes_convergences ,nombre_de_mauvaises_convergences,a_converge ,a_converge_iterMoins1,nb_cycle_test_max_var_residu @@ -1263,7 +1347,7 @@ Tableau Algori::New_tous_les_Algo a_converge_iterMoins1 = indic_convergence[4]; nb_cycle_test_max_var_residu = indic_convergence[5]; }; - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu }; // globalisation des grandeurs globales: proc de calcul -> maitre puis transmission à ParaGlob // et transmission aux proc de calcul: @@ -1339,6 +1423,102 @@ 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; + 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 +////------------- debug -------- +//cout << "\n debug Algori::Passage_energiesEtVolumes() " +// << "\n barriere avant transfert énergies , proc= "<< ParaGlob::Monde()->rank() << flush; +// +////------------- fin debug -------- +// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process + // on crée un vecteur intermédiaire pour le passage d'information + int dim_tav_double = 0;int tail_tab = vol_total2D_avec_plan_ref.Taille(); + for (int i=1;i<= tail_tab;i++) + dim_tav_double += vol_total2D_avec_plan_ref(i).Dimension(); + Vecteur v_val_inter(8+dim_tav_double); + int num_process = ParaGlob::Monde()->rank(); + if (num_process != 0) + {temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu + //on rempli le vecteur de passage + v_val_inter(1) =energTotal.EnergieElastique(); + v_val_inter(2) =energTotal.DissipationPlastique(); + v_val_inter(3) =energTotal.DissipationVisqueuse(); + v_val_inter(4)=energHourglass; + v_val_inter(5)=energStabiliMembBiel; + v_val_inter(6)=E_bulk; + v_val_inter(7)=P_bulk; + v_val_inter(8)=volume_total_matiere; + int indice = 1; + for (int i=1;i<= tail_tab;i++) + { int dim_coord = vol_total2D_avec_plan_ref(i).Dimension(); + if (dim_coord) + for (int j=1;j<= dim_coord;j++,indice++) + v_val_inter(8+indice)=vol_total2D_avec_plan_ref(i)(j); + }; +// //------------- debug -------- +// cout << "\n debug Algori::Passage_energiesEtVolumes() num_process= "<< num_process; +// cout << "\n v_val_inter= "<size(); + for (int i=1;iTaille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif @@ -128,7 +129,8 @@ void AlgoriCombine::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); #ifdef UTILISATION_MPI // passage de l'équilibrage à ParaGlob - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); tab_algo(i)->InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor @@ -185,7 +187,8 @@ void AlgoriCombine::MiseAJourAlgo(ParaGlob * paraGlob,LesMaillages * lesMail, {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); #ifdef UTILISATION_MPI // passage de l'équilibrage à ParaGlob - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor @@ -260,7 +263,8 @@ void AlgoriCombine::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); #ifdef UTILISATION_MPI // passage de l'équilibrage à ParaGlob - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); @@ -330,7 +334,8 @@ void AlgoriCombine::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); #ifdef UTILISATION_MPI // passage de l'équilibrage à ParaGlob - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); @@ -407,7 +412,8 @@ void AlgoriCombine::FinCalcul(ParaGlob * paraGlob,LesMaillages * lesMail,LesRefe {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); #ifdef UTILISATION_MPI // passage de l'équilibrage à ParaGlob - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc index a7b9299..1c7129b 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc @@ -963,7 +963,8 @@ void AlgoriRungeKutta::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc index ed8398e..9b87e88 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc @@ -805,7 +805,8 @@ void AlgoriDynaExpli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc index d234dfe..b87444c 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc @@ -296,7 +296,8 @@ void AlgoriDynaExpli_zhai::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * les if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc index b0ad58a..0b433e5 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc @@ -285,7 +285,8 @@ void Algori_chung_lee::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc index fcf3996..9399d8a 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc @@ -1316,9 +1316,13 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // 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); - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + tempsInitialisation.Arret_du_comptage(); // temps cpu + temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + temps_transfert_court_algo.Arret_du_comptage(); // comptage cpu + tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif @@ -1574,11 +1578,19 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // choix de la matrice de masse, qui est en fait celle qui correspond au ddl Xi // 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) + #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); - if (ParaGlob::NiveauImpression() > 2) + #ifdef UTILISATION_MPI + // seule le process 0 s'occupe de la sortie + if (ParaGlob::Monde()->rank() == 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); @@ -1988,9 +2000,11 @@ Vecteur V_ext(F_int_tdt); }; }; // fin du switch sur compteur_demarrage #ifdef UTILISATION_MPI - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + tempsCalEquilibre.Arret_du_comptage(); // temps cpu + temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu broadcast(*ParaGlob::Monde(), arret_pilotage, 0); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu + tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu #endif if (arret_pilotage) break; // si dans le switch précédent on a un arret de pilotage qui est demandé @@ -2251,10 +2265,21 @@ Vecteur V_ext(F_int_tdt); // mise en place du chargement impose, c-a-d calcul de la puissance externe // si pb on sort de la boucle +//// debug +//cout << "\n debug algo relax " +// << " barriere avant chargement , proc= "<< ParaGlob::Monde()->rank() +// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush; +//// fin debug +// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process if (!(charge->ChargeSecondMembre_Ex_mecaSolid (Ass1,lesMail,lesRef,vglobex,pa,lesCourbes1D,lesFonctionsnD))) { Change_PhaseDeConvergence(-10);break;}; - +//// debug +//cout << "\n debug algo relax " +// << " après chargement , proc= "<< ParaGlob::Monde()->rank() +// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush; +//// fin debug + //// autre essai !! //if (pa.ContactType()==4) // dans le cas d'un contact de type 4 //{V_ext = F_int_tdt; V_ext += F_ext_tdt; @@ -2277,13 +2302,23 @@ Vecteur V_ext(F_int_tdt); vglobaal += vglobex ;vglobaal += vglobin ; // on calcul la matrice de masse qui est très particulière dans le cas de la relaxation dynamique // c'est la partie la plus importante de l'algo: l'adaptation de la masse en continue - //-- *** on utilise le volume de chaque élément, donc il doit avoir été calculé + //-- *** dans le cas historique : type_calcul_mass ==1 + // 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 ,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) @@ -2400,10 +2435,45 @@ Vecteur V_ext(F_int_tdt); }; #ifdef UTILISATION_MPI }; - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu - broadcast(*ParaGlob::Monde(), arretResidu, 0); - broadcast(*ParaGlob::Monde(), arret, 0); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + tempsCalEquilibre.Arret_du_comptage(); // temps cpu + temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu +// TroisEntiers les_arrets(arretResidu,arret,demande_de_break); + Vecteur trois_faux_entiers(3); + trois_faux_entiers(1) = (double) arretResidu; + trois_faux_entiers(2) = (double) arret; + trois_faux_entiers(3) = (double) demande_de_break; + + +////---- debug +//cout << "\n debug algo relax : barriere avant transfert les_arrets proc = " << ParaGlob::Monde()->rank() +// << " les_arrets= " << les_arrets << " compteur= " << compteur << " compteur_demarrage= " << compteur_demarrage << flush; +////--- fin debug +//// debug +//cout << "\n debug algo relax " +// << " barriere avant transfert les_arrets , proc= "<< ParaGlob::Monde()->rank() << flush; +//// fin debug +// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process +// broadcast(*ParaGlob::Monde(), les_arrets, 0); +// broadcast(*ParaGlob::Monde(), trois_faux_entiers, 0); + trois_faux_entiers.Broadcast(0); + +// operator MPI_Comm() const; + + if (ParaGlob::Monde()->rank() != 0) + {arretResidu= (int) trois_faux_entiers(1); //les_arrets.un; + arret = (int) trois_faux_entiers(2); //les_arrets.deux; + demande_de_break = (int) trois_faux_entiers(3); //les_arrets.trois; + }; +////---- debug +//cout << "\n debug algo relax : proc = " << ParaGlob::Monde()->rank() +// << " après transfer: les_arrets= " << les_arrets << " compteur= " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush; +////--- fin debug +////---- debug +//cout << "\n debug algo relax : proc = " << ParaGlob::Monde()->rank() +// << "\n on continue "<< flush; +////--- fin debug + temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu + tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu #endif if (demande_de_break) break; @@ -2430,21 +2500,48 @@ Vecteur V_ext(F_int_tdt); // affichage éventuelle du vecteur solution : accélération if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage du vecteur solution acceleration "; - acceleration_tdt.Affichage_ecran(entete); }; + acceleration_tdt.Affichage_ecran(entete); + }; // retour des accélération dans les reperes generaux, dans le cas où ils ont ete modifie // par des conditions linéaires lesCondLim->RepInitiaux( acceleration_tdt,Ass3.Nb_cas_assemb()); #ifdef UTILISATION_MPI } - else // s'il s'agit d'un process de calcul élémentaire - {sol = &vglobaal; // il faut affecter sol pour récupérer ensuite la solution - }; - // le process 0 transmet aux autres process le vecteur résultat - temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu - sol->Broadcast(0); - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + // s'il s'agit d'un process de calcul élémentaire ou non +// sol = &vglobaal; // il faut affecter sol pour récupérer ensuite la solution + // le process 0 transmet aux autres process le vecteur résultat + tempsCalEquilibre.Arret_du_comptage(); // temps cpu + temps_transfert_long_algo.Mise_en_route_du_comptage(); // comptage cpu +// sol->Broadcast(0); +//// debug +//cout << "\n debug algo relax " +// << " barriere avant transfert acceleration_tdt , proc= "<< ParaGlob::Monde()->rank() +// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush; +//// fin debug +// 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; +//// fin debug + + + temps_transfert_long_algo.Arret_du_comptage(); // fin comptage cpu + tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu +// // debug +// cout << "\n debug algo relax , proc= "<< ParaGlob::Monde()->rank() +// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage << " acceleration: " +// << acceleration_tdt << flush; +// // fin debug + #else +// // debug +// cout << "\n debug algo relax " +// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage << " acceleration: "; +// acceleration_tdt.Affiche(); cout << flush; +// // fin debug #endif - + // effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée lesCondLim->EffMarque(); if (pa.ContactType()) lescontacts->EffMarque(); @@ -2484,8 +2581,13 @@ Vecteur V_ext(F_int_tdt); || ((typeCalRelaxation == 4) && (Cinetique_ou_visqueux(force_recalcul_masse))) ) { relax_vit_acce = AmortissementCinetique(delta_X,1.,X_tdt,*mat_masse_sauve,compteur,vitesse_tdt); +////---- debug +//cout << "\n debug algo relax : proc = " << ParaGlob::Monde()->rank() +// << "\n sortie relaxation: relax_vit_acce= " << relax_vit_acce << " compteur= " << compteur << flush; +////--- fin debug + // il faut re-updater les vitesses -// if (Abs(relax_vit_acce) == 1) +// if (Abs(relax_vit_acce) == 1) if (relax_vit_acce == 1) // il y a eu relaxation {lesMail->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1); list_iter_relax.push_front(compteur); // on sauvegarde l'iter relaxé @@ -2544,7 +2646,9 @@ Vecteur V_ext(F_int_tdt); #ifdef UTILISATION_MPI // seule le process 0 a fait la résolution globale // il gère seul également la convergence, mais il doit tenir au courant les autres process + tempsCalEquilibre.Arret_du_comptage(); // fin comptage cpu Algori::Passage_indicConvergenceAuxProcCalcul(); + tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu // ce qui permet le déroulement correct de la suite pour tous les process #endif @@ -2839,6 +2943,15 @@ void AlgoriRelaxDyna::CalculMatriceMasse dima--; int nbddl_X = mat_masse->Nb_ligne(); int nbNoe = nbddl_X / dima; + #ifdef UTILISATION_MPI + // 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) + if (type_calcul_mass == 1) + { cout << "\n erreur : en calcul MPI, le type 1 de calcul de la masse n'est pas implante "; + Sortie(1); + }; + #endif switch (type_calcul_mass) diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc index 5e658cf..762519f 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc @@ -874,7 +874,8 @@ void AlgoriTchamwa::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif diff --git a/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc b/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc index 825620f..b4f20b2 100644 --- a/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc +++ b/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc @@ -52,7 +52,8 @@ void AlgoriNewmark::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif diff --git a/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc b/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc index f2d6f4f..a44c47b 100644 --- a/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc +++ b/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc @@ -52,10 +52,13 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, // 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); - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + tempsInitialisation.Arret_du_comptage(); // temps cpu + temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + temps_transfert_court_algo.Arret_du_comptage(); // comptage cpu + tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif @@ -969,9 +972,9 @@ decol = false; // pour debugger {arret_iteration = true; }; //break;} // cas ou la méthode Convergence() demande l'arret #ifdef UTILISATION_MPI }; - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu broadcast(*ParaGlob::Monde(), arret_iteration, 0); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu #endif if (arret_iteration) break; @@ -1079,7 +1082,7 @@ decol = false; // pour debugger {sol = &vglobaal; // il faut affecter sol pour récupérer ensuite la solution }; // le process 0 transmet aux autres process le vecteur résultat - temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + temps_transfert_long_algo.Mise_en_route_du_comptage(); // comptage cpu //// essai pour remplacer broadcast // int nb_process = ParaGlob::Monde()->size(); @@ -1103,7 +1106,7 @@ decol = false; // pour debugger // synchronisation ici de tous les process (à supprimer par la suite car n'est // pas nécessaire pour le déroulementa priori ?? ) // ParaGlob::Monde()->barrier(); - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + temps_transfert_long_algo.Arret_du_comptage(); // fin comptage cpu #endif // effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée diff --git a/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc b/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc index 2a9d990..58d708c 100644 --- a/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc +++ b/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc @@ -652,7 +652,8 @@ void AlgoBonelli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 ) {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail); distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); - paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()); + paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); }; #endif diff --git a/Chargement/Charge.cc b/Chargement/Charge.cc index 3eb7a47..391c06f 100644 --- a/Chargement/Charge.cc +++ b/Chargement/Charge.cc @@ -198,6 +198,10 @@ Charge::Charge () : // constructeur par defaut ,temps_fin_non_stricte(0) ,nomtypeCharge(),ancien_num_pt_type5(0),num_pt_courant_type5(0) ,temps_cpu_chargement() + #ifdef UTILISATION_MPI + ,temps_transfert_court(),temps_transfert_long(),temps_attente() + #endif + {// mise à jour de la valeur par défaut du chargement au cas où aucun chargement // n'est définit nomtypeCharge ="TYPE1"; diff --git a/Chargement/Charge.h b/Chargement/Charge.h index 778f07d..161a3b0 100644 --- a/Chargement/Charge.h +++ b/Chargement/Charge.h @@ -257,6 +257,13 @@ class Charge void Change_temps_fin_non_stricte(int methode) {temps_fin_non_stricte = methode;}; + #ifdef UTILISATION_MPI + // cas d'un calcul parallèle: // passage des infos entre process + 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;} ; + #endif + // retourne le temps cumulés relatif à tous les chargements const Temps_CPU_HZpp& Temps_cpu_chargement() const {return temps_cpu_chargement;}; @@ -362,6 +369,13 @@ class Charge // de la variation du pas de temps // mise à jour avec la méthode : Change_temps_fin_non_stricte(int methode) + #ifdef UTILISATION_MPI + // cas d'un calcul parallèle: // passage des infos entre process + Temps_CPU_HZpp temps_transfert_court ; + Temps_CPU_HZpp temps_transfert_long ; + Temps_CPU_HZpp temps_attente ; + #endif + Temps_CPU_HZpp temps_cpu_chargement; // le temps cpu du à tous les chargements // les autres parametres relatif au temps diff --git a/Chargement/Charge2.cc b/Chargement/Charge2.cc index a36566e..080503a 100644 --- a/Chargement/Charge2.cc +++ b/Chargement/Charge2.cc @@ -45,15 +45,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid (Assemblage & assemb,LesMaillages * lesMail,LesReferences* lesRef,Vecteur& vecglob ,const ParaAlgoControle & pa,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD) { -#ifdef UTILISATION_MPI - // cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées - if (ParaGlob::Monde()->rank() != 0) - return true; -#endif temps_cpu_chargement.Mise_en_route_du_comptage(); // temps cpu bool retour = true; // init par défaut try { + #ifndef UTILISATION_MPI // pour tous les maillages, pour tous les éléments on effectue une initialisation éventuelle int nb_mail = lesMail->NbMaillage(); for (int imail = 1;imail<=nb_mail;imail++) @@ -61,15 +57,51 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid for (int iele =1;iele<=nb_ele;iele++) lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement(); }; - + + #else +// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process + // cas d'un calcul multi-CPU , si cpu 0, idem cas non parallèle + if (ParaGlob::Monde()->rank() == 0) + {int nb_mail = lesMail->NbMaillage(); + for (int imail = 1;imail<=nb_mail;imail++) + { int nb_ele = lesMail->Nombre_element(imail); + for (int iele =1;iele<=nb_ele;iele++) + lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement(); + }; + } + else + {// on va parcourir les éléments associés au cpu + // on récupère la distribution d'éléments concernant le cpu en cours + // si c'est le cpu 0 on initialise tous les éléments + const Tableau < list >& tab_list_elem_cpu = + ParaGlob::param->const_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 imail =1; imail<= nb_mail_distrib; imail++) + {const list & list_elem_cpu= tab_list_elem_cpu(imail); // 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 iele = (*il); + lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement(); + }; + }; + }; + #endif + int posi = Id_nom_ddl("X1") -1; int dim = ParaGlob::Dimension(); - - // $$$ --- cas des forces ponctuelles --- $$$ - // on regarde si l'espace de travail est axi-symétrique, si oui on utilise une dimension réduite int dima=dim; // c'est dima qui est utiliser pour la mise en place des efforts ponctuelles if (ParaGlob::AxiSymetrie()) dima--; + + // $$$ --- cas des forces ponctuelles --- $$$ + #ifdef UTILISATION_MPI + // cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0 uniquement + if (ParaGlob::Monde()->rank() == 0) + #endif // on parcours le tableau tabPonctuel for (int i=1;i<= tabPonctuel.Taille();i++) { // recup de la reference correspondant au mot cle @@ -199,9 +231,12 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; }; - // $$$ --- cas des torseurs de forces ponctuelles --- $$$ + #ifdef UTILISATION_MPI + // cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0 uniquement + if (ParaGlob::Monde()->rank() == 0) + #endif // on parcours le tableau tabTorseurPonct for (int i=1;i<= tabTorseurPonct.Taille();i++) { // recup de la reference correspondant au mot cle @@ -317,7 +352,26 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; }; - // --- cas des forces surfaciques ---$$$ + #ifdef UTILISATION_MPI + mpi::request reqs1; + mpi::request reqs2; + // on définit les conteneurs de passage d'info + int nb_proc = ParaGlob::Monde()->size(); + Tableau tab_reqs1(nb_proc); + Tableau tab_reqs2(nb_proc); + Tableau tabV_transfert(nb_proc); + Tableau tab_six_faux_entiers(nb_proc); + for (int i=1;i<=nb_proc;i++)tab_six_faux_entiers(i).Change_taille(6); + int proc_en_cours = ParaGlob::Monde()->rank(); + int index_transfert; // index pour incrémenter dans les tableaux +// la suite à virer qu'en c'est ok + Vecteur cinq_faux_entiers(5); + bool premier_passage = true; + if (proc_en_cours != 0) + { + #endif + + // --- cas des forces surfaciques ---$$$ int tabsurfactaille = tabFsurfac.Taille(); if ( tabsurfactaille != 0) {// on parcours le tableau tabFsurfac dans le repère absolu @@ -338,8 +392,16 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid Coordonnee vforce; // init par défaut int nbref = ref.Taille(); for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (tabFsurfac_i.Champ()) @@ -412,7 +474,40 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // appel du calcul du second membre correspondant à la charge surfacique // Coordonnee vforce = tabFsurfac_i.Coord() * coeff; Vecteur SM = elem.SM_charge_surfacique_E_tdt(vforce,pt_fonct,ref.NumeroFA(ns),pa); - // assemblage du second membre + + #ifdef UTILISATION_MPI + temps_cpu_chargement.Arret_du_comptage(); + // on récupère un signal du process 0 + temps_attente.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(); + }; + temps_attente.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + int tyfront = 5; // init par défaut du type de frontière + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + CinqEntiers num_el_mail_tyfront_nufront + (elem.Num_elt(),elem.Num_maillage() + ,tyfront,ref.NumeroFA(ns),SM.Taille()); + // on transmet les numéros d'élément et de maillage + reqs1 = ParaGlob::Monde()->isend(0, 34, num_el_mail_tyfront_nufront); + 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.Ienvoi_MPI(0,35); + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; // init if (ParaGlob::AxiSymetrie()) @@ -421,15 +516,21 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid else // cas normale {elfront = elem.Frontiere_surfacique(ref.NumeroFA(ns)); };// la surface frontière assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage + } + #endif }; }; }; }; - + // --- cas des pressions ---$$$ int tabPresUniftaille = tabPresUnif.Taille(); if ( tabPresUniftaille != 0) - {// on parcours le tableau tabPresUnif + { + #ifdef UTILISATION_MPI + index_transfert=0; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabPresUnif for (int i=1;i<= tabPresUniftaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabPresUnif_i = tabPresUnif(i); @@ -446,7 +547,14 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid {// Maintenant les éléments et les surfaces associes int nbref = ref.Taille(); for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif// récupération de l'élément fini Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); double press_ac = 0.; // init // récupération de la pression de référence @@ -499,9 +607,65 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid double coeff_charge = (pt_courbe->Valeur(Temps_courant())) * tabPresUnif_i.Echelle_courbe(); press_ac *= coeff_charge; }; + + + #ifdef UTILISATION_MPI // appel du calcul du second membre correspondant à la charge de type pression - // double press_ac = (tabPresUnif_i.Val()) * coeff; - Vecteur SM = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,ref.NumeroFA(ns),pa); + // 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++; + if (index_transfert > nb_proc) // on fait une permutation circulaire sur un nombre = au nombre total de proc + // sachant qu'ici on a toujours le même proc, mais on considère qu'après nb_proc transferts, le premier de la liste + // est terminé + index_transfert = 1;// on revient au premier élément des tableaux de transfert + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + SM_transfert = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,ref.NumeroFA(ns),pa); + temps_cpu_chargement.Arret_du_comptage(); + mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier + mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier + // on s'assure quand même que les précents transferts sont terminés + temps_attente.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(); + }; + temps_attente.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + int tyfront = 5; // init par défaut du type de frontière + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier + six_faux_entiers(1) = (double) elem.Num_elt(); + six_faux_entiers(2) = (double) elem.Num_maillage(); + six_faux_entiers(3) = (double) tyfront; + six_faux_entiers(4) = (double) ref.NumeroFA(ns); + six_faux_entiers(5) = (double) SM_transfert.Taille(); + six_faux_entiers(6) = (double) index_transfert; + // on transmet les numéros d'élément et de maillage + reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); + 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,350+index_transfert); +// // debug +// cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() +// // << " CinqEntiers= "<< num_el_mail_tyfront_nufront +// << " six_faux_entiers= " << six_faux_entiers +// << " SM= " << SM << flush; +// // fin debug + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // appel du calcul du second membre correspondant à la charge de type pression + // ici on récupère une adresse car il n'y a pas de crainte d'écraser un vecteur déjà en cours + Vecteur& SM = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,ref.NumeroFA(ns),pa); // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; // init @@ -511,7 +675,9 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid else // cas normale {elfront = elem.Frontiere_surfacique(ref.NumeroFA(ns)); };// la surface frontière assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage - }; + } + #endif + }; }; } }; @@ -1040,6 +1206,181 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; }; //-- fin de hydrodyna + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu + // maintenant on s'occupe du cpu 0 +#ifdef UTILISATION_MPI + // arrivée ici on va indiquer au CPU 0 que c'est fini + index_transfert++; + if (index_transfert > nb_proc) // on fait une permutation circulaire sur un nombre = au nombre total de proc + index_transfert = 1;// on revient au premier élément des tableaux de transfert + mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier + // on s'assure quand même que les précents transferts sont terminés + temps_attente.Mise_en_route_du_comptage(); // comptage attente + if (premier_passage) {premier_passage = false;} + else {reqs1.wait();}; + temps_attente.Arret_du_comptage(); // fin comptage attente + temps_transfert_court.Mise_en_route_du_comptage(); // comptage transfert cpu + int tyfront = - proc_en_cours; // init par défaut du type de frontière + // le signe - indique une fin + Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier + six_faux_entiers(1) = (double) 0; + six_faux_entiers(2) = (double) 0; + six_faux_entiers(3) = (double) tyfront; + six_faux_entiers(4) = (double) 0; + six_faux_entiers(5) = (double) 0; + six_faux_entiers(6) = (double) index_transfert; + reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); // on transmet + temps_transfert_court.Arret_du_comptage(); // fin comptage transfert cpu + } + else // donc ici cas ou on a le rank == 0 et on récolte + { // récup d'un second membre + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + int nb_proc_terminer = 0; // permettra de terminer + // on va boucler sur les éléments récupérés des différents process + // jusqu'à ce que tous les éléments aient finis + premier_passage = true; + int index_transfert = 1; // on se sert du premier élément de tableau + int ne,nbMail,tyfront,num_front,taille_SM; // inter pour la persistance + int source; // le nb de la source émettante +// int index_local_de_tab = 0; + mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier + mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier + Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de calcul + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + reqs1 = six_faux_entiers.Irecup_MPI(mpi::any_source, 34); + mpi::status stat = reqs1.wait(); + ne = (int) six_faux_entiers(1); + nbMail = (int) six_faux_entiers(2); + 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); + source = stat.source(); + +// // on parcourt les transferts possibles a priori +// if (premier_passage) // au premier passage on balaie tous les transferts possible +// {for (int i = 1;i< nb_proc;i++) +// tab_reqs1(i) = tab_six_faux_entiers(i).Irecup_MPI(mpi::any_source, 34); +// premier_passage=false; +// } +// else // sinon on on réenclanche seulement le cas que l'on vient de traiter +// { tab_reqs1(index_local_de_tab) = tab_six_faux_entiers(index_local_de_tab).Irecup_MPI(mpi::any_source, 34); +// }; +// // on fait une boucle sur tous les status potentiels +// // on en sort quand on a trouvé un transfert terminé +// int j=1; +// do{ // début d'une boucle infinie +// boost::optional statu = tab_reqs1(j).test(); +// if (statu) +// {index_local_de_tab = j; +// Vecteur& six_faux_entiers = tab_six_faux_entiers(index_local_de_tab); // pour simplifier +// ne = (int) six_faux_entiers(1); +// nbMail = (int) six_faux_entiers(2); +// 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); +// source = statu->source(); +// break; // on sort de la boucle +// }; +// j++; +// if (j > nb_proc) // on fait une permutation circulaire sur le nombre total de proc=taille des tableaux +// j = 1;// on revient au premier élément des tableaux de transfert +// }while(1); +// // arrivée ici on a les infos sur le premier conteneur +// // a priori le second ne pose pas de pb de temps d'attente on utilise un simple wait +// Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier +// +// mpi::request req; +// std::string rmsg; +// +// req = world.irecv(mpi::any_source, mpi::any_tag, rmsg); +// do { +// boost::optional stat = req.test(); +// if (stat) { +// std::cout << "From " << stat->source() << std::endl; +// std::cout << "Got " << rmsg << std::endl; +// std::cout << "Tagged " << stat->tag() << std::endl; +// break; +// } +// } while(1); + + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu +////-------debug +//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() +//// << " recup CinqEntiers " << num_el_mail_tyfront_nufront << flush; +// << " recup six_faux_entiers " << six_faux_entiers << flush; +////-------fin debug +// int tyfront = num_el_mail_tyfront_nufront.trois; + if (tyfront > 0) + {Element& elem = lesMail->Element_LesMaille(nbMail,ne); + // def de SM avec la bonne dimension + SM_transfert.Change_taille(taille_SM);//num_el_mail_tyfront_nufront.cinq); + // 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, 350+index_transfert); + reqs2.wait(); // on attend que le conteneur soit rempli + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu +////-------debug +//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() +// << " SM= " << SM << flush; +////-------fin debug + +// assemblage + + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + switch (tyfront) + {case 2: + {const ElFrontiere* elfront = elem.Frontiere_lineique(num_front);// num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + case 3: + {const ElFrontiere* elfront = elem.Frontiere_surfacique(num_front);//num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + default: + {cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours + << " le cas tyfront = " << tyfront << " n'est pas pris en compte pour l'instant !! "; + Sortie(1); + } ; + }; + } + else if (tyfront < 0) + {// on est dans le cas où un proc a terminé + nb_proc_terminer++; + } + else + {cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours + << " tyfront ne doit jamais etre nul !! "; + Sortie(1); + } ; + }; + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu +////-------debug +//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() +// << " vecglob final = " << vecglob << flush; +////------fin debug + }; +#endif + +//#ifdef UTILISATION_MPI +////-------debug +//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid poc= "<< proc_en_cours +// << " SM= " << vecglob << flush; +//#else +// cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid " +// << " SM= "; vecglob.Affiche(); +////------fin debug +//#endif + // affichage éventuelle du second membre if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage du second membre apres chargement"; @@ -1061,7 +1402,9 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; retour = false; }; - +#ifdef UTILISATION_MPI + ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process +#endif temps_cpu_chargement.Arret_du_comptage(); return retour; }; diff --git a/General/Distribution_CPU.cc b/General/Distribution_CPU.cc index af17611..0070920 100755 --- a/General/Distribution_CPU.cc +++ b/General/Distribution_CPU.cc @@ -123,7 +123,12 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai }; }; }; - +//// ----- debug +//cout << "\n debug Distribution_CPU::Calcul_Equilibrage_initiale "; +//Distribution_CPU::Affiche(); +//cout << flush; +//// ----- fin debug --- + } }; @@ -136,7 +141,7 @@ void Distribution_CPU::Passage_Equilibrage_aux_CPU() // mise à jour de ParaGlob, qui peut transmettre à tous // la liste des numéros d'éléments concernés - ParaGlob::param->Init_tableau(&tab_list_maillage_element); + ParaGlob::param->Init_tableau(&tab_list_maillage_element,&tab_indic); }; @@ -233,6 +238,35 @@ void Distribution_CPU::load(Archive & ar, const unsigned int version) } }; +// affichage des infos relatives à la distribution +void Distribution_CPU::Affiche() const + { // comme on a des listes on sauvegarde explicitement + cout << "\n ------ Distribution ---------"; + int nb_proc_calcul = tab_list_maillage_element.Taille(); + cout << std::string(" nb total de proc de calcul : ") << nb_proc_calcul ; + for (int i_proc=1;i_proc<= nb_proc_calcul; i_proc++) + {cout << "\n ... cas du proc de calcul : "<< i_proc; + int nb_mail = tab_list_maillage_element(i_proc).Taille(); + cout << std::string(" nb_mail considere = ")<< nb_mail ; + // on sauvegarde également le nombre total d'élément par maillage + // pour cela on se sert de tab_indic pour le premier cpu + for (int num_mail = 1; num_mail <= nb_mail;num_mail++) + cout << ", nb elem total du maillage " << num_mail << " => " << (int) tab_indic(1)(num_mail).Taille(); + for (int imail=1;imail<=nb_mail;imail++) + { const list & list_maillage_element = tab_list_maillage_element(i_proc)(imail); + cout << " \n cas du maillage "<< imail + << std::string(": nb elem pour le proc => ")<< (int) list_maillage_element.size() + << " c-a-d les elem : \n "; + list ::const_iterator il, ilfin= list_maillage_element.end(); + for (il = list_maillage_element.begin(); il != ilfin; il++) + { int truc = (*il); + cout << truc << " , "; + }; + }; + }; + } + + // cas donne le niveau de la récupération // = 1 : on récupère tout // = 2 : on récupère uniquement les données variables (supposées comme telles) diff --git a/General/Distribution_CPU.h b/General/Distribution_CPU.h index e82b32d..b586953 100755 --- a/General/Distribution_CPU.h +++ b/General/Distribution_CPU.h @@ -98,6 +98,11 @@ class Distribution_CPU else return tab_vide_list_maillage_element; }; + // retourne le tableau indicateur permettant de dire si un élément est concerné par un CPU + // tab_indic(CPU)(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné + // par le CPU + const Tableau > > * Tab_indique_CPU_en_cours() const {return &tab_indic;}; + // indicateur permettant de dire si un élément est concerné par un CPU donné // tab_indic(CPU)(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné // par le CPU @@ -107,6 +112,8 @@ class Distribution_CPU // récup du nombre total d'éléments, cumul sur tous les maillages int NB_total_element() const {return total_elem ;}; + // affichage des infos relatives à la distribution + void Affiche() const ; //============= lecture écriture dans base info ========== // cas donne le niveau de la récupération diff --git a/General/herezh.cc b/General/herezh.cc index a48e5ba..79c1b19 100644 --- a/General/herezh.cc +++ b/General/herezh.cc @@ -220,17 +220,6 @@ int main (int argc, const char * argv[]) { #endif #ifdef UTILISATION_MPI - #ifdef EN_DEBUG_MPI - // intro d'une boucle infinie pour mettre en place les process en debug - {volatile int i = 0; - char hostname[256]; - gethostname(hostname, sizeof(hostname)); - printf("PID %d on %s ready for attach\n", getpid(), hostname); - fflush(stdout); - while (0 == i) - sleep(5); - } - #endif // --- mise en route de la parallèlisation mpi::environment env; @@ -239,6 +228,21 @@ int main (int argc, const char * argv[]) { // on renseigne paraglob ParaGlob::Init_boost_environnement(&env); ParaGlob::Init_boost_communicator (& world); + + #ifdef EN_DEBUG_MPI + // intro d'une boucle infinie pour mettre en place les process en debug + if (world.rank() == 0) //arrêt uniquement pour le proc 0 + {volatile int i = 0; + char hostname[256]; + gethostname(hostname, sizeof(hostname)); + printf("PID %d on %s ready for attach\n", getpid(), hostname); + fflush(stdout); + while (0 == i) + sleep(5); + } + #endif + + #endif diff --git a/Maillage/LesMaillages.cc b/Maillage/LesMaillages.cc index 94e0baa..404bda6 100644 --- a/Maillage/LesMaillages.cc +++ b/Maillage/LesMaillages.cc @@ -33,7 +33,7 @@ #include "ReferenceAF.h" #include "MathUtil.h" #include "ConstMath.h" -#include "LaList.h" +#include "LaLIST.H" #include "CharUtil.h" #include "TypeQuelconqueParticulier.h" diff --git a/Maillage/Maillage.h b/Maillage/Maillage.h index e975c55..0cff924 100755 --- a/Maillage/Maillage.h +++ b/Maillage/Maillage.h @@ -72,7 +72,7 @@ #include "Enum_interpol.h" #include "LesReferences.h" #include "Front.h" -#include "LaList.h" +#include "LaLIST.H" #include "Nb_assemb.h" #include "Ddl_enum_etendu.h" #include "Droite.h" diff --git a/Parametres/EnteteParaGlob.h b/Parametres/EnteteParaGlob.h index 597c9d5..0ead9de 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.017" ; // numéro de version du logiciel + string ParaGlob::nbVersion = "7.018" ; // 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/ParaGlob.h b/Parametres/ParaGlob.h index 7dc246a..32135d3 100644 --- a/Parametres/ParaGlob.h +++ b/Parametres/ParaGlob.h @@ -148,8 +148,11 @@ class ParaGlob static void Init_boost_communicator (boost::mpi::communicator * pt_world) {world = pt_world;}; // -- equilibrage d'éléments - void Init_tableau (const Tableau > >* tab_list_maillage_element) - {tab_list_mail_element = tab_list_maillage_element;}; + void Init_tableau (const Tableau > >* tab_list_maillage_element + ,const Tableau > >* tab_indic) + {tab_list_mail_element = tab_list_maillage_element; + tabb_indic = tab_indic; + }; // retour des listes des éléments relatif au cpu en cours, c-a-d pour tous les maillages // tab (j) donne la liste des éléments pour le maillage j const Tableau < list > & const_List_element_CPU_en_cours() const @@ -157,6 +160,11 @@ class ParaGlob // spécifiquement, la liste des éléments pour le maillage j const list & const_List_element_CPU_en_cours(int j) const {return (*tab_list_mail_element)(world->rank())(j);}; + // indicateur permettant de dire si un élément est concerné par le cpu en cours + // tab_indic(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné + // par le CPU + bool Element_concerner(int mail,int ele) const + {return (*tabb_indic)(world->rank())(mail)(ele);}; #endif // lecture du type de calcul et d'une liste de sous_type éventuel @@ -405,6 +413,11 @@ class ParaGlob // pour le maillage j des num <élément> associés au cpu i // ici il s'agit d'une copie de tab_list_maillage_element qui doit être mise à jour par Distribution_CPU const Tableau > >* tab_list_mail_element; + // indicateur permettant de dire si un élément est concerné par un CPU donné + // tab_indic(CPU)(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné + // par le CPU, il s'agit d'une copie qui doit être mise à jour par Distribution_CPU + const Tableau > >* tabb_indic; + #endif //------------ info sur le temps --------------- // c'est paraAlgoControle qui gère le temps, cependant paraglob sert de relais pour diff --git a/TypeBase/Basiques.cc b/TypeBase/Basiques.cc index 2afc47b..95cfbd0 100644 --- a/TypeBase/Basiques.cc +++ b/TypeBase/Basiques.cc @@ -37,8 +37,11 @@ short int Entier_et_Double::impre_schem_XML=0; short int Deux_String::impre_schem_XML=0; short int String_et_entier::impre_schem_XML=0; short int Trois_String::impre_schem_XML=0; -short int quatre_string_un_entier::impre_schem_XML=0; +short int Quatre_string_un_entier::impre_schem_XML=0; short int TroisEntiers::impre_schem_XML=0; +short int Deux_String_un_entier::impre_schem_XML=0; +short int QuatreEntiers::impre_schem_XML=0; +short int CinqEntiers::impre_schem_XML=0; // sortie du schemaXML: en fonction de enu void DeuxEntiers::SchemaXML_DeuxEntiers(ofstream& sort,const Enum_IO_XML enu) const @@ -68,7 +71,7 @@ istream & DeuxEntiers::LectXML_DeuxEntiers(istream & ent) // surcharge d'ecriture en XML ostream & DeuxEntiers::EcritXML_DeuxEntiers(ostream & sort) - { sort << " un= "<< un << " deux= " << deux << ""; + { sort << " un= "<< un << " deux= " << deux << " "; return sort; }; @@ -102,7 +105,7 @@ istream & DeuxDoubles::LectXML_DeuxDoubles(istream & ent) // surcharge d'ecriture en XML ostream & DeuxDoubles::EcritXML_DeuxDoubles(ostream & sort) - { sort << " un= "<< un << " deux= " << deux << ""; + { sort << " un= "<< un << " deux= " << deux << " "; return sort; }; @@ -136,7 +139,7 @@ istream & Entier_et_Double::LectXML_Entier_et_Double(istream & ent) // surcharge d'ecriture en XML ostream & Entier_et_Double::EcritXML_Entier_et_Double(ostream & sort) - { sort << " un= "<< n << " deux= " << x << ""; + { sort << " un= "<< n << " deux= " << x << " "; return sort; }; @@ -170,7 +173,7 @@ istream & Deux_String::LectXML_Deux_String(istream & ent) // surcharge d'ecriture en XML ostream & Deux_String::EcritXML_Deux_String(ostream & sort) - { sort << " nom1= "<< nom1 << " nom2= " << nom2 << ""; + { sort << " nom1= "<< nom1 << " nom2= " << nom2 << " "; return sort; }; @@ -204,7 +207,7 @@ istream & String_et_entier::LectXML_String_et_entier(istream & ent) // surcharge d'ecriture en XML ostream & String_et_entier::EcritXML_String_et_entier(ostream & sort) - { sort << " nom1= "<< nom << " nom2= " << n << ""; + { sort << " nom1= "<< nom << " n= " << n << " "; return sort; }; @@ -239,17 +242,17 @@ istream & Trois_String::LectXML_Trois_String(istream & ent) // surcharge d'ecriture en XML ostream & Trois_String::EcritXML_Trois_String(ostream & sort) - { sort << " nom1= "<< nom1 << " nom2= " << nom2 << " nom3= " << nom3 << ""; + { sort << " nom1= "<< nom1 << " nom2= " << nom2 << " nom3= " << nom3 << " "; return sort; }; // sortie du schemaXML: en fonction de enu -void quatre_string_un_entier::SchemaXML_quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const +void Quatre_string_un_entier::SchemaXML_Quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const {// sortie balisée simple switch (enu) {case XML_TYPE_GLOBAUX: {sort << "\n " - << "\n" + << "\n" << "\n " << "\n type simple pour definir trois string " << "\n " @@ -259,12 +262,27 @@ void quatre_string_un_entier::SchemaXML_quatre_string_un_entier(ofstream& sort,c << "\n " << "\n " << "\n"; - Trois_String::impre_schem_XML=1; // une seule sortie + Quatre_string_un_entier::impre_schem_XML=1; // une seule sortie }; default: sort << "\n SchemaXML: cas non pris en compte " ; }; }; +// surcharge de lecture en XML +istream & Quatre_string_un_entier::LectXML_Quatre_string_un_entier(istream & ent) + { string nom; + ent >> nom >> nom >> nom1 >> nom >> nom2 >> nom >> nom3 >> nom >> nom4 >> nom >> n >> nom; + return ent; + }; + + // surcharge d'ecriture en XML +ostream & Quatre_string_un_entier::EcritXML_Quatre_string_un_entier(ostream & sort) + { sort << " nom1= "<< nom1 << " nom2= " << nom2 + << " nom3= " << nom3 << "nom4= " << nom4 << " n= " << n << " "; + return sort; + }; + + // sortie du schemaXML: en fonction de enu void TroisEntiers::SchemaXML_TroisEntiers(ofstream& sort,const Enum_IO_XML enu) const {// sortie balisée simple @@ -276,8 +294,8 @@ void TroisEntiers::SchemaXML_TroisEntiers(ofstream& sort,const Enum_IO_XML enu) << "\n type simple pour definir deux entiers " << "\n " << "\n " - << "\n " << "\n " + << "\n " << "\n"; TroisEntiers::impre_schem_XML=1; // une seule sortie }; @@ -286,6 +304,131 @@ void TroisEntiers::SchemaXML_TroisEntiers(ofstream& sort,const Enum_IO_XML enu) }; }; +// surcharge de lecture en XML +istream & TroisEntiers::LectXML_TroisEntiers(istream & ent) + { string nom; + ent >> nom >> nom >> un >> nom >> deux >> nom >> trois >> nom; + return ent; + }; + + // surcharge d'ecriture en XML +ostream & TroisEntiers::EcritXML_TroisEntiers(ostream & sort) + { sort << " un= "<< un << " deux= " << deux << " trois= " << trois << " "; + return sort; + }; + + + // sortie du schemaXML: en fonction de enu +void Deux_String_un_entier::SchemaXML_Deux_String_un_entier(ofstream& sort,const Enum_IO_XML enu) const + {// sortie balisée simple + switch (enu) + {case XML_TYPE_GLOBAUX: + {sort << "\n " + << "\n" + << "\n " + << "\n type simple pour definir trois string " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n"; + Deux_String_un_entier::impre_schem_XML=1; // une seule sortie + }; + default: sort << "\n SchemaXML: cas non pris en compte " ; + }; + }; + +// surcharge de lecture en XML +istream & Deux_String_un_entier::LectXML_Deux_String_un_entier(istream & ent) + { string nom; + ent >> nom >> nom >> nom1 >> nom >> nom2 >> nom >> n >> nom; + return ent; + }; + + // surcharge d'ecriture en XML +ostream & Deux_String_un_entier::EcritXML_Deux_String_un_entier(ostream & sort) + { sort << " nom1= "<< nom1 << " nom2= " << nom2 + << " n= " << n << " "; + return sort; + }; + +// sortie du schemaXML: en fonction de enu +void QuatreEntiers::SchemaXML_QuatreEntiers(ofstream& sort,const Enum_IO_XML enu) const + {// sortie balisée simple + switch (enu) + {case XML_TYPE_GLOBAUX: + {sort << "\n " + << "\n" + << "\n " + << "\n type simple pour definir quatre entiers " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n"; + QuatreEntiers::impre_schem_XML=1; // une seule sortie + }; + default: sort << "\n SchemaXML: cas non pris en compte " ; + + }; + }; + + +// surcharge de lecture en XML +istream & QuatreEntiers::LectXML_QuatreEntiers(istream & ent) + { string nom; + ent >> nom >> nom >> un >> nom >> deux >> nom >> trois >> nom >> quatre >> nom; + return ent; + }; + + // surcharge d'ecriture en XML +ostream & QuatreEntiers::EcritXML_QuatreEntiers(ostream & sort) + { sort << " un= "<< un << " deux= " << deux << " trois= " << trois + << " quatre= " << quatre << " "; + return sort; + }; + + +// sortie du schemaXML: en fonction de enu +void CinqEntiers::SchemaXML_CinqEntiers(ofstream& sort,const Enum_IO_XML enu) const + {// sortie balisée simple + switch (enu) + {case XML_TYPE_GLOBAUX: + {sort << "\n " + << "\n" + << "\n " + << "\n type simple pour definir quatre entiers " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n"; + CinqEntiers::impre_schem_XML=1; // une seule sortie + }; + default: sort << "\n SchemaXML: cas non pris en compte " ; + + }; + }; + + +// surcharge de lecture en XML +istream & CinqEntiers::LectXML_CinqEntiers(istream & ent) + { string nom; + ent >> nom >> nom >> un >> nom >> deux >> nom >> trois + >> nom >> quatre >> nom >> cinq >> nom; + return ent; + }; + + // surcharge d'ecriture en XML +ostream & CinqEntiers::EcritXML_CinqEntiers(ostream & sort) + { sort << " un= "<< un << " deux= " << deux << " trois= " << trois + << " quatre= " << quatre << " cinq= " << cinq << " "; + return sort; + }; + diff --git a/TypeBase/Basiques.h b/TypeBase/Basiques.h index 408e201..2ca46e1 100644 --- a/TypeBase/Basiques.h +++ b/TypeBase/Basiques.h @@ -439,7 +439,7 @@ class Trois_String /// /// cas de 4 string et un entier -class quatre_string_un_entier +class Quatre_string_un_entier { public : // VARIABLES PUBLIQUES : @@ -462,39 +462,39 @@ class quatre_string_un_entier public : // CONSTRUCTEURS : - quatre_string_un_entier() : nom1(""),nom2(""),nom3(""),nom4(""),n(0) {}; - quatre_string_un_entier(const string& n1, const string& n2,const string& n3,const string& n4,const int& nn) : nom1(n1),nom2(n2),nom3(n3),nom4(n4),n(nn) {}; - quatre_string_un_entier(const quatre_string_un_entier & de) : + Quatre_string_un_entier() : nom1(""),nom2(""),nom3(""),nom4(""),n(0) {}; + Quatre_string_un_entier(const string& n1, const string& n2,const string& n3,const string& n4,const int& nn) : nom1(n1),nom2(n2),nom3(n3),nom4(n4),n(nn) {}; + Quatre_string_un_entier(const Quatre_string_un_entier & de) : nom1(de.nom1),nom2(de.nom2),nom3(de.nom3),nom4(de.nom4),n(de.n) {}; // DESTRUCTEUR : - ~quatre_string_un_entier() {}; + ~Quatre_string_un_entier() {}; // METHODES PUBLIQUES : // surcharge de l'affectation - quatre_string_un_entier& operator= (const quatre_string_un_entier& de) + Quatre_string_un_entier& operator= (const Quatre_string_un_entier& de) { nom1 = de.nom1; nom2 = de.nom2; nom3 = de.nom3;nom4 = de.nom4;n=de.n; return (*this);}; // surcharge de l'operator de lecture - friend istream & operator >> (istream & ent, quatre_string_un_entier & de) + friend istream & operator >> (istream & ent, Quatre_string_un_entier & de) { ent >> de.nom1 >> de.nom2 >> de.nom3>> de.nom4>> de.n; return ent;}; // surcharge de l'operator d'ecriture - friend ostream & operator << (ostream & sort , const quatre_string_un_entier & de) + friend ostream & operator << (ostream & sort , const Quatre_string_un_entier & de) { sort << de.nom1 <<" " << de.nom2 << " "<< de.nom3 << " "<< de.nom4 << " "<< de.n << " "; return sort;}; // surcharge de lecture en XML - istream & LectXML_quatre_string_un_entier(istream & ent); + istream & LectXML_Quatre_string_un_entier(istream & ent); // surcharge d'ecriture en XML - ostream & EcritXML_quatre_string_un_entier(ostream & sort); + ostream & EcritXML_Quatre_string_un_entier(ostream & sort); //Surcharge d'operateurs logiques - bool operator == (const quatre_string_un_entier& a) const + bool operator == (const Quatre_string_un_entier& a) const { if (( nom1 == a.nom1) && (nom2 == a.nom2)&& (nom3 == a.nom3)&& (nom4 == a.nom4)&& (n == a.n)) return true; else return false;}; - bool operator != (const quatre_string_un_entier& a) const { return !(*this == a);}; + bool operator != (const Quatre_string_un_entier& a) const { return !(*this == a);}; // sortie du schemaXML: en fonction de enu - void SchemaXML_quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const ; + void SchemaXML_Quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const ; // surchage de l'opérateur de comparaison : ici elle se fait par decroissance // est uniquement intéressante pour classer, - bool operator > (const quatre_string_un_entier& a) const + bool operator > (const Quatre_string_un_entier& a) const { if (this->nom1 > a.nom1) {return true;} else if (this->nom1 < a.nom1) @@ -530,7 +530,7 @@ class quatre_string_un_entier } } }; - bool operator >= (const quatre_string_un_entier& a) const + bool operator >= (const Quatre_string_un_entier& a) const { if (this->nom1 > a.nom1) {return true;} else if (this->nom1 < a.nom1) @@ -567,7 +567,7 @@ class quatre_string_un_entier } }; - bool operator < (const quatre_string_un_entier& a) const + bool operator < (const Quatre_string_un_entier& a) const { if (this->nom1 < a.nom1) {return true;} else if (this->nom1 > a.nom1) @@ -604,7 +604,7 @@ class quatre_string_un_entier } }; - bool operator <= (const quatre_string_un_entier& a) const + bool operator <= (const Quatre_string_un_entier& a) const { if (this->nom1 < a.nom1) {return true;} else if (this->nom1 > a.nom1) @@ -687,7 +687,7 @@ class TroisEntiers { ent >> de.un >> de.deux >> de.trois; return ent;}; // surcharge de l'operator d'ecriture friend ostream & operator << (ostream & sort , const TroisEntiers & de) - { sort << de.un <<" " << de.deux << " "<<" "<< de.trois; return sort;}; + { sort << de.un <<" " << de.deux << " "<< de.trois<< " "; return sort;}; // surcharge de lecture en XML istream & LectXML_TroisEntiers(istream & ent); // surcharge d'ecriture en XML @@ -937,4 +937,356 @@ class Deux_String_un_entier }; /// @} // end of group -#endif +/// @addtogroup Les_conteneurs_ultra_basiques +/// @{ +/// + +/// cas de 4 entiers +class QuatreEntiers +{ + public : + // VARIABLES PUBLIQUES : + int un,deux,trois,quatre; + // gestion schéma XML + static short int impre_schem_XML; + + #ifdef UTILISATION_MPI + private: + friend class boost::serialization::access; + // When the class Archive corresponds to an output archive, the + // & operator is defined similar to <<. Likewise, when the class Archive + // is a type of input archive the & operator is defined similar to >>. + template + void serialize(Archive & ar, const unsigned int version) + { ar & un; ar & deux; ar & trois; ar & quatre;} + #endif + + public : + + // CONSTRUCTEURS : + QuatreEntiers() : un(0),deux(0),trois(0),quatre(0) {}; + QuatreEntiers(int u, int v,int w,int ww) : un(u),deux(v),trois(w),quatre(ww) {}; + QuatreEntiers(const QuatreEntiers & de) : un(de.un),deux(de.deux),trois(de.trois),quatre(de.quatre) {}; + + // DESTRUCTEUR : + ~QuatreEntiers() {}; + + // METHODES PUBLIQUES : + // surcharge de l'affectation + QuatreEntiers& operator= (const QuatreEntiers& de) + { un = de.un; deux = de.deux;trois = de.trois; quatre = de.quatre; return (*this);}; + // surcharge de l'operator de lecture + friend istream & operator >> (istream & ent, QuatreEntiers & de) + { ent >> de.un >> de.deux >> de.trois >> de.quatre; return ent;}; + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort , const QuatreEntiers & de) + { sort << de.un <<" " << de.deux << " "<< de.trois<< " "< (const QuatreEntiers& a) const + { if (un > a.un) + {return true;} + else if (un < a.un) + {return false;} + else // egalité, on test le suivant + {if (deux > a.deux) + {return true;} + else if (deux < a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois > a.trois) + {return true;} + else if (trois < a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre > a.quatre) + {return true;} + else if (quatre < a.quatre) + {return false;} + else // egalité, on test le suivant + {return false;} // car c'est l'égalité parfaite donc pas supérieur + } + } + } + }; + bool operator >= (const QuatreEntiers& a) const + { if (un > a.un) + {return true;} + else if (un < a.un) + {return false;} + else // egalité, on test le suivant + {if (deux > a.deux) + {return true;} + else if (deux < a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois > a.trois) + {return true;} + else if (trois < a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre > a.quatre) + {return true;} + else if (quatre < a.quatre) + {return false;} + else // egalité, on test le suivant + {return true;} // car c'est l'égalité parfaite + } + } + } + }; + bool operator < (const QuatreEntiers& a) const + { if (un < a.un) + {return true;} + else if (un > a.un) + {return false;} + else // egalité, on test le suivant + {if (deux < a.deux) + {return true;} + else if (deux > a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois < a.trois) + {return true;} + else if (trois > a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre < a.quatre) + {return true;} + else if (quatre > a.quatre) + {return false;} + else // egalité, on test le suivant + {return false;} // car c'est l'égalité parfaite donc pas inférieur + } + } + } + }; + bool operator <= (const QuatreEntiers& a) const + { if (un < a.un) + {return true;} + else if (un > a.un) + {return false;} + else // egalité, on test le suivant + {if (deux < a.deux) + {return true;} + else if (deux > a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois < a.trois) + {return true;} + else if (trois > a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre < a.quatre) + {return true;} + else if (quatre > a.quatre) + {return false;} + else // egalité, on test le suivant + {return true;} // car c'est l'égalité parfaite + } + } + } + }; + // sortie du schemaXML: en fonction de enu + void SchemaXML_QuatreEntiers(ofstream& sort,const Enum_IO_XML enu) const ; + }; +/// @} // end of group + +/// @addtogroup Les_conteneurs_ultra_basiques +/// @{ +/// + +/// cas de 5 entiers +class CinqEntiers +{ + public : + // VARIABLES PUBLIQUES : + int un,deux,trois,quatre,cinq; + // gestion schéma XML + static short int impre_schem_XML; + + #ifdef UTILISATION_MPI + private: + friend class boost::serialization::access; + // When the class Archive corresponds to an output archive, the + // & operator is defined similar to <<. Likewise, when the class Archive + // is a type of input archive the & operator is defined similar to >>. + template + void serialize(Archive & ar, const unsigned int version) + { ar & un; ar & deux; ar & trois; ar & quatre; ar & cinq;} + #endif + + public : + + // CONSTRUCTEURS : + CinqEntiers() : un(0),deux(0),trois(0),quatre(0),cinq(0) {}; + CinqEntiers(int u, int v,int w1,int w2,int w3) : un(u),deux(v),trois(w1),quatre(w2),cinq(w3) {}; + CinqEntiers(const CinqEntiers & de) : un(de.un),deux(de.deux),trois(de.trois),quatre(de.quatre) + ,cinq(de.cinq) {}; + + // DESTRUCTEUR : + ~CinqEntiers() {}; + + // METHODES PUBLIQUES : + // surcharge de l'affectation + CinqEntiers& operator= (const CinqEntiers& de) + { un = de.un; deux = de.deux;trois = de.trois; quatre = de.quatre; + cinq = de.cinq; return (*this);}; + // surcharge de l'operator de lecture + friend istream & operator >> (istream & ent, CinqEntiers & de) + { ent >> de.un >> de.deux >> de.trois >> de.quatre >> de.cinq; return ent;}; + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort , const CinqEntiers & de) + { sort << de.un <<" " << de.deux << " "<< de.trois<< " "< (const CinqEntiers& a) const + { if (un > a.un) + {return true;} + else if (un < a.un) + {return false;} + else // egalité, on test le suivant + {if (deux > a.deux) + {return true;} + else if (deux < a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois > a.trois) + {return true;} + else if (trois < a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre > a.quatre) + {return true;} + else if (quatre < a.quatre) + {return false;} + else // egalité, on test le suivant + {if (cinq > a.cinq) + {return true;} + else if (cinq < a.cinq) + {return false;} + else // egalité, on test le suivant + {return false;} // car c'est l'égalité parfaite donc pas supérieur + } + } + } + } + }; + bool operator >= (const CinqEntiers& a) const + { if (un > a.un) + {return true;} + else if (un < a.un) + {return false;} + else // egalité, on test le suivant + {if (deux > a.deux) + {return true;} + else if (deux < a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois > a.trois) + {return true;} + else if (trois < a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre > a.quatre) + {return true;} + else if (quatre < a.quatre) + {return false;} + else // egalité, on test le suivant + {if (cinq > a.cinq) + {return true;} + else if (cinq < a.cinq) + {return false;} + else // egalité, on test le suivant + {return true;} // car c'est l'égalité parfaite + } + } + } + } + }; + bool operator < (const CinqEntiers& a) const + { if (un < a.un) + {return true;} + else if (un > a.un) + {return false;} + else // egalité, on test le suivant + {if (deux < a.deux) + {return true;} + else if (deux > a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois < a.trois) + {return true;} + else if (trois > a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre < a.quatre) + {return true;} + else if (quatre > a.quatre) + {return false;} + else // egalité, on test le suivant + {if (cinq < a.cinq) + {return true;} + else if (cinq > a.cinq) + {return false;} + else // egalité, on test le suivant + {return false;} // car c'est l'égalité parfaite donc pas inférieur + } + } + } + } + }; + bool operator <= (const CinqEntiers& a) const + { if (un < a.un) + {return true;} + else if (un > a.un) + {return false;} + else // egalité, on test le suivant + {if (deux < a.deux) + {return true;} + else if (deux > a.deux) + {return false;} + else // egalité, on test le suivant + {if (trois < a.trois) + {return true;} + else if (trois > a.trois) + {return false;} + else // egalité, on test le suivant + {if (quatre < a.quatre) + {return true;} + else if (quatre > a.quatre) + {return false;} + else // egalité, on test le suivant + {if (cinq < a.cinq) + {return true;} + else if (cinq > a.cinq) + {return false;} + else // egalité, on test le suivant + {return true;} // car c'est l'égalité parfaite + } + } + } + } + }; + // sortie du schemaXML: en fonction de enu + void SchemaXML_CinqEntiers(ofstream& sort,const Enum_IO_XML enu) const ; + }; +/// @} // end of group + +#endif diff --git a/TypeBase/List_io.h b/TypeBase/List_io.h index 7779858..f6dfaf8 100644 --- a/TypeBase/List_io.h +++ b/TypeBase/List_io.h @@ -52,7 +52,7 @@ #include #include #include -#include "LaLIST.h" +#include "LaLIST.H" #include "Sortie.h" #include "ParaGlob.h" using namespace std; //introduces namespace std diff --git a/contact/LesContacts.cc b/contact/LesContacts.cc index a9c966b..beb56ce 100644 --- a/contact/LesContacts.cc +++ b/contact/LesContacts.cc @@ -123,6 +123,9 @@ LesContacts::LesContacts () : ,nb_contact_actif(0),indice(),cont_solide_defor(),liQ_en_sortie() ,t_connectionCLL() ,liste_elemens_front(),tempsContact() +#ifdef UTILISATION_MPI + ,temps_transfert_court(),temps_transfert_long(),temps_attente() +#endif {}; // constructeur de copie LesContacts::LesContacts (const LesContacts& a): @@ -137,6 +140,10 @@ LesContacts::LesContacts (const LesContacts& a): ,nb_contact_actif(a.nb_contact_actif),indice(a.indice),cont_solide_defor(a.cont_solide_defor) ,liste_elemens_front(a.liste_elemens_front),liQ_en_sortie(),tempsContact(a.tempsContact) ,t_connectionCLL(a.t_connectionCLL) +#ifdef UTILISATION_MPI + ,temps_transfert_court(a.temps_transfert_court) + ,temps_transfert_long(a.temps_transfert_long),temps_attente(a.temps_attente) +#endif {}; // DESTRUCTEUR : LesContacts::~LesContacts () @@ -310,7 +317,7 @@ void LesContacts::Init_contact(LesMaillages& lesMail else { // cas d'une zone restreinte de contact // on va iterer sur les noeuds esclaves pour savoir s'ils appartiennent à la zone de contact potentiel - list ::iterator il,ilfin=nom_ref_zone_contact.end(); + list ::iterator il,ilfin=nom_ref_zone_contact.end(); int nb_zone = nom_ref_zone_contact.size(); if (niveau_commentaire_lescontacts >2 ) cout << "\n --> nombre de zone de contact: " << nb_zone; @@ -1996,7 +2003,7 @@ void LesContacts::Affiche() const }; cout << "\n 3) liste des references de zones succeptibles d'entrer en contact"; - list ::const_iterator ill,illfin=nom_ref_zone_contact.end(); + list ::const_iterator ill,illfin=nom_ref_zone_contact.end(); cout << "\n"; for (ill=nom_ref_zone_contact.begin();ill != illfin; ill++) { if ((*ill).nom1.length()) cout << " mail= " << (*ill).nom1 << " "; @@ -2248,7 +2255,7 @@ void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesRefere if (niveau_commentaire_lescontacts >= 4) cout << " debut de la lecture des zones de contact possibles " << endl; while (!motCle.SimotCle(entreePrinc.tablcar)) { // on lit 2 par deux: une ref de noeud + une ref de frontière - quatre_string_un_entier quatre_inter; // une grandeur de travail + Quatre_string_un_entier quatre_inter; // une grandeur de travail quatre_inter.n = indic_glue; // on stocke la glue éventuelle for (int nr=1;nr<=2;nr++) {// on commence par regarder si le nom du maillage est définit pour la référence diff --git a/contact/LesContacts.h b/contact/LesContacts.h index f318e5e..22c23a6 100644 --- a/contact/LesContacts.h +++ b/contact/LesContacts.h @@ -241,7 +241,14 @@ class LesContacts //------- temps cpu ----- // retourne temps cumulé pour imposer les CL imposées const Temps_CPU_HZpp& Temps_cpu_Contact() const {return tempsContact;}; - + +#ifdef UTILISATION_MPI + // cas d'un calcul parallèle: // passage des infos entre process + 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;} ; +#endif + //----- lecture écriture de restart ----- // cas donne le niveau de sauvegarde void Ecri_base_info_LesContacts(ofstream& sort); @@ -298,11 +305,9 @@ class LesContacts return niveau_commentaire_lescontacts; }; -// ne sert plus (à virer car problématique !! ) - // mise à jour du stockage inter, pour prendre en - // compte une nouvelle numérotation des noeuds -// void Prise_en_compte_nouvelle_numerotation_noeud(); - + + + // initialisation de la liste de grandeurs qui sont effectivement gérées par le contact // ok, mais à revoir sans doute cf. pense bete 14 oct // List_io Init_list_grandeur_contact_a_sortir(const Tableau >& li1); @@ -355,7 +360,7 @@ class LesContacts Tableau < const Tableau > *> indice; //--------- les tableaux de gestions pour la recherche de contact ---------------- - list nom_ref_zone_contact; // liste des noms de références des zones de contact éventuelle + list nom_ref_zone_contact; // liste des noms de références des zones de contact éventuelle // cette liste peut être vide, dans ce cas cela signifie que toutes les frontières des pièces sont // suceptible de rentrer en contact. Dans le cas où la liste n'est pas vide, seules les grandeurs // référencées sont succeptibles de rentrer en contact @@ -437,6 +442,12 @@ class LesContacts //------- temps cpu ----- // retourne temps cumulé pour imposer les CL imposées Temps_CPU_HZpp tempsContact; + #ifdef UTILISATION_MPI + // cas d'un calcul parallèle: // passage des infos entre process + Temps_CPU_HZpp temps_transfert_court ; + Temps_CPU_HZpp temps_transfert_long ; + Temps_CPU_HZpp temps_attente ; + #endif // METHODES PROTEGEES : // mise à jour des boites d'encombrement pour les éléments qui contiennent une frontière diff --git a/contact/LesContacts_3.cc b/contact/LesContacts_3.cc index 12f078c..731f3a3 100755 --- a/contact/LesContacts_3.cc +++ b/contact/LesContacts_3.cc @@ -686,8 +686,8 @@ void LesContacts::Suppression_gap_pour_noeud_collant() // on passe en revue les zones de contact et si nécessaire on supprime les gaps // sinon retour bool continuer = false; // init par défaut - // list nom_ref_zone_contact; // liste des noms de références des zones de contact - list ::iterator iu,iufin = nom_ref_zone_contact.end(); + // list nom_ref_zone_contact; // liste des noms de références des zones de contact + list ::iterator iu,iufin = nom_ref_zone_contact.end(); for (iu = nom_ref_zone_contact.begin();iu != iufin; iu++) if ((*iu).n == 2) {continuer = true; break;};