From d599e5fcb0b0d09919cc1150bf48c5c2307bfabe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Rio?= Date: Tue, 5 Sep 2023 12:47:10 +0200 Subject: [PATCH] mise en place de tous les chargements en MPI: expicite et implicite --- Chargement/Charge.cc | 127 ++- Chargement/Charge.h | 37 +- Chargement/Charge2.cc | 1485 +++++++++++++++++++++++++---------- Parametres/EnteteParaGlob.h | 2 +- TypeBase/Temps_CPU_HZpp.cc | 88 +-- TypeBase/Temps_CPU_HZpp.h | 85 +- 6 files changed, 1359 insertions(+), 465 deletions(-) diff --git a/Chargement/Charge.cc b/Chargement/Charge.cc index 391c06f..dbd5c15 100644 --- a/Chargement/Charge.cc +++ b/Chargement/Charge.cc @@ -200,6 +200,8 @@ Charge::Charge () : // constructeur par defaut ,temps_cpu_chargement() #ifdef UTILISATION_MPI ,temps_transfert_court(),temps_transfert_long(),temps_attente() + ,tab_reqs1(),tab_reqs2(),tab_reqs3() + ,tabV_transfert(),tabMat_transfert(),tab_six_faux_entiers() #endif {// mise à jour de la valeur par défaut du chargement au cas où aucun chargement @@ -207,6 +209,19 @@ Charge::Charge () : // constructeur par defaut nomtypeCharge ="TYPE1"; tabType.Change_taille(1); tabType(1) = 1.; + + #ifdef UTILISATION_MPI + // on définit les conteneurs de passage d'info + int taille_passage = 8; + tab_reqs1.Change_taille(taille_passage); + tab_reqs2.Change_taille(taille_passage); + tab_reqs3.Change_taille(taille_passage); + tabV_transfert.Change_taille(taille_passage); + tabMat_transfert.Change_taille(taille_passage); + tab_six_faux_entiers.Change_taille(taille_passage); + for (int i=1;i<=taille_passage;i++)tab_six_faux_entiers(i).Change_taille(6); + #endif + } Charge::~Charge () { if (f_charge != NULL) @@ -1305,5 +1320,115 @@ void Charge::Ecriture_base_info(ofstream& sort,const int cas) }; }; - +#ifdef UTILISATION_MPI +// transfert du second membre "SM_transfert" et mise à jour +// de l'index des tableaux "index_transfert" par rotation cyclique +// NB: tous les tableaux doivent avoir la même taille +void Charge::Transfert_SM(bool& premier_passage, + const int& tyfront, + const int& num_front, + Vecteur & SM_transfert, + int& index_transfert, + const int & numail, + const int & numelem + ) + { + temps_attente.Mise_en_route_du_comptage(); // comptage cpu + mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier + mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier + int taille_tableau = tab_six_faux_entiers.Taille(); + // on récupère un signal du process 0 + if (premier_passage) {premier_passage = false;} + else // on regarde l'activité , car au début avant le balayage de tous les éléments des tableaux + {if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés + if (reqs2.active()) reqs2.wait(); // car aucun transfert n'a encore été effectué + }; + temps_attente.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier + six_faux_entiers(1) = (double) numelem; + six_faux_entiers(2) = (double) numail; + six_faux_entiers(3) = (double) tyfront; + six_faux_entiers(4) = (double) num_front; + six_faux_entiers(5) = (double) SM_transfert.Taille(); + six_faux_entiers(6) = (double) index_transfert; + // on transmet les numéros d'élément et de maillage etc. + reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + // puis on transmets le vecteur résidu sauf si tyfront est négatif + if (tyfront > 0) + {temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + reqs2 = SM_transfert.Ienvoi_MPI(0,35); + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + // // debug + // cout << "\n debug Charge::Transfert_SM( proc= "<< ParaGlob::Monde()->rank() + // << " six_faux_entiers= " << six_faux_entiers + // << " SM_transfert= " << SM_transfert << flush; + // // fin debug + }; + // ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore + // en transfert vers le proc 0 + index_transfert++; + if (index_transfert > taille_tableau) // on fait une permutation circulaire + index_transfert = 1;// on revient au premier élément des tableaux de transfert + }; + +// transfert du second membre "SM_transfert" et de la matrice "MAT_transfert" et mise à jour +// de l'index des tableaux "index_transfert" par rotation cyclique +// NB: tous les tableaux doivent avoir la même taille +void Charge::Transfert_MatSm(bool& premier_passage, + const int& tyfront, + const int& num_front, + Vecteur & SM_transfert, + Mat_pleine * MAT_transfert, + int& index_transfert, + const int & numail, + const int & numelem + ) + { + temps_attente.Mise_en_route_du_comptage(); // comptage cpu + mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier + mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier + mpi::request & reqs3 = tab_reqs3(index_transfert); // pour simplifier + int taille_tableau = tab_six_faux_entiers.Taille(); + // on récupère un signal du process 0 + if (premier_passage) {premier_passage = false;} + else // on regarde l'activité , car au début avant le balayage de tous les éléments des tableaux + {if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés + if (reqs2.active()) reqs2.wait(); // car aucun transfert n'a encore été effectué + if (reqs3.active()) reqs3.wait(); // car aucun transfert n'a encore été effectué + }; + temps_attente.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier + six_faux_entiers(1) = (double) numelem; + six_faux_entiers(2) = (double) numail; + six_faux_entiers(3) = (double) tyfront; + six_faux_entiers(4) = (double) num_front; + six_faux_entiers(5) = (double) SM_transfert.Taille(); + six_faux_entiers(6) = (double) index_transfert; + // on transmet les numéros d'élément et de maillage etc. + reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); + // // debug + // cout << "\n debug Charge::Transfert_SM( proc= "<< ParaGlob::Monde()->rank() + // << " six_faux_entiers= " << six_faux_entiers + // << " SM_transfert= " << SM_transfert << flush; + // // fin debug + temps_transfert_court.Arret_du_comptage(); // fin comptage cpu + // puis on transmets le vecteur résidu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + reqs2 = SM_transfert.Ienvoi_MPI(0,35); + // puis on transmets éventuellementla matrice de raideur + if (MAT_transfert != NULL) + reqs3 = MAT_transfert->Ienvoi_MPI(0,36); + // ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore + // en transfert vers le proc 0 + index_transfert++; + if (index_transfert > taille_tableau) // on fait une permutation circulaire + index_transfert = 1;// on revient au premier élément des tableaux de transfert + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + }; + +#endif + diff --git a/Chargement/Charge.h b/Chargement/Charge.h index 161a3b0..380b5d7 100644 --- a/Chargement/Charge.h +++ b/Chargement/Charge.h @@ -369,14 +369,47 @@ class Charge // de la variation du pas de temps // mise à jour avec la méthode : Change_temps_fin_non_stricte(int methode) + Temps_CPU_HZpp temps_cpu_chargement; // le temps cpu du à tous les chargements + #ifdef UTILISATION_MPI // cas d'un calcul parallèle: // passage des infos entre process Temps_CPU_HZpp temps_transfert_court ; Temps_CPU_HZpp temps_transfert_long ; - Temps_CPU_HZpp temps_attente ; + Temps_CPU_HZpp temps_attente ; + + // on définit les conteneurs de passage d'info + Tableau tab_reqs1; + Tableau tab_reqs2; + Tableau tab_reqs3; + Tableau tabV_transfert; + Tableau tabMat_transfert; + Tableau tab_six_faux_entiers; + + // transfert du second membre "SM_transfert" et mise à jour + // de l'index des tableaux "index_transfert" par rotation cyclique + // NB: tous les tableaux doivent avoir la même taille + void Transfert_SM(bool& premier_passage, + const int& tyfront, + const int& num_front, + Vecteur & SM_transfert, + int& index_transfert, + const int & numail, + const int & numelem + ); + // transfert du second membre "SM_transfert" et de la matrice "MAT_transfert" et mise à jour + // de l'index des tableaux "index_transfert" par rotation cyclique + // NB: tous les tableaux doivent avoir la même taille + void Transfert_MatSm(bool& premier_passage, + const int& tyfront, + const int& num_front, + Vecteur & SM_transfert, + Mat_pleine * MAT_transfert, + int& index_transfert, + const int & numail, + const int & numelem + ); #endif - Temps_CPU_HZpp temps_cpu_chargement; // le temps cpu du à tous les chargements // les autres parametres relatif au temps //-// double deltatmaxi; // increment de temps maxi diff --git a/Chargement/Charge2.cc b/Chargement/Charge2.cc index 080503a..52bf9bf 100644 --- a/Chargement/Charge2.cc +++ b/Chargement/Charge2.cc @@ -232,7 +232,6 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; // $$$ --- cas des torseurs de forces ponctuelles --- $$$ - #ifdef UTILISATION_MPI // cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0 uniquement if (ParaGlob::Monde()->rank() == 0) @@ -353,19 +352,10 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; #ifdef UTILISATION_MPI - mpi::request reqs1; - mpi::request reqs2; // on définit les conteneurs de passage d'info - int nb_proc = ParaGlob::Monde()->size(); - Tableau tab_reqs1(nb_proc); - Tableau tab_reqs2(nb_proc); - Tableau tabV_transfert(nb_proc); - Tableau tab_six_faux_entiers(nb_proc); - for (int i=1;i<=nb_proc;i++)tab_six_faux_entiers(i).Change_taille(6); int proc_en_cours = ParaGlob::Monde()->rank(); int index_transfert; // index pour incrémenter dans les tableaux -// la suite à virer qu'en c'est ok - Vecteur cinq_faux_entiers(5); + bool premier_passage = true; if (proc_en_cours != 0) { @@ -374,7 +364,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // --- cas des forces surfaciques ---$$$ int tabsurfactaille = tabFsurfac.Taille(); if ( tabsurfactaille != 0) - {// on parcours le tableau tabFsurfac dans le repère absolu + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabFsurfac dans le repère absolu for (int i=1;i<= tabsurfactaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabFsurfac_i = tabFsurfac(i); @@ -471,21 +465,13 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid double coeff_charge = (pt_courbe->Valeur(Temps_courant())) * tabFsurfac_i.Echelle_courbe(); vforce *= coeff_charge; }; - // appel du calcul du second membre correspondant à la charge surfacique - // Coordonnee vforce = tabFsurfac_i.Coord() * coeff; - Vecteur SM = elem.SM_charge_surfacique_E_tdt(vforce,pt_fonct,ref.NumeroFA(ns),pa); #ifdef UTILISATION_MPI - temps_cpu_chargement.Arret_du_comptage(); - // on récupère un signal du process 0 - temps_attente.Mise_en_route_du_comptage(); // comptage cpu - if (premier_passage) {premier_passage = false;} - else // on attend que les transferts soient finis - {reqs1.wait(); - reqs2.wait(); - }; - temps_attente.Arret_du_comptage(); // fin comptage cpu - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_face = ref.NumeroFA(ns); + SM_transfert = elem.SM_charge_surfacique_E_tdt(vforce,pt_fonct,num_face,pa); int tyfront = 5; // init par défaut du type de frontière if (ParaGlob::AxiSymetrie()) // dans le cas axiSymétrique, les surfaces sont générées par les lignes, @@ -493,21 +479,20 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid tyfront = 2;} else // cas normale {tyfront = 3; };// la surface - CinqEntiers num_el_mail_tyfront_nufront - (elem.Num_elt(),elem.Num_maillage() - ,tyfront,ref.NumeroFA(ns),SM.Taille()); - // on transmet les numéros d'élément et de maillage - reqs1 = ParaGlob::Monde()->isend(0, 34, num_el_mail_tyfront_nufront); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu - // puis on transmets le vecteur résidu - temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu - reqs2 = SM.Ienvoi_MPI(0,35); - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_face,SM_transfert, + index_transfert,num_mail,num_elem + ); temps_cpu_chargement.Mise_en_route_du_comptage(); } }; #else // cas non // - { // assemblage du second membre + { + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM = elem.SM_charge_surfacique_E_tdt(vforce,pt_fonct,ref.NumeroFA(ns),pa); + // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; // init if (ParaGlob::AxiSymetrie()) @@ -528,7 +513,7 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid if ( tabPresUniftaille != 0) { #ifdef UTILISATION_MPI - index_transfert=0; // index pour incrémenter dans les tableaux + index_transfert=1; // index pour incrémenter dans les tableaux #endif // on parcours le tableau tabPresUnif for (int i=1;i<= tabPresUniftaille;i++) @@ -549,13 +534,14 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid for (int ns=1;ns<= nbref;ns++) { int num_elem = ref.NumeroElem(ns); int num_mail = ref.Nbmaille(); - #ifdef UTILISATION_MPI - // on ne continue que si l'élément est concerné - if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) - {if (proc_en_cours != 0) - { - #endif// récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); double press_ac = 0.; // init // récupération de la pression de référence // on traite en fonction du fait que c'est un champ ou non @@ -611,54 +597,22 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid #ifdef UTILISATION_MPI // appel du calcul du second membre correspondant à la charge de type pression - // ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore - // en transfert vers le proc 0 - index_transfert++; - if (index_transfert > nb_proc) // on fait une permutation circulaire sur un nombre = au nombre total de proc - // sachant qu'ici on a toujours le même proc, mais on considère qu'après nb_proc transferts, le premier de la liste - // est terminé - index_transfert = 1;// on revient au premier élément des tableaux de transfert Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier - SM_transfert = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,ref.NumeroFA(ns),pa); - temps_cpu_chargement.Arret_du_comptage(); - mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier - mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier - // on s'assure quand même que les précents transferts sont terminés - temps_attente.Mise_en_route_du_comptage(); // comptage cpu - if (premier_passage) {premier_passage = false;} - else // on regarde l'activité , car au début avant, le balayage de tous les éléments des tableaux - {if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés - if (reqs2.active()) reqs2.wait(); - }; - temps_attente.Arret_du_comptage(); // fin comptage cpu - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + int num_face = ref.NumeroFA(ns); + SM_transfert = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,num_face,pa); int tyfront = 5; // init par défaut du type de frontière if (ParaGlob::AxiSymetrie()) // dans le cas axiSymétrique, les surfaces sont générées par les lignes, {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; - tyfront = 2;} - else // cas normale - {tyfront = 3; };// la surface - Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier - six_faux_entiers(1) = (double) elem.Num_elt(); - six_faux_entiers(2) = (double) elem.Num_maillage(); - six_faux_entiers(3) = (double) tyfront; - six_faux_entiers(4) = (double) ref.NumeroFA(ns); - six_faux_entiers(5) = (double) SM_transfert.Taille(); - six_faux_entiers(6) = (double) index_transfert; - // on transmet les numéros d'élément et de maillage - reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu - // puis on transmets le vecteur résidu - temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu - reqs2 = SM_transfert.Ienvoi_MPI(0,350+index_transfert); -// // debug -// cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() -// // << " CinqEntiers= "<< num_el_mail_tyfront_nufront -// << " six_faux_entiers= " << six_faux_entiers -// << " SM= " << SM << flush; -// // fin debug - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_face,SM_transfert, + index_transfert,num_mail,num_elem + ); temps_cpu_chargement.Mise_en_route_du_comptage(); } }; @@ -687,7 +641,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // direction localement pendant toute la transformation int PresUniDirtaille = PresUniDir.Taille(); if ( PresUniDirtaille != 0) - {// on parcours le tableau PresUniDir + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau PresUniDir for (int i=1;i<= PresUniDirtaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& PresUniDir_i = PresUniDir(i); @@ -705,8 +663,16 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid int nbref = ref.Taille(); Coordonnee press_uni; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + {int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (PresUniDir_i.Champ()) @@ -777,8 +743,34 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid press_uni *= coeff_charge; }; // appel du calcul du second membre correspondant à la charge de type pression - // Coordonnee press_uni = (PresUniDir_i.Coord()) * coeff; - Vecteur SM = elem.SM_charge_presUniDir_E_tdt(press_uni,pt_fonct,ref.NumeroFA(ns),pa); + + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_face = ref.NumeroFA(ns); + SM_transfert = elem.SM_charge_presUniDir_E_tdt(press_uni,pt_fonct,num_face,pa); + int tyfront = 5; // init par défaut du type de frontière + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + temps_cpu_chargement.Arret_du_comptage(); + + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_face,SM_transfert, + index_transfert,num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // appel du calcul du second membre correspondant à la charge de type pression + // ici on récupère une adresse car il n'y a pas de crainte d'écraser un vecteur déjà en cours + Vecteur& SM = elem.SM_charge_presUniDir_E_tdt(press_uni,pt_fonct,ref.NumeroFA(ns),pa); // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; // init @@ -788,6 +780,8 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid else // cas normale {elfront = elem.Frontiere_surfacique(ref.NumeroFA(ns)); };// la surface frontière assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage + } + #endif }; }; }; @@ -796,7 +790,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // --- cas des forces lineique ---$$$ int tablineiquetaille = tabFlineique.Taille(); if ( tablineiquetaille != 0) - {// on parcours le tableau tabFlineique dans le repère absolu + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabFlineique dans le repère absolu for (int i=1;i<= tablineiquetaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabFlineique_i = tabFlineique(i); @@ -814,8 +812,16 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid int nbref = ref.Taille(); Coordonnee f_lin; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (tabFlineique_i.Champ()) @@ -885,14 +891,34 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid double coeff_charge = (pt_courbe->Valeur(Temps_courant())) * tabFlineique_i.Echelle_courbe(); f_lin *= coeff_charge; }; - // appel du calcul du second membre correspondant à la charge lineique - // Vecteur f_lin = (tabFlineique_i.Coord()) * coeff ; - Vecteur SM = elem.SM_charge_lineique_E_tdt(f_lin,pt_fonct,ref.NumeroFA(ns),pa); + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_ligne = ref.NumeroFA(ns); + SM_transfert =elem.SM_charge_lineique_E_tdt(f_lin,pt_fonct,num_ligne,pa); + int tyfront = 2; // type de frontière ligne + // si on est en axi c'est interprété comme une force surfacique + // on ne change pas le type de frontière + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_ligne,SM_transfert, + index_transfert,num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // appel du calcul du second membre correspondant à la charge lineique + Vecteur& SM = elem.SM_charge_lineique_E_tdt(f_lin,pt_fonct,ref.NumeroFA(ns),pa); // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la ligne chargée const ElFrontiere* elfront = elem.Frontiere_lineique(ref.NumeroFA(ns)); // l'arete frontière assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage - }; + } + #endif + }; }; } }; @@ -900,7 +926,10 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // --- cas des forces lineiques suiveuses ---$$$ int tablineiqueSuivtaille = tabFlineiqueSuiv.Taille(); if ( tablineiqueSuivtaille != 0) - {// on parcours le tableau tabFlineiqueSuiv des forces exprimées dans le repère global + {// on parcours le tableau tabFlineiqueSuiv des forces exprimées dans le repère global + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif for (int i=1;i<= tablineiqueSuivtaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim > & tabFlineiqueSuiv_i = tabFlineiqueSuiv(i); @@ -918,8 +947,16 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid int nbref = ref.Taille(); Coordonnee f_lin; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (tabFlineiqueSuiv_i.Champ()) @@ -989,14 +1026,36 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid double coeff_charge = (pt_courbe->Valeur(Temps_courant())) * tabFlineiqueSuiv_i.Echelle_courbe(); f_lin *= coeff_charge; } + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_ligne = ref.NumeroFA(ns); + SM_transfert = elem.SM_charge_lineique_Suiv_E_tdt(f_lin,pt_fonct,num_ligne,pa); + int tyfront = 2; // type de frontière ligne + // si on est en axi c'est interprété comme une force surfacique + // on ne change pas le type de frontière + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_ligne,SM_transfert, + index_transfert,num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // appel du calcul du second membre correspondant à la charge lineique // appel du calcul du second membre correspondant à la charge lineique // Vecteur f_lin = (tabFlineiqueSuiv_i.Coord()) * coeff ; - Vecteur SM = elem.SM_charge_lineique_Suiv_E_tdt(f_lin,pt_fonct,ref.NumeroFA(ns),pa); + Vecteur SM& = elem.SM_charge_lineique_Suiv_E_tdt(f_lin,pt_fonct,ref.NumeroFA(ns),pa); // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la ligne chargée const ElFrontiere* elfront = elem.Frontiere_lineique(ref.NumeroFA(ns)); // l'arete frontière assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage - }; + }; + #endif + }; }; } }; @@ -1004,7 +1063,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // --- cas des forces volumiques ---$$$ int tabvoltaille = tabFvol.Taille(); if ( tabvoltaille != 0) - {// on parcours le tableau tabFvol dans le repère absolu + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabFvol dans le repère absolu for (int i=1;i<= tabvoltaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabFvol_i = tabFvol(i); @@ -1022,8 +1085,16 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid int nbref = ref.Taille(); Coordonnee f_vol; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.Numero(ns)); + { int num_elem = ref.Numero(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (tabFvol_i.Champ()) @@ -1095,13 +1166,31 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; // on indique si éventuellement on veut se référer au volume initial bool volume_finale = !(tabFvol_i.Attribut() == "sur_volume_initial_"); - // appel du calcul du second membre correspondant à la charge volumique - // Vecteur f_vol = (tabFvol_i.Coord()) * coeff; - Vecteur SM = elem.SM_charge_volumique_E_tdt(f_vol,pt_fonct,pa,volume_finale); - // assemblage du second membre - // il faut utiliser les noeuds et les ddlelement correspondant à l'élément - assemb.AssemSM (vecglob,SM,elem.TableauDdl(),elem.Tab_noeud()); // assemblage - }; + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_inter = 0; // ne sert pas ici + SM_transfert = elem.SM_charge_volumique_E_tdt(f_vol,pt_fonct,pa,volume_finale); + int tyfront = 4; // type d'un volume + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_inter,SM_transfert, + index_transfert,num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + {// appel du calcul du second membre correspondant à la charge volumique + Vecteur SM& = elem.SM_charge_volumique_E_tdt(f_vol,pt_fonct,pa,volume_finale); + // assemblage du second membre + // il faut utiliser les noeuds et les ddlelement correspondant à l'élément + assemb.AssemSM (vecglob,SM,elem.TableauDdl(),elem.Tab_noeud()); // assemblage + } + #endif + }; }; } } @@ -1109,7 +1198,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // --- cas des des pressions hydrostatiques ---$$$ int PresHydrotaille = PresHydro.Taille(); if ( PresHydrotaille != 0) - {// on parcours le tableau PresHydro + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau PresHydro for (int i=1;i<= PresHydrotaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim > & PresHydro_i = PresHydro(i); @@ -1130,8 +1223,16 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid const Coordonnee& A = PresHydro_i.Point_M(); // récup du point de la surface libre double p_hydro_ref = (PresHydro_i.Val(1)); for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); double p_hydro = p_hydro_ref; // maintenant deux cas: soit avec ou sans courbes de charge if(pt_courbe == NULL) @@ -1144,18 +1245,46 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // appel du calcul du second membre correspondant à la charge de type pression bool sans_limitation=false; if (PresHydro_i.Attribut() == "sans_limitation_") sans_limitation= true; - Vecteur SM = elem.SM_charge_hydrostatique_E_tdt - (N,p_hydro,ref.NumeroFA(ns),A,pa,sans_limitation) ; - // assemblage du second membre - // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée - const ElFrontiere* elfront = NULL; // init + + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_face = ref.NumeroFA(ns); + SM_transfert = elem.SM_charge_hydrostatique_E_tdt + (N,p_hydro,num_face,A,pa,sans_limitation) ; + int tyfront = 5; // init par défaut du type de frontière if (ParaGlob::AxiSymetrie()) // dans le cas axiSymétrique, les surfaces sont générées par les lignes, - {elfront = elem.Frontiere_lineique(ref.NumeroFA(ns));} - else // cas normale - {elfront = elem.Frontiere_surfacique(ref.NumeroFA(ns)); };// la surface frontière - assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + temps_cpu_chargement.Arret_du_comptage(); + + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_face,SM_transfert, + index_transfert,num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); } + }; + #else // cas non // + {Vecteur SM& = elem.SM_charge_hydrostatique_E_tdt + (N,p_hydro,ref.NumeroFA(ns),A,pa,sans_limitation) ; + // assemblage du second membre + // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée + const ElFrontiere* elfront = NULL; // init + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {elfront = elem.Frontiere_lineique(ref.NumeroFA(ns));} + else // cas normale + {elfront = elem.Frontiere_surfacique(ref.NumeroFA(ns)); };// la surface frontière + assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage + }; + #endif + }; }; } }; @@ -1163,7 +1292,15 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // --- cas des des efforts hydrodynamiques ---$$$ int coefHydroDynataille = coefHydroDyna.Taille(); if ( coefHydroDynataille != 0) - {// on parcours le tableau coefHydroDyna + {if (ParaGlob::AxiSymetrie()) // pas pris en compte + {cout << "\n *** erreur : le chargement hydrodynamique en axisymetrique n'est pas pris en compte ! "; + Sortie(1); + }; + + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau coefHydroDyna for (int i=1;i<= coefHydroDynataille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim > & coefHydroDyna_i = coefHydroDyna(i); @@ -1182,14 +1319,48 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // récup du poids volumique poids volumique = ro * g, qui n'est pas soumis à la courbe de charge double poidvol = (coefHydroDyna_i.Val(1)); for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // maintenant deux cas: soit avec ou sans courbes de charge double coeff_charge=1.; if(pt_courbe != NULL) { coeff_charge = (pt_courbe->Valeur(Temps_courant())) * coefHydroDyna_i.Echelle_courbe();}; - // appel du calcul du second membre correspondant aux efforts hydrodynamique - Vecteur SM = elem.SM_charge_hydrodynamique_E_tdt(coefHydroDyna_i.Frot_fluid(),poidvol + + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_front = ref.NumeroFA(ns); + SM_transfert = elem.SM_charge_hydrodynamique_E_tdt + (coefHydroDyna_i.Frot_fluid(),poidvol + ,coefHydroDyna_i.Coef_aero_n(),num_front,coeff_charge + ,coefHydroDyna_i.Coef_aero_t(),pa) ; + int tyfront = 5; // init par défaut du type de frontière + switch (ParaGlob::Dimension()) + { case 3: {tyfront=3; break;};// la surface frontière + case 2: {tyfront=2; break;};// la ligne frontière + case 1: {tyfront=1; break;};// le point frontière + }; + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_SM(premier_passage,tyfront, + num_front,SM_transfert, + index_transfert,num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + {// appel du calcul du second membre correspondant aux efforts hydrodynamique + Vecteur SM& = elem.SM_charge_hydrodynamique_E_tdt(coefHydroDyna_i.Frot_fluid(),poidvol ,coefHydroDyna_i.Coef_aero_n(),ref.NumeroFA(ns),coeff_charge ,coefHydroDyna_i.Coef_aero_t(),pa) ; // assemblage du second membre @@ -1201,7 +1372,9 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid case 1: {elfront = elem.Frontiere_points(ref.NumeroFA(ns)); break;};// le point frontière }; assemb.AssemSM (vecglob,SM,elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage - }; + } + #endif + }; }; }; }; //-- fin de hydrodyna @@ -1209,124 +1382,73 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu // maintenant on s'occupe du cpu 0 #ifdef UTILISATION_MPI + // arrivée ici on va indiquer au CPU 0 que c'est fini - index_transfert++; - if (index_transfert > nb_proc) // on fait une permutation circulaire sur un nombre = au nombre total de proc - index_transfert = 1;// on revient au premier élément des tableaux de transfert - mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier - // on s'assure quand même que les précents transferts sont terminés - temps_attente.Mise_en_route_du_comptage(); // comptage attente - if (premier_passage) {premier_passage = false;} - else {reqs1.wait();}; - temps_attente.Arret_du_comptage(); // fin comptage attente - temps_transfert_court.Mise_en_route_du_comptage(); // comptage transfert cpu int tyfront = - proc_en_cours; // init par défaut du type de frontière // le signe - indique une fin - Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier - six_faux_entiers(1) = (double) 0; - six_faux_entiers(2) = (double) 0; - six_faux_entiers(3) = (double) tyfront; - six_faux_entiers(4) = (double) 0; - six_faux_entiers(5) = (double) 0; - six_faux_entiers(6) = (double) index_transfert; - reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); // on transmet - temps_transfert_court.Arret_du_comptage(); // fin comptage transfert cpu + // appel du transfert et mise à jour de l'index des tableaux + Vecteur& SM_transfert = tabV_transfert(index_transfert); // ne sert pas ici + Transfert_SM(premier_passage,tyfront, + 0,SM_transfert, + index_transfert,0,0 + ); } - else // donc ici cas ou on a le rank == 0 et on récolte - { // récup d'un second membre - temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu - int nb_proc_terminer = 0; // permettra de terminer - // on va boucler sur les éléments récupérés des différents process - // jusqu'à ce que tous les éléments aient finis - premier_passage = true; - int index_transfert = 1; // on se sert du premier élément de tableau - int ne,nbMail,tyfront,num_front,taille_SM; // inter pour la persistance - int source; // le nb de la source émettante -// int index_local_de_tab = 0; - mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier - mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier - Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier - Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier - while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront - { // on récupère un résultat de calcul - temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu - temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu - reqs1 = six_faux_entiers.Irecup_MPI(mpi::any_source, 34); - mpi::status stat = reqs1.wait(); - ne = (int) six_faux_entiers(1); - nbMail = (int) six_faux_entiers(2); - tyfront = (int) six_faux_entiers(3); - num_front = (int) six_faux_entiers(4); - taille_SM = (int) six_faux_entiers(5); - index_transfert = six_faux_entiers(6); - source = stat.source(); + else // donc ici cas ou on a le rank == 0 et on récolte + { // récup d'un second membre + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + int nb_proc_terminer = 0; // permettra de terminer + // on va boucler sur les éléments récupérés des différents process + // jusqu'à ce que tous les éléments aient finis + premier_passage = true; + int index_transfert = 1; // on se sert du premier élément de tableau + int ne,nbMail,tyfront,num_front,taille_SM; // inter pour la persistance + int source; // le nb de la source émettante +// int index_local_de_tab = 0; + mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier + mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier + Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier +// int i_proc = 1; // essai de réception avec le num du proc +// Tableau < int > non_fin_proc(nb_proc-1,1); // essai + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de calcul + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + reqs1 = six_faux_entiers.Irecup_MPI(mpi::any_source, 34); +// if (non_fin_proc(i_proc)) // essai +// {reqs1 = six_faux_entiers.Irecup_MPI(i_proc, 34); // essai +// temps_transfert_court.Arret_du_comptage(); // comptage cpu +// temps_attente.Mise_en_route_du_comptage(); // comptage cpu + mpi::status stat = reqs1.wait(); + temps_transfert_court.Arret_du_comptage(); // comptage cpu +// temps_attente.Arret_du_comptage(); // comptage cpu + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + ne = (int) six_faux_entiers(1); + nbMail = (int) six_faux_entiers(2); + tyfront = (int) six_faux_entiers(3); + num_front = (int) six_faux_entiers(4); + taille_SM = (int) six_faux_entiers(5); + index_transfert = six_faux_entiers(6); + source = stat.source(); -// // on parcourt les transferts possibles a priori -// if (premier_passage) // au premier passage on balaie tous les transferts possible -// {for (int i = 1;i< nb_proc;i++) -// tab_reqs1(i) = tab_six_faux_entiers(i).Irecup_MPI(mpi::any_source, 34); -// premier_passage=false; -// } -// else // sinon on on réenclanche seulement le cas que l'on vient de traiter -// { tab_reqs1(index_local_de_tab) = tab_six_faux_entiers(index_local_de_tab).Irecup_MPI(mpi::any_source, 34); -// }; -// // on fait une boucle sur tous les status potentiels -// // on en sort quand on a trouvé un transfert terminé -// int j=1; -// do{ // début d'une boucle infinie -// boost::optional statu = tab_reqs1(j).test(); -// if (statu) -// {index_local_de_tab = j; -// Vecteur& six_faux_entiers = tab_six_faux_entiers(index_local_de_tab); // pour simplifier -// ne = (int) six_faux_entiers(1); -// nbMail = (int) six_faux_entiers(2); -// tyfront = (int) six_faux_entiers(3); -// num_front = (int) six_faux_entiers(4); -// taille_SM = (int) six_faux_entiers(5); -// index_transfert = six_faux_entiers(6); -// source = statu->source(); -// break; // on sort de la boucle -// }; -// j++; -// if (j > nb_proc) // on fait une permutation circulaire sur le nombre total de proc=taille des tableaux -// j = 1;// on revient au premier élément des tableaux de transfert -// }while(1); -// // arrivée ici on a les infos sur le premier conteneur -// // a priori le second ne pose pas de pb de temps d'attente on utilise un simple wait -// Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier -// -// mpi::request req; -// std::string rmsg; -// -// req = world.irecv(mpi::any_source, mpi::any_tag, rmsg); -// do { -// boost::optional stat = req.test(); -// if (stat) { -// std::cout << "From " << stat->source() << std::endl; -// std::cout << "Got " << rmsg << std::endl; -// std::cout << "Tagged " << stat->tag() << std::endl; -// break; -// } -// } while(1); - temps_transfert_court.Arret_du_comptage(); // fin comptage cpu - temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu ////-------debug //cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() //// << " recup CinqEntiers " << num_el_mail_tyfront_nufront << flush; // << " recup six_faux_entiers " << six_faux_entiers << flush; ////-------fin debug // int tyfront = num_el_mail_tyfront_nufront.trois; - if (tyfront > 0) - {Element& elem = lesMail->Element_LesMaille(nbMail,ne); - // def de SM avec la bonne dimension - SM_transfert.Change_taille(taille_SM);//num_el_mail_tyfront_nufront.cinq); - // récupération des conteneurs ad hoc vecteur et raideur - temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu - temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu - reqs2 = SM_transfert.Irecup_MPI(source, 350+index_transfert); - reqs2.wait(); // on attend que le conteneur soit rempli - temps_transfert_long.Arret_du_comptage(); // fin comptage cpu + if (tyfront > 0) + {Element& elem = lesMail->Element_LesMaille(nbMail,ne); + // def de SM avec la bonne dimension + SM_transfert.Change_taille(taille_SM);//num_el_mail_tyfront_nufront.cinq); + // récupération des conteneurs ad hoc vecteur et raideur + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + // reqs2 = SM_transfert.Irecup_MPI(source, 350+index_transfert); + reqs2 = SM_transfert.Irecup_MPI(source, 35); + reqs2.wait(); // on attend que le conteneur soit rempli + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu ////-------debug //cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() // << " SM= " << SM << flush; @@ -1334,41 +1456,56 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid // assemblage - temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu - switch (tyfront) - {case 2: - {const ElFrontiere* elfront = elem.Frontiere_lineique(num_front);// num_el_mail_tyfront_nufront.quatre); - assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); - break; - } - case 3: - {const ElFrontiere* elfront = elem.Frontiere_surfacique(num_front);//num_el_mail_tyfront_nufront.quatre); - assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); - break; - } - default: - {cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours - << " le cas tyfront = " << tyfront << " n'est pas pris en compte pour l'instant !! "; - Sortie(1); - } ; - }; - } - else if (tyfront < 0) - {// on est dans le cas où un proc a terminé - nb_proc_terminer++; - } - else - {cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours - << " tyfront ne doit jamais etre nul !! "; - Sortie(1); - } ; - }; + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + switch (tyfront) + { + case 1: // cas d'un point frontière + {const ElFrontiere* elfront =elem.Frontiere_points(num_front);// num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + case 2: // cas d'une ligne + {const ElFrontiere* elfront = elem.Frontiere_lineique(num_front);// num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + case 3: // cas d'une surface + {const ElFrontiere* elfront = elem.Frontiere_surfacique(num_front);//num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + case 4: // cas d'un volume + {assemb.AssemSM (vecglob,SM_transfert,elem.TableauDdl(),elem.Tab_noeud()); + break; + } + default: + {cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours + << " le cas tyfront = " << tyfront << " n'est pas pris en compte pour l'instant !! "; + Sortie(1); + } ; + }; + } + else if (tyfront < 0) + {// on est dans le cas où un proc a terminé + nb_proc_terminer++; + // non_fin_proc(i_proc)=0; // essai + } + else + {cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours + << " tyfront ne doit jamais etre nul !! "; + Sortie(1); + } ; +// }; // essai +// i_proc++; // essai +// if (i_proc > nb_proc-1) // essai +// i_proc = 1; // essai + }; temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu ////-------debug //cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank() // << " vecglob final = " << vecglob << flush; ////------fin debug - }; + }; #endif //#ifdef UTILISATION_MPI @@ -1402,10 +1539,12 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid }; retour = false; }; +temps_cpu_chargement.Arret_du_comptage(); #ifdef UTILISATION_MPI + temps_attente.Mise_en_route_du_comptage(); ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process + temps_attente.Arret_du_comptage(); #endif - temps_cpu_chargement.Arret_du_comptage(); return retour; }; @@ -1426,32 +1565,64 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid ,const ParaAlgoControle & pa ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD) { -#ifdef UTILISATION_MPI - // cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées - if (ParaGlob::Monde()->rank() != 0) - return true; -#endif temps_cpu_chargement.Mise_en_route_du_comptage(); bool retour = true; // init par défaut try - {// pour tous les maillages, pour tous les éléments on effectue une initialisation éventuelle + { + #ifndef UTILISATION_MPI + // pour tous les maillages, pour tous les éléments on effectue une initialisation éventuelle int nb_mail = lesMail->NbMaillage(); for (int imail = 1;imail<=nb_mail;imail++) { int nb_ele = lesMail->Nombre_element(imail); for (int iele =1;iele<=nb_ele;iele++) lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement(); }; - + #else + // cas d'un calcul multi-CPU , si cpu 0, idem cas non parallèle + if (ParaGlob::Monde()->rank() == 0) + {int nb_mail = lesMail->NbMaillage(); + for (int imail = 1;imail<=nb_mail;imail++) + { int nb_ele = lesMail->Nombre_element(imail); + for (int iele =1;iele<=nb_ele;iele++) + lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement(); + }; + } + else + {// on va parcourir les éléments associés au cpu + // on récupère la distribution d'éléments concernant le cpu en cours + // si c'est le cpu 0 on initialise tous les éléments + const Tableau < list >& tab_list_elem_cpu = + ParaGlob::param->const_List_element_CPU_en_cours(); + // la taille est identique à nbMailMax, sauf si c'est le cpu 0, là le tableau est vide et il n'y + // aura pas de boucle, (ou plutôt on sortira directement de la boucle + // le cas CPU 0 est traité à part + int nb_mail_distrib = tab_list_elem_cpu.Taille(); + for (int imail =1; imail<= nb_mail_distrib; imail++) + {const list & list_elem_cpu= tab_list_elem_cpu(imail); // pour simplifier + // on balaie les éléments nécessaires + list ::const_iterator il,ilfin=list_elem_cpu.end(); + for (il = list_elem_cpu.begin();il != ilfin;il++) + { int iele = (*il); + lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement(); + }; + }; + }; + #endif + // récup bool avec_raid = pa.Var_charge_externe(); int cas_assemblage = (assemb.Nb_cas_assemb()).n; // récup du cas d'assemblage int posi = Id_nom_ddl("X1") -1; int dim = ParaGlob::Dimension(); - - // $$$--- cas des forces ponctuelles ---$$$ // on regarde si l'espace de travail est axi-symétrique, si oui on utilise une dimension réduite int dima=dim; // c'est dima qui est utiliser pour la mise en place des efforts ponctuelles if (ParaGlob::AxiSymetrie()) dima--; + + // $$$--- cas des forces ponctuelles ---$$$ + #ifdef UTILISATION_MPI + // cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0uniquement + if (ParaGlob::Monde()->rank() == 0) + #endif // on parcours le tableau tabPonctuel // ici il n'y a pas d'implication sur la raideur for (int i=1;i<= tabPonctuel.Taille();i++) @@ -1590,6 +1761,10 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des torseurs de forces ponctuelles ---$$$ + #ifdef UTILISATION_MPI + // cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0 uniquement + if (ParaGlob::Monde()->rank() == 0) + #endif for (int i=1;i<= tabTorseurPonct.Taille();i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabTorseurPonct_i = tabTorseurPonct(i); @@ -1708,11 +1883,25 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid }; }; + #ifdef UTILISATION_MPI + // on définit les conteneurs de passage d'info + int proc_en_cours = ParaGlob::Monde()->rank(); + int index_transfert; // index pour incrémenter dans les tableaux + bool premier_passage = true; + if (proc_en_cours != 0) + { + #endif + + // $$$--- cas des forces surfaciques ---$$$ // il y a une implication éventuelle sur la raideur int tabsurfactaille = tabFsurfac.Taille(); if ( tabsurfactaille != 0) - {// on parcours le tableau tabFsurfac dans le repère absolu + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabFsurfac dans le repère absolu for (int i=1;i<= tabsurfactaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabFsurfac_i = tabFsurfac(i); @@ -1730,82 +1919,122 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid int nbref = ref.Taille(); Coordonnee vforce; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); - // récupération de la force de référence - // on traite en fonction du fait que c'est un champ ou non - switch (tabFsurfac_i.Champ()) - { case 1: // c'est un champ de valeurs - vforce = (tabFsurfac_i.Vect_de_coordonnee(ns)); break; - case 2: // c'est un champ de fonctions - // pour l'instant, le seul cas est celui des fonctions du temps - // on récupère les courbes pour les dim composantes - { switch (dima) - { case 3 : {Courbe1D * pt_courbe_force_ns_3 = - lesCourbes1D->Trouve(tabFsurfac_i.Nom_vect(ns,3)); - vforce(3) = pt_courbe_force_ns_3->Valeur(Temps_courant()); - } - case 2 : {Courbe1D * pt_courbe_force_ns_2 = - lesCourbes1D->Trouve(tabFsurfac_i.Nom_vect(ns,2)); - vforce(2) = pt_courbe_force_ns_2->Valeur(Temps_courant()); - } - case 1 : {Courbe1D * pt_courbe_force_ns_1 = - lesCourbes1D->Trouve(tabFsurfac_i.Nom_vect(ns,1)); - vforce(1) = pt_courbe_force_ns_1->Valeur(Temps_courant()); - } - }; - break; - } - case 0: default:// ce n'est pas un champ - vforce = (tabFsurfac_i.Vect_de_coordonnee(1)); break; - }; + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); + // récupération de la force de référence + // on traite en fonction du fait que c'est un champ ou non + switch (tabFsurfac_i.Champ()) + { case 1: // c'est un champ de valeurs + vforce = (tabFsurfac_i.Vect_de_coordonnee(ns)); break; + case 2: // c'est un champ de fonctions + // pour l'instant, le seul cas est celui des fonctions du temps + // on récupère les courbes pour les dim composantes + { switch (dima) + { case 3 : {Courbe1D * pt_courbe_force_ns_3 = + lesCourbes1D->Trouve(tabFsurfac_i.Nom_vect(ns,3)); + vforce(3) = pt_courbe_force_ns_3->Valeur(Temps_courant()); + } + case 2 : {Courbe1D * pt_courbe_force_ns_2 = + lesCourbes1D->Trouve(tabFsurfac_i.Nom_vect(ns,2)); + vforce(2) = pt_courbe_force_ns_2->Valeur(Temps_courant()); + } + case 1 : {Courbe1D * pt_courbe_force_ns_1 = + lesCourbes1D->Trouve(tabFsurfac_i.Nom_vect(ns,1)); + vforce(1) = pt_courbe_force_ns_1->Valeur(Temps_courant()); + } + }; + break; + } + case 0: default:// ce n'est pas un champ + vforce = (tabFsurfac_i.Vect_de_coordonnee(1)); break; + }; - // on regarde si jamais on a une dépendance à des grandeurs globales - const string & nomF_charge = tabFsurfac_i.NomF_charge(); - Fonction_nD * pt_fonct = NULL; - if(nomF_charge.length()) - {pt_fonct = lesFonctionsnD->Trouve(tabFsurfac_i.NomF_charge()); - if (pt_fonct->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales - {// on vérifie qu'en retour on a un scalaire ou un vecteur de dimension = la dimension de l'espace - Tableau & tava = pt_fonct->Valeur_pour_variables_globales(); // pour simplifier - if (pt_fonct->NbComposante() == 1) - {vforce *= tava(1);} - else if (pt_fonct->NbComposante() == dima) - {switch (dima) - { case 3 : vforce(3) *= tava(3); - case 2 : vforce(2) *= tava(2); - case 1 : vforce(1) *= tava(1); - }; - } - else - {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD avec grandeur(s) globale(s)" - << " cas des forces surfaciques sur la ref: "<< tabFsurfac_i.NomRef() - << " en retour, le nombre de composante est different de 1 et la dimension de l'espace : " - << dima << endl; - Sortie(1); - }; - // on désactive la fonction nD car elle a déjà été utilisée - pt_fonct = NULL; - }; - }; - - // maintenant deux cas: soit avec ou sans courbes de charge - if(pt_courbe == NULL) - {if (!nomF_charge.length()) // pas de courbe et pas de fonction nD - { vforce *= coeff;} // cas d'une grandeur fixe - else // sinon il ne reste plus qu'à intégrer l'échelle - { vforce *= tabFsurfac_i.Echelle_courbe();}; - } - else //sinon c'est idem avec ou sans fonction nD car c'est déjà intégré - { // cas d'une courbe de charge calcul de la valeur du coeff de charge - double coeff_charge = (pt_courbe->Valeur(Temps_courant())) * tabFsurfac_i.Echelle_courbe(); - vforce *= coeff_charge; - }; - // -- appel du calcul du second membre et de la raideur éventuelle + // on regarde si jamais on a une dépendance à des grandeurs globales + const string & nomF_charge = tabFsurfac_i.NomF_charge(); + Fonction_nD * pt_fonct = NULL; + if(nomF_charge.length()) + {pt_fonct = lesFonctionsnD->Trouve(tabFsurfac_i.NomF_charge()); + if (pt_fonct->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales + {// on vérifie qu'en retour on a un scalaire ou un vecteur de dimension = la dimension de l'espace + Tableau & tava = pt_fonct->Valeur_pour_variables_globales(); // pour simplifier + if (pt_fonct->NbComposante() == 1) + {vforce *= tava(1);} + else if (pt_fonct->NbComposante() == dima) + {switch (dima) + { case 3 : vforce(3) *= tava(3); + case 2 : vforce(2) *= tava(2); + case 1 : vforce(1) *= tava(1); + }; + } + else + {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD avec grandeur(s) globale(s)" + << " cas des forces surfaciques sur la ref: "<< tabFsurfac_i.NomRef() + << " en retour, le nombre de composante est different de 1 et la dimension de l'espace : " + << dima << endl; + Sortie(1); + }; + // on désactive la fonction nD car elle a déjà été utilisée + pt_fonct = NULL; + }; + }; + + // maintenant deux cas: soit avec ou sans courbes de charge + if(pt_courbe == NULL) + {if (!nomF_charge.length()) // pas de courbe et pas de fonction nD + { vforce *= coeff;} // cas d'une grandeur fixe + else // sinon il ne reste plus qu'à intégrer l'échelle + { vforce *= tabFsurfac_i.Echelle_courbe();}; + } + else //sinon c'est idem avec ou sans fonction nD car c'est déjà intégré + { // cas d'une courbe de charge calcul de la valeur du coeff de charge + double coeff_charge = (pt_courbe->Valeur(Temps_courant())) * tabFsurfac_i.Echelle_courbe(); + vforce *= coeff_charge; + }; + // -- appel du calcul du second membre et de la raideur éventuelle // correspondant à la charge surfacique Element::ResRaid resu = elem.SMR_charge_surfacique_I(vforce,pt_fonct,ref.NumeroFA(ns),pa); - // ((tabFsurfac_i.Coord())*coeff ,ref.NumeroFA(ns),pa); - // assemblage du second membre + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int num_face = ref.NumeroFA(ns); + // on change de conteneur pour permettre de calculer plusieurs chargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); + if (avec_raid) + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + + int tyfront = 5; // init par défaut du type de frontière + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_face,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; if (!ParaGlob::AxiSymetrie()) @@ -1817,7 +2046,9 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); - }; + } + #endif + }; }; }; }; @@ -1825,7 +2056,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des pressions ---$$$ int tabPresUniftaille = tabPresUnif.Taille(); if ( tabPresUniftaille != 0) - {// on parcours le tableau tabPresUnif + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabPresUnif for (int i=1;i<= tabPresUniftaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabPresUnif_i = tabPresUnif(i); @@ -1842,8 +2077,16 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid {// Maintenant les éléments et les surfaces associes int nbref = ref.Taille(); for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); double press_ac = 0.; // init // récupération de la pression de référence // on traite en fonction du fait que c'est un champ ou non @@ -1898,8 +2141,40 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // appel du calcul du second membre et de la raideur éventuelle // correspondant à la charge de type pression Element::ResRaid resu = elem.SMR_charge_pression_I(press_ac,pt_fonct,ref.NumeroFA(ns),pa); - // (coeff *(tabPresUnif_i.Val()),ref.NumeroFA(ns),pa); - // assemblage du second membre + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int num_face = ref.NumeroFA(ns); + // on change de conteneur pour permettre de calculer plusieurs chargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); + if (avec_raid) + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + + int tyfront = 5; // init par défaut du type de frontière + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_face,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; if (!ParaGlob::AxiSymetrie()) @@ -1911,7 +2186,9 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); - } + } + #endif + }; }; } } @@ -1922,7 +2199,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // direction localement pendant toute la transformation int PresUniDirtaille = PresUniDir.Taille(); if ( PresUniDirtaille != 0) - {// on parcours le tableau PresUniDir + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau PresUniDir for (int i=1;i<= PresUniDirtaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& PresUniDir_i = PresUniDir(i); @@ -1940,8 +2221,16 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid int nbref = ref.Taille(); Coordonnee press_uni; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (PresUniDir_i.Champ()) @@ -2015,7 +2304,42 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // correspondant à la charge de type pression // Vecteur pres_u = (PresUniDir_i.Coord()) * coeff; Element::ResRaid resu = elem.SMR_charge_presUniDir_I(press_uni,pt_fonct,ref.NumeroFA(ns),pa); - // assemblage du second membre + + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int num_face = ref.NumeroFA(ns); + // on change de conteneur pour permettre de calculer plusieurs chargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); + if (avec_raid) + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + + int tyfront = 5; // init par défaut du type de frontière + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_face,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + + { // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; if (!ParaGlob::AxiSymetrie()) @@ -2027,7 +2351,9 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); - }; + } + #endif + }; }; } } @@ -2035,7 +2361,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des forces lineique ---$$$ int tablineiquetaille = tabFlineique.Taille(); if ( tablineiquetaille != 0) - {// on parcours le tableau tabFlineique dans le repère absolu + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabFlineique dans le repère absolu for (int i=1;i<= tablineiquetaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabFlineique_i = tabFlineique(i); @@ -2053,8 +2383,16 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid int nbref = ref.Taille(); Coordonnee f_lin; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (tabFlineique_i.Champ()) @@ -2128,7 +2466,35 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // correspondant à la charge lineique // Vecteur f_lin = (tabFlineique_i.Coord()) * coeff; Element::ResRaid resu = elem.SMR_charge_lineique_I(f_lin,pt_fonct,ref.NumeroFA(ns),pa) ; - // assemblage du second membre + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int num_ligne = ref.NumeroFA(ns); + // on change de conteneur pour permettre de calculer plusieurs chargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); + if (avec_raid) + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + int tyfront = 2; // type de frontière ligne + // si on est en axi c'est interprété comme une force surfacique + // on ne change pas le type de frontière + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_ligne,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la ligne chargée const ElFrontiere* elfront = elem.Frontiere_lineique(ref.NumeroFA(ns)); // l'arrête frontière assemb.AssemSM (vecglob,*(resu.res),elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage @@ -2136,7 +2502,9 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); - }; + } + #endif + }; }; }; }; @@ -2144,7 +2512,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des forces lineiques suiveuses ---$$$ int tablineiqueSuivtaille = tabFlineiqueSuiv.Taille(); if ( tablineiqueSuivtaille != 0) - {// on parcours le tableau tabFlineiqueSuiv dans le repère global + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabFlineiqueSuiv dans le repère global for (int i=1;i<= tablineiqueSuivtaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim > & tabFlineiqueSuiv_i = tabFlineiqueSuiv(i); @@ -2162,8 +2534,16 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid int nbref = ref.Taille(); Coordonnee f_lin; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (tabFlineiqueSuiv_i.Champ()) @@ -2237,7 +2617,35 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // correspondant à la charge lineique // Vecteur f_lin = (tabFlineiqueSuiv_i.Coord()) * coeff; Element::ResRaid resu = elem.SMR_charge_lineique_Suiv_I(f_lin,pt_fonct,ref.NumeroFA(ns),pa) ; - // assemblage du second membre + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int num_ligne = ref.NumeroFA(ns); + // on change de conteneur pour permettre de calculer plusieurs chargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); + if (avec_raid) + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + int tyfront = 2; // type de frontière ligne + // si on est en axi c'est interprété comme une force surfacique + // on ne change pas le type de frontière + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_ligne,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la ligne chargée const ElFrontiere* elfront = elem.Frontiere_lineique(ref.NumeroFA(ns)); // l'arrête frontière assemb.AssemSM (vecglob,*(resu.res),elfront->DdlElem_const(),elfront->TabNoeud_const()); // assemblage @@ -2245,7 +2653,9 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); - }; + } + #endif + }; }; }; }; @@ -2253,7 +2663,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des forces volumiques ---$$$ int tabvoltaille = tabFvol.Taille(); if ( tabvoltaille != 0) - {// on parcours le tableau tabFvol dans le repère absolu + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau tabFvol dans le repère absolu for (int i=1;i<= tabvoltaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim >& tabFvol_i = tabFvol(i); @@ -2271,8 +2685,16 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid int nbref = ref.Taille(); Coordonnee f_vol; // init par défaut for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.Numero(ns)); + { int num_elem = ref.Numero(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // récupération de la force de référence // on traite en fonction du fait que c'est un champ ou non switch (tabFvol_i.Champ()) @@ -2348,14 +2770,42 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid bool volume_finale = !(tabFvol_i.Attribut() == "sur_volume_initial_"); // Vecteur f_vol = (tabFvol_i.Coord()) * coeff; Element::ResRaid resu = elem.SMR_charge_volumique_I(f_vol,pt_fonct,pa,volume_finale); - // assemblage du second membre - // il faut utiliser les noeuds et les ddlelement correspondant à l'élément - assemb.AssemSM (vecglob,*(resu.res),elem.TableauDdl(),elem.Tab_noeud()); // assemblage - // assemblage de la raideur si nécessaire + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int num_inter = 0; // ne sert pas ici + // on change de conteneur pour permettre de calculer plusieurs hargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); if (avec_raid) - // appel de la fonction adoc, via le pointeur de fonction - (assemb.*assembMat) (matglob,*(resu.raid),elem.TableauDdl(),elem.Tab_noeud()); - }; + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + int tyfront = 4; // type d'un volume + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_inter,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + { // assemblage du second membre + // il faut utiliser les noeuds et les ddlelement correspondant à l'élément + assemb.AssemSM (vecglob,*(resu.res),elem.TableauDdl(),elem.Tab_noeud()); // assemblage + // assemblage de la raideur si nécessaire + if (avec_raid) + // appel de la fonction adoc, via le pointeur de fonction + (assemb.*assembMat) (matglob,*(resu.raid),elem.TableauDdl(),elem.Tab_noeud()); + } + #endif + }; }; } }; @@ -2363,7 +2813,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des des pressions hydrostatiques ---$$$ int PresHydrotaille = PresHydro.Taille(); if ( PresHydrotaille != 0) - {// on parcours le tableau PresHydro + { + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau PresHydro for (int i=1;i<= PresHydrotaille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim > & PresHydro_i = PresHydro(i); @@ -2384,8 +2838,16 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // Maintenant les éléments et les surfaces associes int nbref = ref.Taille(); for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); double p_hydro = p_hydro_ref; // maintenant deux cas: soit avec ou sans courbes de charge if(pt_courbe == NULL) @@ -2401,7 +2863,40 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (PresHydro_i.Attribut() == "sans_limitation_") sans_limitation= true; Element::ResRaid resu = elem.SMR_charge_hydrostatique_I (N,p_hydro,ref.NumeroFA(ns),A,pa,sans_limitation) ; - // assemblage du second membre + + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_face = ref.NumeroFA(ns); + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int tyfront = 5; // init par défaut du type de frontière + if (ParaGlob::AxiSymetrie()) + // dans le cas axiSymétrique, les surfaces sont générées par les lignes, + {//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM }; + tyfront = 2;} + else // cas normale + {tyfront = 3; };// la surface + // on change de conteneur pour permettre de calculer plusieurs hargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); + if (avec_raid) + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_face,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + {// assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront = NULL; if (!ParaGlob::AxiSymetrie()) @@ -2413,7 +2908,9 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); - }; + }; + #endif + }; }; } }; @@ -2421,7 +2918,15 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // $$$--- cas des des efforts hydrodynamiques ---$$$ int coefHydroDynataille = coefHydroDyna.Taille(); if ( coefHydroDynataille != 0) - {// on parcours le tableau coefHydroDyna + {if (ParaGlob::AxiSymetrie()) // pas pris en compte + {cout << "\n *** erreur : le chargement hydrodynamique en axisymetrique n'est pas pris en compte ! "; + Sortie(1); + }; + + #ifdef UTILISATION_MPI + index_transfert=1; // index pour incrémenter dans les tableaux + #endif + // on parcours le tableau coefHydroDyna for (int i=1;i<= coefHydroDynataille;i++) { // recup de la reference correspondant au mot cle BlocCharge< BlocDdlLim > & coefHydroDyna_i = coefHydroDyna(i); @@ -2440,8 +2945,16 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid // récup du poids volumique poids volumique = ro * g, qui n'est pas soumis à la courbe de charge double poidvol = (coefHydroDyna_i.Val(1)); for (int ns=1;ns<= nbref;ns++) - { // récupération de l'élément fini - Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns)); + { int num_elem = ref.NumeroElem(ns); + int num_mail = ref.Nbmaille(); + #ifdef UTILISATION_MPI + // on ne continue que si l'élément est concerné + if (ParaGlob::param->Element_concerner(num_mail,num_elem) ) + {if (proc_en_cours != 0) + { + #endif + // récupération de l'élément fini + Element& elem = lesMail->Element_LesMaille(num_mail, num_elem); // maintenant deux cas: soit avec ou sans courbes de charge double coeff_charge=1.; if(pt_courbe != NULL) @@ -2450,7 +2963,39 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid Element::ResRaid resu = elem.SMR_charge_hydrodynamique_I(coefHydroDyna_i.Frot_fluid(),poidvol ,coefHydroDyna_i.Coef_aero_n(),ref.NumeroFA(ns),coeff_charge ,coefHydroDyna_i.Coef_aero_t(),pa) ; - // assemblage du second membre + + + #ifdef UTILISATION_MPI + // appel du calcul du second membre correspondant à la charge de type pression + // appel du calcul du second membre correspondant à la charge surfacique + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + int num_front = ref.NumeroFA(ns); + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); + Mat_pleine* pt_MAT = NULL; + int tyfront = 5; // init par défaut du type de frontière + switch (ParaGlob::Dimension()) + { case 3: {tyfront=3; break;};// la surface frontière + case 2: {tyfront=2; break;};// la ligne frontière + case 1: {tyfront=1; break;};// le point frontière + }; + // on change de conteneur pour permettre de calculer plusieurs hargements même si le transfert n'est pas terminé + SM_transfert = *(resu.res); + if (avec_raid) + {MAT_transfert = *(resu.raid); + pt_MAT = &MAT_transfert; + }; + temps_cpu_chargement.Arret_du_comptage(); + // appel du transfert et mise à jour de l'index des tableaux + Transfert_MatSm(premier_passage,tyfront, + num_front,SM_transfert, + pt_MAT,index_transfert, + num_mail,num_elem + ); + temps_cpu_chargement.Mise_en_route_du_comptage(); + } + }; + #else // cas non // + {// assemblage du second membre // il faut utiliser les noeuds et les ddlelement correspondant à la face chargée const ElFrontiere* elfront; switch (ParaGlob::Dimension()) @@ -2463,10 +3008,160 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid if (avec_raid) // appel de la fonction adoc, via le pointeur de fonction (assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const()); - }; + } + #endif + }; }; }; - }; //-- fin de hydrodyna + }; //-- fin de hydrodyna + + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu + // maintenant on s'occupe du cpu 0 +#ifdef UTILISATION_MPI + + // arrivée ici on va indiquer au CPU 0 que c'est fini + int tyfront = - proc_en_cours; // init par défaut du type de frontière + // le signe - indique une fin + // appel du transfert et mise à jour de l'index des tableaux + Vecteur& SM_transfert = tabV_transfert(index_transfert); // ne sert pas ici + Transfert_SM(premier_passage,tyfront, + 0,SM_transfert, + index_transfert,0,0 + ); + } + else // donc ici cas ou on a le rank == 0 et on récolte + { // récup d'un second membre et de la matrice + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + int nb_proc_terminer = 0; // permettra de terminer + // on va boucler sur les éléments récupérés des différents process + // jusqu'à ce que tous les éléments aient finis + premier_passage = true; + int index_transfert = 1; // on se sert du premier élément de tableau + int ne,nbMail,tyfront,num_front,taille_SM; // inter pour la persistance + int source; // le nb de la source émettante + mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier + mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier + mpi::request & reqs3 = tab_reqs3(index_transfert); // pour simplifier + Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier + Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier + Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert); // idem + while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront + { // on récupère un résultat de calcul + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu + temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu + reqs1 = six_faux_entiers.Irecup_MPI(mpi::any_source, 34); + mpi::status stat = reqs1.wait(); + temps_transfert_court.Arret_du_comptage(); // comptage cpu + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + ne = (int) six_faux_entiers(1); + nbMail = (int) six_faux_entiers(2); + tyfront = (int) six_faux_entiers(3); + num_front = (int) six_faux_entiers(4); + taille_SM = (int) six_faux_entiers(5); + index_transfert = six_faux_entiers(6); + source = stat.source(); + +////-------debug +//cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< ParaGlob::Monde()->rank() +//// << " recup CinqEntiers " << num_el_mail_tyfront_nufront << flush; +// << " recup six_faux_entiers " << six_faux_entiers << flush; +////-------fin debug +// int tyfront = num_el_mail_tyfront_nufront.trois; + if (tyfront > 0) + {Element& elem = lesMail->Element_LesMaille(nbMail,ne); + // def de SM et MAT avec la bonne dimension + SM_transfert.Change_taille(taille_SM); + if (MAT_transfert.Nb_ligne () != taille_SM) + MAT_transfert.Initialise(taille_SM,taille_SM); + // récupération des conteneurs ad hoc vecteur et raideur + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu + temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu + reqs2 = SM_transfert.Irecup_MPI(source, 35); + reqs2.wait(); // on attend que le conteneur soit rempli + // idem pour la matrice + reqs3 = MAT_transfert.Irecup_MPI(source,36); + temps_transfert_long.Arret_du_comptage(); // fin comptage cpu +////-------debug +//cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< ParaGlob::Monde()->rank() +// << " SM= " << SM << flush; +////-------fin debug + +// assemblage + + temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu + switch (tyfront) + { + case 1: // cas d'un point frontière + {const ElFrontiere* elfront =elem.Frontiere_points(num_front);// num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + // assemblage de la raideur si nécessaire + if (avec_raid) + // appel de la fonction adoc, via le pointeur de fonction + (assemb.*assembMat) (matglob,MAT_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + case 2: // cas d'une ligne + {const ElFrontiere* elfront = elem.Frontiere_lineique(num_front);// num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + // assemblage de la raideur si nécessaire + if (avec_raid) + // appel de la fonction adoc, via le pointeur de fonction + (assemb.*assembMat) (matglob,MAT_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + case 3: // cas d'une surface + {const ElFrontiere* elfront = elem.Frontiere_surfacique(num_front);//num_el_mail_tyfront_nufront.quatre); + assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + // assemblage de la raideur si nécessaire + if (avec_raid) + // appel de la fonction adoc, via le pointeur de fonction + (assemb.*assembMat) (matglob,MAT_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const()); + break; + } + case 4: // cas d'un volume + {assemb.AssemSM (vecglob,SM_transfert,elem.TableauDdl(),elem.Tab_noeud()); + // assemblage de la raideur si nécessaire + if (avec_raid) + // appel de la fonction adoc, via le pointeur de fonction + (assemb.*assembMat) (matglob,MAT_transfert,elem.TableauDdl(),elem.Tab_noeud()); + break; + } + default: + {cout << "\n erreur*** Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< proc_en_cours + << " le cas tyfront = " << tyfront << " n'est pas pris en compte pour l'instant !! "; + Sortie(1); + } ; + }; + } + else if (tyfront < 0) + {// on est dans le cas où un proc a terminé + nb_proc_terminer++; + } + else + {cout << "\n erreur*** Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< proc_en_cours + << " tyfront ne doit jamais etre nul !! "; + Sortie(1); + } ; + + }; + temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu +////-------debug +//cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< ParaGlob::Monde()->rank() +// << " vecglob final = " << vecglob << flush; +////------fin debug + }; +#endif + +//#ifdef UTILISATION_MPI +////-------debug +//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid poc= "<< proc_en_cours +// << " SM= " << vecglob << flush; +//#else +// cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid " +// << " SM= "; vecglob.Affiche(); +////------fin debug +//#endif + // affichage éventuelle de la matrice de raideur et du second membre diff --git a/Parametres/EnteteParaGlob.h b/Parametres/EnteteParaGlob.h index 0ead9de..f15274a 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.018" ; // numéro de version du logiciel + string ParaGlob::nbVersion = "7.019" ; // 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/TypeBase/Temps_CPU_HZpp.cc b/TypeBase/Temps_CPU_HZpp.cc index ea1d288..91ca7e5 100755 --- a/TypeBase/Temps_CPU_HZpp.cc +++ b/TypeBase/Temps_CPU_HZpp.cc @@ -34,55 +34,55 @@ short int Temps_CPU_HZpp::impre_schem_XML=0; // CONSTRUCTEURS : -// par défaut on initialise à défaut -Temps_CPU_HZpp::Temps_CPU_HZpp(): - temps_user(0),debut_temps_user(0),comptage_en_cours(false) - {}; +//// par défaut on initialise à défaut +//Temps_CPU_HZpp::Temps_CPU_HZpp(): +// temps_user(0),debut_temps_user(0),comptage_en_cours(false) +// {}; -// mise en route du comptage -void Temps_CPU_HZpp::Mise_en_route_du_comptage() - { -#ifdef UTILISATION_DE_LA_LIBRAIRIE_BOOST - if (!comptage_en_cours) - { comptage_en_cours = true; - // on récup le temps depuis le début : c'est la seule qui marche pour le cumul -//high_resolution_clock - // -- pour le temps user -// boost::chrono::process_user_cpu_clock::duration tuti_1 -// = boost::chrono::process_user_cpu_clock::now().time_since_epoch(); - boost::chrono::high_resolution_clock::duration tuti_1 - = boost::chrono::high_resolution_clock::now().time_since_epoch(); - // on transforme en microseconde -// debut_temps_user = boost::chrono::duration_cast(tuti_1); - debut_temps_user = boost::chrono::duration_cast(tuti_1); - }; -#endif - }; +//// mise en route du comptage +//void Temps_CPU_HZpp::Mise_en_route_du_comptage() +// { +//#ifdef UTILISATION_DE_LA_LIBRAIRIE_BOOST +// if (!comptage_en_cours) +// { comptage_en_cours = true; +// // on récup le temps depuis le début : c'est la seule qui marche pour le cumul +////high_resolution_clock +// // -- pour le temps user +//// boost::chrono::process_user_cpu_clock::duration tuti_1 +//// = boost::chrono::process_user_cpu_clock::now().time_since_epoch(); +// boost::chrono::high_resolution_clock::duration tuti_1 +// = boost::chrono::high_resolution_clock::now().time_since_epoch(); +// // on transforme en microseconde +//// debut_temps_user = boost::chrono::duration_cast(tuti_1); +// debut_temps_user = boost::chrono::duration_cast(tuti_1); +// }; +//#endif +// }; -// arrêt du comptage et cumul -void Temps_CPU_HZpp::Arret_du_comptage() - { // comptage -#ifdef UTILISATION_DE_LA_LIBRAIRIE_BOOST - if (comptage_en_cours) - { comptage_en_cours = false; - // on récup le temps en nano depuis le début - - // -- pour le temps user -// boost::chrono::process_user_cpu_clock::duration tuti_1 -// = boost::chrono::process_user_cpu_clock::now().time_since_epoch(); - boost::chrono::high_resolution_clock::duration tuti_1 - = boost::chrono::high_resolution_clock::now().time_since_epoch(); - // on transforme en microseconde et on incrémente -// temps_user += boost::chrono::duration_cast(tuti_1) - debut_temps_user; - temps_user += boost::chrono::duration_cast(tuti_1) - debut_temps_user; - }; - -#endif - }; +//// arrêt du comptage et cumul +//void Temps_CPU_HZpp::Arret_du_comptage() +// { // comptage +//#ifdef UTILISATION_DE_LA_LIBRAIRIE_BOOST +// if (comptage_en_cours) +// { comptage_en_cours = false; +// // on récup le temps en nano depuis le début +// +// // -- pour le temps user +//// boost::chrono::process_user_cpu_clock::duration tuti_1 +//// = boost::chrono::process_user_cpu_clock::now().time_since_epoch(); +// boost::chrono::high_resolution_clock::duration tuti_1 +// = boost::chrono::high_resolution_clock::now().time_since_epoch(); +// // on transforme en microseconde et on incrémente +//// temps_user += boost::chrono::duration_cast(tuti_1) - debut_temps_user; +// temps_user += boost::chrono::duration_cast(tuti_1) - debut_temps_user; +// }; +// +//#endif +// }; // affichage // si niveau = 1 ou plus, on a plus d'info pour le débug par exemple -void Temps_CPU_HZpp::Affiche(ostream & sort,int niveau) +void Temps_CPU_HZpp::Affiche(ostream & sort,int niveau) { // on arrondi en ms #ifdef UTILISATION_DE_LA_LIBRAIRIE_BOOST diff --git a/TypeBase/Temps_CPU_HZpp.h b/TypeBase/Temps_CPU_HZpp.h index ae0bf51..c812e4d 100755 --- a/TypeBase/Temps_CPU_HZpp.h +++ b/TypeBase/Temps_CPU_HZpp.h @@ -155,10 +155,32 @@ class Temps_CPU_HZpp // surcharge de l'operator d'ecriture friend ostream & operator << (ostream & sort , const Temps_CPU_HZpp & a); + private : + // VARIABLES PROTEGEES : + + // def des variables du process + bool comptage_en_cours; // indique si oui ou non on est dans une phase de comptage + // microseconds temps_user; + nanoseconds temps_user; + // def des variables de début: au lieu d'utiliser un time_point et une duration + // j'utilise directement des microsecondes car sinon tout est en nanoseconde et + // il faut redéfinir un compteur en microsecondes: c'est une solution possible qui a été faite + // dans Chrono_GR.h mais je ne suis pas sûr que 1) cela soit indispensable, 2) que cela soit pérenne + // car j'ai été obligé de récupérer du code de boost et de l'adapter du coup c'est une usine dont je ne + // suis pas sûr de bien tout maîtriser donc j'utilise une solution plus simple + // microseconds debut_temps_user; + nanoseconds debut_temps_user; + + // gestion schéma XML + static short int impre_schem_XML; + public : // CONSTRUCTEURS : - Temps_CPU_HZpp(); // par défaut, initialise à défaut - + // Temps_CPU_HZpp(); // par défaut, initialise à défaut + Temps_CPU_HZpp(): + temps_user(0),debut_temps_user(0),comptage_en_cours(false) + {}; + // constructeur de copie Temps_CPU_HZpp(const Temps_CPU_HZpp& tps): temps_user(tps.temps_user),debut_temps_user(tps.debut_temps_user) @@ -169,9 +191,46 @@ class Temps_CPU_HZpp // --- METHODES PUBLIQUES : // mise en route du comptage - void Mise_en_route_du_comptage(); + void Mise_en_route_du_comptage() + { + #ifdef UTILISATION_DE_LA_LIBRAIRIE_BOOST + if (!comptage_en_cours) + { comptage_en_cours = true; + // on récup le temps depuis le début : c'est la seule qui marche pour le cumul + //high_resolution_clock + // -- pour le temps user + // boost::chrono::process_user_cpu_clock::duration tuti_1 + // = boost::chrono::process_user_cpu_clock::now().time_since_epoch(); + boost::chrono::high_resolution_clock::duration tuti_1 + = boost::chrono::high_resolution_clock::now().time_since_epoch(); + // on transforme en microseconde + // debut_temps_user = boost::chrono::duration_cast(tuti_1); + debut_temps_user = boost::chrono::duration_cast(tuti_1); + }; + #endif + }; + // arrêt du comptage et cumul - void Arret_du_comptage(); + void Arret_du_comptage() + { // comptage + #ifdef UTILISATION_DE_LA_LIBRAIRIE_BOOST + if (comptage_en_cours) + { comptage_en_cours = false; + // on récup le temps en nano depuis le début + + // -- pour le temps user + // boost::chrono::process_user_cpu_clock::duration tuti_1 + // = boost::chrono::process_user_cpu_clock::now().time_since_epoch(); + boost::chrono::high_resolution_clock::duration tuti_1 + = boost::chrono::high_resolution_clock::now().time_since_epoch(); + // on transforme en microseconde et on incrémente + // temps_user += boost::chrono::duration_cast(tuti_1) - debut_temps_user; + temps_user += boost::chrono::duration_cast(tuti_1) - debut_temps_user; + }; + + #endif + }; + // indique si oui ou non, on est en phase de comptage // permet de fermer un comptage en catastrophe, bool Comptage_en_cours() const {return comptage_en_cours;}; @@ -218,24 +277,6 @@ class Temps_CPU_HZpp void SchemaXML_Temps_CPU_HZpp(ofstream& sort,const Enum_IO_XML enu) const ; - private : - // VARIABLES PROTEGEES : - - // def des variables du process - bool comptage_en_cours; // indique si oui ou non on est dans une phase de comptage -// microseconds temps_user; - nanoseconds temps_user; - // def des variables de début: au lieu d'utiliser un time_point et une duration - // j'utilise directement des microsecondes car sinon tout est en nanoseconde et - // il faut redéfinir un compteur en microsecondes: c'est une solution possible qui a été faite - // dans Chrono_GR.h mais je ne suis pas sûr que 1) cela soit indispensable, 2) que cela soit pérenne - // car j'ai été obligé de récupérer du code de boost et de l'adapter du coup c'est une usine dont je ne - // suis pas sûr de bien tout maîtriser donc j'utilise une solution plus simple -// microseconds debut_temps_user; - nanoseconds debut_temps_user; - - // gestion schéma XML - static short int impre_schem_XML; };