From b670e8f9b8ebec4638fac9f473bfd48bc88a7d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Rio?= Date: Fri, 15 Dec 2023 19:17:23 +0100 Subject: [PATCH] =?UTF-8?q?V=207.020=20:=20int=C3=A9gration=20=20en=20cour?= =?UTF-8?q?s=20de=20=20la=20parall=C3=A8lisation=20MPI=20dans=20le=20conta?= =?UTF-8?q?ct,=20version=20interm=C3=A9diaire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Algo/AlgoRef/Algori4.cc | 27 +- Algo/AlgorithmeCombiner/AlgoriCombine2.cc | 36 +- .../AlgoDynaExplicite/AlgoRungeKutta.cc | 6 +- .../AlgoDynaExplicite/AlgoriDynaExpli.cc | 6 +- .../AlgoDynaExplicite/AlgoriDynaExpli2.cc | 18 +- .../AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc | 12 +- .../AlgoDynaExplicite/Algori_chung_lee.cc | 18 +- .../AlgoDynaExplicite/Algori_relax_dyna.cc | 12 +- .../AlgoDynaExplicite/Algori_tchamwa.cc | 12 +- .../AlgoDynaImplicite/AlgoriNewmark2.cc | 12 +- .../AlgoStatiques/AlgoriNonDyna2.cc | 14 +- .../AlgoStatiques/ImpliNonDynaCont.cc | 4 +- .../DG_DynaExplicite/AlgoBonelli.cc | 6 +- Chargement/Charge2.cc | 2 +- General/Distribution_CPU.cc | 118 +- General/Distribution_CPU.h | 52 + Maillage/LesCondLim.cc | 28 +- Maillage/LesCondLim.h | 4 +- Parametres/EnteteParaGlob.h | 2 +- Parametres/ParaGlob.h | 31 +- Resolin/Resolution_Condi/Condilineaire.cc | 86 ++ Resolin/Resolution_Condi/Condilineaire.h | 34 +- Resolin/Resolution_Condi/Condilineaire_2.cc | 91 ++ TypeBase/Nb_assemb.h | 33 +- contact/ElContact.cc | 10 +- contact/LesContacts.cc | 1157 ++++++++++++----- contact/LesContacts.h | 40 +- contact/LesContacts_3.cc | 149 ++- 28 files changed, 1548 insertions(+), 472 deletions(-) create mode 100755 Resolin/Resolution_Condi/Condilineaire_2.cc diff --git a/Algo/AlgoRef/Algori4.cc b/Algo/AlgoRef/Algori4.cc index 6fcf92f..6808737 100644 --- a/Algo/AlgoRef/Algori4.cc +++ b/Algo/AlgoRef/Algori4.cc @@ -992,12 +992,19 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul {// si demandé, renumérotation en fonction des éléments en contact if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation()) { // récup des connexions entre noeud dues aux contacts - const Tableau & tabCondLine= lescontacts->ConnectionCLL(); - if (tabCondLine.Taille() > 0) //cas où il faut en tenir compte + list & listCondLine= lescontacts->ConnectionCLL(); + if (listCondLine.size() > 0) //cas où il faut en tenir compte {// récup des connexions entre noeuds dues aux CLL externes Tableau > tabCLL(lesCondLim->ConnectionCLL(lesMail,lesRef)); int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); - tabCLL(tailtabCLL+1) = tabCondLine; // ajout de la partie contact +// tabCLL(tailtabCLL+1) = listCondLine; + // ajout de la partie contact + Tableau & tabCLL_contact = tabCLL(tailtabCLL+1); // pour simplifier + tabCLL_contact.Change_taille(listCondLine.size()); + list ::iterator il,ilfin = listCondLine.end(); + int i=1; + for (il = listCondLine.begin();il != ilfin;il++,i++) + tabCLL_contact(i) = (*il); if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation en tenant compte des elements de contact "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage @@ -1029,13 +1036,19 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul {if (nouvelle_situation_contact) {if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation()) { // récup des connexions entre noeud dues aux contacts - const Tableau & tabCondLine= lescontacts->ConnectionCLL(); - if (tabCondLine.Taille() > 0) //cas où il faut en tenir compte + list & listCondLine= lescontacts->ConnectionCLL(); + if (listCondLine.size() > 0) //cas où il faut en tenir compte {// récup des connexions entre noeuds dues aux CLL externes: comme les cll ont été mises à jour // on récupère directement le tableau Tableau > tabCLL(lesCondLim->Tab_CLinApplique()); int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); - tabCLL(tailtabCLL+1) = tabCondLine; // ajout de la partie contact + // ajout de la partie contact + Tableau & tabCLL_contact = tabCLL(tailtabCLL+1); // pour simplifier + tabCLL_contact.Change_taille(listCondLine.size()); + list ::iterator il,ilfin = listCondLine.end(); + int i=1; + for (il = listCondLine.begin();il != ilfin;il++,i++) + tabCLL_contact(i) = (*il); if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation en tenant compte d'un changement de contact "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage @@ -1107,7 +1120,7 @@ bool Algori::Gestion_stockage_et_renumerotation_sans_contact(LesContacts* lesco { // récup des connexions entre noeuds dues aux CLL externes Tableau > tabCLL(lesCondLim->ConnectionCLL(lesMail,lesRef)); // int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); - // tabCLL(tailtabCLL+1) = tabCondLine; // ajout de la partie contact + // tabCLL(tailtabCLL+1) = listCondLine; // ajout de la partie contact if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation des pointeurs d'assemblage en tenant compte des CLL "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage diff --git a/Algo/AlgorithmeCombiner/AlgoriCombine2.cc b/Algo/AlgorithmeCombiner/AlgoriCombine2.cc index e20bd35..2cfc186 100755 --- a/Algo/AlgorithmeCombiner/AlgoriCombine2.cc +++ b/Algo/AlgorithmeCombiner/AlgoriCombine2.cc @@ -53,8 +53,10 @@ void AlgoriCombine::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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -129,8 +131,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); tab_algo(i)->InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor @@ -187,8 +191,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor @@ -263,8 +269,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); @@ -334,8 +342,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); #endif charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo()); @@ -412,8 +422,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_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 1c7129b..63e61fa 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoRungeKutta.cc @@ -963,8 +963,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli.cc index f881bf2..e6de489 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli.cc @@ -755,9 +755,9 @@ void AlgoriDynaExpli::Calcul_Equilibre(ParaGlob * paraGlob,LesMaillages * lesMai lesContacts->CalculReaction(F_ext_tdt,decol,Ass1.Nb_cas_assemb(),aff_incr); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if (pa.ContactType()) - tabCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée if (pa.Amort_visco_artificielle()) @@ -779,7 +779,7 @@ void AlgoriDynaExpli::Calcul_Equilibre(ParaGlob * paraGlob,LesMaillages * lesMai bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,vglobaal,Ass3.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc index 9b87e88..ebc3523 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli2.cc @@ -536,9 +536,9 @@ void AlgoriDynaExpli::Calcul_Equilibre2(ParaGlob * paraGlob,LesMaillages * lesMa lesContacts->CalculReaction(F_ext_tdt,decol,Ass1.Nb_cas_assemb(),aff_incr); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if (pa.ContactType()) - tabCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée if (pa.Amort_visco_artificielle()) @@ -560,7 +560,7 @@ void AlgoriDynaExpli::Calcul_Equilibre2(ParaGlob * paraGlob,LesMaillages * lesMa bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,vglobaal,Ass3.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir @@ -805,8 +805,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -1419,9 +1421,9 @@ void AlgoriDynaExpli::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail lesContacts->CalculReaction(F_ext_tdt,decol,Ass1.Nb_cas_assemb(),aff_incr); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if ((pa.ContactType())&&(compteur_demarrage > 0)) - tabCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée if (pa.Amort_visco_artificielle()) @@ -1444,7 +1446,7 @@ void AlgoriDynaExpli::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,vglobaal,Ass3.Nb_cas_assemb(),vglob_stat); if ((pa.ContactType()==1)&&(compteur_demarrage > 0)) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir // ***donc pour l'instant du a un bug je commente diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc index b87444c..2d38395 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/AlgoriDynaExpli_zhai.cc @@ -296,8 +296,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -881,9 +883,9 @@ void AlgoriDynaExpli_zhai::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMa lesContacts->CalculReaction(F_ext_tdt,decol,Ass1.Nb_cas_assemb(),aff_incr); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if (pa.ContactType()) - tabCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée if (pa.Amort_visco_artificielle()) @@ -906,7 +908,7 @@ void AlgoriDynaExpli_zhai::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMa bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,(vglobaal),Ass3.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,(vglobaal),*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,(vglobaal),*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir // ***donc pour l'instant du a un bug je commente diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc index 0b433e5..e76fd5f 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_chung_lee.cc @@ -285,8 +285,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -806,9 +808,9 @@ void Algori_chung_lee::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail, lesContacts->CalculReaction(F_ext_tdt,decol,Ass1.Nb_cas_assemb(),aff_incr); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if (pa.ContactType()) - tabCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée if (pa.Amort_visco_artificielle()) @@ -831,7 +833,7 @@ void Algori_chung_lee::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail, bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,vglobaal,Ass3.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir // ***donc pour l'instant du a un bug je commente @@ -1486,9 +1488,9 @@ void Algori_chung_lee::Calcul_Equilibre(ParaGlob * paraGlob,LesMaillages * lesMa lesContacts->CalculReaction(F_ext_tdt,decol,Ass1.Nb_cas_assemb(),aff_incr); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if (pa.ContactType()) - tabCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée if (pa.Amort_visco_artificielle()) @@ -1509,7 +1511,7 @@ void Algori_chung_lee::Calcul_Equilibre(ParaGlob * paraGlob,LesMaillages * lesMa bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,vglobaal,Ass3.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc index 9399d8a..6dda520 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_relax_dyna.cc @@ -1321,8 +1321,10 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); 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()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -2328,9 +2330,9 @@ Vecteur V_ext(F_int_tdt); lescontacts->CalculReaction(vglobin,decol,Ass1.Nb_cas_assemb(),aff_iteration); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list *listCondLine = NULL; // init donc sans élément if (((pa.ContactType()==1) || (pa.ContactType()==3))&&(compteur_demarrage > 0)) - tabCondLine = &(lescontacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lescontacts->ConditionLin(Ass1.Nb_cas_assemb())); // -- dans le cas d'un amortissement visqueux critique ou // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée @@ -2376,7 +2378,7 @@ Vecteur V_ext(F_int_tdt); bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,vglobaal,Ass3.Nb_cas_assemb(),vglob_stat); if ((pa.ContactType()==1)&&(compteur_demarrage > 0)) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,vglobaal,*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir diff --git a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc index 762519f..b884611 100644 --- a/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc +++ b/Algo/GalerkinContinu/AlgoDynaExplicite/Algori_tchamwa.cc @@ -874,8 +874,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -1497,9 +1499,9 @@ void AlgoriTchamwa::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail lesContacts->CalculReaction(F_ext_tdt,decol,Ass1.Nb_cas_assemb(),aff_incr); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if (pa.ContactType()) - tabCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lesContacts->ConditionLin(Ass1.Nb_cas_assemb())); // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée if (pa.Amort_visco_artificielle()) @@ -1522,7 +1524,7 @@ void AlgoriTchamwa::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail bool modif_repere = lesCondLim->CoLinCHrepere_int(*mat_masse,(vglobaal),Ass3.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) // idem pour le contact conduisant à des conditions linéaires modif_repere = modif_repere || - lesCondLim->CoLinCHrepere_ext(*mat_masse,(vglobaal),*tabCondLine,Ass3.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(*mat_masse,(vglobaal),*listCondLine,Ass3.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir diff --git a/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc b/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc index b4f20b2..7082d48 100644 --- a/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc +++ b/Algo/GalerkinContinu/AlgoDynaImplicite/AlgoriNewmark2.cc @@ -52,8 +52,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -873,9 +875,9 @@ void AlgoriNewmark::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail lescontacts->CalculReaction(vglobin,decol,Ass1.Nb_cas_assemb(),aff_iteration); // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if (pa.ContactType()) - tabCondLine = &(lescontacts->ConditionLin(Ass1.Nb_cas_assemb())); + listCondLine = &(lescontacts->ConditionLin(Ass1.Nb_cas_assemb())); //------ fin de la partie pour laquelle je m'interroge -------------------- // dans le cas où l'on utilise de l'amortissement numérique, calcul de la part visqueuse dans SM et K @@ -928,7 +930,7 @@ void AlgoriNewmark::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail // -->> expression de la raideur et du second membre dans un nouveau repere lesCondLim->CoLinCHrepere_int((*matglob),vglobaal,Ass1.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) - lesCondLim->CoLinCHrepere_ext((*matglob),vglobaal,*tabCondLine,Ass1.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext((*matglob),vglobaal,*listCondLine,Ass1.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // en fait ne sert à rien, car les réactions maxi sont calculées dans condlin, mais comme c'est peut-être un peu spécial ici on laisse // mais dans les autres algos c'est supprimé !!!!! diff --git a/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc b/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc index a44c47b..b404e9c 100644 --- a/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc +++ b/Algo/GalerkinContinu/AlgoStatiques/AlgoriNonDyna2.cc @@ -57,8 +57,10 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail, distribution_CPU_algo.Passage_Equilibrage_aux_CPU(); 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()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif @@ -870,9 +872,9 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail // - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau // (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires) - const Tableau * tabCondLine=NULL; + list * listCondLine=NULL; if ((pa.ContactType()==1) || (pa.ContactType()==3)) - tabCondLine = &(lescontacts->ConditionLin(Ass.Nb_cas_assemb())); + listCondLine = &(lescontacts->ConditionLin(Ass.Nb_cas_assemb())); // - initialisation des sauvegardes sur matrice et second membre lesCondLim->InitSauve(Ass.Nb_cas_assemb()); @@ -892,9 +894,9 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail // mais ici on n'impose pas les conditons, on fait simplement le changement de repère lesCondLim->CoLinCHrepere_int((*matglob),vglobaal,Ass.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==1) - lesCondLim->CoLinCHrepere_ext((*matglob),vglobaal,*tabCondLine,Ass.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext((*matglob),vglobaal,*listCondLine,Ass.Nb_cas_assemb(),vglob_stat); if (pa.ContactType()==3) // *** exploratoire - lesCondLim->CoLinUneOpe_ext((*matglob),vglobaal,*tabCondLine,Ass.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinUneOpe_ext((*matglob),vglobaal,*listCondLine,Ass.Nb_cas_assemb(),vglob_stat); // sauvegarde des reactions pour les ddl bloques (simplement) // en fait ne sert à rien, car les réactions maxi sont calculées dans condlin, mais comme c'est peut-être un peu spécial ici on laisse // mais dans les autres algos c'est supprimé !!!!! diff --git a/Algo/GalerkinContinu/AlgoStatiques/ImpliNonDynaCont.cc b/Algo/GalerkinContinu/AlgoStatiques/ImpliNonDynaCont.cc index 87e90e7..871a18d 100644 --- a/Algo/GalerkinContinu/AlgoStatiques/ImpliNonDynaCont.cc +++ b/Algo/GalerkinContinu/AlgoStatiques/ImpliNonDynaCont.cc @@ -498,7 +498,7 @@ void ImpliNonDynaCont::Calcul_Equilibre(ParaGlob * paraGlob,LesMaillages * lesMa maxPuissExt = vglobex.Max_val_abs(); F_ext_tdt = vglobex; // sauvegarde des forces généralisées extérieures // - definition des conditions limites de contact - const Tableau & tabCondLine = lescontacts->ConditionLin(Ass.Nb_cas_assemb()); + list & listCondLine = lescontacts->ConditionLin(Ass.Nb_cas_assemb()); // -- appel du calcul de la raideur et du second membre, énergies // dans le cas d'un calcul inexploitable arrêt de la boucle if (!RaidSmEner(lesMail,Ass,vglobin,matglob)) break; @@ -525,7 +525,7 @@ void ImpliNonDynaCont::Calcul_Equilibre(ParaGlob * paraGlob,LesMaillages * lesMa vglobal.Affiche();*/ // cout <<" \n une valeur continuer ? "; cin >> toti; // expression de la raideur et du second membre dans un nouveau repere - lesCondLim->CoLinCHrepere_ext(matglob,vglobaal,tabCondLine,Ass.Nb_cas_assemb(),vglob_stat); + lesCondLim->CoLinCHrepere_ext(matglob,vglobaal,listCondLine,Ass.Nb_cas_assemb(),vglob_stat); /* cout << "\n matrice et second membre dans le nouveau repere"; matglob.Affiche1(1,4,1,1,4,1); vglobal.Affiche(); */ diff --git a/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc b/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc index 58d708c..4071fab 100644 --- a/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc +++ b/Algo/GalerkinDiscontinu/DG_DynaExplicite/AlgoBonelli.cc @@ -652,8 +652,10 @@ 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() - ,distribution_CPU_algo.Tab_indique_CPU_en_cours()); + paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_CPU_en_cours() + ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours() + ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours()); }; #endif diff --git a/Chargement/Charge2.cc b/Chargement/Charge2.cc index 52bf9bf..309e0b2 100644 --- a/Chargement/Charge2.cc +++ b/Chargement/Charge2.cc @@ -1620,7 +1620,7 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des forces ponctuelles ---$$$ #ifdef UTILISATION_MPI - // cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0uniquement + // 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 diff --git a/General/Distribution_CPU.cc b/General/Distribution_CPU.cc index 0070920..6443254 100755 --- a/General/Distribution_CPU.cc +++ b/General/Distribution_CPU.cc @@ -38,6 +38,9 @@ Distribution_CPU::Distribution_CPU(): tab_list_maillage_element(),tab_indic() ,total_elem(0) ,tab_vide_list_maillage_element() + ,tab_list_maillage_noeud(),tab_indic_noeud() + ,total_noeud(0) + ,tab_vide_list_maillage_noeud() {}; // constructeur de copie @@ -45,6 +48,9 @@ Distribution_CPU::Distribution_CPU (const Distribution_CPU& a): tab_list_maillage_element(a.tab_list_maillage_element) ,tab_indic(a.tab_indic),total_elem(a.total_elem) ,tab_vide_list_maillage_element() + ,tab_list_maillage_noeud(a.tab_list_maillage_noeud) + ,tab_indic_noeud(a.tab_indic_noeud),total_noeud(a.total_noeud) + ,tab_vide_list_maillage_noeud() {}; // calcul de l'équilibrage initiale @@ -63,8 +69,6 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai Sortie(1); }; - tab_indic.Change_taille(nb_proc_calcul); - // dans une première étape on ne s'intéresse qu'aux éléments // on suppose que les éléments sont identiques en temps de calcul // on repère les éléments par le numéro de maillage + le numéro d'élément, en cours @@ -73,13 +77,18 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai total_elem = 0; // init Tableau > inter(nb_mail); // inter utilisé ensuite pour dimensionner tab_indic + Tableau > inter_noeud(nb_mail); // inter utilisé ensuite pour dimensionner tab_indic_noeud for (int i=1;i<=nb_mail;i++) {int nb_elem_mail = lesMaillages->Nombre_element(i); total_elem += nb_elem_mail; inter(i).Change_taille(nb_elem_mail,false); + int nb_noeud_mail = lesMaillages->Nombre_noeud(i); + total_noeud += nb_noeud_mail; + inter_noeud(i).Change_taille(nb_noeud_mail,false); }; // on dimensionne tab_indic, tout est à false tab_indic.Change_taille(nb_proc_calcul,inter); + tab_indic_noeud.Change_taille(nb_proc_calcul,inter_noeud); // il faut que le nombre d'élément soit au moins >= au nb de proc de calcul // pour que l'on puisse distribuer au moin un elem par proc de calcul if (total_elem < nb_proc_calcul) @@ -97,8 +106,11 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai tab_list_maillage_element.Change_taille(nb_proc_calcul); for (int iproc =1;iproc <= nb_proc_calcul; iproc++) {tab_list_maillage_element(iproc).Change_taille(nb_mail); + tab_list_maillage_noeud(iproc).Change_taille(nb_mail); for (int imail=1; imail<= nb_mail; imail++) - tab_list_maillage_element(iproc)(imail).clear(); + {tab_list_maillage_element(iproc)(imail).clear(); + tab_list_maillage_noeud(iproc)(imail).clear(); + }; }; // on parcours tous les éléments et on remplit les tableaux int iproc = 1; // le num du proc en cours @@ -107,10 +119,20 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai { int nb_ele = lesMaillages->Nombre_element(imail); {list * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init + list * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init // de la liste courante for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++) { li_maillage_element->push_back(ile); tab_indic(iproc)(imail)(ile)=true; // on signale + // idem pour les noeuds + Element& ele = lesMaillages->Element_LesMaille(imail,ile); + Tableau& tab_N = ele.Tab_noeud(); + int nb_N = tab_N.Taille(); + for (int ne =1;ne<=nb_N;ne++) + {int num_noeud = tab_N(ne)->Num_noeud(); + tab_indic_noeud(iproc)(imail)(num_noeud)=true; + li_maillage_noeud->push_back(num_noeud); + }; // on regarde s'il faut changer de cpu // si c'est le dernier cpu, on ne change pas -> pour éviter // les pb d'arrondi @@ -119,6 +141,7 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai {iproc++; nb_ele_enreg_iproc=1; // reinit du compteur li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée + li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); }; }; }; @@ -141,7 +164,8 @@ 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,&tab_indic); + ParaGlob::param->Init_tableau(&tab_list_maillage_element,&tab_indic + ,&tab_list_maillage_noeud,&tab_indic_noeud); }; @@ -162,15 +186,30 @@ void Distribution_CPU::save(Archive & ar, const unsigned int version) const // pour cela on se sert de tab_indic pour le premier cpu for (int num_mail = 1; num_mail <= nb_mail;num_mail++) ar << (int) tab_indic(1)(num_mail).Taille(); + // maintenant tab_list_maillage_element for (int imail=1;imail<=nb_mail;imail++) { const list & list_maillage_element = tab_list_maillage_element(i_proc)(imail); - ar << std::string(" list:i_taille= ")<< (int) list_maillage_element.size() ; + ar << std::string(" list_maillage_element:i_taille= ")<< (int) list_maillage_element.size() ; list ::const_iterator il, ilfin= list_maillage_element.end(); for (il = list_maillage_element.begin(); il != ilfin; il++) { int truc = (*il); ar << truc ; }; }; + // on sauvegarde également le nombre total de noeud par maillage + // pour cela on se sert de tab_indic_noeud pour le premier cpu + for (int num_mail = 1; num_mail <= nb_mail;num_mail++) + ar << (int) tab_indic_noeud(1)(num_mail).Taille(); + // puis tab_list_maillage_noeud + for (int imail=1;imail<=nb_mail;imail++) + { const list & list_maillage_noeud = tab_list_maillage_noeud(i_proc)(imail); + ar << std::string(" list_maillage_noeud:i_taille= ")<< (int) list_maillage_noeud.size() ; + list ::const_iterator il, ilfin= list_maillage_noeud.end(); + for (il = list_maillage_noeud.begin(); il != ilfin; il++) + { int truc = (*il); + ar << truc ; + }; + }; }; } @@ -192,25 +231,30 @@ void Distribution_CPU::load(Archive & ar, const unsigned int version) // redimentionnement éventuel, si même taille, aucune action tab_list_maillage_element.Change_taille(nb_proc_calcul); + tab_list_maillage_noeud.Change_taille(nb_proc_calcul); // idem tab_indic tab_indic.Change_taille(nb_proc_calcul); - + tab_indic_noeud.Change_taille(nb_proc_calcul); + total_elem = 0; // init - + total_noeud = 0; // init + for (int i_proc=1;i_proc<= nb_proc_calcul; i_proc++) { int nb_mail; ar >> toto >> nb_mail; tab_list_maillage_element(i_proc).Change_taille(nb_mail); tab_indic(i_proc).Change_taille(nb_mail); + tab_list_maillage_noeud(i_proc).Change_taille(nb_mail); + tab_indic_noeud(i_proc).Change_taille(nb_mail); // on va lire le nombre total d'éléments pour chaque maillage for (int num_mail = 1; num_mail <= nb_mail;num_mail++) { int nb_elem_mail; ar >> nb_elem_mail; tab_indic(i_proc)(num_mail).Change_taille(nb_elem_mail,false); }; + // puis les tableaux for (int imail=1;imail<=nb_mail;imail++) { Tableau & tab_indic_cpu_mail = tab_indic(i_proc)(imail); // pour simplifier -// tab_indic_cpu_mail.Inita(false); // par défaut init à false pour tous les éléments list & list_maillage_element = tab_list_maillage_element(i_proc)(imail); int size_list; ar >> toto >> size_list; @@ -223,7 +267,7 @@ void Distribution_CPU::load(Archive & ar, const unsigned int version) tab_indic_cpu_mail(inter)=true; // on rempli tab_indic } } - else // cas où la taille n'est pas bonne + else // cas où la taille n'est pas bonne {list_maillage_element.clear(); int inter; // élément de travail for (int j=1;j<= size_list;j++) @@ -232,10 +276,43 @@ void Distribution_CPU::load(Archive & ar, const unsigned int version) tab_indic_cpu_mail(inter)=true; // on rempli tab_indic }; }; - // mise à jour du nombre total d'élément - total_elem += list_maillage_element.size(); + // mise à jour du nombre total d'élément + total_elem += list_maillage_element.size(); + }; + // on va lire le nombre total de noeud pour chaque maillage + for (int num_mail = 1; num_mail <= nb_mail;num_mail++) + { int nb_noeud_mail; + ar >> nb_noeud_mail; + tab_indic_noeud(i_proc)(num_mail).Change_taille(nb_noeud_mail,false); }; - } + // puis les tableaux + for (int imail=1;imail<=nb_mail;imail++) + { Tableau & tab_indic_noeud_cpu_mail = tab_indic_noeud(i_proc)(imail); // pour simplifier + list & list_maillage_noeud = tab_list_maillage_noeud(i_proc)(imail); + int size_list; + ar >> toto >> size_list; + if (size_list == list_maillage_noeud.size()) + {// si la liste existante a la bonne taille, on ne fait que lire + int inter; + list ::iterator il, ilfin= list_maillage_noeud.end(); + for (il = list_maillage_noeud.begin(); il != ilfin; il++) + {ar >> inter; (*il)=inter; + tab_indic_noeud_cpu_mail(inter)=true; // on rempli tab_indic + } + } + else // cas où la taille n'est pas bonne + {list_maillage_noeud.clear(); + int inter; // élément de travail + for (int j=1;j<= size_list;j++) + {ar >> inter; + list_maillage_noeud.push_back(inter); + tab_indic_noeud_cpu_mail(inter)=true; // on rempli tab_indic + }; + }; + // mise à jour du nombre total d'élément + total_noeud += list_maillage_noeud.size(); + }; + }; }; // affichage des infos relatives à la distribution @@ -248,7 +325,7 @@ void Distribution_CPU::Affiche() const {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 + // on affiche é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(); @@ -263,6 +340,21 @@ void Distribution_CPU::Affiche() const cout << truc << " , "; }; }; + // idem pour les noeuds on affiche le nombre total de noeud par maillage + // pour cela on se sert de tab_indic_noeud pour le premier cpu + for (int num_mail = 1; num_mail <= nb_mail;num_mail++) + cout << ", nb noeud total du maillage " << num_mail << " => " << (int) tab_indic_noeud(1)(num_mail).Taille(); + for (int imail=1;imail<=nb_mail;imail++) + { const list & list_maillage_noeud = tab_list_maillage_noeud(i_proc)(imail); + cout << " \n cas du maillage "<< imail + << std::string(": nb noeud pour le proc => ")<< (int) list_maillage_noeud.size() + << " c-a-d les elem : \n "; + list ::const_iterator il, ilfin= list_maillage_noeud.end(); + for (il = list_maillage_noeud.begin(); il != ilfin; il++) + { int truc = (*il); + cout << truc << " , "; + }; + }; }; } diff --git a/General/Distribution_CPU.h b/General/Distribution_CPU.h index b586953..a26cd67 100755 --- a/General/Distribution_CPU.h +++ b/General/Distribution_CPU.h @@ -56,6 +56,10 @@ * BUT: une classe qui a pour objectif de gérer, calculer, * certaines particularités liées à la parallélisation: * - l'équilibrage de charge de calcul sur les processeurs +* La classe sert de conteneur basique: des tableaux de numéros +* L'idée est d'avoir un accès rapide aux données. +* NB: Par contre si les maillages évolues (nb noeuds, nb éléments, numérotations) +* il faut réinitialiser les tableaux * * * \author Gérard Rio @@ -97,6 +101,20 @@ class Distribution_CPU return tab_list_maillage_element(ParaGlob::Monde()->rank()); else return tab_vide_list_maillage_element; }; + // retour de tab_list_maillage_noeud(i)(j) contient la liste + // pour le maillage j des num associés au cpu i + // NB: si la taille du tableau == 0, cela signifie qu'il n'a pas encore été construit + // on peut dans ce cas déclancher un calcul d'équilibrage initial + const Tableau > > * Tableau_noeud_CPU_en_cours() const + {return &tab_list_maillage_noeud;}; + + // retour de la liste des noeud relatif au cpu en cours + // si c'est le cpu 0, retourne un tableau vide + const Tableau < list > & List_noeud_CPU_en_cours() const + {if (ParaGlob::Monde()->rank() != 0) + return tab_list_maillage_noeud(ParaGlob::Monde()->rank()); + else return tab_vide_list_maillage_noeud; + }; // 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é @@ -111,6 +129,20 @@ class Distribution_CPU // récup du nombre total d'éléments, cumul sur tous les maillages int NB_total_element() const {return total_elem ;}; + + // retourne le tableau indicateur permettant de dire si un noeud est concerné par un CPU + // tab_indic_noeud(CPU)(mail)(ne) : = 1 si le noeud ne du maillage mail est concerné + // par le CPU + const Tableau > > * Tab_indique_noeud_CPU_en_cours() const {return &tab_indic_noeud;}; + + // indicateur permettant de dire si un noeud est concerné par un CPU donné + // tab_indic_noeud(CPU)(mail)(ne) : = 1 si le noeud ne du maillage mail est concerné + // par le CPU + bool Noeud_concerner(int CPU,int mail,int ne) const + {return tab_indic_noeud(CPU)(mail)(ne);}; + + // récup du nombre total de noeud, cumul sur tous les maillages + int NB_total_noeud() const {return total_noeud ;}; // affichage des infos relatives à la distribution void Affiche() const ; @@ -129,6 +161,10 @@ class Distribution_CPU private : // VARIABLES PROTEGEES : + // les conteneurs sont basiques, en particulier on ne stocke pas + // un pointeur sur les maillages, du coup il faut tout sauvegarder et + // tout relire, mais normalement c'est une opération qui s'effectue peu souvent (à voir !!) + // tab_list_maillage_element(i)(j) contient la liste // pour le maillage j des num <élément> associés au cpu i Tableau > > tab_list_maillage_element; @@ -141,6 +177,22 @@ class Distribution_CPU Tableau > > tab_indic; int total_elem ; // nombre total d'éléments cumulé sur tous les maillages + + // tab_list_maillage_noeud(i)(j) contient la liste + // pour le maillage j des num associés au cpu i + // c-a-d appartenent à un élément de maillage associés au cpu + // important: un noeud peut être associés à plusieurs cpu + Tableau > > tab_list_maillage_noeud; + // un tableau vide, qui correspond au cas du CPU 0 + Tableau < list > tab_vide_list_maillage_noeud; + + // indicateur permettant de dire si un noeud est concerné par un CPU donné + // tab_indic_noeud(CPU)(mail)(ne) : = 1 si le noeud ne du maillage mail est concerné + // par le CPU + Tableau > > tab_indic_noeud; + + int total_noeud; // nombre total de noeud cumulé sur tous les maillages + // METHODES PROTEGEES : // -- serialisation --- diff --git a/Maillage/LesCondLim.cc b/Maillage/LesCondLim.cc index f98774a..d52fb97 100644 --- a/Maillage/LesCondLim.cc +++ b/Maillage/LesCondLim.cc @@ -2855,7 +2855,7 @@ void LesCondLim::Affiche_reaction(ofstream& sort,const LesMaillages * lesMail) c // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob // mais sans sauvegarde (correspond par exemple à une partie de vecglob) bool LesCondLim::CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob - ,const Tableau & tab,const Nb_assemb& nb_casAssemb,Vecteur* vec2) + ,list & listCondLine,const Nb_assemb& nb_casAssemb,Vecteur* vec2) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées @@ -2866,19 +2866,21 @@ bool LesCondLim::CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob tempsCLL.Mise_en_route_du_comptage(); // temps cpu // on boucle sur le tableau et pour chaque element on impose une condition lineaire - int tabTaille = tab.Taille(); +/// int tabTaille = tab.Taille(); bool modification = false; // init du retour - for (int i=1;i<= tabTaille; i++) - {Condilineaire& condi = tab(i); + list ::iterator il,ilfin = listCondLine.end(); + for (il = listCondLine.begin();il != ilfin;il++) +// for (int i=1;i<= tabTaille; i++) + {Condilineaire& condi = (*il); // calcul des pointeurs d'assemblage condi.ConditionPourPointeursAssemblage(nb_casAssemb); // application de la condition condlim(nb_casAssemb.n).CondlineaireCHRepere - ( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2); + ( matglob,vecglob,condi.Pt_t(),condi.Val(),condi.Beta(),vec2); modification=true; }; // affichage éventuelle de la matrice de raideur et du second membre - if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0)) + if ((ParaGlob::NiveauImpression() >= 10) && (listCondLine.size() != 0)) { string entete = " affichage de la matrice apres changement de repere du aux conditions limites externes (ex contact)"; matglob.Affichage_ecran(entete); entete = " affichage du second membre apres changement de repere du aux conditions limites externes (ex contact) "; @@ -2895,7 +2897,7 @@ bool LesCondLim::CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob // mais sans sauvegarde (correspond par exemple à une partie de vecglob) bool LesCondLim::CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob - ,const Tableau & tab + ,list & listCondLine ,const Nb_assemb& nb_casAssemb,Vecteur* vec2) { #ifdef UTILISATION_MPI @@ -2906,21 +2908,21 @@ bool LesCondLim::CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob tempsCLL.Mise_en_route_du_comptage(); // temps cpu - // on boucle sur le tableau et pour chaque element on impose une condition lineaire - int tabTaille = tab.Taille(); + // on boucle dans la liste et pour chaque element on impose une condition lineaire bool modification = false; // init du retour - for (int i=1;i<= tabTaille; i++) - {Condilineaire& condi = tab(i); + list ::iterator il,ilfin = listCondLine.end(); + for (il = listCondLine.begin();il != ilfin;il++) + {Condilineaire& condi = (*il); // calcul des pointeurs d'assemblage condi.ConditionPourPointeursAssemblage(nb_casAssemb); // application d'une condition linéaire seule, avec en retour, la situation de la condition linéaire // imposée, ramené dans le repère initial condlim(nb_casAssemb.n).CondiLineaireImposeComplet - ( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2); + ( matglob,vecglob,condi.Pt_t(),condi.Val(),condi.Beta(),vec2); modification=true; }; // affichage éventuelle de la matrice de raideur et du second membre - if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0)) + if ((ParaGlob::NiveauImpression() >= 10) && (listCondLine.size() != 0)) { string entete = " affichage de la matrice apres application CLL externes (ex contact) "; matglob.Affichage_ecran(entete); entete = " affichage du second membre apres apres application CLL externes (ex contact) "; diff --git a/Maillage/LesCondLim.h b/Maillage/LesCondLim.h index 1088c17..da4a298 100644 --- a/Maillage/LesCondLim.h +++ b/Maillage/LesCondLim.h @@ -295,7 +295,7 @@ class LesCondLim // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob // mais sans sauvegarde (correspond par exemple à une partie de vecglob) bool CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob - ,const Tableau & tabCondLine + , list & listCondLine ,const Nb_assemb& nb_casAssemb,Vecteur* vec2); // blocage des seconds membres pour les conditions lineaires @@ -316,7 +316,7 @@ class LesCondLim // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob // mais sans sauvegarde (correspond par exemple à une partie de vecglob) bool CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob - ,const Tableau & tabCondLine + ,list & listCondLine ,const Nb_assemb& nb_casAssemb,Vecteur* vec2); diff --git a/Parametres/EnteteParaGlob.h b/Parametres/EnteteParaGlob.h index f15274a..88388b7 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.019" ; // numéro de version du logiciel + string ParaGlob::nbVersion = "7.020" ; // 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 32135d3..a1f75f9 100644 --- a/Parametres/ParaGlob.h +++ b/Parametres/ParaGlob.h @@ -147,11 +147,15 @@ class ParaGlob static boost::mpi::communicator * Monde() {return world;}; static void Init_boost_communicator (boost::mpi::communicator * pt_world) {world = pt_world;}; - // -- equilibrage d'éléments + // -- equilibrage d'éléments et noeuds associés void Init_tableau (const Tableau > >* tab_list_maillage_element - ,const Tableau > >* tab_indic) + ,const Tableau > >* tab_indic + ,const Tableau > >* tab_list_maillage_noeud + ,const Tableau > >* tab_indic_noeud) {tab_list_mail_element = tab_list_maillage_element; tabb_indic = tab_indic; + tab_list_mail_noeud = tab_list_maillage_noeud; + tabb_indic_noeud = tab_indic_noeud; }; // 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 @@ -165,6 +169,20 @@ class ParaGlob // par le CPU bool Element_concerner(int mail,int ele) const {return (*tabb_indic)(world->rank())(mail)(ele);}; + + // retour des listes des noeuds relatif au cpu en cours, c-a-d pour tous les maillages + // tab (j) donne la liste des noeuds pour le maillage j + const Tableau < list > & const_List_noeud_CPU_en_cours() const + {return (*tab_list_mail_noeud)(world->rank());}; + // spécifiquement, la liste des noeud pour le maillage j + const list & const_List_noeud_CPU_en_cours(int j) const + {return (*tab_list_mail_noeud)(world->rank())(j);}; + // indicateur permettant de dire si un noeud est concerné par le cpu en cours + // tab_indic_noeud(mail)(ne) : = 1 si noeud ne du maillage mail est concerné + // par le CPU + bool Noeud_concerner(int mail,int ne) const + {return (*tabb_indic_noeud)(world->rank())(mail)(ne);}; + #endif // lecture du type de calcul et d'une liste de sous_type éventuel @@ -417,6 +435,15 @@ class ParaGlob // 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; + // -- noeuds associés aux éléments + // tab_list_maillage_noeud(i)(j) contient la liste + // pour le maillage j des num associés au cpu i + // ici il s'agit d'une copie de tab_list_maillage_noeud qui doit être mise à jour par Distribution_CPU + const Tableau > >* tab_list_mail_noeud; + // indicateur permettant de dire si un noeud est concerné par un CPU donné + // tab_indic_noeud(CPU)(mail)(ne) : = 1 si le noeud ne 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_noeud; #endif //------------ info sur le temps --------------- diff --git a/Resolin/Resolution_Condi/Condilineaire.cc b/Resolin/Resolution_Condi/Condilineaire.cc index 691a5cc..50af0fe 100644 --- a/Resolin/Resolution_Condi/Condilineaire.cc +++ b/Resolin/Resolution_Condi/Condilineaire.cc @@ -186,3 +186,89 @@ void Condilineaire::Ecriture_base_info(ofstream& sort) // le numéro d'ordre du ddl modifié dans noeud sort << iddl << " \n"; }; + +#ifdef UTILISATION_MPI // spécifique au calcul parallèle + // stockage dans un unique vecteur, des infos à partir de l'indice rang inclus + // correspond à une sérialisation des infos + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + int Condilineaire::Pack_vecteur(Vecteur& v,int rang) const + { // le tableau de pointeurs + int taille_pt = pt.Taille(); + v(rang) = taille_pt;rang++; + for (int i=1;i<=taille_pt;i++) + {v(rang)= pt(i);rang++;}; + // le vecteur val + int taille_val = val.Taille(); + v(rang) = taille_val; + for (int i=1;i<=taille_val;i++) + {v(rang)= val(i);rang++;}; + // beta + v(rang)=beta; rang++; + // Uk_impose + v(rang)=Uk_impose; rang++; + // le cas d'assemblage associé + rang = casAssemb.Pack_vecteur(v,rang); + // le tableau t_enu + int taille_t_enu = t_enu.Taille(); + v(rang) = taille_t_enu;rang++; + for (int i=1;i<=taille_t_enu;i++) + {v(rang)= t_enu(i);rang++;}; + // iddl + v(rang)=iddl; rang++; + // le taleau t_noeud + // on considère que la numérotation est la même pour tous les cpu + // du coup on sauvegarde le numéro de maillage et le numéro de noeud + int taille_t_noeud = t_noeud.Taille();rang++; + v(rang)= taille_t_noeud; + for (int i=1;i<=taille_t_noeud;i++) + {v(rang)= t_noeud(i)->Num_Mail();rang++; + v(rang)= t_noeud(i)->Num_noeud();rang++; + }; + if (rang > v.Taille()) rang = 0; + return rang; + }; + + // taille du conteneur actuel de la condition linéaire + int Condilineaire::Taille_Pack() const + {int taille_pack = 0; // init + taille_pack += pt.Taille() + 1; + taille_pack += val.Taille() + 1; + taille_pack += 2; + taille_pack += casAssemb.Taille_Pack(); + taille_pack += t_enu.Taille()+1; + taille_pack += 1; + taille_pack += 2*t_noeud.Taille()+1; + return taille_pack; + }; + +#endif + +/* + + // VARIABLES PROTEGEES : + Tableau pt; //tableau des pointeurs de ddl concerne, pt(i) = la position du ddl i + // dans la matrice globale + Vecteur val; // tableau des coefficients de la condition lineaire + double beta; // valeur beta a laquelle est egale la condition lineaire + // dans le cas de la mise en place de la CL à partir d'un changement de repère, on peut stocker la valeur imposée avant chg de repère + double Uk_impose; // valeur a imposer sur le ddl avant changement de repère, qui correspondra à beta après chg de repère + // Uk_impose sert uniquement de stockage, mais n'est pas forcément cohérent avec la CL, sa manipulation est faite en dehors de la classe + // via : ChangeUk_impose et Val_Uk_impose + Nb_assemb casAssemb; // le cas d'assemblage associé + + // le blocage de condition est appliquee sur le ddl numero "iddl" du noeud "noe" + Tableau t_enu; // tableau des identificateur de ddl de la CLL + // t_enu(1) est l'identificateur du ddl qui est bloqué pour la CLL + // lorsque seul t_enu(1) existe, cela signifie qu'il faut construire + // les indices, + + // iddl -> le numéro d'ordre dans sa famille, du ddl bloqué + // NB: ce n'est pas la position du ddl dans le noeud !!, cette dernière est: Tab_Enum()(1) + int iddl; + // le tableau des noeuds de la CLL, le premier contient la condition + Tableau < Noeud *> t_noeud; + +*/ + + diff --git a/Resolin/Resolution_Condi/Condilineaire.h b/Resolin/Resolution_Condi/Condilineaire.h index 595037e..88c5556 100644 --- a/Resolin/Resolution_Condi/Condilineaire.h +++ b/Resolin/Resolution_Condi/Condilineaire.h @@ -56,6 +56,17 @@ #include "Noeud.h" #include "Nb_assemb.h" +#include +#ifdef UTILISATION_MPI + #include + #include + #include "mpi.h" + #include + #include + #include + #include + namespace mpi = boost::mpi; +#endif /// @addtogroup Les_classes_Matrices @@ -166,7 +177,24 @@ class Condilineaire // attibuer le noeud void Lecture_base_info(Tableau & numMaillage, ifstream& ent,Tableau & numNoeud) ; void Ecriture_base_info(ofstream& sort) ; - + #ifdef UTILISATION_MPI // spécifique au calcul parallèle + // stockage dans un unique vecteur, des infos à partir de l'indice rang inclus + // correspond à une sérialisation des infos + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + int Pack_vecteur(Vecteur& v,int rang) const; + // taille du conteneur actuel de la condition linéaire + int Taille_Pack() const; + // modification des infos à partir de l'indice rang inclus en fonction du vecteur passé en paramètre + // correspond à une désérialisation + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + // on passe un pointeur de fonctions qui ramène un noeud en fonction d'un numéro de maillage et d'un + // numéro de noeud, ceci pour éviter de passer toute l'instance de la classe Les_maillages + template int UnPack_vecteur(T& instance,const Vecteur& v,int rang, + Noeud & (T::*Ptfonc) (int num_mail,int num_noeud) const ); + #endif + protected : // VARIABLES PROTEGEES : Tableau pt; //tableau des pointeurs de ddl concerne, pt(i) = la position du ddl i @@ -195,6 +223,10 @@ class Condilineaire // METHODES PROTEGEES : }; + // pour faire de l'inline: nécessaire avec les templates + // on n'inclut que les méthodes templates + #include "Condilineaire_2.cc" + #define Condilineaire_deja_inclus /// @} // end of group #endif diff --git a/Resolin/Resolution_Condi/Condilineaire_2.cc b/Resolin/Resolution_Condi/Condilineaire_2.cc new file mode 100755 index 0000000..d1bd709 --- /dev/null +++ b/Resolin/Resolution_Condi/Condilineaire_2.cc @@ -0,0 +1,91 @@ + + // This file is part of the Herezh++ application. + // + // The finite element software Herezh++ is dedicated to the field + // of mechanics for large transformations of solid structures. + // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) + // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . + // + // Herezh++ is distributed under GPL 3 license ou ultérieure. + // + // Copyright (C) 1997-2022 Université Bretagne Sud (France) + // AUTHOR : Gérard Rio + // E-MAIL : gerardrio56@free.fr + // + // This program is free software: you can redistribute it and/or modify + // it under the terms of the GNU General Public License as published by + // the Free Software Foundation, either version 3 of the License, + // or (at your option) any later version. + // + // This program is distributed in the hope that it will be useful, + // but WITHOUT ANY WARRANTY; without even the implied warranty + // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + // See the GNU General Public License for more details. + // + // You should have received a copy of the GNU General Public License + // along with this program. If not, see . + // + // For more information, please consult: . + +#ifndef Condilineaire_deja_inclus + #include "Condilineaire.h" +#endif + +// contient que les méthodes nécessitant les templates, qui doivent donc être +//incluses dans le .h + +#ifndef Condilineaire_deja_inclus + + #include "Condilineaire.h" + + + #ifdef UTILISATION_MPI // spécifique au calcul parallèle + + // modification des infos à partir de l'indice rang inclus en fonction du vecteur passé en paramètre + // correspond à une désérialisation + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + // on passe un pointeur de fonctions qui ramène un noeud en fonction d'un numéro de maillage et d'un + // numéro de noeud, ceci pour éviter de passer toute l'instance de la classe Les_maillages + template int Condilineaire::UnPack_vecteur(T& instance,const Vecteur& v,int rang, + Noeud & (T::*Ptfonc) (int num_mail,int num_noeud) const ) + { // le tableau de pointeurs + int taille_pt = (int) v(rang);rang++; + pt.Change_taille(taille_pt); + for (int i=1;i<=taille_pt;i++) + {pt(i) = (int) v(rang);rang++;}; + // le vecteur val + int taille_val = (int) v(rang);rang++; + val.Change_taille(taille_val); + for (int i=1;i<=taille_val;i++) + {val(i) = v(rang);rang++;}; + // beta + beta = v(rang); rang++; + // Uk_impose + Uk_impose = v(rang); rang++; + // le cas d'assemblage associé + rang = casAssemb.UnPack_vecteur(v,rang); + // le tableau t_enu + int taille_t_enu = (int) v(rang);rang++; + t_enu.Change_taille(taille_t_enu); + for (int i=1;i<=taille_t_enu;i++) + {t_enu(i) = (Enum_ddl) v(rang);rang++;}; + // iddl + iddl = (int) v(rang); rang++; + // le taleau t_noeud + // on considère que la numérotation est la même pour tous les cpu + // du coup on sauvegarde le numéro de maillage et le numéro de noeud + int taille_t_noeud = (int) v(rang);rang++; + t_noeud.Change_taille(taille_t_noeud); + for (int i=1;i<=taille_t_noeud;i++) + {int num_mail = (int) v(rang);rang++; + int num_noeud = (int) v(rang);rang++; + t_noeud(i) = &((instance.*Ptfonc) (num_mail,num_noeud)); + }; + if (rang > v.Taille()) rang = 0; + return rang; + }; + #endif + +#endif + diff --git a/TypeBase/Nb_assemb.h b/TypeBase/Nb_assemb.h index 29bd27c..85207d3 100644 --- a/TypeBase/Nb_assemb.h +++ b/TypeBase/Nb_assemb.h @@ -88,13 +88,34 @@ class Nb_assemb { n = c.n; return (*this);} //Surcharge d'operateur logique - bool operator == (const Nb_assemb& a) const - { return (a.n == n); }; - bool operator != (const Nb_assemb& a) const - { return (a.n != n); }; + bool operator == (const Nb_assemb& a) const + { return (a.n == n); }; + bool operator != (const Nb_assemb& a) const + { return (a.n != n); }; - - // donnée + #ifdef UTILISATION_MPI // spécifique au calcul parallèle + // stockage dans un unique vecteur, des infos à partir de l'indice rang inclus + // correspond à une sérialisation des infos + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + int Pack_vecteur(Vecteur& v,int rang) const + {v(rang)=n; int next = rang+1; if (next > v.Taille()) next = 0; + return next; }; + // taille du conteneur actuel de la condition linéaire + // stocké en réel + int Taille_Pack() const {return 1;}; + // opération inverse + // modification des infos à partir de l'indice rang inclus en fonction du vecteur passé en paramètre + // correspond à une désérialisation + // ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v + // dans ce cas ramène 0 + int UnPack_vecteur(const Vecteur& v,int rang) + { n = (int) v(rang); + int next = rang+1; if (next > v.Taille()) next = 0; + return next;} ; + #endif + + // donnée int n; }; diff --git a/contact/ElContact.cc b/contact/ElContact.cc index 3ef697d..fd59ddc 100644 --- a/contact/ElContact.cc +++ b/contact/ElContact.cc @@ -267,7 +267,7 @@ ElContact::Fct_nD_contact& ElContact::Fct_nD_contact::operator= (const ElContact } case NOEUD_FACETTE_EN_CONTACT: { tqi(i) = new TypeQuelconque(NOEUD_FACETTE_EN_CONTACT,X1,grand_courant_double); - Grandeur_scalaire_double& gr= *((Grandeur_scalaire_double*) ((*tqi(i)).Grandeur_pointee())); +// Grandeur_scalaire_double& gr= *((Grandeur_scalaire_double*) ((*tqi(i)).Grandeur_pointee())); trouver = true; break; } @@ -713,7 +713,7 @@ bool ElContact::Contact( bool init) // 1) === le cas des angles morts est particulier, on commence par le traiter if (elfront->Angle_mort()) - { ElFrontiere & elfro = *(elfront->Eleme()); // pour commodite + { //ElFrontiere & elfro = *(elfront->Eleme()); // pour commodite int dim = noeud->Dimension(); Plan pl(dim); Droite dr(dim); int indic; // def des variables de tangence N = Calcul_Normale(dim,pl,dr,indic); @@ -1628,6 +1628,9 @@ Coordonnee ElContact::Intersection( const Coordonnee& V,bool init) // retour du point d'intersection return M1; }; + // si on arrive ici on considère qu'il n'y a pas d'intersection + Coordonnee a(0); + return a; }; // construction de la condition lineaire de contact @@ -1912,7 +1915,8 @@ int ElContact::Actualisation() ElFrontiere & elfro = *(elfront->Eleme()); // pour commodite // ici on recherche avec une précision donnée double extra_in_surface = ParaGlob::param->ParaAlgoControleActifs().PointInternePrecThetaiInterne(); - int contactType = ElContact::Recup_et_mise_a_jour_type_contact(); +// int contactType = + ElContact::Recup_et_mise_a_jour_type_contact(); if ((elfro.InSurf(extra_in_surface)) || (nb_change_frontiere > nb_change_frontiere_max) // pour limiter les flip-flop ) diff --git a/contact/LesContacts.cc b/contact/LesContacts.cc index beb56ce..74a4df4 100644 --- a/contact/LesContacts.cc +++ b/contact/LesContacts.cc @@ -113,7 +113,7 @@ bool LesContacts::ReactCont::operator != (const LesContacts::ReactCont& a) // CONSTRUCTEURS : // constructeur par defaut LesContacts::LesContacts () : - tabCoLin(),tabReacCont(),listContact()//,numtesN() + listCoLin(),tabReacCont(),listContact()//,numtesN() ,sauve_lesFonctionsnD(NULL),fct_nD_contact() ,listContact_nouveau_tatdt(),listContact_efface_tatdt() ,nom_ref_zone_contact(),lissage_de_la_normale() @@ -125,11 +125,12 @@ LesContacts::LesContacts () : ,liste_elemens_front(),tempsContact() #ifdef UTILISATION_MPI ,temps_transfert_court(),temps_transfert_long(),temps_attente() + ,inter_transfer(),inter_transfer2(),lesMaille(NULL) #endif {}; // constructeur de copie LesContacts::LesContacts (const LesContacts& a): - tabCoLin(a.tabCoLin),tabReacCont(a.tabReacCont) + listCoLin(a.listCoLin),tabReacCont(a.tabReacCont) ,sauve_lesFonctionsnD(a.sauve_lesFonctionsnD),fct_nD_contact(a.fct_nD_contact) ,listContact(a.listContact)//,numtesN(a.numtesN) ,listContact_nouveau_tatdt(a.listContact_nouveau_tatdt),listContact_efface_tatdt(a.listContact_efface_tatdt) @@ -143,6 +144,7 @@ LesContacts::LesContacts (const LesContacts& a): #ifdef UTILISATION_MPI ,temps_transfert_court(a.temps_transfert_court) ,temps_transfert_long(a.temps_transfert_long),temps_attente(a.temps_attente) + ,inter_transfer(),inter_transfer2(),lesMaille(NULL) #endif {}; // DESTRUCTEUR : @@ -170,6 +172,12 @@ void LesContacts::Init_contact(LesMaillages& lesMail // on met à jour le niveau de commentaire dans les éléments de contact ElContact::Mise_a_jour_niveau_commentaire(); if (niveau_commentaire_lescontacts > 4) + #ifdef UTILISATION_MPI + // on sauvegarde un pointeur sur les maillages + lesMaille = &lesMail; + + if (ParaGlob::Monde()->rank() == 0) + #endif cout << "\n -- LesContacts::Init_contact: "; // sauvegarde de la liste des fonctions nD @@ -200,29 +208,47 @@ void LesContacts::Init_contact(LesMaillages& lesMail { Fonction_nD * pt_fonct = lesFonctionsnD->Trouve(nom_fct4); // on vérifie pour l'instant que c'est bien une fonction de grandeurs globales if (pt_fonct->NbVariable_locale() != 0) // cas où il n'y a pas que des variables globales + #ifdef UTILISATION_MPI + {if (ParaGlob::Monde()->rank() == 0) + #endif { cout << "\n *** erreur dans la definition de la fonction nD de pilotage " << " du type de contact 4 : " << nom_fct4 << " n'utilise pas que des variables globales !! "; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); } + #ifdef UTILISATION_MPI + } + #endif else if (pt_fonct->NbComposante() > 2) + #ifdef UTILISATION_MPI + {if (ParaGlob::Monde()->rank() == 0) + #endif { cout << "\n *** erreur dans la definition de la fonction nD de pilotage " << " du type de contact 4 : " << nom_fct4 << " ramene plus de 2 composantes !! "; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); } + #ifdef UTILISATION_MPI + } + #endif else // sinon ok {ElContact::Init_fct_pilotage_contact4(pt_fonct);} } else + #ifdef UTILISATION_MPI + {if (ParaGlob::Monde()->rank() == 0) + #endif { cout << "\n *** erreur dans la definition de la fonction nD de pilotage " << " du type de contact 4 , le nom : " << nom_fct4 << " ne correspond pas a une fonction nD existante !! "; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; + #ifdef UTILISATION_MPI + }; + #endif }; /* // ----pour le débug @@ -250,6 +276,9 @@ void LesContacts::Init_contact(LesMaillages& lesMail // -> nbEscla == ntmail == nbmailautocontact == nbmailMaitre nbmailMaitre = ntmail-(nb_mail_Esclave-nbmailautocontact); // def du nombre de maillage maitres // dans le cas d'auto-contact, on vérifie la cohérence + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (nbmailautocontact != 0) {if ((nbmailautocontact <1) || (nbmailautocontact > nb_mail_Esclave)) // nbmailautocontact doit etre >= 0 et < nb_mail_Esclave @@ -266,6 +295,9 @@ void LesContacts::Init_contact(LesMaillages& lesMail }; // on récupère le tableau indice indice = ind; + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n >>>> Information : Initialisation du contact: "; // dimensionnement du premier niveau des tableaux @@ -295,6 +327,9 @@ void LesContacts::Init_contact(LesMaillages& lesMail tesctotal(ii)(1)(itai) = (*tescin(ii))(itai); tesN_collant(ii)(1)(itai) = 0; // pas de contact collant car le contact est non restreint }; + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n mail. esclave "<::iterator iMi,iMifin=(*listFrontiere(jf)).end(); for (iMi = (*listFrontiere(jf)).begin();iMi != iMifin; iMi++) lis_fronta.push_back((*iMi)); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) - cout << "\n mail. maitre "<::iterator il,ilfin=nom_ref_zone_contact.end(); int nb_zone = nom_ref_zone_contact.size(); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n --> nombre de zone de contact: " << nb_zone; // --- tout d'abord on s'occupe des noeuds esclaves @@ -334,6 +375,9 @@ void LesContacts::Init_contact(LesMaillages& lesMail } const Reference & ref = lesRef.Trouve((*il).nom2,nom_mail_noe); // on continue que si c'est une référence de noeud + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (ref.Indic() != 1) { // ce n'est pas normal -> message d'erreur cout << "\n *** erreur la reference de zone de contact n'est pas " @@ -366,13 +410,19 @@ void LesContacts::Init_contact(LesMaillages& lesMail tesctotal(intot)(izone)(no_dans_ref)= &(lesMail.Noeud_LesMaille(ref.Nbmaille(),num_noe_ref)); tesN_collant(intot)(izone)(no_dans_ref)= (*il).n; }; // -- fin de la boucle sur les noeuds de la référence + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) - cout << "\n maillage esclave "< " << nb_noe << " noeuds esclaves pour contact "; - // arrivée ici, c'est que la zone a été définie - zone_definie = true; + cout << "\n maillage esclave "< " << nb_noe << " noeuds esclaves pour contact "; + // arrivée ici, c'est que la zone a été définie + zone_definie = true; }; // -- fin de la boucle sur intot c-a-d les maillages esclave // message d'erreur si la zone n'a pas été définie + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (!zone_definie) { cout << "\n *** erreur dans la construction de la zone de contact "<rank() == 0) + #endif if (!lesRef.Existe(nom_ref,nom_mail_face)) { cout << "\n *** erreur la reference "<< nom_ref; if (nom_mail_face != NULL) @@ -457,6 +510,9 @@ void LesContacts::Init_contact(LesMaillages& lesMail default: // ici la frontière peut-être n'importe quoi: point, arête, surface // on vérifie que ce ne sont pas des ref Indic 5 ou 6 ou plus ou 1 ou 2 + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif { cout << "\n *** erreur la reference de zone de frontiere de contact n'est pas " << " une reference acceptable ! " << " seules les ref d'aretes ou de surface sont possibles " ; @@ -464,13 +520,16 @@ void LesContacts::Init_contact(LesMaillages& lesMail cout << "\n LesContacts::Init_contact(..." << endl; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); - break; }; + break; }; // fin du switch sur le type de frontière }; }; //-- fin de la boucle sur zone de contact }; //-- fin de la boucle sur les maillages maîtres // petit message si nécessaire + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) //&& (list_fronta.size() > 0)) { for (int i=1;i<= nb_zone;i++) // boucle sur les références de zone_contact { cout << "\n zone de contact: " << i << " => " @@ -613,18 +672,22 @@ void LesContacts::Verification() // ramène true s'il y a effectivement création d'élément de contact bool LesContacts::DefElemCont(double dep_max) { - #ifdef UTILISATION_MPI - // cas d'un calcul //, - // pour l'instant seule le CPU 0 est concernée - if (ParaGlob::Monde()->rank() != 0) - return false; - #endif - tempsContact.Mise_en_route_du_comptage(); // def deb compt bool retour = false; // init par défaut int niveau_commentaire_lescontacts = Permet_affichage(); + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + #endif + if (niveau_commentaire_lescontacts > 4) - cout << "\n ==> LesContacts::Def Elem Cont, initialement "< LesContacts::Def Elem Cont, initialement "< LesContacts::Def Elem Cont, initialement "<Num_Mail(); int n_noee = noee->Num_noeud(); {int nb_contact=0; //au début pas de contact pour le noeud (pour gérer les doublons en contact) - -// const Coordonnee& pt_esc = noee->Coord2(); // position du noeud esclave const Coordonnee pt_esc = noee->Coord2(); // position du noeud esclave for (int jlf=1;jlf<=nbmailMaitre;jlf++) // boucle sur les maillages maitres {LaLIST_io & t_listFront_jlf_j = t_listFront(jlf)(j_zone); iMfin= t_listFront_jlf_j.end(); for (iM = t_listFront_jlf_j.begin() ; iM != iMfin; iM++) // boucle sur les front { + bool a_considerer = true; // init par défaut + #ifdef UTILISATION_MPI + // dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu + {Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere + // on ne continue que si l'élément est concerné + if (!(ParaGlob::param->Element_concerner(elem.Num_maillage(),elem.Num_elt_const()) )) + a_considerer=false; + }; + #endif + std::map::iterator > >& tesN_encontact_ii = tesN_encontact(num_mail_noe_esclave); // on regarde si la liste existe, si oui on peut tester les membres sinon, on ne fait rien // car autrement on crée automatiquement une liste avec un élément vide std::map::iterator > >::iterator it_liste; - bool a_considerer = true; // init par défaut if (tesN_encontact_ii.find(noee) != tesN_encontact_ii.end()) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[noee]; LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); @@ -744,7 +814,12 @@ bool LesContacts::DefElemCont(double dep_max) bool ret = elcont.Contact(init_inter); if (niveau_commentaire_lescontacts > 5) { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\n recherche du contact entre noeud " << elcont.Esclave()->Num_noeud() + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " recherche du contact entre noeud " << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() << " et frontiere " << (*iM).Num_frontiere() << " de l'element " << elem.Num_elt() << " du maillage " @@ -776,7 +851,11 @@ bool LesContacts::DefElemCont(double dep_max) { // s'il existe déjà ce n'est pas normal #ifdef MISE_AU_POINT {if (Element_contact_deja_present(elcont) != NULL) - { cout << "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal " + { + #ifdef UTILISATION_MPI + cout << "\n *** erreur: proc " << proc_en_cours; + #endif + cout << "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal " << (elcont).Esclave()->Num_noeud() << " du maillage " << (elcont).Esclave()->Num_Mail() << " la suite n'est pas possible " @@ -795,7 +874,12 @@ bool LesContacts::DefElemCont(double dep_max) nb_contact++; if (niveau_commentaire_lescontacts > 3) { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\ncontact entre noeud " ; + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << "\ncontact entre noeud " ; if (tesN_col(inesc)) cout << " collant "; cout << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() @@ -842,7 +926,12 @@ bool LesContacts::DefElemCont(double dep_max) // on n'intervient pas sur tesN_encontact, car ça ne change pas if (niveau_commentaire_lescontacts > 2) { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\n --- changement d'element en contact ---"; + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " --- changement d'element en contact ---"; cout << "\ncontact entre noeud " ; if (tesN_col(inesc)) cout << " collant "; cout << elcont.Esclave()->Num_noeud() @@ -872,7 +961,13 @@ bool LesContacts::DefElemCont(double dep_max) }; //-- fin de la boucle sur les zones // retour if (niveau_commentaire_lescontacts > 2) // ==> LesContacts:: - { cout << "\n apres Def Elem Cont: "<< listContact.size() << " elem contact "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " apres Def Elem Cont: "<< listContact.size() << " elem contact "; if ( listContact_nouveau_tatdt.size()) cout <<", "<< listContact_nouveau_tatdt.size() << " nouveau(x) "; if (listContact_efface_tatdt.size()) @@ -892,16 +987,31 @@ bool LesContacts::Nouveau(double dep_max) { tempsContact.Mise_en_route_du_comptage(); // def deb compt int niveau_commentaire_lescontacts = Permet_affichage(); + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + #endif + int nb_zone = MaX(1,nom_ref_zone_contact.size()); // on sauvegarde la liste au départ int taille_list_contact_nouveau_au_debut = listContact_nouveau_tatdt.size(); if (niveau_commentaire_lescontacts > 3) - cout << "\n ==> LesContacts::Nouveau: temps= " << ParaGlob::Variables_de_temps().TempsCourant(); + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " ==> LesContacts::Nouveau: temps= " << ParaGlob::Variables_de_temps().TempsCourant(); // on montre les noeuds actuellement en contact if (niveau_commentaire_lescontacts > 5) - {cout << "\n >> bilan des noeud(s) actuellement en contact: "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " >> bilan des noeud(s) actuellement en contact: "; for (int intot = 1;intot<= nb_mail_Esclave;intot++) // boucle sur les maillages esclaves for (int j=1;j<= nb_zone;j++) {const Tableau & tesc= tesctotal(intot)(j); // pout simplifier la notation @@ -931,7 +1041,7 @@ bool LesContacts::Nouveau(double dep_max) // car autrement on crée automatiquement une liste avec un élément vide std::map::iterator > >::iterator it_liste; if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end()) - {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; + {//LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; // LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); cout << "\n --> noeud actuellement en contact "; if (tesN_collant(num_mail_noe_esclave)(j)(inesc)) cout << " collant "; @@ -944,13 +1054,20 @@ bool LesContacts::Nouveau(double dep_max) }; if (niveau_commentaire_lescontacts > 4) // on va lister les éléments de contact - { cout << "\n liste des Elcontact au debut de LesContacts::Nouveau: (fct du niveau de commentaire des elcontact): "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " liste des Elcontact au debut de LesContacts::Nouveau: (fct du niveau de commentaire des elcontact): "; LaLIST::iterator ipp,ippfin=listContact.end(); for (ipp=listContact.begin();ipp != ippfin; ipp++) {(*ipp).Affiche(2);}; - }; + }; // on met à jour les boites des éléments qui contiennent les frontières + // ?? on pourrait peut-être restreindre aux seuls éléments de frontières du cpu i , à voir où est utilisée la méthode ?? Mise_a_jour_boite_encombrement_element_contenant_front(); // on met à jour le déplacement maxi toléré pour la classe ElContact double coef_mult_dep_max = 3.; // comme un noeud peut se déplacer de dep_max et que l'on @@ -961,7 +1078,9 @@ bool LesContacts::Nouveau(double dep_max) // --- 1) on va tout d'abord parcourir les éléments inactifs et regarder s'ils sont en contact // si oui on les valide, sinon on les supprimes. Il faut le faire avant de prospecter car // ces éléments inactifs ne vont pas être pris en compte car tesN_encontact(num_mail_noe_esclave)(inesc) = 0 - // mais ils pourraient redevenir actifs, dans ce cas on aurait un noeud avec deux contacts + // mais ils pourraient redevenir actifs, dans ce cas on aurait un noeud avec deux contacts + // dans le cas //, on considère que les contacts déjà calculés sont a considérer avec le cpu en cours + // car les tests d'appartenance on déjà été effectué au moment de la création { // ++ encapsulage LaLIST ::iterator iE ; // on met .end(), car cette borne peut changer au gré des suppression @@ -972,44 +1091,35 @@ bool LesContacts::Nouveau(double dep_max) { LaLIST ::iterator iiE = iE; if ((*iE).Contact()) { // on valide si le contact est ok -// int num_mail = (*iE).Esclave()->Num_Mail(); -// int num_noeud = (*iE).Esclave()->Num_noeud(); -// tesN_encontact(num_mail)(num_noeud) += 1; // mise à jour de l'indicateur (*iE).Met_actif(); if (niveau_commentaire_lescontacts > 3) - { Element & elem = *(*iiE).Elfront()->PtEI(); - int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\nreactivation (dans newcontact) contact: "; + { cout << "\nreactivation (dans newcontact) contact: "; (*iiE).Affiche(1); cout << endl; }; } else { // sinon on supprime car il n'y a pas de contact iE--; // pointe sur le precedent element - int num_mail_esclave = (*iiE).Esclave()->Num_Mail(); - int num_noeud = (*iiE).Esclave()->Num_noeud(); + Noeud* noe_esclave = (*iiE).Esclave(); + int num_mail_esclave = noe_esclave->Num_Mail(); + int num_noeud = noe_esclave->Num_noeud(); if (niveau_commentaire_lescontacts > 3) - { Element & elem = *(*iiE).Elfront()->PtEI(); - int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\neffacement contact (dans newcontact): "; + { cout << "\neffacement contact (dans newcontact): "; (*iiE).Affiche(1);cout << endl; }; listContact_efface_tatdt.push_front(*iiE); // mémorise #ifdef MISE_AU_POINT - if (tesN_encontact((*iiE).Esclave()->Num_Mail()).find((*iiE).Esclave()) - == tesN_encontact((*iiE).Esclave()->Num_Mail()).end() ) + if (tesN_encontact(num_mail_esclave).find(noe_esclave) + == tesN_encontact(num_mail_esclave).end() ) { cout << "\n*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave " - << (*iiE).Esclave()->Num_noeud() - << " du maillage " << (*iiE).Esclave()->Num_Mail() - << " la suite n'est pas possible " - << " LesContacts::Nouveau(.. \n"; + << num_noeud << " du maillage " << num_mail_esclave + << " la suite n'est pas possible " << " LesContacts::Nouveau(.. \n"; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; #endif LaLIST < LaLIST::iterator > & list_tesN - = tesN_encontact((*iiE).Esclave()->Num_Mail())[(*iiE).Esclave()]; -// tesN_encontact(num_mail_esclave)(num_noeud).remove(iiE); + = tesN_encontact(num_mail_esclave)[noe_esclave]; list_tesN.remove(iiE); listContact.erase(iiE); // efface l'element }; @@ -1062,15 +1172,19 @@ bool LesContacts::Nouveau(double dep_max) int nb_contact=0; if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end()) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; -// LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); nb_contact = list_tesN.size(); }; if (niveau_commentaire_lescontacts > 5) - { cout << "\n (re) examen eventuel : contact du noeud " << n_noee << " du maillage " << num_mail_noe_esclave; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " (re) examen eventuel : contact du noeud " << n_noee << " du maillage " << num_mail_noe_esclave; cout << " coord2= "; no->Coord2().Affiche_1(cout); if (niveau_commentaire_lescontacts > 5) {cout << " num_mail_dans_contact = " << num_mail_noe_esclave <<" inesc(num N local)= " << inesc -// << "\n tesN_encontact= " << tesN_encontact(num_mail_noe_esclave)(n_noee).size() << "\n tesN_encontact= " << nb_contact << " contacts enregistres"; }; @@ -1113,7 +1227,7 @@ bool LesContacts::Nouveau(double dep_max) // on parcours les elements maitres de la zone // si le noeud esclave est déjà en contact avec la frontière ce n'est pas la peine de tester {// donc on passe en revue les éléments en contact - + // si calcul // et élément déjà en contact c'est aussi vrai bool a_considerer = true; // init par défaut if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end()) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; @@ -1130,7 +1244,16 @@ bool LesContacts::Nouveau(double dep_max) break;} }; }; + #ifdef UTILISATION_MPI + // dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu + {Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere + // on ne continue que si l'élément est concerné + if (!(ParaGlob::param->Element_concerner(elem.Num_maillage(),elem.Num_elt_const()) )) + a_considerer=false; + }; + #endif // donc on ne continue que si la face n'est pas déjà en contact avec le noeud + // et dans le cas // que c'est ok if (a_considerer) {// on regarde si le noeud esclave est dans la boite d'encombrement de l'élément // qui contient l'élément frontière (car l'élément frontière à une épaisseur nulle!) @@ -1138,7 +1261,12 @@ bool LesContacts::Nouveau(double dep_max) Front& elfront = (*iM); if (niveau_commentaire_lescontacts > 5) {// --- sortie d'info pour vérifier l'appartenance à la boite ou non - cout << "\n rappel: coordonnee noeud esclave : " ; no->Coord2().Affiche_1(cout); + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " rappel: coordonnee noeud esclave : " ; no->Coord2().Affiche_1(cout); cout << "\n boite d'encombrement de l'element maitre qui contient la frontiere:\n mini -> "; elem.RecupBoite_encombre_element().Premier().Affiche(); cout << " maxi -> "; @@ -1156,7 +1284,13 @@ bool LesContacts::Nouveau(double dep_max) }; if (niveau_commentaire_lescontacts > 5) - { cout << "\n frontiere: " << elfront.Num_frontiere() << " (nb loc: "<Type_geom_front()) << " de l'element " << elem.Geometrie() << " : " << elfront.PtEI()->Num_elt() @@ -1170,9 +1304,9 @@ bool LesContacts::Nouveau(double dep_max) // à un élément que l'on vient juste d'effacer, si oui, on ne crée pas d'élément et // on attend un prochain incrément, si effectivement l'élément doit se créer, il sera alors créé // *** non, ça pose pb, on commente pour l'instant - {LaLIST ::iterator ila,ilafin=listContact_efface_tatdt.end(); + {//LaLIST ::iterator ila,ilafin=listContact_efface_tatdt.end(); bool vraiment_nouveau_element=true; // par défaut -// for (ila = listContact_efface_tatdt.begin();ila != ilafin;ila++) +/* // for (ila = listContact_efface_tatdt.begin();ila != ilafin;ila++) // { if (((*ila).Esclave()->Num_noeud() == n_noee) // && ((*((*ila).Elfront()->Eleme())) == (*((*iM).Eleme()))) // && ((*ila).Esclave()->Num_Mail() == num_mail_noe_esclave)) @@ -1183,7 +1317,7 @@ bool LesContacts::Nouveau(double dep_max) // }; // break;}; // }; - +*/ if (niveau_commentaire_lescontacts > 5) {//cout << "\n 2debug LesContacts::Nouveau( " ; LaLIST ::iterator ila,ilafin=listContact_efface_tatdt.end(); @@ -1215,7 +1349,13 @@ bool LesContacts::Nouveau(double dep_max) if (con.Elfront()->MemeOrigine(elfront)) {creation = false; if (con.Permet_affichage() > 5) - { cout << "\n frontiere en contact deja existante , on arrete la creation "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " frontiere en contact deja existante , on arrete la creation "; elfront.Affiche(1); }; } @@ -1231,10 +1371,15 @@ bool LesContacts::Nouveau(double dep_max) if ((niveau_commentaire_lescontacts > 5) || (elcont.Permet_affichage() > 5)) { Front* elfront = elcont.Elfront(); - cout << "\n examen plus precis: frontiere: " << elfront->Num_frontiere() - << ", type: " << Nom_type_geom(elfront->Eleme_const()->Type_geom_front()) - << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage " - << elfront->PtEI()->Num_maillage() ; + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " examen plus precis: frontiere: " << elfront->Num_frontiere() + << ", type: " << Nom_type_geom(elfront->Eleme_const()->Type_geom_front()) + << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage " + << elfront->PtEI()->Num_maillage() ; if (niveau_commentaire_lescontacts > 7) elcont.Affiche(); }; @@ -1258,8 +1403,13 @@ bool LesContacts::Nouveau(double dep_max) retour=true; // on valide le retour if ((niveau_commentaire_lescontacts > 3) || (elcont.Permet_affichage() > 3)) - { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\n newcontact: " ; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << "\n newcontact: " ; if (tesN_col(inesc)) cout << " collant "; elcont.Affiche(1); }; @@ -1311,22 +1461,38 @@ bool LesContacts::Nouveau(double dep_max) }// -- fin de la boucle sur les zones for (int j=1;j<= nb_zone;j++) };// -- boucle sur intot if (niveau_commentaire_lescontacts > 3) - { cout << "\nbilan: "<< listContact.size() << " elem contact "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " bilan: "<< listContact.size() << " elem contact "; if ( listContact_nouveau_tatdt.size()) cout <<", "<< (listContact_nouveau_tatdt.size()-taille_list_contact_nouveau_au_debut) << " nouveau(x) "; if (listContact_efface_tatdt.size()) cout <<", "< 4) // on va lister les éléments de contact - { cout << "\n liste des Elcontact a la fin de LesContacts::Nouveau: (fct du niveau de commentaire des elcontact): "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " liste des Elcontact a la fin de LesContacts::Nouveau: (fct du niveau de commentaire des elcontact): "; LaLIST::iterator ipp,ippfin=listContact.end(); for (ipp=listContact.begin();ipp != ippfin; ipp++) {(*ipp).Affiche(2);}; }; - tempsContact.Arret_du_comptage(); // fin cpu //cout << "\n tempsContact.Temps_CPU_User = " << tempsContact.Temps_CPU_User() << flush; @@ -1340,8 +1506,18 @@ bool LesContacts::SuppressionDefinitiveElemInactif() { tempsContact.Mise_en_route_du_comptage(); // def deb compt int niveau_commentaire_lescontacts = Permet_affichage(); +#ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); +#endif if (niveau_commentaire_lescontacts > 4) - cout << "\n -- LesContacts::SuppressionDefinitiveElemInactif: "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " -- LesContacts::SuppressionDefinitiveElemInactif: "; + }; bool change = false; int nb_effacement=0; // return change; @@ -1411,7 +1587,14 @@ bool LesContacts::SuppressionDefinitiveElemInactif() // info if (niveau_commentaire_lescontacts > 2) { if (nb_effacement) - cout << "\n sup: "<< nb_effacement << " effacement(s) definitif(s) de contact "; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " sup: "<< nb_effacement << " effacement(s) definitif(s) de contact "; + }; }; if ((niveau_commentaire_lescontacts > 6) && (nb_effacement==0)) cout << " aucun effacement "; @@ -1427,8 +1610,16 @@ bool LesContacts::RelachementNoeudcolle() { tempsContact.Mise_en_route_du_comptage(); // def deb compt int niveau_commentaire_lescontacts = Permet_affichage(); + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + #endif if (niveau_commentaire_lescontacts > 4) - cout << "\n -- LesContacts::RelachementNoeudcolle(): "; + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << " -- LesContacts::RelachementNoeudcolle(): "; bool change = false; // return change; //------- pour le débug LaLIST ::iterator iE ; @@ -1445,19 +1636,20 @@ bool LesContacts::RelachementNoeudcolle() //S'il y a décolement on ne doit plus tenir compte du contact et donc on inactive l'élément de contact { LaLIST ::iterator iiE = iE; // list ::iterator iiden = iden; - int num_mail_esclave = (*iiE).Esclave()->Num_Mail(); - int num_noeud = (*iiE).Esclave()->Num_noeud(); if (niveau_commentaire_lescontacts > 2) - { Element & elem = *(*iiE).Elfront()->PtEI(); - int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\ninactivation (relachement) pour cause de decollement du contact"; + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << "inactivation (relachement) pour cause de decollement du contact"; (*iiE).Affiche(1); cout << endl; ////------ debug //{cout << "\n debug: LesContacts::RelachementNoeudcolle() "; // (*iE).Decol(); //} //// ------- fin debug - }; change = true; (*iE).Met_Inactif(); @@ -1473,45 +1665,99 @@ bool LesContacts::RelachementNoeudcolle() // definition des conditions lineaires de contact // casAssemb : donne le cas d'assemblage a prendre en compte // et marquage des ddl imposé par le contact -const Tableau & LesContacts::ConditionLin(const Nb_assemb& casAssemb) +// Dans le cas d'un calcul parallèle, il y a transfert des conditions au cpu 0 +// seules les cpu i calculent les conditions linéaires +// NB: on ne met pas la liste en const car on a besoin de pouvoir modifier les infos à l'intérieur +// des CL pour les utiliser, mais l'idée est la liste elle, reste constante +list & LesContacts::ConditionLin(const Nb_assemb& casAssemb) { tempsContact.Mise_en_route_du_comptage(); // def deb compt + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + if (proc_en_cours != 0) + { + #endif // on crée des conditions linéaires dans le cas du type 1: contact cinématique // mais aussi dans les autres cas pour l'optimisation de largeur de bande par exemple -// if (ParaGlob::param->ParaAlgoControleActifs().ContactType() == 1) -// definition du tableau -// int tail = listContact.size();//(int) listContact.size(); -// tabCoLin.Change_taille(tail); {Calcul_Nb_contact_actif(); - tabCoLin.Change_taille(nb_contact_actif); + listCoLin.clear();// Change_taille(nb_contact_actif); //cout << "\n nb actif pour condlin = " << nb_contact_actif; // on boucle sur les elements de contact - int i=1; LaLIST ::iterator iE,iEfin=listContact.end() ; for (iE = listContact.begin(); iE != iEfin; iE++) if ((*iE).Actif()) // on n'intervient que si le contact est actif // appel de la fonction de construction de condition lineaire dans l'element de contact - {tabCoLin(i) = (*iE).ConditionLi(casAssemb.n);i++; -//cout << " i="<::iterator il,ilfin = listCoLin.end(); + for (il = listCoLin.begin();il != ilfin;il++) + taille_conteneur += (*il).Taille_Pack(); + inter_transfer.Change_taille(taille_conteneur); // le conteneur + // on rempli le conteneur + int rang = 1; // init + for (il = listCoLin.begin();il != ilfin;il++) + rang = (*il).Pack_vecteur(inter_transfer,rang); + temps_attente.Arret_du_comptage(); + // on transfert + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 40, taille_conteneur); - tempsContact.Arret_du_comptage(); // fin cpu + mpi::request reqs2 = inter_transfer.Ienvoi_MPI(0,41); + // on attend pas + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les conditions linéaires + tempsContact.Arret_du_comptage(); // fin cpu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + int nb_proc_terminer = 0; // permettra de terminer + listCoLin.clear();// Change_taille(nb_contact_actif); + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de cpu i + + int taille_transfert; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 40, taille_transfert); + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + inter_transfer.Change_taille(taille_transfert); // le conteneur + int source = stat.source(); // récupération du numéro de la source + // on récupère + mpi::request reqs2 = inter_transfer.Irecup_MPI(source, 41); + reqs2.wait(); // on attend que le conteneur soit rempli + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + // on va remplir la liste des conditions limites + int rang = 1; // init + while (rang != 0) + { Condilineaire condi; // une condition intermédiaire + rang = condi.UnPack_vecteur(*lesMaille,inter_transfer,rang, + &LesMaillages::Noeud_LesMaille); + listCoLin.push_back(condi); + }; + }; + temps_transfert_long.Arret_du_comptage(); + }; + #endif + +// tempsContact.Arret_du_comptage(); // fin cpu // retour du tableau - return tabCoLin; + return listCoLin; }; // effacement du marquage de ddl bloque du au conditions lineaire de contact void LesContacts::EffMarque() { tempsContact.Mise_en_route_du_comptage(); // def deb compt - // on parcours le tableau des conditions lineaires - int tailletabcolin = tabCoLin.Taille(); - for (int i=1;i<=tailletabcolin;i++) + // on parcours la liste des conditions lineaires + list ::iterator il,ilfin = listCoLin.end(); + for (il = listCoLin.begin();il != ilfin;il++) { // on libere la condition - Condilineaire& C = tabCoLin(i); + Condilineaire& C = (*il); C.Noe()->Change_fixe(C.Tab_Enum()(1),false); }; tempsContact.Arret_du_comptage(); // fin cpu @@ -1522,7 +1768,6 @@ void LesContacts::EffMarque() // retourne true si les déplacements des maîtres sont imposés bool LesContacts::Maitres_avec_deplacement_imposer() const { bool retour = true; // init par défaut -// int nb_maitre = t_listFront.Taille(); // le nombre de maîtres int dim = ParaGlob::Dimension(); int nb_zone = MaX(1,nom_ref_zone_contact.size()); // seule sont disponibles les zones de contact (restreintes éventuellement) @@ -1561,59 +1806,101 @@ bool LesContacts::Maitres_avec_deplacement_imposer() const // = true : si la largeur de bande en noeud est supérieure à 1 (cas d'un contact avec une surface déformable) // = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur // en noeud (cas d'un contact avec une surface rigide) +// dans le cas d'un calcul // seule le cpu 0 effectue la résolution, par contre tous les cpu i contribuent +// ils vont donc transmettre les informations au cpu 0 bool LesContacts::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb,int& cumule) { tempsContact.Mise_en_route_du_comptage(); // def deb compt + bool retour = false; // par défaut on se met dans le cas le plus simple : contact avec surface rigide // dans le cas d'un contact avec surface déformable, le contact modifie la largeur de bande demi = 0; - total = 0; // c'est le plus important, car la bande sup réelle est en général différente - // de la bande inf, mais ce qui sera utilisé pour le dimensionnement de la bande de la matrice - // c'est le total: inf + sup + 1 (le 1 est pour la diagonale, il ne sert à rien) - cumule = 0; - bool retour = false; // par défaut on se met dans le cas le plus simple : contact avec surface rigide - LaLIST ::iterator iE,iEfin=listContact.end(); - int nb_Assemb = casAssemb.n; // récup du numéro d'assemblage -//------ debug -// cout << "\n LesContacts::Largeur_Bande "; -// ------ fin debug - // on boucle sur les elements de contact - for ( iE = listContact.begin(); iE !=iEfin; iE++) - { -//------ debug -// (*iE).Affiche(); -// ------ fin debug - - // on n'intervient que si le contact est actif et que ce n'est pas un contact solide déformable - if (((*iE).Actif()) && ((*iE).Cas_solide() == 0)) - { //on boucle sur les noeuds de l'element de contact - const Tableau & tabnoeud = (*iE).TabNoeud(); - int maxiPourLeContact=0; // stocke le maxi pour chaque condition linéaire - retour = true; // ici la largeur de bande en noeud est augmenté, car le noeud en contact - // est en relation avec des noeuds d'une surface déformable - - for (int noe=1; noe<= tabnoeud.Taille();noe++) - for ( int no=noe+1; no<=tabnoeud.Taille();no++) - { Noeud & nne = *tabnoeud(noe); - Noeud & nno = *tabnoeud(no); - int di; - if (nne.PosiAssemb(nb_Assemb) >= nno.PosiAssemb(nb_Assemb)) - di = nne.PosiAssemb(nb_Assemb) - nno.PosiAssemb(nb_Assemb) - + nne.NB_ddl_actif_casAssemb(nb_Assemb); - else - di = nno.PosiAssemb(nb_Assemb) - nne.PosiAssemb(nb_Assemb) - + nno.NB_ddl_actif_casAssemb(nb_Assemb); - if ( di > demi) demi = di; - if ( di > maxiPourLeContact) maxiPourLeContact = di; - if ( 2*di > total) total = 2*di; - }; - cumule += maxiPourLeContact; - }; - }; - total += 1; - demi += 1; - - tempsContact.Arret_du_comptage(); // fin cpu - // retour de l'indicateur + total = 0; // c'est le plus important, car la bande sup réelle est en général différente + // de la bande inf, mais ce qui sera utilisé pour le dimensionnement de la bande de la matrice + // c'est le total: inf + sup + 1 (le 1 est pour la diagonale, il ne sert à rien) + cumule = 0; + + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + if (proc_en_cours != 0) + { + #endif + // encapsulage de la partie hors calcul parallèle + { + LaLIST ::iterator iE,iEfin=listContact.end(); + int nb_Assemb = casAssemb.n; // récup du numéro d'assemblage + //------ debug + // cout << "\n LesContacts::Largeur_Bande "; + // ------ fin debug + // on boucle sur les elements de contact + for ( iE = listContact.begin(); iE !=iEfin; iE++) + { + //------ debug + // (*iE).Affiche(); + // ------ fin debug + + // on n'intervient que si le contact est actif et que ce n'est pas un contact solide déformable + if (((*iE).Actif()) && ((*iE).Cas_solide() == 0)) + { //on boucle sur les noeuds de l'element de contact + const Tableau & tabnoeud = (*iE).TabNoeud(); + int maxiPourLeContact=0; // stocke le maxi pour chaque condition linéaire + retour = true; // ici la largeur de bande en noeud est augmenté, car le noeud en contact + // est en relation avec des noeuds d'une surface déformable + + for (int noe=1; noe<= tabnoeud.Taille();noe++) + for ( int no=noe+1; no<=tabnoeud.Taille();no++) + { Noeud & nne = *tabnoeud(noe); + Noeud & nno = *tabnoeud(no); + int di; + if (nne.PosiAssemb(nb_Assemb) >= nno.PosiAssemb(nb_Assemb)) + di = nne.PosiAssemb(nb_Assemb) - nno.PosiAssemb(nb_Assemb) + + nne.NB_ddl_actif_casAssemb(nb_Assemb); + else + di = nno.PosiAssemb(nb_Assemb) - nne.PosiAssemb(nb_Assemb) + + nno.NB_ddl_actif_casAssemb(nb_Assemb); + if ( di > demi) demi = di; + if ( di > maxiPourLeContact) maxiPourLeContact = di; + if ( 2*di > total) total = 2*di; + }; + cumule += maxiPourLeContact; + }; + }; + total += 1; + demi += 1; + tempsContact.Arret_du_comptage(); // fin cpu + } + #ifdef UTILISATION_MPI + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + // maintenant on va transmettre au cpu 0 + // pour cela on va utiliser un conteneur intermédiaire + QuatreEntiers inter_entiers(demi,total,cumule,retour); + // on transmet les infos au proc 0 + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 44, inter_entiers); + // on attend pas + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + } +else // cas du cpu 0 + {// l'objectif ici est de récupérer les infos + tempsContact.Arret_du_comptage(); // fin cpu + int nb_proc_terminer = 0; // permettra de terminer + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de cpu i + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + QuatreEntiers inter_entiers; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 44, inter_entiers); + reqs1.wait(); // on attend que le conteneur soit rempli + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + tempsContact.Mise_en_route_du_comptage(); // def deb compt + if (inter_entiers.un > demi) demi = inter_entiers.un; + if (inter_entiers.deux > total) total = inter_entiers.deux; + cumule += inter_entiers.trois; + retour = (retour || ((bool)inter_entiers.quatre)); + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + tempsContact.Arret_du_comptage(); + }; + }; +#endif + +// retour de l'indicateur return retour; }; @@ -1628,178 +1915,242 @@ bool LesContacts::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb, // si l'intersection n'est pas calculable, // NB: pour les deux choix, s'il y a doublon d'élément de contact, due à un changement de frontière // en cours d'actualisation, on inactive le(s) doublon(s) +// dans le cas d'un calcul // chaque proc i effectue son actualisation, s'il y a changement de surface avec sortie +// de la surface gérée par le proc i, cela sera vérifié au niveau de l'élément de contact +// Le proc 0 se contente de récupérer et globaliser les retours des proc i + bool LesContacts::Actualisation(int choix) { tempsContact.Mise_en_route_du_comptage(); // def deb compt bool retour = false; // init par défaut - // on boucle sur les elements de contact - int i; - LaLIST ::iterator iE,iEfin=listContact.end(); - - int niveau_commentaire_lescontacts = Permet_affichage(); + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + if (proc_en_cours != 0) + { + #endif + { + // on boucle sur les elements de contact + int i; + LaLIST ::iterator iE,iEfin=listContact.end(); + + int niveau_commentaire_lescontacts = Permet_affichage(); - if (niveau_commentaire_lescontacts > 4) - cout << "\n -- LesContacts::Actualisation: choix: "<< choix; - if (niveau_commentaire_lescontacts > 4) - // on va lister les éléments de contact - { cout << "\n liste des Elcontact avant actualisation (fct du niveau de commentaire des elcontact): "; - LaLIST::iterator ipp,ippfin=listContact.end(); - for (ipp=listContact.begin();ipp != ippfin; ipp++) - {(*ipp).Affiche(2);}; - }; + if (niveau_commentaire_lescontacts > 4) + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours << ": -- LesContacts::Actualisation: choix: "<< choix; + #else + cout << "\n -- LesContacts::Actualisation: choix: "<< choix; + #endif + if (niveau_commentaire_lescontacts > 4) + // on va lister les éléments de contact + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + << ": liste des Elcontact avant actualisation (fct du niveau de commentaire des elcontact): "; + #else + cout << "\n liste des Elcontact avant actualisation (fct du niveau de commentaire des elcontact): "; + #endif + + LaLIST::iterator ipp,ippfin=listContact.end(); + for (ipp=listContact.begin();ipp != ippfin; ipp++) + {(*ipp).Affiche(2);}; + }; - for (i=1, iE = listContact.begin(); iE !=iEfin; iE++,i++)//,iden++) - // appel de la fonction d'actualisation de chaque element de contact - if ((*iE).Actif()) // on intervient si le contact est déclaré actif - // on intervient également si c'est collant, car il faut quand même actualiser - // le contact, - { int test=0; // init - { - // Si le retour est négatif et que l'élément est actif, cela signifie que l'on ne peut pas calculer le contact - // là on on se contente d'inactiver l'élément - // si le retour == 0: on peut calculer mais on sort de l'élément et même des mitoyens - // là aussi on se contente d'inactiver l'élément - // durant l'actualisation, on peut changer d'élément frontière, du coup l'élément de contact résultant - // peut être égale à un élément déjà existant, et cela va faire double emploi - // dans ce cas précis on ne va pas valider l'actualisation, mais on se contente d'inactiver l'élément - - // actualisation de la projection du noeud esclave en fonction de la position de l'element - // maitre frontiere. Lorsque le noeud change d'element fontiere, on change l'element - // frontiere de l'element de contact en consequence - // retourne: - // 0 : dans le cas ou on ne trouve pas d'intersection, cas d'une intersection qui n'est pas calculable - // 1 : contact ok, sur l'élément - // -1 : contact ok, mais hors de l'élément (là, on a parcouru tous les mitoyens et aucun ne convient - // du coup on utilise l'élément initial pour la projection - // 2 : changement de frontière, et contact ok sur la nouvelle frontière - // NB: sauf pour le cas 0, dans tous les autres cas, les grandeurs locales sont correctement calculées - // c-a-d : la projection, la normale - // en fonction de la méthode de contact, le noeud est ramené éventuellement sur la frontière - - - - test = (*iE).Actualisation(); - ElContact* test_existance=NULL; - if (test == 2) - {// on a changé de frontière, on regarde si l'élément de contact avec la nouvelle frontière n'est pas - //identique à un élément existant - test_existance= Element_contact_deja_present(iE); - }; - if ( ((test < 0) && (choix == 0) && !((*iE).Collant())) // si c'est collant, on maintient le contact arbitrairement sauf si on - // est arrivé sur un élément existant - || (test == 0) // ou que l'on ne peut pas calculer une intersection ... ce qui fait que le - // calcul des second membre et raideur ne sera pas possible - ) - // on inactive l'element de contact - { LaLIST ::iterator iiE = iE; - int num_mail_esclave = (*iiE).Esclave()->Num_Mail(); - int num_noeud = (*iiE).Esclave()->Num_noeud(); - if (niveau_commentaire_lescontacts >= 3) - { Element & elem = *(*iiE).Elfront()->PtEI(); - int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\ninactivation contact (les_contacts) pour cause de perte de contact:"; - #ifdef MISE_AU_POINT - if (niveau_commentaire_lescontacts > 4) - cout << " test= "<Actif()) - { LaLIST ::iterator iiE = iE; - int num_mail_esclave = (*iiE).Esclave()->Num_Mail(); - int num_noeud = (*iiE).Esclave()->Num_noeud(); - if (niveau_commentaire_lescontacts >= 3) - { Element & elem = *(*iiE).Elfront()->PtEI(); - int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\ninactivation contact apres chgt de frontiere (les_contacts) pour cause de duplication:"; - (*iiE).Affiche(1); - }; - (*iiE).Met_Inactif(); // inactive l'élément - retour = true; // on signale le changement - }; - } - - else // arrivée ici cela veut dire que test > 0 ou que c'est collant et test n'est pas négatif - // ou alors que test < 0 mais on a choix == 1, c-a-d que l'on veut maintenir le contact même en dehors de l'élément actuel - // (c'est par exemple une situation transitoire pendant les itérations en implicite) - { if (niveau_commentaire_lescontacts >= 7) - { Element & elem = *(*iE).Elfront()->PtEI(); - int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\n contact maintenu: ";(*iE).Affiche(1); - - }; - }; - // si on a inactivé l'élément, on regarde s'il n'y a pas un autre contact, utilisant le même noeud - // que l'on pourrait activer - if (!(*iE).Actif()) - {Noeud* noe = (*iE).Esclave(); - int num_mail_noe_esclave = noe->Num_Mail(); - std::map::iterator > >& tesN_encontact_ii - = tesN_encontact(num_mail_noe_esclave); // pour simplifier - // la liste doit exister ! car au moins (*iE) y appartient -// Tableau < std::map::iterator > > > tesN_encontact; - // tesN_encontact(numMail_esclave)[*pt_noeud] -> la liste des iterators d'élément en contact - // avec le noeud - // on regarde si la liste existe, si oui on peut tester les membres sinon, on ne fait rien - // car autrement on crée automatiquement une liste avec un élément vide - std::map::iterator > >::iterator it_liste; - if (tesN_encontact_ii.find(noe) != tesN_encontact_ii.end()) - {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[noe]; - LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); - int nb_contact = list_tesN.size(); - for (pl = list_tesN.begin();pl != plfin;pl++) - {ElContact& elc = (*(*pl)); - // là on va faire une actualisation simplifiée: le cas collant n'est pas à prendre en compte - // car on n'arrive jamais ici en collant - bool actif_transitoire = true; - elc.Met_actif(); // on doit activer l'élément pour utiliser Actualisation - // cela veut dire que systématiquement on calcule comme si le noeud esclave se déplace en contact - // (ce n'est pas une initialisation ) - test = elc.Actualisation(); - test_existance = NULL ; // init - if (test == 2) - {// on a changé de frontière, on regarde si l'élément de contact avec la nouvelle frontière n'est pas - //identique à un élément existant - test_existance= Element_contact_deja_present(iE); - }; - if ((test_existance == NULL) && (test > 0)) - // arrivée ici cela veut dire que le contact est valide - // on conserve l'élément actif - { actif_transitoire=false; // active l'élément - if (niveau_commentaire_lescontacts > 2) - { Element & elem = *(*iE).Elfront()->PtEI(); - int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); - cout << "\nreactivation contact :";elc.Affiche(1); - - }; - } - else // sinon on inactive l'élément ; - elc.Met_Inactif(); + for (i=1, iE = listContact.begin(); iE !=iEfin; iE++,i++)//,iden++) + // appel de la fonction d'actualisation de chaque element de contact + if ((*iE).Actif()) // on intervient si le contact est déclaré actif + // on intervient également si c'est collant, car il faut quand même actualiser + // le contact, + { int test=0; // init + { +/* // Si le retour est négatif et que l'élément est actif, cela signifie que l'on ne peut pas calculer le contact + // là on on se contente d'inactiver l'élément + // si le retour == 0: on peut calculer mais on sort de l'élément et même des mitoyens + // là aussi on se contente d'inactiver l'élément + // durant l'actualisation, on peut changer d'élément frontière, du coup l'élément de contact résultant + // peut être égale à un élément déjà existant, et cela va faire double emploi + // dans ce cas précis on ne va pas valider l'actualisation, mais on se contente d'inactiver l'élément + + // actualisation de la projection du noeud esclave en fonction de la position de l'element + // maitre frontiere. Lorsque le noeud change d'element fontiere, on change l'element + // frontiere de l'element de contact en consequence + // retourne: + // 0 : dans le cas ou on ne trouve pas d'intersection, cas d'une intersection qui n'est pas calculable + // 1 : contact ok, sur l'élément + // -1 : contact ok, mais hors de l'élément (là, on a parcouru tous les mitoyens et aucun ne convient + // du coup on utilise l'élément initial pour la projection + // 2 : changement de frontière, et contact ok sur la nouvelle frontière + // NB: sauf pour le cas 0, dans tous les autres cas, les grandeurs locales sont correctement calculées + // c-a-d : la projection, la normale + // en fonction de la méthode de contact, le noeud est ramené éventuellement sur la frontière +*/ + + test = (*iE).Actualisation(); + ElContact* test_existance=NULL; + if (test == 2) + {// on a changé de frontière, on regarde si l'élément de contact avec la nouvelle frontière n'est pas + //identique à un élément existant + test_existance= Element_contact_deja_present(iE); }; - }; + if ( ((test < 0) && (choix == 0) && !((*iE).Collant())) // si c'est collant, on maintient le contact arbitrairement sauf si on + // est arrivé sur un élément existant + || (test == 0) // ou que l'on ne peut pas calculer une intersection ... ce qui fait que le + // calcul des second membre et raideur ne sera pas possible + ) + // on inactive l'element de contact + { LaLIST ::iterator iiE = iE; + if (niveau_commentaire_lescontacts >= 3) + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours<<": " + #else + cout << "\n" + #endif + << " inactivation contact (les_contacts) pour cause de perte de contact:"; + #ifdef MISE_AU_POINT + if (niveau_commentaire_lescontacts > 4) + cout << " test= "<Actif()) + { LaLIST ::iterator iiE = iE; + if (niveau_commentaire_lescontacts >= 3) + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours<<": " + #else + cout << "\n" + #endif + << "inactivation contact apres chgt de frontiere (les_contacts) pour cause de duplication:"; + (*iiE).Affiche(1); + }; + (*iiE).Met_Inactif(); // inactive l'élément + retour = true; // on signale le changement + }; + } + + else // arrivée ici cela veut dire que test > 0 ou que c'est collant et test n'est pas négatif + // ou alors que test < 0 mais on a choix == 1, c-a-d que l'on veut maintenir le contact même en dehors de l'élément actuel + // (c'est par exemple une situation transitoire pendant les itérations en implicite) + { if (niveau_commentaire_lescontacts >= 7) + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours<<": " + #else + cout << "\n" + #endif + << " contact maintenu: ";(*iE).Affiche(1); + }; + // si on a inactivé l'élément, on regarde s'il n'y a pas un autre contact, utilisant le même noeud + // que l'on pourrait activer + if (!(*iE).Actif()) + {Noeud* noe = (*iE).Esclave(); + int num_mail_noe_esclave = noe->Num_Mail(); + std::map::iterator > >& tesN_encontact_ii + = tesN_encontact(num_mail_noe_esclave); // pour simplifier + // la liste doit exister ! car au moins (*iE) y appartient + // Tableau < std::map::iterator > > > tesN_encontact; + // tesN_encontact(numMail_esclave)[*pt_noeud] -> la liste des iterators d'élément en contact + // avec le noeud + // on regarde si la liste existe, si oui on peut tester les membres sinon, on ne fait rien + // car autrement on crée automatiquement une liste avec un élément vide + std::map::iterator > >::iterator it_liste; + if (tesN_encontact_ii.find(noe) != tesN_encontact_ii.end()) + {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[noe]; + LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); + for (pl = list_tesN.begin();pl != plfin;pl++) + {ElContact& elc = (*(*pl)); + // là on va faire une actualisation simplifiée: le cas collant n'est pas à prendre en compte + // car on n'arrive jamais ici en collant + bool actif_transitoire = true; + elc.Met_actif(); // on doit activer l'élément pour utiliser Actualisation + // cela veut dire que systématiquement on calcule comme si le noeud esclave se déplace en contact + // (ce n'est pas une initialisation ) + test = elc.Actualisation(); + test_existance = NULL ; // init + if (test == 2) + {// on a changé de frontière, on regarde si l'élément de contact avec la nouvelle frontière n'est pas + //identique à un élément existant + test_existance= Element_contact_deja_present(iE); + }; + if ((test_existance == NULL) && (test > 0)) + // arrivée ici cela veut dire que le contact est valide + // on conserve l'élément actif + { actif_transitoire=false; // active l'élément + if (niveau_commentaire_lescontacts > 2) + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours<<": " + #else + cout << "\n" + #endif + << "reactivation contact :";elc.Affiche(1); + } + else // sinon on inactive l'élément ; + elc.Met_Inactif(); + }; + }; + + } + }; + } + // else + // {nb_contact_actif++; }; // on sauvegarde l'activité + if (niveau_commentaire_lescontacts > 4) + // on va lister les éléments de contact + { + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours<<": " + #else + cout << "\n" + #endif + << " liste des Elcontact apres actualisation (fct du niveau de commentaire des elcontact): "; + LaLIST::iterator ipp,ippfin=listContact.end(); + for (ipp=listContact.begin();ipp != ippfin; ipp++) + {(*ipp).Affiche(2);}; + // on calcule et affiche le nombre de contact actif + Calcul_Nb_contact_actif(); + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours<<": " + #else + cout << "\n" + #endif + << " nb_contact_actif= " << nb_contact_actif << endl; + }; + + } + #ifdef UTILISATION_MPI + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + // maintenant on va transmettre au cpu 0 + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 45, retour); + // on attend pas + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les infos + tempsContact.Arret_du_comptage(); // fin cpu + int nb_proc_terminer = 0; // permettra de terminer + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de cpu i + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + bool inter_retour; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 45, inter_retour); + reqs1.wait(); // on attend que le conteneur soit rempli + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + tempsContact.Mise_en_route_du_comptage(); // def deb compt + retour = (retour || (inter_retour)); + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + tempsContact.Arret_du_comptage(); + }; + }; + #endif - } - }; - } -// else -// {nb_contact_actif++; }; // on sauvegarde l'activité - if (niveau_commentaire_lescontacts > 4) - // on va lister les éléments de contact - { cout << "\n liste des Elcontact apres actualisation (fct du niveau de commentaire des elcontact): "; - LaLIST::iterator ipp,ippfin=listContact.end(); - for (ipp=listContact.begin();ipp != ippfin; ipp++) - {(*ipp).Affiche(2);}; - // on calcule et affiche le nombre de contact actif - Calcul_Nb_contact_actif(); - cout << "\n nb_contact_actif= " << nb_contact_actif << endl; - }; // retour tempsContact.Arret_du_comptage(); // fin cpu return retour; @@ -1808,28 +2159,104 @@ bool LesContacts::Actualisation(int choix) // ramène une liste de noeuds dont la position a été perturbé par le contact // (dépend du type de contact : ex cas contact = 4) // la liste passée en paramètre est supprimée et remplacée par la liste résultat +// dans le cas d'un calcul // chaque proc i calcule une liste et la transmet au proc 0 +// Le proc 0 globalise toutes les liste void LesContacts::Liste_noeuds_position_changer(list & li_noe) { tempsContact.Mise_en_route_du_comptage(); // def deb compt // récup du type de contact int contact_type = ElContact::Recup_et_mise_a_jour_type_contact(); li_noe.clear(); // on vide la liste - - if (contact_type== 4) // pour l'instant c'est le seul type de contact qui est concerné - { // on boucle sur les elements de contact - int i; - LaLIST ::iterator iE,iEfin=listContact.end(); - - int niveau_commentaire_lescontacts = Permet_affichage(); - if (niveau_commentaire_lescontacts >= 7) - cout << "\n -- LesContacts::Liste_noeuds_position_changer: "; + int niveau_commentaire_lescontacts = Permet_affichage(); + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + if (proc_en_cours != 0) + { + #endif + { + if (contact_type== 4) // pour l'instant c'est le seul type de contact qui est concerné + { // on boucle sur les elements de contact + int i; + LaLIST ::iterator iE,iEfin=listContact.end(); + + #ifndef UTILISATION_MPI + if (niveau_commentaire_lescontacts >= 7) + cout << "\n -- LesContacts::Liste_noeuds_position_changer: "; + #endif + + for (i=1, iE = listContact.begin(); iE !=iEfin; iE++,i++)//,iden++) + if ((*iE).Actif()) // on intervient si le contact est déclaré actif + {// récup du noeud esclave + Noeud* noe = (*iE).Esclave(); + li_noe.push_back(noe); + }; + }; + } + #ifdef UTILISATION_MPI + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + // maintenant on va transmettre au cpu 0 + int taille_list = li_noe.size(); + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 46, taille_list); + // on attend pas + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + // maintenant on va transmettre au cpu 0 + // on va se servir d'un conteneur intermédiaire + union double_int + { double x; + int n[2]; + } ; + double_int xinter; + Vecteur v_inter(taille_list); + list ::iterator il,ilfin=li_noe.end(); + int i=1; + for (il = li_noe.begin();il !=ilfin;il++,i++) + {xinter.n[0] = (*il)->Num_Mail(); xinter.n[1] = (*il)->Num_noeud(); + v_inter(i)=xinter.x; + }; + // envoi + v_inter.Ienvoi_MPI(0,47); + // on attend pas + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les infos + tempsContact.Arret_du_comptage(); // fin cpu + union double_int + { double x; + int n[2]; + } ; + double_int xinter; + int nb_proc_terminer = 0; // permettra de terminer + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de cpu i + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + int taille_list ; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 46, taille_list ); + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + int source = stat.source(); // récupération du numéro de la source + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + Vecteur v_inter(taille_list); + mpi::request reqs2 = v_inter.Irecup_MPI(source, 47); + reqs2.wait(); // on attend que le conteneur soit rempli + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + tempsContact.Mise_en_route_du_comptage(); // def deb compt + // maintenant on abonde la liste + for (int i=1;i<= taille_list;i++) + {xinter.x = v_inter(i); + li_noe.push_back(&(lesMaille->Noeud_LesMaille(xinter.n[0],xinter.n[1]))); + }; + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + tempsContact.Arret_du_comptage(); + }; + #ifdef UTILISATION_MPI + if (niveau_commentaire_lescontacts >= 7) + cout << "\n proc 0: -- LesContacts::Liste_noeuds_position_changer: "; + #endif + + }; + #endif - for (i=1, iE = listContact.begin(); iE !=iEfin; iE++,i++)//,iden++) - if ((*iE).Actif()) // on intervient si le contact est déclaré actif - {// récup du noeud esclave - Noeud* noe = (*iE).Esclave(); - li_noe.push_back(noe); - }; - }; tempsContact.Arret_du_comptage(); // fin cpu }; @@ -1978,7 +2405,16 @@ void LesContacts::Affiche(ofstream& sort) const // affichage à l'écran des informations liées au contact void LesContacts::Affiche() const - { cout << "\n ---- affichage des informations liees au contact --------"; + { + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + #endif + #ifdef UTILISATION_MPI + cout << "\n proc " << proc_en_cours + #else + cout << "\n" + #endif + << "\n ---- affichage des informations liees au contact --------"; cout << "\n 1) liste des elements en contact"; LaLIST ::const_iterator il,ilfin=listContact.end(); for (il=listContact.begin();il != ilfin; il++) @@ -2018,7 +2454,14 @@ void LesContacts::Affiche() const // affichage et definition interactive des commandes void LesContacts::Info_commande_LesContacts(UtilLecture & entreePrinc) -{ ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier +{ + #ifdef UTILISATION_MPI + cout << "\n *** erreur , la methode LesContacts::Info_commande_LesContacts " + << " n'est pas utilisable en exécution MPI !!! "; + Sortie(1); + #endif + + ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier //On va proposer un menu string rep=" "; sort << "\n# --- les contact ------- "; @@ -2212,8 +2655,14 @@ void LesContacts::Info_commande_LesContacts(UtilLecture & entreePrinc) // lecture éventuelle des zones où le contact doit être recherché, à l'exclusion de tout // autre zone, ainsi que la définition de l'auto-contact éventuel // ainsi que des contacts solide-deformables éventuel +// cas d'un calcul parallèle, tous les proc utilisent la méthode, seule le proc 0 affiche void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesReferences& lesRef) -{ list li_lissage_de_la_normale; // stockage intermédiaire pour créer le tableau lissage_de_la_normale +{ + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + #endif + + list li_lissage_de_la_normale; // stockage intermédiaire pour créer le tableau lissage_de_la_normale int niveau_commentaire_lescontacts = Permet_affichage(); while ( (strstr(entreePrinc.tablcar,"auto_contact")!=NULL) || (strstr(entreePrinc.tablcar,"zone_contact")!=NULL) @@ -2231,10 +2680,16 @@ void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesRefere // cas ou l'on a des domaines esclaves en auto-contact, lecture du nombre { entreePrinc.NouvelleDonnee(); if (niveau_commentaire_lescontacts >= 4) + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif cout << " lecture du nombre de domaines esclaves en auto-contact " << endl; *(entreePrinc.entree) >> nbmailautocontact; // lecture du nombre if (niveau_commentaire_lescontacts >= 5) cout << nbmailautocontact << endl; if (niveau_commentaire_lescontacts >= 4) + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif cout << " fin de la lecture du nombre de domaines esclaves en auto-contact " << endl; entreePrinc.NouvelleDonnee(); // positionnement sur une nouvelle info }; @@ -2252,7 +2707,11 @@ void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesRefere // lecture tant qu'il n'y a pas de nouveau mot clé entreePrinc.NouvelleDonnee(); - if (niveau_commentaire_lescontacts >= 4) cout << " debut de la lecture des zones de contact possibles " << endl; + if (niveau_commentaire_lescontacts >= 4) + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif + 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 @@ -2278,7 +2737,12 @@ void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesRefere goodbit = 0 // -> O };*/ // lecture normale, vérification que la référence existe bien - { if (!(lesRef.Existe(nom_ref,nom_mail))) + { + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + + #endif + if (!(lesRef.Existe(nom_ref,nom_mail))) { cout << "\n erreur le nom de reference de zone de contact : " << nom_ref << " , n'existe pas !!" << "\n LesContacts::Lecture_zone_contact(.."; @@ -2307,19 +2771,32 @@ void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesRefere { entreePrinc.NouvelleDonnee(); } // lecture d'un nouvelle enregistrement #endif else // cas d'une erreur de lecture - { cout << "\n erreur de lecture inconnue au niveau des references de zone de contact"; - entreePrinc.MessageBuffer("** LesContacts::Lecture_zone_contact(.. **"); - Affiche(); - throw (UtilLecture::ErrNouvelleDonnee(-1)); - Sortie (1); + { + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif + { cout << "\n erreur de lecture inconnue au niveau des references de zone de contact"; + entreePrinc.MessageBuffer("** LesContacts::Lecture_zone_contact(.. **"); + Affiche(); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie (1); + }; }; }; // -- fin for (int nr=1;nr<=2;nr++) }; //-- fin du while (!motCle.SimotCle(entreePrinc.tablcar)) - if (niveau_commentaire_lescontacts >= 4) cout << " fin de la lecture des zones de contact " << endl; + if (niveau_commentaire_lescontacts >= 4) + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif + cout << " fin de la lecture des zones de contact " << endl; }; // --- cas des contacts solide-deformable if (strstr(entreePrinc.tablcar,"contact_solide_deformable")!=NULL) - { if (niveau_commentaire_lescontacts >= 4) cout << " debut de la lecture des contacts solide-deformable " << endl; + { if (niveau_commentaire_lescontacts >= 4) + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif + cout << " debut de la lecture des contacts solide-deformable " << endl; string toto; // variables de travail while (strstr(entreePrinc.tablcar,"fin_liste_des_couples_de_noms_solide_deformable")==NULL) // && (!motCle.SimotCle(entreePrinc.tablcar))) @@ -2330,7 +2807,11 @@ void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesRefere }; // on passe le mot clé de fin entreePrinc.NouvelleDonnee(); - if (niveau_commentaire_lescontacts >= 4) cout << " fin de la lecture des contacts solide-deformable " << endl; + if (niveau_commentaire_lescontacts >= 4) + #ifdef UTILISATION_MPI + if (proc_en_cours == 0) + #endif + cout << " fin de la lecture des contacts solide-deformable " << endl; }; }; // création du tableau lissage_de_la_normale diff --git a/contact/LesContacts.h b/contact/LesContacts.h index 22c23a6..30509b4 100644 --- a/contact/LesContacts.h +++ b/contact/LesContacts.h @@ -64,6 +64,17 @@ #include "Basiques.h" #include "TypeQuelconque.h" #include "Temps_CPU_HZpp.h" +#include +#ifdef UTILISATION_MPI + #include + #include + #include "mpi.h" + #include + #include + #include + #include + namespace mpi = boost::mpi; +#endif /// @addtogroup Groupe_sur_les_contacts @@ -144,14 +155,21 @@ class LesContacts // definition de conditions lineaires de contact // marquage des ddl correspondant aux directions bloquees s'il s'agit d'un contact de type 1 // casAssemb : donne le cas d'assemblage en cours - // - const Tableau & ConditionLin(const Nb_assemb& casAssemb); + // Dans le cas d'un calcul parallèle, il y a transfert des conditions au cpu 0 + // seules les cpu i calculent les conditions linéaires + // NB: on ne met pas la liste en const car on a besoin de pouvoir modifier les infos à l'intérieur + // des CL pour les utiliser, mais l'idée est la liste elle, reste constante + list & ConditionLin(const Nb_assemb& casAssemb); - // création d'un tableau de condition linéaire, correspondant à tous les éléments de contact en cours + // création d'une liste de condition linéaire, correspondant à tous les éléments de contact en cours // qu'ils soient actifs ou pas (a prior cette méthode est conçu pour donner des infos relativement à la largeur // de bandes en noeuds due aux CLL) // chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, - const Tableau & ConnectionCLL(); + // Dans le cas d'un calcul parallèle, il y a transfert des conditions au cpu 0 + // seules les cpu i calculent les conditions linéaires + // NB: on ne met pas la liste en const car on a besoin de pouvoir modifier les infos à l'intérieur + // des CL pour les utiliser, mais l'idée est la liste elle, reste constante + list & ConnectionCLL(); // effacement du marquage de ddl bloque du au conditions lineaire de contact void EffMarque(); @@ -172,6 +190,8 @@ class LesContacts // = true : si la largeur de bande en noeud est supérieure à 1 (cas d'un contact avec une surface déformable) // = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur // en noeud (cas d'un contact avec une surface rigide) + // dans le cas d'un calcul // seule le cpu 0 effectue la résolution, par contre tous les cpu i contribuent + // ils vont donc transmettre les informations au cpu 0 bool Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb,int& cumule); // actualisation du contact, on examine que les elements de contact, dont on @@ -185,6 +205,9 @@ class LesContacts // si l'intersection n'est pas calculable // NB: pour les deux choix, s'il y a doublon d'élément de contact, due à un changement de frontière // en cours d'actualisation, on inactive le(s) doublon(s) + // dans le cas d'un calcul // chaque proc i effectue son actualisation, s'il y a changement de surface avec sortie + // de la surface gérée par le proc i, cela sera vérifié au niveau de l'élément de contact + // Le proc 0 se contente de récupérer et globaliser les retours des proc i bool Actualisation(int choix); // ramène une liste de noeuds dont la position a été perturbé par le contact @@ -231,6 +254,7 @@ class LesContacts // lecture éventuelle des zones où le contact doit être recherché, à l'exclusion de tout // autre zone, ainsi que la définition de l'auto-contact éventuel // ainsi que des contacts solide-deformables éventuel + // cas d'un calcul parallèle, tous les proc utilisent la méthode, seule le proc 0 affiche void Lecture_zone_contact(UtilLecture & entreePrinc,const LesReferences& lesRef); // récupération des ddl ou des grandeurs actives de tdt vers t @@ -350,7 +374,7 @@ class LesContacts // list numtesN; // .un : maillage, .deux: num zone de contact, .trois: num propre du noeud // // la liste des numéros dans tesN des noeuds en contact Tableau tabReacCont; // les reactions - Tableau tabCoLin; // tableau des conditions lineaires + list listCoLin; // tableau des conditions lineaires static MotCle motCle; // liste des mots clés // la liste des éléments qui contiennent des frontières, est reconstitué au démarrage avec Init_contact(.. @@ -437,7 +461,7 @@ class LesContacts List_io liQ_en_sortie; // liste de grandeurs quelconque qu'il faut sortir // -------- une variable de travail pour la méthode LesContacts::ConnectionCLL()--- - Tableau t_connectionCLL; + list t_connectionCLL; //------- temps cpu ----- // retourne temps cumulé pour imposer les CL imposées @@ -447,6 +471,10 @@ class LesContacts Temps_CPU_HZpp temps_transfert_court ; Temps_CPU_HZpp temps_transfert_long ; Temps_CPU_HZpp temps_attente ; + Vecteur inter_transfer; // un conteneur de transfert pour ConditionLin + Vecteur inter_transfer2; // un conteneur de transfert pour ConnectionCLL + // on sauvegarde un pointeur sur les maillages + LesMaillages* lesMaille; #endif // METHODES PROTEGEES : diff --git a/contact/LesContacts_3.cc b/contact/LesContacts_3.cc index 731f3a3..32b9ddb 100755 --- a/contact/LesContacts_3.cc +++ b/contact/LesContacts_3.cc @@ -695,6 +695,9 @@ void LesContacts::Suppression_gap_pour_noeud_collant() return; // sinon il faut effectivement faire une suppression de gap + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts > 2) cout << "\n >>>> Suppression_gap_pour_noeud_collant : "; // on va iterer sur les noeuds esclaves collants dont on veut supprimer le gap @@ -706,7 +709,11 @@ void LesContacts::Suppression_gap_pour_noeud_collant() int boucle_maxi = 10; // 10 boucle maxi int boucle = 1; do - { if (niveau_commentaire_lescontacts >2 ) + { + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif + if (niveau_commentaire_lescontacts >2 ) cout << "\n boucle : "<::iterator il,ilfin=list_P.end(); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >5 ) {cout << "\n " << list_P.size() << " proj trouvees " << " Noe: "<Num_noeud() @@ -784,6 +794,9 @@ void LesContacts::Suppression_gap_pour_noeud_collant() LaLIST_io ::iterator>::iterator iface_maxi ; for (il=list_P.begin(); il!= ilfin;il++,iface++) { double Ndis = (M-(*il)).Norme(); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >5 ) cout << " dist: " << Ndis ; if (Ndis < distance) @@ -803,9 +816,15 @@ void LesContacts::Suppression_gap_pour_noeud_collant() tout_projeter=false; if (distance > le_maxi_des_distances_trouve) le_maxi_des_distances_trouve = distance; + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >3 ) cout << "\n suppression gap=("<Num_noeud() << " du maillage " << noee->Num_Mail() << " (zone "<rank() == 0) + #endif if (niveau_commentaire_lescontacts >4 ) {cout << "\n ancienne coordonnee "<< pt_esc << " nouvelle " << P; @@ -830,11 +849,18 @@ void LesContacts::Suppression_gap_pour_noeud_collant() {compteur_noeuds_projecte++;}; }; if ((!projection_ok) && (boucle==1)) // au premier passage - { if (niveau_commentaire_lescontacts >3 ) + { + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif + if (niveau_commentaire_lescontacts >3 ) cout << "\n pas de projection trouvee donc de suppression gap du noeud "<Num_noeud() << " du maillage" << noee->Num_Mail() << " (zone "<rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) {if (compteur_noeuds_projecte) cout << "\n zone: " << j <<", " << compteur_noeuds_projecte << " suppression(s) de gap, maxi_distance= " @@ -905,20 +931,82 @@ int LesContacts::Recup_ref( ElContact& al) // qu'ils soient actifs ou pas (a prior cette méthode est conçu pour donner des infos relativement à la largeur // de bandes en noeuds due aux CLL) // chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, -const Tableau & LesContacts::ConnectionCLL() +list & LesContacts::ConnectionCLL() { - // on boucle sur le tableau et pour chaque element on crée une condition lineaire - int tabTaille = listContact.size(); - t_connectionCLL.Change_taille(tabTaille); - // un tableau servant à la def de la CLL - Tableau t_enu(1); t_enu(1)=X1 ; - LaLIST ::const_iterator il,ilfin=listContact.end(); - int posi=1; // init pour le tableau - for (il=listContact.begin();il != ilfin;il++,posi++) - { const Tableau < Noeud *>& t_n = (*il).Const_TabNoeud(); - // on est dans le cas ou l'on connait les infos relatives uniquements aux noeuds, aux enum ddl - t_connectionCLL(posi) = Condilineaire(t_enu, t_n); - }; + tempsContact.Mise_en_route_du_comptage(); // def deb compt + #ifdef UTILISATION_MPI + int proc_en_cours = ParaGlob::Monde()->rank(); + if (proc_en_cours != 0) + { + #endif + { + // // on boucle sur le tableau et pour chaque element on crée une condition lineaire + // int tabTaille = listContact.size(); + // t_connectionCLL.Change_taille(tabTaille); + t_connectionCLL.clear(); + // un tableau servant à la def de la CLL + Tableau t_enu(1); t_enu(1)=X1 ; + LaLIST ::const_iterator il,ilfin=listContact.end(); + int posi=1; // init pour le tableau + for (il=listContact.begin();il != ilfin;il++,posi++) + { const Tableau < Noeud *>& t_n = (*il).Const_TabNoeud(); + // on est dans le cas ou l'on connait les infos relatives uniquements aux noeuds, aux enum ddl + t_connectionCLL.push_back(Condilineaire(t_enu, t_n)); + }; + tempsContact.Arret_du_comptage(); // fin cpu + } + #ifdef UTILISATION_MPI + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + // maintenant on va les transmettres au cpu 0 + // pour cela on va utiliser un conteneur intermédiaire + // on calcul la taille nécessaire pour le conteneur (a découper éventuellement ??) + int taille_conteneur=0; + list ::iterator il,ilfin = t_connectionCLL.end(); + for (il = t_connectionCLL.begin();il != ilfin;il++) + taille_conteneur += (*il).Taille_Pack(); + inter_transfer2.Change_taille(taille_conteneur); // le conteneur + // on rempli le conteneur + int rang = 1; // init + for (il = t_connectionCLL.begin();il != ilfin;il++) + rang = (*il).Pack_vecteur(inter_transfer2,rang); + temps_attente.Arret_du_comptage(); + // on transfert + mpi::request reqs1 = ParaGlob::Monde()->isend(0, 42, taille_conteneur); + + mpi::request reqs2 = inter_transfer2.Ienvoi_MPI(0,43); + // on attend pas + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + } + else // cas du cpu 0 + {// l'objectif ici est de récupérer les conditions linéaires + tempsContact.Arret_du_comptage(); // fin cpu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + int nb_proc_terminer = 0; // permettra de terminer + t_connectionCLL.clear();// Change_taille(nb_contact_actif); + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de cpu i + + int taille_transfert; + mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 42, taille_transfert); + mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli + inter_transfer2.Change_taille(taille_transfert); // le conteneur + int source = stat.source(); // récupération du numéro de la source + // on récupère + mpi::request reqs2 = inter_transfer2.Irecup_MPI(source, 43); + reqs2.wait(); // on attend que le conteneur soit rempli + nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur + // on va remplir la liste des conditions limites + int rang = 1; // init + while (rang != 0) + { Condilineaire condi; // une condition intermédiaire + rang = condi.UnPack_vecteur(*lesMaille,inter_transfer2,rang, + &LesMaillages::Noeud_LesMaille); + t_connectionCLL.push_back(condi); + }; + }; + temps_transfert_long.Arret_du_comptage(); + }; + #endif // retour return t_connectionCLL; @@ -1330,6 +1418,9 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) // ** mais on a: les éléments de frontière de t_listFront(i) font partie du maillage // i + (nb_mail_Esclave-nbmailautocontact) int niveau_commentaire_lescontacts = Permet_affichage(); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts > 4) cout << "\n ==> LesContacts::ElementAngleMort: "; @@ -1439,6 +1530,9 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) } }; int nb_front_fin = la_list_des_front.size(); // la taille finale + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n mail. maitre "<rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n mail. maitre "<rank() == 0) + #endif if (niveau_commentaire_lescontacts >4 ) { cout << "\n ajout front point: noeud "<Num_noeud(num_noe_local) << " mail: " << jf //<< " zone " @@ -1635,12 +1734,18 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) }; }; int nb_front_fin = la_list_des_front.size(); // la taille finale + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n ajout angle mort pour contact: mail. maitre "<< jf <<" : "<<(nb_front_fin-nb_front_init) << " frontieres point "; #ifdef MISE_AU_POINT // petite vérif en passant + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if ((nb_front_fin-nb_front_init) != front_angle_mort.size()) {cout << "\n *** erreur dans la definition des elements point d'angle mort " << " on a deux listes qui les representent mais qui n'ont pas la meme taille " @@ -1794,6 +1899,9 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) // on sauvegarde le nouvelle front dans une liste spécifique front_angle_mort.push_front(&(*iik)); + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >4 ) { cout << "\n ajout front point: noeud "<Num_noeud(num_noe_local) << " mail: " << jf << " zone "<< i_zone @@ -1804,6 +1912,9 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) }; }; int nb_front_fin = la_list_des_front.size(); // la taille finale + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n ajout angle mort pour contact: mail. maitre "<rank() == 0) + #endif if ((nb_front_fin-nb_front_init) != front_angle_mort.size()) {cout << "\n *** erreur dans la definition des elements point d'angle mort " << " on a deux listes qui les representent mais qui n'ont pas la meme taille " @@ -1838,6 +1952,9 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail) }; }; }; + #ifdef UTILISATION_MPI + if (ParaGlob::Monde()->rank() == 0) + #endif if (niveau_commentaire_lescontacts >7 ) { cout << "\n liste finale des elements angle mort " << " mail: " << jf << " zone "<< i_zone;