- mise en place calcul parallèle (MPI) dans algo RD

- idem pour le calcul des second membres (Algori)
- idem pour le chargement pression en explicite
- tests ok pour calcul MPI en RD avec pression
This commit is contained in:
Gérard Rio 2023-09-03 10:10:17 +02:00
parent 42083fc4aa
commit ce2d011450
32 changed files with 1744 additions and 254 deletions

View file

@ -154,8 +154,11 @@ Algori::Algori () : // par defaut
#ifndef UTILISATION_MPI
,lesTempsCpu(16)
#else
,lesTempsCpu(19),distribution_CPU_algo()
,temps_transfert_court(),temps_transfert_long(),temps_attente()
,lesTempsCpu(28),distribution_CPU_algo()
,temps_transfert_court_algo(),temps_transfert_long_algo(),temps_attente_algo()
,temps_transfert_court_matSm(),temps_transfert_long_matSm(),temps_attente_matSm()
,temps_transfert_court_charge(),temps_transfert_long_charge(),temps_attente_charge()
,temps_transfert_court_contact(),temps_transfert_long_contact(),temps_attente_contact()
#endif
//---------- stockage pour la transmission des grandeurs consultables -----
// ,stock_compteur(GENERIQUE_UNE_GRANDEUR_GLOBALE),val_stock_compteur(NULL)
@ -245,8 +248,11 @@ Algori::Algori (EnumTypeCalcul type,const bool avec_typeDeCal
#ifndef UTILISATION_MPI
,lesTempsCpu(16)
#else
,lesTempsCpu(19),distribution_CPU_algo()
,temps_transfert_court(),temps_transfert_long(),temps_attente()
,lesTempsCpu(28),distribution_CPU_algo()
,temps_transfert_court_algo(),temps_transfert_long_algo(),temps_attente_algo()
,temps_transfert_court_matSm(),temps_transfert_long_matSm(),temps_attente_matSm()
,temps_transfert_court_charge(),temps_transfert_long_charge(),temps_attente_charge()
,temps_transfert_court_contact(),temps_transfert_long_contact(),temps_attente_contact()
#endif
//---------- stockage pour la transmission des grandeurs consultables -----
@ -437,9 +443,17 @@ Algori::Algori (const Algori& algo) :
#ifndef UTILISATION_MPI
,lesTempsCpu(16)
#else
,lesTempsCpu(18),distribution_CPU_algo(algo.distribution_CPU_algo) // distribution de charge sur les CPU
,temps_transfert_court(algo.temps_transfert_court),temps_transfert_long(algo.temps_transfert_long)
,temps_attente(algo.temps_attente)
,lesTempsCpu(28),distribution_CPU_algo(algo.distribution_CPU_algo) // distribution de charge sur les CPU
,temps_transfert_court_algo(algo.temps_transfert_court_algo),temps_transfert_long_algo(algo.temps_transfert_long_algo)
,temps_attente_algo(algo.temps_attente_algo)
,temps_transfert_court_matSm(algo.temps_transfert_court_matSm),temps_transfert_long_matSm(algo.temps_transfert_long_matSm)
,temps_attente_matSm(algo.temps_attente_matSm)
,temps_transfert_court_charge(algo.temps_transfert_court_charge)
,temps_transfert_long_charge(algo.temps_transfert_long_charge)
,temps_attente_charge(algo.temps_attente_charge)
,temps_transfert_court_contact(algo.temps_transfert_court_contact)
,temps_transfert_long_contact(algo.temps_transfert_long_contact)
,temps_attente_contact(algo.temps_attente_contact)
#endif
//---------- stockage pour la transmission des grandeurs consultables -----
@ -606,9 +620,19 @@ void Algori::Preparation_conteneurs_interne(LesMaillages& lesMail)
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
// si calcul //:
// Temps_CPU_HZpp temps_transfert_court; // lesTempsCpu(17)
// Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_attente ; // lesTempsCpu(18)
// // cas d'un calcul parallèle: // passage des infos entre process
// Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(17)
// Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18)
// Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20)
// Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21)
// Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22)
// Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23)
// Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24)
// Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25)
// Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26)
// Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27)
// Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28)
// Tableau <Coordonnee3> lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties
// // via listeVarGlob, mais c'est les variables Temps_CPU_HZpp qui stockent
@ -658,8 +682,20 @@ void Algori::Preparation_conteneurs_interne(LesMaillages& lesMail)
listeVarGlob["tpsU_rech_contact"]=&lesTempsCpu(16)(1);
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle
listeVarGlob["tpsU_transfert_inter_cpu"]=&lesTempsCpu(17)(1);
listeVarGlob["tpsU_attente_inter_cpu"]=&lesTempsCpu(18)(1);
listeVarGlob["tpsU_transfert_court_inter_cpu_Algo"]=&lesTempsCpu(17)(1);
listeVarGlob["tpsU_attente_inter_cpu_Algo"]=&lesTempsCpu(18)(1);
listeVarGlob["tpsU_transfert_long_inter_cpu_Algo"]=&lesTempsCpu(19)(1);
listeVarGlob["tpsU_transfert_court_inter_cpu_Mat-Smloc"]=&lesTempsCpu(20)(1);
listeVarGlob["tpsU_attente_inter_cpu_Mat-Smloc"]=&lesTempsCpu(21)(1);
listeVarGlob["tpsU_transfert_long_inter_cpu-Mat-Smloc"]=&lesTempsCpu(22)(1);
listeVarGlob["tpsU_transfert_court_inter_cpu_charge"]=&lesTempsCpu(23)(1);
listeVarGlob["tpsU_transfert_long_inter_cpu_charge"]=&lesTempsCpu(24)(1);
listeVarGlob["tpsU_attente_inter_cpu_charge"]=&lesTempsCpu(25)(1);
listeVarGlob["tpsU_transfert_court_inter_cpu_contact"]=&lesTempsCpu(26)(1);
listeVarGlob["tpsU_transfert_long_inter_cpu_contact"]=&lesTempsCpu(27)(1);
listeVarGlob["tpsU_attente_inter_cpu_contact"]=&lesTempsCpu(28)(1);
#endif
// cas des vecteurs globaux
@ -1513,9 +1549,8 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
E_bulk = 0.; // init
P_bulk=0.; // init
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
{vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension()));
vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension()));
};
#ifdef UTILISATION_MPI
mpi::request reqs1;
mpi::request reqs2;
@ -1523,9 +1558,9 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
bool premier_passage = true;
#endif
// on gère les exceptions éventuelles en mettant le bloc sous surveillance
int nbMailMax = lesMail->NbMaillage();
try
{// boucle sur les elements
int nbMailMax = lesMail->NbMaillage();
#ifndef UTILISATION_MPI
// cas d'un calcul mono CPU
for (int nbMail =1; nbMail<= nbMailMax; nbMail++)
@ -1536,7 +1571,7 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
// cas d'un calcul multi-CPU
// on va parcourir les éléments associés au cpu
// on récupère la distribution d'éléments concernant le cpu en cours
const Tableau < list <int > > tab_list_elem_cpu = distribution_CPU_algo.List_element_CPU_en_cours();
const Tableau < list <int > >& tab_list_elem_cpu = distribution_CPU_algo.List_element_CPU_en_cours();
// la taille est identique à nbMailMax, sauf si c'est le cpu 0, là le tableau est vide et il n'y
// aura pas de boucle, (ou plutôt on sortira directement de la boucle
// le cas CPU 0 est traité à part
@ -1548,14 +1583,14 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
for (il = list_elem_cpu.begin();il != ilfin;il++)
{ int ne = (*il);
// on récupère un signal du process 0
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu
if (premier_passage) {premier_passage = false;}
else // on attend que les transferts soient finis
{reqs1.wait();
reqs2.wait();
reqs3.wait();
};
temps_attente.Arret_du_comptage(); // fin comptage cpu
temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu
#endif
//calcul de la raideur local et du residu local
@ -1596,6 +1631,24 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
Ass.AssembMatSym (matglob,*(resu.raid),el.TableauDdl(),taN); // de la raideur
else
Ass.AssembMatnonSym (matglob,*(resu.raid),el.TableauDdl(),taN); // de la raideur
#else
// cas d'un calcul parallèle, et CPU != 0
int num_process = ParaGlob::Monde()->rank();
if (num_process != 0)
{tempsRaidSmEner.Arret_du_comptage();
temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
DeuxEntiers num_el_et_mail(el.Num_elt(),el.Num_maillage());
// on transmet les numéros d'élément et de maillage
reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail);
// puis on transmets le vecteur résidu
reqs2 = resu.res->Ienvoi_MPI(0,25);
//puis la matrice
reqs3 = resu.raid->Ienvoi_MPI(0, 26);
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
tempsRaidSmEner.Mise_en_route_du_comptage();
};
#endif
// globalisation des énergies
energTotal += el.EnergieTotaleElement();
energHourglass += el.Energie_Hourglass();
@ -1615,24 +1668,6 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
// << " " << *(listeVarGlob["vol_total2D_avec_plan_xy"]) << endl;
// fin débug
};
#else
// cas d'un calcul parallèle, et CPU != 0
int num_process = ParaGlob::Monde()->rank();
if (num_process != 0)
{tempsRaidSmEner.Arret_du_comptage();
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
DeuxEntiers num_el_et_mail(el.Num_elt(),el.Num_maillage());
// on transmet les numéros d'élément et de maillage
reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail);
// puis on transmets le vecteur résidu
reqs2 = resu.res->Ienvoi_MPI(0,25);
//puis la matrice
reqs3 = resu.raid->Ienvoi_MPI(0, 26);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
tempsRaidSmEner.Mise_en_route_du_comptage();
};
#endif
// globalisation des temps cpu loi de comp et métrique
temps_lois_comportement += el.Temps_lois_comportement();
temps_lois_comportement -= temps_debut_lois_comportement;
@ -1701,11 +1736,6 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
entete = " affichage du second membre (puissance interne) avant condition limites ";
vglobin.Affichage_ecran(entete);
};
// -- on transfert en global les énergies internes
Transfert_ParaGlob_energies_internesLoisComp();
Transfert_ParaGlob_energies_hourglass_bulk_stab();
// idem pour les volumes entre plans
Transfert_ParaGlob_volume_entre_plans();
// -- calcul des intégrales éventuelles avec transfert en global
lesMail->Integration();
// --- debug ------- essai ----
@ -1718,9 +1748,6 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
if (permet_affichage >3) cout << "\n -- fin calcul second membre et raideur " << flush;
tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu
// --- debug ------- essai ----
// cout << "\temps cpu raid SM energ " << tempsRaidSmEner;
// --- fin debug ------- essai ----
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() == 0)
{ tempsRaidSmEner.Mise_en_route_du_comptage(); // comptage cpu
@ -1731,13 +1758,13 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
int nb_elem_deja_calcule = 0; // init
while (nb_elem_deja_calcule < total_elem)
{ // on récupère un résultat de calcul
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
DeuxEntiers num_el_et_mail;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 24, num_el_et_mail);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu
mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
temps_attente.Arret_du_comptage(); // fin comptage cpu
temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu
int ne = num_el_et_mail.un; // numero d'identification de l'element
int nbMail = num_el_et_mail.deux; // numéro de maillage
// d'où l'élément
@ -1745,16 +1772,16 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
// récupération des conteneurs ad hoc vecteur et raideur
int source = stat.source(); // récupération du numéro de la source
Vecteur * residu = el.Conteneur_Residu();
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
mpi::request reqs2 = residu->Irecup_MPI(source, 25);
Mat_pleine* raideur = el.Conteneur_raideur();
mpi::request reqs3 = raideur->Irecup_MPI(source, 26);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu
reqs2.wait(); // on attend que le conteneur soit rempli
reqs3.wait(); // on attend que le conteneur soit rempli
temps_attente.Arret_du_comptage(); // fin comptage cpu
temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu
Tableau<Noeud *>& taN = el.Tab_noeud(); // tableau de noeuds de l'el
// --- assemblage
@ -1767,18 +1794,21 @@ bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
nb_elem_deja_calcule++;
};
tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu
}
// else
// {// on récupère le dernier signal du process 0
//// std::string msg;
//// ParaGlob::Monde()->recv(0, 12, msg);
// // synchronisation ici de tous les process
// ParaGlob::Monde()->barrier();
// };
// synchronisation ici de tous les process
// ParaGlob::Monde()->barrier();
};
#endif
#ifdef UTILISATION_MPI
tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu
// récupération de toutes les énergies par le cpu 0
Algori::Passage_energiesEtVolumes();
tempsRaidSmEner.Mise_en_route_du_comptage(); // fin comptage cpu
#endif
// -- on transfert en global les énergies internes
Transfert_ParaGlob_energies_internesLoisComp();
Transfert_ParaGlob_energies_hourglass_bulk_stab();
// idem pour les volumes entre plans
Transfert_ParaGlob_volume_entre_plans();
// retour indiquant que tout c'est bien passé
return true ;
};
@ -1802,16 +1832,61 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur &
volume_total_matiere = 0.; // init
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension()));
#ifdef UTILISATION_MPI
mpi::request reqs1;
mpi::request reqs2;
Vecteur deux_faux_entiers(2);
bool premier_passage = true;
#endif
// on gère les exceptions éventuelles en mettant le bloc sous surveillance
try
{for (int nbMail =1; nbMail<= lesMail->NbMaillage(); nbMail++)
for (int ne=1; ne<= lesMail->Nombre_element(nbMail);ne++)
{ //calcul du residu local
{// boucle sur les elements
int nbMailMax = lesMail->NbMaillage();
#ifndef UTILISATION_MPI
// cas d'un calcul mono CPU
for (int nbMail =1; nbMail<= nbMailMax; nbMail++)
{int nemax = lesMail->Nombre_element(nbMail);
for (int ne=1; ne<= nemax;ne++)
{
#else
// cas d'un calcul multi-CPU
// on va parcourir les éléments associés au cpu
// on récupère la distribution d'éléments concernant le cpu en cours
const Tableau < list <int > > & tab_list_elem_cpu = distribution_CPU_algo.List_element_CPU_en_cours();
// la taille est identique à nbMailMax, sauf si c'est le cpu 0, là le tableau est vide et il n'y
// aura pas de boucle, (ou plutôt on sortira directement de la boucle
// le cas CPU 0 est traité à part
int nb_mail_distrib = tab_list_elem_cpu.Taille();
for (int nbMail =1; nbMail<= nb_mail_distrib; nbMail++)
{const list <int >& list_elem_cpu= tab_list_elem_cpu(nbMail); // pour simplifier
// on balaie les éléments nécessaires
list <int >::const_iterator il,ilfin=list_elem_cpu.end();
for (il = list_elem_cpu.begin();il != ilfin;il++)
{ int ne = (*il);
// on récupère un signal du process 0
temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu
if (premier_passage) {premier_passage = false;}
else // on attend que le premier transfert soit fini
{reqs1.wait();
};
temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu
#endif
//calcul du residu local
ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element
Tableau<Noeud *>& taN = el.Tab_noeud(); // tableau de noeuds de l'el
Temps_CPU_HZpp temps_debut_lois_comportement=el.Temps_lois_comportement(); // init
Temps_CPU_HZpp temps_debut_metrique_K_SM = el.Temps_metrique_K_SM(); // init
Vecteur* res = el.CalculResidu_tdt(pa);
////--- debug
//cout << "\n debug .... Algori::SecondMembreEnerg( "
// << "\n CPU= "<< ParaGlob::Monde()->rank();
// // vecteur résidu
//cout << "\n res = " << *res ;
//
////--- fin debug
////--- debug
//if (res->Max_val_abs() > 10)
// { cout << "\n debug .... Algori::SecondMembreEnerg( "
@ -1821,9 +1896,43 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur &
// };
//
////--- fin debug
#ifndef UTILISATION_MPI
// --- assemblage et calcul de grandeur globale, pour mono-CPU
// assemblage
Ass.AssemSM (vglobin,*res,el.TableauDdl(),taN); // du second membre
#else
// cas d'un calcul parallèle, et CPU != 0
int num_process = ParaGlob::Monde()->rank();
if (num_process != 0)
{tempsSecondMembreEnerg.Arret_du_comptage();
temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
// DeuxEntiers num_el_et_mail(el.Num_elt(),el.Num_maillage());
deux_faux_entiers(1) = (double ) el.Num_elt();
deux_faux_entiers(2) = (double ) el.Num_maillage();
// on transmet les numéros d'élément et de maillage
reqs1 = deux_faux_entiers.Ienvoi_MPI(0, 24);
// reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail);
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
// puis on transmets le vecteur résidu
temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu
if (!premier_passage)
reqs2.wait();
temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu
temps_transfert_long_matSm.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = res->Ienvoi_MPI(0,25);
temps_transfert_long_matSm.Arret_du_comptage(); // fin comptage cpu
tempsSecondMembreEnerg.Mise_en_route_du_comptage();
};
#endif
////--- debug
// { cout << "\n debug .... Algori::SecondMembreEnerg( ";
// // on recalcule pour le debug le vecteur résidu
// cout << "\n second membre local = " << (*res);
//// res = el.CalculResidu_tdt(pa);
// };
//--- fin debug
// globalisation des énergies
energTotal += el.EnergieTotaleElement();
energHourglass += el.Energie_Hourglass();
@ -1832,15 +1941,16 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur &
P_bulk += el.Puissance_Bulk();
// globalisation des volumes
volume_total_matiere += el.Volume();
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
{ const Coordonnee& volPlan = el.VolumePlan();
if (volPlan.Dimension())
vol_total2D_avec_plan_ref(nbMail) += volPlan;
};
// globalisation des temps cpu loi de comp et métrique
temps_lois_comportement += el.Temps_lois_comportement();
temps_lois_comportement -= temps_debut_lois_comportement;
temps_metrique_K_SM += el.Temps_metrique_K_SM();
temps_metrique_K_SM -= temps_debut_metrique_K_SM;
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
{ const Coordonnee& volPlan = el.VolumePlan();
if (volPlan.Dimension())
vol_total2D_avec_plan_ref(nbMail) += volPlan;
};
};
}
@ -1890,10 +2000,6 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur &
vglobin.Affichage_ecran(entete);
};
if (permet_affichage >3) cout << "\n -- fin calcul second membre " << flush;
// -- on transfert en global les énergies internes
Transfert_ParaGlob_energies_internesLoisComp();
Transfert_ParaGlob_energies_hourglass_bulk_stab();
// idem pour les volumes entre plans
//---- debug
// if (pa.CalVolTotalEntreSurfaceEtPlansRef())
// { //Tableau <Coordonnee> vol_total2D_avec_plan_ref; // volume total entre la surface et : yz, xz,xy
@ -1902,12 +2008,66 @@ bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur &
// << vol_total2D_avec_plan_ref(1) << flush;
// };
//---- fin debug
Transfert_ParaGlob_volume_entre_plans();
// -- calcul des intégrales éventuelles avec transfert en global
lesMail->Integration();
tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() == 0)
{ tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu
// récup du nombre total d'éléments, cumul sur tous les maillages
int total_elem = distribution_CPU_algo.NB_total_element();
// on va boucler sur les éléments récupérés des différents process
// jusqu'au nombre maxi d'élément
int nb_elem_deja_calcule = 0; // init
while (nb_elem_deja_calcule < total_elem)
{ tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu
// on récupère un résultat de calcul
temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
// DeuxEntiers num_el_et_mail;
// mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 24, num_el_et_mail);
reqs1 = deux_faux_entiers.Irecup_MPI(mpi::any_source, 24);
mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu
// temps_attente.Mise_en_route_du_comptage(); // comptage cpu
// mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
// temps_attente.Arret_du_comptage(); // fin comptage cpu
int ne = (int) deux_faux_entiers(1); //num_el_et_mail.un; // numero d'identification de l'element
int nbMail = (int) deux_faux_entiers(2);//num_el_et_mail.deux; // numéro de maillage
// d'où l'élément
ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne));
// récupération des conteneurs ad hoc vecteur et raideur
int source = stat.source(); // récupération du numéro de la source
Vecteur * residu = el.Conteneur_Residu();
tempsSecondMembreEnerg.Arret_du_comptage();
temps_transfert_long_matSm.Mise_en_route_du_comptage(); // comptage cpu
mpi::request reqs2 = residu->Irecup_MPI(source, 25);
reqs2.wait(); // on attend que le conteneur soit rempli
temps_transfert_long_matSm.Arret_du_comptage(); // fin comptage cpu
tempsSecondMembreEnerg.Mise_en_route_du_comptage();
Tableau<Noeud *>& taN = el.Tab_noeud(); // tableau de noeuds de l'el
// --- assemblage
Ass.AssemSM (vglobin,*residu,el.TableauDdl(),taN); // du second membre
// on incrémente le nombre d'élément traité
nb_elem_deja_calcule++;
};
tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu
};
// récupération de toutes les énergies par le cpu 0
tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu
Algori::Passage_energiesEtVolumes();
tempsSecondMembreEnerg.Mise_en_route_du_comptage();
#endif
tempsSecondMembreEnerg.Mise_en_route_du_comptage();
// -- on transfert en global les énergies internes
Transfert_ParaGlob_energies_internesLoisComp();
Transfert_ParaGlob_energies_hourglass_bulk_stab();
// idem pour les volumes entre plans
Transfert_ParaGlob_volume_entre_plans();
// retour indiquant que tout c'est bien passé
return true ;

View file

@ -741,9 +741,18 @@ class Algori
Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
Temps_CPU_HZpp temps_transfert_court ; // lesTempsCpu(17)
Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(19)
Temps_CPU_HZpp temps_attente ; // lesTempsCpu(18)
Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(17)
Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18)
Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19)
Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20)
Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21)
Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22)
Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23)
Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24)
Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25)
Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26)
Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27)
Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28)
#endif
Tableau <Coordonnee3> lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties
@ -1290,6 +1299,13 @@ class Algori
};
};
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle, passage des énergies, volumes
// a priori utilisée dans le calcul de raideur et second membres
void Passage_energiesEtVolumes();
#endif
};
/// @} // end of group

View file

@ -1893,9 +1893,18 @@ void Algori::Ecriture_base_info
sort << "\n tps_chargement "<< temps_chargement;
sort << "\n tps_rech_contact "<< temps_rech_contact;
#ifdef UTILISATION_MPI
sort << "\n tps_transfert_court_proc "<< temps_transfert_court;
sort << "\n tps_transfert_long_proc "<< temps_transfert_long;
sort << "\n tps_attente_proc "<< temps_attente;
sort << "\n tps_transfert_court_Algo "<< temps_transfert_court_algo;
sort << "\n tps_transfert_long_Algo "<< temps_transfert_long_algo;
sort << "\n tps_attente_Algo "<< temps_attente_algo;
sort << "\n tps_transfert_court_matSm "<< temps_transfert_court_matSm;
sort << "\n tps_transfert_long_matSm "<< temps_transfert_long_matSm;
sort << "\n tps_attente_matSm "<< temps_attente_matSm;
sort << "\n tps_transfert_court_charge "<< temps_transfert_court_charge;
sort << "\n tps_transfert_long_charge "<< temps_transfert_long_charge;
sort << "\n tps_attente_charge "<< temps_attente_charge;
sort << "\n tps_transfert_court_contact "<< temps_transfert_court_contact;
sort << "\n tps_transfert_long_contact "<< temps_transfert_long_contact;
sort << "\n tps_attente_contact "<< temps_attente_contact;
#endif
// ----- écriture éventuelle des paramètres de l'algorithme et informations particulières
@ -2084,9 +2093,18 @@ void Algori::Lecture_base_info(ifstream& ent,const int cas)
ent >> nom1 >> temps_chargement;
ent >> nom1 >> temps_rech_contact;
#ifdef UTILISATION_MPI
ent >> nom1 >> temps_transfert_court;
ent >> nom1 >> temps_transfert_long;
ent >> nom1 >> temps_attente;
ent >> nom1 >> temps_transfert_court_algo;
ent >> nom1 >> temps_transfert_long_algo;
ent >> nom1 >> temps_attente_algo;
ent >> nom1 >> temps_transfert_court_matSm;
ent >> nom1 >> temps_transfert_long_matSm;
ent >> nom1 >> temps_attente_matSm;
ent >> nom1 >> temps_transfert_court_charge;
ent >> nom1 >> temps_transfert_long_charge;
ent >> nom1 >> temps_attente_charge;
ent >> nom1 >> temps_transfert_court_contact;
ent >> nom1 >> temps_transfert_long_contact;
ent >> nom1 >> temps_attente_contact;
#endif
// --- lecture éventuelle des paramètres de l'algorithme

View file

@ -1194,6 +1194,12 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_
cout << "\n >>> changement de inter_nb_entre_relax de " << old_valeur
<< " en ==> "<< inter_nb_entre_relax;
};
// #ifdef UTILISATION_MPI
// // debug
// cout << "\n debug Algori::AmortissementCinetique N: " << icharge
// << " debut, proc= "<< ParaGlob::Monde()->rank() << flush;
// // fin debug
// #endif
// // dans le cas où l'on veut un amortissement individuel aux noeuds, on appelle la méthode spécifique
// int relax_vit_individuel = 0;
@ -1202,6 +1208,7 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_
//*** je ne comprends pas le test que j'ai mis ici: abscon !! 16 oct 2018
// on ne continue que s'il n'y a pas d'amortissement cinétique en route
bool relaxation_effectuee = false; // initialisation
if (!((icharge > nb_deb_test_amort_cinetique_noe) && amortissement_cinetique_au_noeud))
// ---- non la suite n'est pas bonne et converge beaucoup moins bien !!
// je le remplace : on test si on est en amortissement cinétique, et que le nombre d'itérations
@ -1224,7 +1231,6 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_
// si > 0 : indique que la procédure est active, et que, de manière consécutive, indique
// le nombre de fois où il y a eu baisse
bool relaxation_effectuee = false; // initialisation
bool relaxation_reactive = false; // "
if ((amortissement_cinetique)&&(icharge != 0) && (icharge > nb_deb_test_amort_cinetique))
{ // on regarde si l'énergie cinétique a déjà été calculée, sinon on la calcule
@ -1326,6 +1332,7 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_
&& (nb_depuis_derniere_relax >= inter_nb_entre_relax))
{ // cas ou on met en place l'amortissement
V.Zero();relaxation_effectuee=true;
nb_depuis_derniere_relax = 0;
dernier_pic = pic_E_cint_t; // on sauvegarde
if (taille_moyenne_glissante != 1) // on remet tout à 0
@ -1387,7 +1394,7 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_
// on tente d'afficher que si l'amortissement a effectivement eu lieu
// if (relax_vit && pa.AfficheIncrEnergie())
if (relaxation_effectuee)
if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2))
{if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2))
{cout << "\n N:" << icharge << " relaxation cinetique effectuee "
<< " pic_E_cint_t("<<compteur_pic_energie<<") " << dernier_pic
<< " max_pic_E_cin= " << max_pic_E_cin;
@ -1407,17 +1414,59 @@ int Algori::AmortissementCinetique(const Vecteur & delta_ddl,const double& coef_
cout << " relaxation_re_active ";
cout << endl;
};
};
};
#ifdef UTILISATION_MPI
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
broadcast(*ParaGlob::Monde(), relaxation_effectuee, 0);
// debug
//cout << "\n debug Algori::AmortissementCinetique "
// << " barriere transfert relaxation_effectuee , proc= "<< ParaGlob::Monde()->rank() << flush;
// fin debug
// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu
#endif
#ifdef UTILISATION_MPI
// // debug
// cout << "\n debug Algori::AmortissementCinetique "
// << " relaxation_effectué = "<< relaxation_effectuee << " proc= "<< ParaGlob::Monde()->rank() << flush;
// // fin debug
if (relaxation_effectuee && (ParaGlob::Monde()->rank() != 0))
// if (relaxation_effectuee )
{ V.Zero();
// // debug
// cout << "\n debug Algori::AmortissementCinetique "
// << " mise à 0 du vecteur vitesse, proc= "<< ParaGlob::Monde()->rank() << flush;
// // fin debug
};
#endif
// dans le cas où l'on veut également un amortissement individuel aux noeuds, on appelle la méthode spécifique
// que si il n'y a pas eu d'amortissement cinétique global
int relax_vit_individuel = 0;
int relax_vit_individuel = 0;int retour = 0;
if (amortissement_cinetique_au_noeud && !relax_vit)
{ relax_vit_individuel=AmortissementCinetique_individuel_aux_noeuds(delta_ddl,coef_mass,X,mat_mass,icharge,V);
// ici on a relax_vit = 0 donc le retour est uniquement particularisé par relax_vit_individuel
return relax_vit_individuel;
retour = relax_vit_individuel;
}
else // sinon on est dans le cas où on a seulement un amortissement global et seul relax_vit donne une info à ce sujet
{ return relax_vit;};
{ retour = relax_vit;};
#ifdef UTILISATION_MPI
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
broadcast(*ParaGlob::Monde(), retour, 0);
temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu
//// debug
//cout << "\n debug Algori::AmortissementCinetique N: " << icharge
// << " fin, proc= "<< ParaGlob::Monde()->rank() << flush;
//// fin debug
#endif
return retour;
// la ligne qui suit est fausse car avec un "ou" le résultat est uniquement 1 ou 0, et en particulier
// les - sont supprimé !! ce qui pose un pb lorsque relax_vit = -1 !!

View file

@ -422,9 +422,18 @@ void Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(L
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
// si calcul //
// Temps_CPU_HZpp temps_transfert_court; // lesTempsCpu(17)
// Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_attente; // lesTempsCpu(18)
//Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(17)
//Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18)
//Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19)
//Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20)
//Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21)
//Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22)
//Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23)
//Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24)
//Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25)
//Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26)
//Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27)
//Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28)
//
// Tableau <Coordonnee3> lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties
@ -481,14 +490,34 @@ void Algori::Temps_CPU_HZpp_to_lesTempsCpu
temps_rech_contact = contact.Temps_cpu_Contact();
lesTempsCpu(16)(1)= temps_rech_contact.Temps_CPU_User();
#ifdef UTILISATION_MPI
lesTempsCpu(17)(1)= temps_transfert_court.Temps_CPU_User();
lesTempsCpu(19)(1)= temps_transfert_long.Temps_CPU_User();
lesTempsCpu(18)(1)= temps_attente.Temps_CPU_User();
// cas des temps de l'algorithme
lesTempsCpu(17)(1)= temps_transfert_court_algo.Temps_CPU_User();
lesTempsCpu(18)(1)= temps_transfert_long_algo.Temps_CPU_User();
lesTempsCpu(19)(1)= temps_attente_algo.Temps_CPU_User();
// des mat et SM locaux
lesTempsCpu(20)(1)= temps_transfert_court_matSm.Temps_CPU_User();
lesTempsCpu(21)(1)= temps_transfert_long_matSm.Temps_CPU_User();
lesTempsCpu(22)(1)= temps_attente_matSm.Temps_CPU_User();
// du chargement
temps_transfert_court_charge = charge.Temps_transfert_court();
lesTempsCpu(23)(1)= temps_transfert_court_charge.Temps_CPU_User();
temps_transfert_long_charge = charge.Temps_transfert_long();
lesTempsCpu(24)(1)= temps_transfert_long_charge.Temps_CPU_User();
temps_attente_charge = charge.Temps_attente();
lesTempsCpu(25)(1)= temps_attente_charge.Temps_CPU_User();
// du contact
temps_transfert_court_contact = contact.Temps_transfert_court();
lesTempsCpu(26)(1)= temps_transfert_court_contact.Temps_CPU_User();
temps_transfert_long_contact = contact.Temps_transfert_long();
lesTempsCpu(27)(1)= temps_transfert_long_contact.Temps_CPU_User();
temps_attente_contact = contact.Temps_attente();
lesTempsCpu(28)(1)= temps_attente_contact.Temps_CPU_User();
#endif
};
// idem la méthode de transfert si-dessus mais concerne uniquement les temps internes à l'algo
// utilisé par l'algo combiné
// ajoute au tableau passé en paramètre, les temps de l'algo
Tableau <Temps_CPU_HZpp> & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau <Temps_CPU_HZpp> & lesTsCpu)
{ // test éventuel de la taille du tableau
@ -513,9 +542,18 @@ Tableau <Temps_CPU_HZpp> & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau <
lesTsCpu(9) += tempsRaidSmEnerContact; // conversion de long long en double
lesTsCpu(10) += tempsSecondMembreEnergContact; // conversion de long long en double
#ifdef UTILISATION_MPI
lesTsCpu(17) += temps_transfert_court;
lesTsCpu(19) += temps_transfert_long;
lesTsCpu(18) += temps_attente;
lesTsCpu(17) += temps_transfert_court_algo;
lesTsCpu(18) += temps_transfert_long_algo;
lesTsCpu(19) += temps_attente_algo;
lesTsCpu(20) += temps_transfert_court_matSm;
lesTsCpu(21) += temps_transfert_long_matSm;
lesTsCpu(22) += temps_attente_matSm;
lesTsCpu(23) += temps_transfert_court_charge;
lesTsCpu(24) += temps_transfert_long_charge;
lesTsCpu(25) += temps_attente_charge;
lesTsCpu(26) += temps_transfert_court_contact;
lesTsCpu(27) += temps_transfert_long_contact;
lesTsCpu(28) += temps_attente_contact;
#endif
// retour
return lesTsCpu;
@ -542,9 +580,18 @@ void Algori::Arret_du_comptage_CPU()
temps_chargement.Arret_du_comptage();
temps_rech_contact.Arret_du_comptage();
#ifdef UTILISATION_MPI
temps_transfert_court.Arret_du_comptage();
temps_transfert_long.Arret_du_comptage();
temps_attente.Arret_du_comptage();
temps_transfert_court_algo.Arret_du_comptage();
temps_transfert_long_algo.Arret_du_comptage();
temps_attente_algo.Arret_du_comptage();
temps_transfert_court_matSm.Arret_du_comptage();
temps_transfert_long_matSm.Arret_du_comptage();
temps_attente_matSm.Arret_du_comptage();
temps_transfert_court_charge.Arret_du_comptage();
temps_transfert_long_charge.Arret_du_comptage();
temps_attente_charge.Arret_du_comptage();
temps_transfert_court_contact.Arret_du_comptage();
temps_transfert_long_contact.Arret_du_comptage();
temps_attente_contact.Arret_du_comptage();
#endif
};
@ -667,17 +714,54 @@ void Algori::Sortie_temps_cpu(const LesCondLim& lesCondLim
<< tempsSortieFilCalcul.Temps_CPU_User_milli()
;
#ifdef UTILISATION_MPI
sort_cpu << "\n tps__transfert_cour_inter_cpu "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_court.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_court.Temps_CPU_User_milli()
sort_cpu << "\n --------- dialogue inter cpu --------- ";
sort_cpu << "\n tps__transfert_court_Algo "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_court_algo.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_court_algo.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__transfert_long_inter_cpu "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_long.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_long.Temps_CPU_User_milli()
sort_cpu << "\n tps__transfert_long_Algo "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_long_algo.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_long_algo.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__attente_inter_cpu "
<< "("<< std::setw(nbdigit) << (100*temps_attente.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_attente.Temps_CPU_User_milli()
sort_cpu << "\n tps__attente_Algo "
<< "("<< std::setw(nbdigit) << (100*temps_attente_algo.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_attente_algo.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__transfert_court-Mat-Smloc "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_court_matSm.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_court_matSm.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__transfert_long-Mat-Smloc "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_long_matSm.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_long_matSm.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__attente-Mat-Smloc "
<< "("<< std::setw(nbdigit) << (100*temps_attente_matSm.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_attente_matSm.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__transfert_court_charge "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_court_charge.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_court_charge.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__transfert_long_charge "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_long_charge.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_long_charge.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__attente_charge "
<< "("<< std::setw(nbdigit) << (100*temps_attente_charge.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_attente_charge.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__transfert_court_contact "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_court_contact.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_court_contact.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__transfert_long_contact "
<< "("<< std::setw(nbdigit) << (100*temps_transfert_long_contact.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_transfert_long_contact.Temps_CPU_User_milli()
;
sort_cpu << "\n tps__attente_contact "
<< "("<< std::setw(nbdigit) << (100*temps_attente_contact.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_attente_contact.Temps_CPU_User_milli()
;
#endif
sort_cpu << "\n";
@ -1247,7 +1331,7 @@ Tableau <Algori *> Algori::New_tous_les_Algo
{// seule le process 0 a fait la résolution globale
// il gère seul également la convergence, mais il doit tenir au courant les autres process
// on utilise un std::array pour passer en une fois les infos
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
std::array<int,6> indic_convergence = {phase_de_convergence,nombre_de_bonnes_convergences
,nombre_de_mauvaises_convergences,a_converge
,a_converge_iterMoins1,nb_cycle_test_max_var_residu
@ -1263,7 +1347,7 @@ Tableau <Algori *> Algori::New_tous_les_Algo
a_converge_iterMoins1 = indic_convergence[4];
nb_cycle_test_max_var_residu = indic_convergence[5];
};
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu
};
// globalisation des grandeurs globales: proc de calcul -> maitre puis transmission à ParaGlob
// et transmission aux proc de calcul:
@ -1339,6 +1423,102 @@ Tableau <Algori *> Algori::New_tous_les_Algo
};
// cas d'un calcul parallèle, passage des énergies, volumes
// a priori utilisée dans le calcul de raideur et second membres
void Algori::Passage_energiesEtVolumes()
{ mpi::request reqs1;
bool premier_passage = true;
// récupération de toutes les énergies par le cpu 0
// on dit à tous les process d'attendre sauf le master
////------------- debug --------
//cout << "\n debug Algori::Passage_energiesEtVolumes() "
// << "\n barriere avant transfert énergies , proc= "<< ParaGlob::Monde()->rank() << flush;
//
////------------- fin debug --------
// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
// on crée un vecteur intermédiaire pour le passage d'information
int dim_tav_double = 0;int tail_tab = vol_total2D_avec_plan_ref.Taille();
for (int i=1;i<= tail_tab;i++)
dim_tav_double += vol_total2D_avec_plan_ref(i).Dimension();
Vecteur v_val_inter(8+dim_tav_double);
int num_process = ParaGlob::Monde()->rank();
if (num_process != 0)
{temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
//on rempli le vecteur de passage
v_val_inter(1) =energTotal.EnergieElastique();
v_val_inter(2) =energTotal.DissipationPlastique();
v_val_inter(3) =energTotal.DissipationVisqueuse();
v_val_inter(4)=energHourglass;
v_val_inter(5)=energStabiliMembBiel;
v_val_inter(6)=E_bulk;
v_val_inter(7)=P_bulk;
v_val_inter(8)=volume_total_matiere;
int indice = 1;
for (int i=1;i<= tail_tab;i++)
{ int dim_coord = vol_total2D_avec_plan_ref(i).Dimension();
if (dim_coord)
for (int j=1;j<= dim_coord;j++,indice++)
v_val_inter(8+indice)=vol_total2D_avec_plan_ref(i)(j);
};
// //------------- debug --------
// cout << "\n debug Algori::Passage_energiesEtVolumes() num_process= "<< num_process;
// cout << "\n v_val_inter= "<<v_val_inter;
//
// //------------- fin debug --------
temps_transfert_court_matSm.Arret_du_comptage();
// on récupère un signal du process 0
temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu
if (premier_passage) {premier_passage = false;}
else // on attend que les transferts soient finis
{reqs1.wait();
};
temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
// on transmet le vecteur intermédiaire
reqs1 = v_val_inter.Ienvoi_MPI(0,27);
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
}
else // cas du proocess 0
{int nb_process = ParaGlob::Monde()->size();
for (int i=1;i<nb_process;i++) // < absolu, donc le max c'est nb_process-1
{temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
reqs1 = v_val_inter.Irecup_MPI(mpi::any_source, 27);
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
temps_attente_matSm.Mise_en_route_du_comptage(); // comptage cpu
reqs1.wait(); // on attend que le conteneur soit rempli
temps_attente_matSm.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
//on récupère les info via le vecteur de passage
EnergieMeca inter(v_val_inter(1),v_val_inter(2),v_val_inter(3));
energTotal += inter;
energHourglass += v_val_inter(4);
energStabiliMembBiel += v_val_inter(5);
E_bulk += v_val_inter(6);
P_bulk += v_val_inter(7);
volume_total_matiere += v_val_inter(8);
int indice = 1;
for (int i=1;i<= tail_tab;i++)
{ int dim_coord = vol_total2D_avec_plan_ref(i).Dimension();
if (dim_coord)
for (int j=1;j<= dim_coord;j++,indice++)
vol_total2D_avec_plan_ref(i)(j) += v_val_inter(8+indice);
};
temps_transfert_court_matSm.Arret_du_comptage(); // fin comptage cpu
};
};
////------------- debug --------
//cout << "\n debug Algori::Passage_energiesEtVolumes() ";
//cout << "\n energTotal "<<energTotal
// << " volume_total_matiere "<< volume_total_matiere;
//
////------------- fin debug --------
};
#endif

View file

@ -927,8 +927,14 @@ void AlgoriCombine::AutreSortieTempsCPU(ofstream& sort,const int ) const
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
// cas d'un calcul parallèle: // passage des infos entre process
// Temps_CPU_HZpp temps_transfert_court ; // lesTempsCpu(17)
// Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_attente ; // lesTempsCpu(18)
// Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(18)
// Temps_CPU_HZpp temps_attente ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(20)
// Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(21)
// Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(22)
// Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(23)
// Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(24)
// Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(25)
sort << "\n tps_InitAlgo " << lesTsCpu(1);
sort << "\n tps_MiseAJourAlgo "<< lesTsCpu(2);
sort << "\n tps_CalEquilibre "<< lesTsCpu(3);

View file

@ -53,7 +53,8 @@ void AlgoriCombine::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif
@ -128,7 +129,8 @@ void AlgoriCombine::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
{ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
#ifdef UTILISATION_MPI
// passage de l'équilibrage à ParaGlob
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
#endif
charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
tab_algo(i)->InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
@ -185,7 +187,8 @@ void AlgoriCombine::MiseAJourAlgo(ParaGlob * paraGlob,LesMaillages * lesMail,
{ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
#ifdef UTILISATION_MPI
// passage de l'équilibrage à ParaGlob
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
#endif
charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
@ -260,7 +263,8 @@ void AlgoriCombine::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
#ifdef UTILISATION_MPI
// passage de l'équilibrage à ParaGlob
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
#endif
charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
@ -330,7 +334,8 @@ void AlgoriCombine::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
#ifdef UTILISATION_MPI
// passage de l'équilibrage à ParaGlob
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
#endif
charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
@ -407,7 +412,8 @@ void AlgoriCombine::FinCalcul(ParaGlob * paraGlob,LesMaillages * lesMail,LesRefe
{ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
#ifdef UTILISATION_MPI
// passage de l'équilibrage à ParaGlob
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
#endif
charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());

View file

@ -963,7 +963,8 @@ void AlgoriRungeKutta::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif

View file

@ -805,7 +805,8 @@ void AlgoriDynaExpli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif

View file

@ -296,7 +296,8 @@ void AlgoriDynaExpli_zhai::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * les
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif

View file

@ -285,7 +285,8 @@ void Algori_chung_lee::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif

View file

@ -1316,9 +1316,13 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
tempsInitialisation.Arret_du_comptage(); // temps cpu
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
temps_transfert_court_algo.Arret_du_comptage(); // comptage cpu
tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif
@ -1574,10 +1578,18 @@ void AlgoriRelaxDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
// choix de la matrice de masse, qui est en fait celle qui correspond au ddl Xi
// ici le numéro d'assemblage est celui de X car on projette bien sur des vitesses virtuelles c-a-d ddl X*.
#ifdef UTILISATION_MPI
// seule le process 0 s'occupe de la sortie
if (ParaGlob::Monde()->rank() == 0)
#endif
if (ParaGlob::NiveauImpression() > 2)
cout << "\n matrice masse principale: ";
mat_masse = Choix_matrice_masse(nbddl_X,mat_masse,lesMail,lesRef
,Ass1.Nb_cas_assemb(),lescontacts,lesCondLim);
#ifdef UTILISATION_MPI
// seule le process 0 s'occupe de la sortie
if (ParaGlob::Monde()->rank() == 0)
#endif
if (ParaGlob::NiveauImpression() > 2)
cout << "\n matrice masse secondaire: ";
mat_masse_sauve = Choix_matrice_masse(nbddl_X,mat_masse_sauve,lesMail,lesRef
@ -1988,9 +2000,11 @@ Vecteur V_ext(F_int_tdt);
};
}; // fin du switch sur compteur_demarrage
#ifdef UTILISATION_MPI
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
tempsCalEquilibre.Arret_du_comptage(); // temps cpu
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
broadcast(*ParaGlob::Monde(), arret_pilotage, 0);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu
tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
#endif
if (arret_pilotage) break; // si dans le switch précédent on a un arret de pilotage qui est demandé
@ -2251,9 +2265,20 @@ Vecteur V_ext(F_int_tdt);
// mise en place du chargement impose, c-a-d calcul de la puissance externe
// si pb on sort de la boucle
//// debug
//cout << "\n debug algo relax "
// << " barriere avant chargement , proc= "<< ParaGlob::Monde()->rank()
// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush;
//// fin debug
// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
if (!(charge->ChargeSecondMembre_Ex_mecaSolid
(Ass1,lesMail,lesRef,vglobex,pa,lesCourbes1D,lesFonctionsnD)))
{ Change_PhaseDeConvergence(-10);break;};
//// debug
//cout << "\n debug algo relax "
// << " après chargement , proc= "<< ParaGlob::Monde()->rank()
// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush;
//// fin debug
//// autre essai !!
//if (pa.ContactType()==4) // dans le cas d'un contact de type 4
@ -2277,12 +2302,22 @@ Vecteur V_ext(F_int_tdt);
vglobaal += vglobex ;vglobaal += vglobin ;
// on calcul la matrice de masse qui est très particulière dans le cas de la relaxation dynamique
// c'est la partie la plus importante de l'algo: l'adaptation de la masse en continue
//-- *** on utilise le volume de chaque élément, donc il doit avoir été calculé
//-- *** dans le cas historique : type_calcul_mass ==1
// on utilise le volume de chaque élément, donc il doit avoir été calculé
// -- ** ce qui est le cas au moment du calcul des forces internes
// sauf en MPI
#ifdef UTILISATION_MPI
// seule le process 0 s'occupe du calcul de la masse
if (ParaGlob::Monde()->rank() == 0)
{
#endif
CalculEnContinuMatriceMasse
(relax_vit_acce,lesMail,Ass1,compteur
,diversStockage,lesRef,X1,premier_calcul,lescontacts
,force_recalcul_masse,lesFonctionsnD);
#ifdef UTILISATION_MPI
};
#endif
// calcul des reactions de contact pour les noeuds esclaves
// dans le repere absolu ( pour la sortie des infos sur le contact)
@ -2400,10 +2435,45 @@ Vecteur V_ext(F_int_tdt);
};
#ifdef UTILISATION_MPI
};
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
broadcast(*ParaGlob::Monde(), arretResidu, 0);
broadcast(*ParaGlob::Monde(), arret, 0);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
tempsCalEquilibre.Arret_du_comptage(); // temps cpu
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
// TroisEntiers les_arrets(arretResidu,arret,demande_de_break);
Vecteur trois_faux_entiers(3);
trois_faux_entiers(1) = (double) arretResidu;
trois_faux_entiers(2) = (double) arret;
trois_faux_entiers(3) = (double) demande_de_break;
////---- debug
//cout << "\n debug algo relax : barriere avant transfert les_arrets proc = " << ParaGlob::Monde()->rank()
// << " les_arrets= " << les_arrets << " compteur= " << compteur << " compteur_demarrage= " << compteur_demarrage << flush;
////--- fin debug
//// debug
//cout << "\n debug algo relax "
// << " barriere avant transfert les_arrets , proc= "<< ParaGlob::Monde()->rank() << flush;
//// fin debug
// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
// broadcast(*ParaGlob::Monde(), les_arrets, 0);
// broadcast(*ParaGlob::Monde(), trois_faux_entiers, 0);
trois_faux_entiers.Broadcast(0);
// operator MPI_Comm() const;
if (ParaGlob::Monde()->rank() != 0)
{arretResidu= (int) trois_faux_entiers(1); //les_arrets.un;
arret = (int) trois_faux_entiers(2); //les_arrets.deux;
demande_de_break = (int) trois_faux_entiers(3); //les_arrets.trois;
};
////---- debug
//cout << "\n debug algo relax : proc = " << ParaGlob::Monde()->rank()
// << " après transfer: les_arrets= " << les_arrets << " compteur= " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush;
////--- fin debug
////---- debug
//cout << "\n debug algo relax : proc = " << ParaGlob::Monde()->rank()
// << "\n on continue "<< flush;
////--- fin debug
temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu
tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
#endif
if (demande_de_break)
break;
@ -2430,19 +2500,46 @@ Vecteur V_ext(F_int_tdt);
// affichage éventuelle du vecteur solution : accélération
if (ParaGlob::NiveauImpression() >= 10)
{ string entete = " affichage du vecteur solution acceleration ";
acceleration_tdt.Affichage_ecran(entete); };
acceleration_tdt.Affichage_ecran(entete);
};
// retour des accélération dans les reperes generaux, dans le cas où ils ont ete modifie
// par des conditions linéaires
lesCondLim->RepInitiaux( acceleration_tdt,Ass3.Nb_cas_assemb());
#ifdef UTILISATION_MPI
}
else // s'il s'agit d'un process de calcul élémentaire
{sol = &vglobaal; // il faut affecter sol pour récupérer ensuite la solution
};
// s'il s'agit d'un process de calcul élémentaire ou non
// sol = &vglobaal; // il faut affecter sol pour récupérer ensuite la solution
// le process 0 transmet aux autres process le vecteur résultat
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
sol->Broadcast(0);
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
tempsCalEquilibre.Arret_du_comptage(); // temps cpu
temps_transfert_long_algo.Mise_en_route_du_comptage(); // comptage cpu
// sol->Broadcast(0);
//// debug
//cout << "\n debug algo relax "
// << " barriere avant transfert acceleration_tdt , proc= "<< ParaGlob::Monde()->rank()
// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush;
//// fin debug
// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
acceleration_tdt.Broadcast(0);
//// debug
//cout << "\n debug algo relax "
// << " barriere après transfert acceleration_tdt , proc= "<< ParaGlob::Monde()->rank()
// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage<< flush;
//// fin debug
temps_transfert_long_algo.Arret_du_comptage(); // fin comptage cpu
tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
// // debug
// cout << "\n debug algo relax , proc= "<< ParaGlob::Monde()->rank()
// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage << " acceleration: "
// << acceleration_tdt << flush;
// // fin debug
#else
// // debug
// cout << "\n debug algo relax "
// << " compteur = " << compteur << " compteur_demarrage= " << compteur_demarrage << " acceleration: ";
// acceleration_tdt.Affiche(); cout << flush;
// // fin debug
#endif
// effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée
@ -2484,6 +2581,11 @@ Vecteur V_ext(F_int_tdt);
|| ((typeCalRelaxation == 4) && (Cinetique_ou_visqueux(force_recalcul_masse)))
)
{ relax_vit_acce = AmortissementCinetique(delta_X,1.,X_tdt,*mat_masse_sauve,compteur,vitesse_tdt);
////---- debug
//cout << "\n debug algo relax : proc = " << ParaGlob::Monde()->rank()
// << "\n sortie relaxation: relax_vit_acce= " << relax_vit_acce << " compteur= " << compteur << flush;
////--- fin debug
// il faut re-updater les vitesses
// if (Abs(relax_vit_acce) == 1)
if (relax_vit_acce == 1) // il y a eu relaxation
@ -2544,7 +2646,9 @@ Vecteur V_ext(F_int_tdt);
#ifdef UTILISATION_MPI
// seule le process 0 a fait la résolution globale
// il gère seul également la convergence, mais il doit tenir au courant les autres process
tempsCalEquilibre.Arret_du_comptage(); // fin comptage cpu
Algori::Passage_indicConvergenceAuxProcCalcul();
tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
// ce qui permet le déroulement correct de la suite pour tous les process
#endif
@ -2839,6 +2943,15 @@ void AlgoriRelaxDyna::CalculMatriceMasse
dima--;
int nbddl_X = mat_masse->Nb_ligne();
int nbNoe = nbddl_X / dima;
#ifdef UTILISATION_MPI
// seule le process 0 s'occupe du calcul de la masse
// et celui-ci ne peut pas être le type historique : 1, car le volume de chaque élément
// n'est pas dispo (il est dispo dans les processus != 0)
if (type_calcul_mass == 1)
{ cout << "\n erreur : en calcul MPI, le type 1 de calcul de la masse n'est pas implante ";
Sortie(1);
};
#endif
switch (type_calcul_mass)

View file

@ -874,7 +874,8 @@ void AlgoriTchamwa::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif

View file

@ -52,7 +52,8 @@ void AlgoriNewmark::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif

View file

@ -52,10 +52,13 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
tempsInitialisation.Arret_du_comptage(); // temps cpu
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
temps_transfert_court_algo.Arret_du_comptage(); // comptage cpu
tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif
@ -969,9 +972,9 @@ decol = false; // pour debugger
{arret_iteration = true; }; //break;} // cas ou la méthode Convergence() demande l'arret
#ifdef UTILISATION_MPI
};
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
broadcast(*ParaGlob::Monde(), arret_iteration, 0);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu
#endif
if (arret_iteration)
break;
@ -1079,7 +1082,7 @@ decol = false; // pour debugger
{sol = &vglobaal; // il faut affecter sol pour récupérer ensuite la solution
};
// le process 0 transmet aux autres process le vecteur résultat
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
temps_transfert_long_algo.Mise_en_route_du_comptage(); // comptage cpu
//// essai pour remplacer broadcast
// int nb_process = ParaGlob::Monde()->size();
@ -1103,7 +1106,7 @@ decol = false; // pour debugger
// synchronisation ici de tous les process (à supprimer par la suite car n'est
// pas nécessaire pour le déroulementa priori ?? )
// ParaGlob::Monde()->barrier();
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
temps_transfert_long_algo.Arret_du_comptage(); // fin comptage cpu
#endif
// effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée

View file

@ -652,7 +652,8 @@ void AlgoBonelli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours());
paraGlob->Init_tableau (distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours());
};
#endif

View file

@ -198,6 +198,10 @@ Charge::Charge () : // constructeur par defaut
,temps_fin_non_stricte(0)
,nomtypeCharge(),ancien_num_pt_type5(0),num_pt_courant_type5(0)
,temps_cpu_chargement()
#ifdef UTILISATION_MPI
,temps_transfert_court(),temps_transfert_long(),temps_attente()
#endif
{// mise à jour de la valeur par défaut du chargement au cas où aucun chargement
// n'est définit
nomtypeCharge ="TYPE1";

View file

@ -257,6 +257,13 @@ class Charge
void Change_temps_fin_non_stricte(int methode)
{temps_fin_non_stricte = methode;};
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
const Temps_CPU_HZpp& Temps_transfert_court() const {return temps_transfert_court;} ;
const Temps_CPU_HZpp& Temps_transfert_long() const {return temps_transfert_long;} ;
const Temps_CPU_HZpp& Temps_attente() const {return temps_attente;} ;
#endif
// retourne le temps cumulés relatif à tous les chargements
const Temps_CPU_HZpp& Temps_cpu_chargement() const {return temps_cpu_chargement;};
@ -362,6 +369,13 @@ class Charge
// de la variation du pas de temps
// mise à jour avec la méthode : Change_temps_fin_non_stricte(int methode)
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
Temps_CPU_HZpp temps_transfert_court ;
Temps_CPU_HZpp temps_transfert_long ;
Temps_CPU_HZpp temps_attente ;
#endif
Temps_CPU_HZpp temps_cpu_chargement; // le temps cpu du à tous les chargements
// les autres parametres relatif au temps

View file

@ -45,15 +45,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
(Assemblage & assemb,LesMaillages * lesMail,LesReferences* lesRef,Vecteur& vecglob
,const ParaAlgoControle & pa,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD)
{
#ifdef UTILISATION_MPI
// cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées
if (ParaGlob::Monde()->rank() != 0)
return true;
#endif
temps_cpu_chargement.Mise_en_route_du_comptage(); // temps cpu
bool retour = true; // init par défaut
try
{
#ifndef UTILISATION_MPI
// pour tous les maillages, pour tous les éléments on effectue une initialisation éventuelle
int nb_mail = lesMail->NbMaillage();
for (int imail = 1;imail<=nb_mail;imail++)
@ -62,14 +58,50 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement();
};
#else
// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
// cas d'un calcul multi-CPU , si cpu 0, idem cas non parallèle
if (ParaGlob::Monde()->rank() == 0)
{int nb_mail = lesMail->NbMaillage();
for (int imail = 1;imail<=nb_mail;imail++)
{ int nb_ele = lesMail->Nombre_element(imail);
for (int iele =1;iele<=nb_ele;iele++)
lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement();
};
}
else
{// on va parcourir les éléments associés au cpu
// on récupère la distribution d'éléments concernant le cpu en cours
// si c'est le cpu 0 on initialise tous les éléments
const Tableau < list <int > >& 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 <int >& list_elem_cpu= tab_list_elem_cpu(imail); // pour simplifier
// on balaie les éléments nécessaires
list <int >::const_iterator il,ilfin=list_elem_cpu.end();
for (il = list_elem_cpu.begin();il != ilfin;il++)
{ int iele = (*il);
lesMail->Element_LesMaille(imail,iele).Initialisation_avant_chargement();
};
};
};
#endif
int posi = Id_nom_ddl("X1") -1;
int dim = ParaGlob::Dimension();
// $$$ --- cas des forces ponctuelles --- $$$
// on regarde si l'espace de travail est axi-symétrique, si oui on utilise une dimension réduite
int dima=dim; // c'est dima qui est utiliser pour la mise en place des efforts ponctuelles
if (ParaGlob::AxiSymetrie()) dima--;
// $$$ --- cas des forces ponctuelles --- $$$
#ifdef UTILISATION_MPI
// cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0 uniquement
if (ParaGlob::Monde()->rank() == 0)
#endif
// on parcours le tableau tabPonctuel
for (int i=1;i<= tabPonctuel.Taille();i++)
{ // recup de la reference correspondant au mot cle
@ -199,9 +231,12 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
};
};
// $$$ --- cas des torseurs de forces ponctuelles --- $$$
#ifdef UTILISATION_MPI
// cas d'un calcul //, les chargements aux noeuds sont calculés par le cpu 0 uniquement
if (ParaGlob::Monde()->rank() == 0)
#endif
// on parcours le tableau tabTorseurPonct
for (int i=1;i<= tabTorseurPonct.Taille();i++)
{ // recup de la reference correspondant au mot cle
@ -317,6 +352,25 @@ 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 <mpi::request > tab_reqs1(nb_proc);
Tableau <mpi::request > tab_reqs2(nb_proc);
Tableau <Vecteur > tabV_transfert(nb_proc);
Tableau <Vecteur > tab_six_faux_entiers(nb_proc);
for (int i=1;i<=nb_proc;i++)tab_six_faux_entiers(i).Change_taille(6);
int proc_en_cours = ParaGlob::Monde()->rank();
int index_transfert; // index pour incrémenter dans les tableaux
// la suite à virer qu'en c'est ok
Vecteur cinq_faux_entiers(5);
bool premier_passage = true;
if (proc_en_cours != 0)
{
#endif
// --- cas des forces surfaciques ---$$$
int tabsurfactaille = tabFsurfac.Taille();
if ( tabsurfactaille != 0)
@ -338,8 +392,16 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
Coordonnee vforce; // init par défaut
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
{ // récupération de l'élément fini
Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns));
{ int num_elem = ref.NumeroElem(ns);
int num_mail = ref.Nbmaille();
#ifdef UTILISATION_MPI
// on ne continue que si l'élément est concerné
if (ParaGlob::param->Element_concerner(num_mail,num_elem) )
{if (proc_en_cours != 0)
{
#endif
// récupération de l'élément fini
Element& elem = lesMail->Element_LesMaille(num_mail, num_elem);
// récupération de la force de référence
// on traite en fonction du fait que c'est un champ ou non
switch (tabFsurfac_i.Champ())
@ -412,7 +474,40 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
// appel du calcul du second membre correspondant à la charge surfacique
// Coordonnee vforce = tabFsurfac_i.Coord() * coeff;
Vecteur SM = elem.SM_charge_surfacique_E_tdt(vforce,pt_fonct,ref.NumeroFA(ns),pa);
// assemblage du second membre
#ifdef UTILISATION_MPI
temps_cpu_chargement.Arret_du_comptage();
// on récupère un signal du process 0
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
if (premier_passage) {premier_passage = false;}
else // on attend que les transferts soient finis
{reqs1.wait();
reqs2.wait();
};
temps_attente.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
int tyfront = 5; // init par défaut du type de frontière
if (ParaGlob::AxiSymetrie())
// dans le cas axiSymétrique, les surfaces sont générées par les lignes,
{//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM };
tyfront = 2;}
else // cas normale
{tyfront = 3; };// la surface
CinqEntiers num_el_mail_tyfront_nufront
(elem.Num_elt(),elem.Num_maillage()
,tyfront,ref.NumeroFA(ns),SM.Taille());
// on transmet les numéros d'élément et de maillage
reqs1 = ParaGlob::Monde()->isend(0, 34, num_el_mail_tyfront_nufront);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
// puis on transmets le vecteur résidu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM.Ienvoi_MPI(0,35);
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
temps_cpu_chargement.Mise_en_route_du_comptage();
}
};
#else // cas non //
{ // assemblage du second membre
// il faut utiliser les noeuds et les ddlelement correspondant à la face chargée
const ElFrontiere* elfront = NULL; // init
if (ParaGlob::AxiSymetrie())
@ -421,6 +516,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
};
};
};
@ -429,7 +526,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
// --- cas des pressions ---$$$
int tabPresUniftaille = tabPresUnif.Taille();
if ( tabPresUniftaille != 0)
{// on parcours le tableau tabPresUnif
{
#ifdef UTILISATION_MPI
index_transfert=0; // index pour incrémenter dans les tableaux
#endif
// on parcours le tableau tabPresUnif
for (int i=1;i<= tabPresUniftaille;i++)
{ // recup de la reference correspondant au mot cle
BlocCharge< BlocDdlLim<BlocIntensite> >& tabPresUnif_i = tabPresUnif(i);
@ -446,7 +547,14 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
{// Maintenant les éléments et les surfaces associes
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
{ // récupération de l'élément fini
{ int num_elem = ref.NumeroElem(ns);
int num_mail = ref.Nbmaille();
#ifdef UTILISATION_MPI
// on ne continue que si l'élément est concerné
if (ParaGlob::param->Element_concerner(num_mail,num_elem) )
{if (proc_en_cours != 0)
{
#endif// récupération de l'élément fini
Element& elem = lesMail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns));
double press_ac = 0.; // init
// récupération de la pression de référence
@ -499,9 +607,65 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
double coeff_charge = (pt_courbe->Valeur(Temps_courant())) * tabPresUnif_i.Echelle_courbe();
press_ac *= coeff_charge;
};
#ifdef UTILISATION_MPI
// appel du calcul du second membre correspondant à la charge de type pression
// double press_ac = (tabPresUnif_i.Val()) * coeff;
Vecteur SM = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,ref.NumeroFA(ns),pa);
// ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore
// en transfert vers le proc 0
index_transfert++;
if (index_transfert > nb_proc) // on fait une permutation circulaire sur un nombre = au nombre total de proc
// sachant qu'ici on a toujours le même proc, mais on considère qu'après nb_proc transferts, le premier de la liste
// est terminé
index_transfert = 1;// on revient au premier élément des tableaux de transfert
Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier
SM_transfert = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,ref.NumeroFA(ns),pa);
temps_cpu_chargement.Arret_du_comptage();
mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier
mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier
// on s'assure quand même que les précents transferts sont terminés
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
if (premier_passage) {premier_passage = false;}
else // on regarde l'activité , car au début avant, le balayage de tous les éléments des tableaux
{if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés
if (reqs2.active()) reqs2.wait();
};
temps_attente.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
int tyfront = 5; // init par défaut du type de frontière
if (ParaGlob::AxiSymetrie())
// dans le cas axiSymétrique, les surfaces sont générées par les lignes,
{//enum Enum_type_geom { POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM };
tyfront = 2;}
else // cas normale
{tyfront = 3; };// la surface
Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier
six_faux_entiers(1) = (double) elem.Num_elt();
six_faux_entiers(2) = (double) elem.Num_maillage();
six_faux_entiers(3) = (double) tyfront;
six_faux_entiers(4) = (double) ref.NumeroFA(ns);
six_faux_entiers(5) = (double) SM_transfert.Taille();
six_faux_entiers(6) = (double) index_transfert;
// on transmet les numéros d'élément et de maillage
reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
// puis on transmets le vecteur résidu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM_transfert.Ienvoi_MPI(0,350+index_transfert);
// // debug
// cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank()
// // << " CinqEntiers= "<< num_el_mail_tyfront_nufront
// << " six_faux_entiers= " << six_faux_entiers
// << " SM= " << SM << flush;
// // fin debug
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
temps_cpu_chargement.Mise_en_route_du_comptage();
}
};
#else // cas non //
{ // appel du calcul du second membre correspondant à la charge de type pression
// ici on récupère une adresse car il n'y a pas de crainte d'écraser un vecteur déjà en cours
Vecteur& SM = elem.SM_charge_pression_E_tdt(press_ac,pt_fonct,ref.NumeroFA(ns),pa);
// assemblage du second membre
// il faut utiliser les noeuds et les ddlelement correspondant à la face chargée
const ElFrontiere* elfront = NULL; // init
@ -511,6 +675,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
};
};
}
@ -1040,6 +1206,181 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
};
}; //-- fin de hydrodyna
temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu
// maintenant on s'occupe du cpu 0
#ifdef UTILISATION_MPI
// arrivée ici on va indiquer au CPU 0 que c'est fini
index_transfert++;
if (index_transfert > nb_proc) // on fait une permutation circulaire sur un nombre = au nombre total de proc
index_transfert = 1;// on revient au premier élément des tableaux de transfert
mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier
// on s'assure quand même que les précents transferts sont terminés
temps_attente.Mise_en_route_du_comptage(); // comptage attente
if (premier_passage) {premier_passage = false;}
else {reqs1.wait();};
temps_attente.Arret_du_comptage(); // fin comptage attente
temps_transfert_court.Mise_en_route_du_comptage(); // comptage transfert cpu
int tyfront = - proc_en_cours; // init par défaut du type de frontière
// le signe - indique une fin
Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier
six_faux_entiers(1) = (double) 0;
six_faux_entiers(2) = (double) 0;
six_faux_entiers(3) = (double) tyfront;
six_faux_entiers(4) = (double) 0;
six_faux_entiers(5) = (double) 0;
six_faux_entiers(6) = (double) index_transfert;
reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34); // on transmet
temps_transfert_court.Arret_du_comptage(); // fin comptage transfert cpu
}
else // donc ici cas ou on a le rank == 0 et on récolte
{ // récup d'un second membre
temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu
int nb_proc_terminer = 0; // permettra de terminer
// on va boucler sur les éléments récupérés des différents process
// jusqu'à ce que tous les éléments aient finis
premier_passage = true;
int index_transfert = 1; // on se sert du premier élément de tableau
int ne,nbMail,tyfront,num_front,taille_SM; // inter pour la persistance
int source; // le nb de la source émettante
// int index_local_de_tab = 0;
mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier
mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier
Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier
Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
{ // on récupère un résultat de calcul
temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
reqs1 = six_faux_entiers.Irecup_MPI(mpi::any_source, 34);
mpi::status stat = reqs1.wait();
ne = (int) six_faux_entiers(1);
nbMail = (int) six_faux_entiers(2);
tyfront = (int) six_faux_entiers(3);
num_front = (int) six_faux_entiers(4);
taille_SM = (int) six_faux_entiers(5);
index_transfert = six_faux_entiers(6);
source = stat.source();
// // on parcourt les transferts possibles a priori
// if (premier_passage) // au premier passage on balaie tous les transferts possible
// {for (int i = 1;i< nb_proc;i++)
// tab_reqs1(i) = tab_six_faux_entiers(i).Irecup_MPI(mpi::any_source, 34);
// premier_passage=false;
// }
// else // sinon on on réenclanche seulement le cas que l'on vient de traiter
// { tab_reqs1(index_local_de_tab) = tab_six_faux_entiers(index_local_de_tab).Irecup_MPI(mpi::any_source, 34);
// };
// // on fait une boucle sur tous les status potentiels
// // on en sort quand on a trouvé un transfert terminé
// int j=1;
// do{ // début d'une boucle infinie
// boost::optional<mpi::status> 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<mpi::status> stat = req.test();
// if (stat) {
// std::cout << "From " << stat->source() << std::endl;
// std::cout << "Got " << rmsg << std::endl;
// std::cout << "Tagged " << stat->tag() << std::endl;
// break;
// }
// } while(1);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu
////-------debug
//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank()
//// << " recup CinqEntiers " << num_el_mail_tyfront_nufront << flush;
// << " recup six_faux_entiers " << six_faux_entiers << flush;
////-------fin debug
// int tyfront = num_el_mail_tyfront_nufront.trois;
if (tyfront > 0)
{Element& elem = lesMail->Element_LesMaille(nbMail,ne);
// def de SM avec la bonne dimension
SM_transfert.Change_taille(taille_SM);//num_el_mail_tyfront_nufront.cinq);
// récupération des conteneurs ad hoc vecteur et raideur
temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM_transfert.Irecup_MPI(source, 350+index_transfert);
reqs2.wait(); // on attend que le conteneur soit rempli
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
////-------debug
//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank()
// << " SM= " << SM << flush;
////-------fin debug
// assemblage
temps_cpu_chargement.Mise_en_route_du_comptage(); // comptage cpu
switch (tyfront)
{case 2:
{const ElFrontiere* elfront = elem.Frontiere_lineique(num_front);// num_el_mail_tyfront_nufront.quatre);
assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const());
break;
}
case 3:
{const ElFrontiere* elfront = elem.Frontiere_surfacique(num_front);//num_el_mail_tyfront_nufront.quatre);
assemb.AssemSM (vecglob,SM_transfert,elfront->DdlElem_const(),elfront->TabNoeud_const());
break;
}
default:
{cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours
<< " le cas tyfront = " << tyfront << " n'est pas pris en compte pour l'instant !! ";
Sortie(1);
} ;
};
}
else if (tyfront < 0)
{// on est dans le cas où un proc a terminé
nb_proc_terminer++;
}
else
{cout << "\n erreur*** Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< proc_en_cours
<< " tyfront ne doit jamais etre nul !! ";
Sortie(1);
} ;
};
temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu
////-------debug
//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid proc= "<< ParaGlob::Monde()->rank()
// << " vecglob final = " << vecglob << flush;
////------fin debug
};
#endif
//#ifdef UTILISATION_MPI
////-------debug
//cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid poc= "<< proc_en_cours
// << " SM= " << vecglob << flush;
//#else
// cout << "\n debug Charge::ChargeSecondMembre_Ex_mecaSolid "
// << " SM= "; vecglob.Affiche();
////------fin debug
//#endif
// affichage éventuelle du second membre
if (ParaGlob::NiveauImpression() >= 10)
{ string entete = " affichage du second membre apres chargement";
@ -1061,7 +1402,9 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
};
retour = false;
};
#ifdef UTILISATION_MPI
ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
#endif
temps_cpu_chargement.Arret_du_comptage();
return retour;
};

View file

@ -123,6 +123,11 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai
};
};
};
//// ----- debug
//cout << "\n debug Distribution_CPU::Calcul_Equilibrage_initiale ";
//Distribution_CPU::Affiche();
//cout << flush;
//// ----- fin debug ---
}
};
@ -136,7 +141,7 @@ void Distribution_CPU::Passage_Equilibrage_aux_CPU()
// mise à jour de ParaGlob, qui peut transmettre à tous
// la liste des numéros d'éléments concernés
ParaGlob::param->Init_tableau(&tab_list_maillage_element);
ParaGlob::param->Init_tableau(&tab_list_maillage_element,&tab_indic);
};
@ -233,6 +238,35 @@ void Distribution_CPU::load(Archive & ar, const unsigned int version)
}
};
// affichage des infos relatives à la distribution
void Distribution_CPU::Affiche() const
{ // comme on a des listes on sauvegarde explicitement
cout << "\n ------ Distribution ---------";
int nb_proc_calcul = tab_list_maillage_element.Taille();
cout << std::string(" nb total de proc de calcul : ") << nb_proc_calcul ;
for (int i_proc=1;i_proc<= nb_proc_calcul; i_proc++)
{cout << "\n ... cas du proc de calcul : "<< i_proc;
int nb_mail = tab_list_maillage_element(i_proc).Taille();
cout << std::string(" nb_mail considere = ")<< nb_mail ;
// on sauvegarde également le nombre total d'élément par maillage
// pour cela on se sert de tab_indic pour le premier cpu
for (int num_mail = 1; num_mail <= nb_mail;num_mail++)
cout << ", nb elem total du maillage " << num_mail << " => " << (int) tab_indic(1)(num_mail).Taille();
for (int imail=1;imail<=nb_mail;imail++)
{ const list <int >& list_maillage_element = tab_list_maillage_element(i_proc)(imail);
cout << " \n cas du maillage "<< imail
<< std::string(": nb elem pour le proc => ")<< (int) list_maillage_element.size()
<< " c-a-d les elem : \n ";
list <int >::const_iterator il, ilfin= list_maillage_element.end();
for (il = list_maillage_element.begin(); il != ilfin; il++)
{ int truc = (*il);
cout << truc << " , ";
};
};
};
}
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)

View file

@ -98,6 +98,11 @@ class Distribution_CPU
else return tab_vide_list_maillage_element;
};
// retourne le tableau indicateur permettant de dire si un élément est concerné par un CPU
// tab_indic(CPU)(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné
// par le CPU
const Tableau <Tableau < Tableau <bool > > > * Tab_indique_CPU_en_cours() const {return &tab_indic;};
// indicateur permettant de dire si un élément est concerné par un CPU donné
// tab_indic(CPU)(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné
// par le CPU
@ -107,6 +112,8 @@ class Distribution_CPU
// récup du nombre total d'éléments, cumul sur tous les maillages
int NB_total_element() const {return total_elem ;};
// affichage des infos relatives à la distribution
void Affiche() const ;
//============= lecture écriture dans base info ==========
// cas donne le niveau de la récupération

View file

@ -220,8 +220,18 @@ int main (int argc, const char * argv[]) {
#endif
#ifdef UTILISATION_MPI
// --- mise en route de la parallèlisation
mpi::environment env;
// def global d'un communicator
mpi::communicator world;
// on renseigne paraglob
ParaGlob::Init_boost_environnement(&env);
ParaGlob::Init_boost_communicator (& world);
#ifdef EN_DEBUG_MPI
// intro d'une boucle infinie pour mettre en place les process en debug
if (world.rank() == 0) //arrêt uniquement pour le proc 0
{volatile int i = 0;
char hostname[256];
gethostname(hostname, sizeof(hostname));
@ -232,13 +242,7 @@ int main (int argc, const char * argv[]) {
}
#endif
// --- mise en route de la parallèlisation
mpi::environment env;
// def global d'un communicator
mpi::communicator world;
// on renseigne paraglob
ParaGlob::Init_boost_environnement(&env);
ParaGlob::Init_boost_communicator (& world);
#endif

View file

@ -33,7 +33,7 @@
#include "ReferenceAF.h"
#include "MathUtil.h"
#include "ConstMath.h"
#include "LaList.h"
#include "LaLIST.H"
#include "CharUtil.h"
#include "TypeQuelconqueParticulier.h"

View file

@ -72,7 +72,7 @@
#include "Enum_interpol.h"
#include "LesReferences.h"
#include "Front.h"
#include "LaList.h"
#include "LaLIST.H"
#include "Nb_assemb.h"
#include "Ddl_enum_etendu.h"
#include "Droite.h"

View file

@ -41,7 +41,7 @@
EnumLangue ParaGlob::langueHZ = FRANCAIS; // langue utilisée pour les entrées sorties
int ParaGlob::nbComposantesTenseur = 1; // nombre de composantes par defaut a 1
int ParaGlob::nivImpression = 2; // niveau d'impression
string ParaGlob::nbVersion = "7.017" ; // numéro de version du logiciel
string ParaGlob::nbVersion = "7.018" ; // numéro de version du logiciel
string ParaGlob::NbVersionsurfichier = ""; // numéro de version lue en entrée fichier
int ParaGlob::nb_diggit_double_calcul= 17; // nombre de chiffre significatifs utilisé pour
// l'affichage des double précision pour l'archivage

View file

@ -148,8 +148,11 @@ class ParaGlob
static void Init_boost_communicator (boost::mpi::communicator * pt_world)
{world = pt_world;};
// -- equilibrage d'éléments
void Init_tableau (const Tableau <Tableau < list <int > > >* tab_list_maillage_element)
{tab_list_mail_element = tab_list_maillage_element;};
void Init_tableau (const Tableau <Tableau < list <int > > >* tab_list_maillage_element
,const Tableau <Tableau < Tableau <bool > > >* tab_indic)
{tab_list_mail_element = tab_list_maillage_element;
tabb_indic = tab_indic;
};
// retour des listes des éléments relatif au cpu en cours, c-a-d pour tous les maillages
// tab (j) donne la liste des éléments pour le maillage j
const Tableau < list <int > > & const_List_element_CPU_en_cours() const
@ -157,6 +160,11 @@ class ParaGlob
// spécifiquement, la liste des éléments pour le maillage j
const list <int > & const_List_element_CPU_en_cours(int j) const
{return (*tab_list_mail_element)(world->rank())(j);};
// indicateur permettant de dire si un élément est concerné par le cpu en cours
// tab_indic(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné
// par le CPU
bool Element_concerner(int mail,int ele) const
{return (*tabb_indic)(world->rank())(mail)(ele);};
#endif
// lecture du type de calcul et d'une liste de sous_type éventuel
@ -405,6 +413,11 @@ class ParaGlob
// pour le maillage j des num <élément> associés au cpu i
// ici il s'agit d'une copie de tab_list_maillage_element qui doit être mise à jour par Distribution_CPU
const Tableau <Tableau < list <int > > >* tab_list_mail_element;
// indicateur permettant de dire si un élément est concerné par un CPU donné
// tab_indic(CPU)(mail)(ele) : = 1 si l'élément ele du maillage mail est concerné
// par le CPU, il s'agit d'une copie qui doit être mise à jour par Distribution_CPU
const Tableau <Tableau < Tableau <bool > > >* tabb_indic;
#endif
//------------ info sur le temps ---------------
// c'est paraAlgoControle qui gère le temps, cependant paraglob sert de relais pour

View file

@ -37,8 +37,11 @@ short int Entier_et_Double::impre_schem_XML=0;
short int Deux_String::impre_schem_XML=0;
short int String_et_entier::impre_schem_XML=0;
short int Trois_String::impre_schem_XML=0;
short int quatre_string_un_entier::impre_schem_XML=0;
short int Quatre_string_un_entier::impre_schem_XML=0;
short int TroisEntiers::impre_schem_XML=0;
short int Deux_String_un_entier::impre_schem_XML=0;
short int QuatreEntiers::impre_schem_XML=0;
short int CinqEntiers::impre_schem_XML=0;
// sortie du schemaXML: en fonction de enu
void DeuxEntiers::SchemaXML_DeuxEntiers(ofstream& sort,const Enum_IO_XML enu) const
@ -68,7 +71,7 @@ istream & DeuxEntiers::LectXML_DeuxEntiers(istream & ent)
// surcharge d'ecriture en XML
ostream & DeuxEntiers::EcritXML_DeuxEntiers(ostream & sort)
{ sort << "<DeuxDoubles> un= "<< un << " deux= " << deux << "</DeuxDoubles>";
{ sort << "<DeuxEntiers> un= "<< un << " deux= " << deux << " </DeuxEntiers>";
return sort;
};
@ -136,7 +139,7 @@ istream & Entier_et_Double::LectXML_Entier_et_Double(istream & ent)
// surcharge d'ecriture en XML
ostream & Entier_et_Double::EcritXML_Entier_et_Double(ostream & sort)
{ sort << "<DeuxDoubles> un= "<< n << " deux= " << x << "</DeuxDoubles>";
{ sort << "<Entier_et_Double> un= "<< n << " deux= " << x << " </Entier_et_Double>";
return sort;
};
@ -204,7 +207,7 @@ istream & String_et_entier::LectXML_String_et_entier(istream & ent)
// surcharge d'ecriture en XML
ostream & String_et_entier::EcritXML_String_et_entier(ostream & sort)
{ sort << "<String_et_entier> nom1= "<< nom << " nom2= " << n << "</String_et_entier>";
{ sort << "<String_et_entier> nom1= "<< nom << " n= " << n << " </String_et_entier>";
return sort;
};
@ -239,17 +242,17 @@ istream & Trois_String::LectXML_Trois_String(istream & ent)
// surcharge d'ecriture en XML
ostream & Trois_String::EcritXML_Trois_String(ostream & sort)
{ sort << "<Deux_String> nom1= "<< nom1 << " nom2= " << nom2 << " nom3= " << nom3 << "</Deux_String>";
{ sort << "<Trois_String> nom1= "<< nom1 << " nom2= " << nom2 << " nom3= " << nom3 << " </Trois_String>";
return sort;
};
// sortie du schemaXML: en fonction de enu
void quatre_string_un_entier::SchemaXML_quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const
void Quatre_string_un_entier::SchemaXML_Quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const
{// sortie balisée simple
switch (enu)
{case XML_TYPE_GLOBAUX:
{sort << "\n <!-- ******************************************************* -->"
<< "\n<xs:complexType name=\"quatre_string_un_entier\" >"
<< "\n<xs:complexType name=\"Quatre_string_un_entier\" >"
<< "\n <xs:annotation>"
<< "\n <xs:documentation> type simple pour definir trois string </xs:documentation>"
<< "\n </xs:annotation>"
@ -259,12 +262,27 @@ void quatre_string_un_entier::SchemaXML_quatre_string_un_entier(ofstream& sort,c
<< "\n <xs:attribute name=\"n\" type=\"xs:string\" use=\"required\" />"
<< "\n <xs:attribute name=\"x\" type=\"xs:int\" use=\"required\" />"
<< "\n</xs:complexType>";
Trois_String::impre_schem_XML=1; // une seule sortie
Quatre_string_un_entier::impre_schem_XML=1; // une seule sortie
};
default: sort << "\n SchemaXML: cas non pris en compte " ;
};
};
// surcharge de lecture en XML
istream & Quatre_string_un_entier::LectXML_Quatre_string_un_entier(istream & ent)
{ string nom;
ent >> nom >> nom >> nom1 >> nom >> nom2 >> nom >> nom3 >> nom >> nom4 >> nom >> n >> nom;
return ent;
};
// surcharge d'ecriture en XML
ostream & Quatre_string_un_entier::EcritXML_Quatre_string_un_entier(ostream & sort)
{ sort << "<Quatre_string_un_entier> nom1= "<< nom1 << " nom2= " << nom2
<< " nom3= " << nom3 << "nom4= " << nom4 << " n= " << n << " </Quatre_string_un_entier>";
return sort;
};
// sortie du schemaXML: en fonction de enu
void TroisEntiers::SchemaXML_TroisEntiers(ofstream& sort,const Enum_IO_XML enu) const
{// sortie balisée simple
@ -276,8 +294,8 @@ void TroisEntiers::SchemaXML_TroisEntiers(ofstream& sort,const Enum_IO_XML enu)
<< "\n <xs:documentation> type simple pour definir deux entiers </xs:documentation>"
<< "\n </xs:annotation>"
<< "\n <xs:attribute name=\"un\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"un\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"deux\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"trois\" type=\"xs:int\" use=\"required\" />"
<< "\n</xs:complexType>";
TroisEntiers::impre_schem_XML=1; // une seule sortie
};
@ -286,6 +304,131 @@ void TroisEntiers::SchemaXML_TroisEntiers(ofstream& sort,const Enum_IO_XML enu)
};
};
// surcharge de lecture en XML
istream & TroisEntiers::LectXML_TroisEntiers(istream & ent)
{ string nom;
ent >> nom >> nom >> un >> nom >> deux >> nom >> trois >> nom;
return ent;
};
// surcharge d'ecriture en XML
ostream & TroisEntiers::EcritXML_TroisEntiers(ostream & sort)
{ sort << "<TroisEntiers> un= "<< un << " deux= " << deux << " trois= " << trois << " </TroisEntiers>";
return sort;
};
// sortie du schemaXML: en fonction de enu
void Deux_String_un_entier::SchemaXML_Deux_String_un_entier(ofstream& sort,const Enum_IO_XML enu) const
{// sortie balisée simple
switch (enu)
{case XML_TYPE_GLOBAUX:
{sort << "\n <!-- ******************************************************* -->"
<< "\n<xs:complexType name=\"Deux_String_un_entier\" >"
<< "\n <xs:annotation>"
<< "\n <xs:documentation> type simple pour definir trois string </xs:documentation>"
<< "\n </xs:annotation>"
<< "\n <xs:attribute name=\"n\" type=\"xs:string\" use=\"required\" />"
<< "\n <xs:attribute name=\"x\" type=\"xs:string\" use=\"required\" />"
<< "\n <xs:attribute name=\"x\" type=\"xs:int\" use=\"required\" />"
<< "\n</xs:complexType>";
Deux_String_un_entier::impre_schem_XML=1; // une seule sortie
};
default: sort << "\n SchemaXML: cas non pris en compte " ;
};
};
// surcharge de lecture en XML
istream & Deux_String_un_entier::LectXML_Deux_String_un_entier(istream & ent)
{ string nom;
ent >> nom >> nom >> nom1 >> nom >> nom2 >> nom >> n >> nom;
return ent;
};
// surcharge d'ecriture en XML
ostream & Deux_String_un_entier::EcritXML_Deux_String_un_entier(ostream & sort)
{ sort << "<Deux_String_un_entier> nom1= "<< nom1 << " nom2= " << nom2
<< " n= " << n << " </Deux_String_un_entier>";
return sort;
};
// sortie du schemaXML: en fonction de enu
void QuatreEntiers::SchemaXML_QuatreEntiers(ofstream& sort,const Enum_IO_XML enu) const
{// sortie balisée simple
switch (enu)
{case XML_TYPE_GLOBAUX:
{sort << "\n <!-- ******************************************************* -->"
<< "\n<xs:complexType name=\"QuatreEntiers\" >"
<< "\n <xs:annotation>"
<< "\n <xs:documentation> type simple pour definir quatre entiers </xs:documentation>"
<< "\n </xs:annotation>"
<< "\n <xs:attribute name=\"un\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"deux\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"trois\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"quatre\" type=\"xs:int\" use=\"required\" />"
<< "\n</xs:complexType>";
QuatreEntiers::impre_schem_XML=1; // une seule sortie
};
default: sort << "\n SchemaXML: cas non pris en compte " ;
};
};
// surcharge de lecture en XML
istream & QuatreEntiers::LectXML_QuatreEntiers(istream & ent)
{ string nom;
ent >> nom >> nom >> un >> nom >> deux >> nom >> trois >> nom >> quatre >> nom;
return ent;
};
// surcharge d'ecriture en XML
ostream & QuatreEntiers::EcritXML_QuatreEntiers(ostream & sort)
{ sort << "<QuatreEntiers> un= "<< un << " deux= " << deux << " trois= " << trois
<< " quatre= " << quatre << " </QuatreEntiers>";
return sort;
};
// sortie du schemaXML: en fonction de enu
void CinqEntiers::SchemaXML_CinqEntiers(ofstream& sort,const Enum_IO_XML enu) const
{// sortie balisée simple
switch (enu)
{case XML_TYPE_GLOBAUX:
{sort << "\n <!-- ******************************************************* -->"
<< "\n<xs:complexType name=\"CinqEntiers\" >"
<< "\n <xs:annotation>"
<< "\n <xs:documentation> type simple pour definir quatre entiers </xs:documentation>"
<< "\n </xs:annotation>"
<< "\n <xs:attribute name=\"un\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"deux\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"trois\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"quatre\" type=\"xs:int\" use=\"required\" />"
<< "\n <xs:attribute name=\"cinq\" type=\"xs:int\" use=\"required\" />"
<< "\n</xs:complexType>";
CinqEntiers::impre_schem_XML=1; // une seule sortie
};
default: sort << "\n SchemaXML: cas non pris en compte " ;
};
};
// surcharge de lecture en XML
istream & CinqEntiers::LectXML_CinqEntiers(istream & ent)
{ string nom;
ent >> nom >> nom >> un >> nom >> deux >> nom >> trois
>> nom >> quatre >> nom >> cinq >> nom;
return ent;
};
// surcharge d'ecriture en XML
ostream & CinqEntiers::EcritXML_CinqEntiers(ostream & sort)
{ sort << "<CinqEntiers> un= "<< un << " deux= " << deux << " trois= " << trois
<< " quatre= " << quatre << " cinq= " << cinq << " </CinqEntiers>";
return sort;
};

View file

@ -439,7 +439,7 @@ class Trois_String
///
/// cas de 4 string et un entier
class quatre_string_un_entier
class Quatre_string_un_entier
{
public :
// VARIABLES PUBLIQUES :
@ -462,39 +462,39 @@ class quatre_string_un_entier
public :
// CONSTRUCTEURS :
quatre_string_un_entier() : nom1(""),nom2(""),nom3(""),nom4(""),n(0) {};
quatre_string_un_entier(const string& n1, const string& n2,const string& n3,const string& n4,const int& nn) : nom1(n1),nom2(n2),nom3(n3),nom4(n4),n(nn) {};
quatre_string_un_entier(const quatre_string_un_entier & de) :
Quatre_string_un_entier() : nom1(""),nom2(""),nom3(""),nom4(""),n(0) {};
Quatre_string_un_entier(const string& n1, const string& n2,const string& n3,const string& n4,const int& nn) : nom1(n1),nom2(n2),nom3(n3),nom4(n4),n(nn) {};
Quatre_string_un_entier(const Quatre_string_un_entier & de) :
nom1(de.nom1),nom2(de.nom2),nom3(de.nom3),nom4(de.nom4),n(de.n) {};
// DESTRUCTEUR :
~quatre_string_un_entier() {};
~Quatre_string_un_entier() {};
// METHODES PUBLIQUES :
// surcharge de l'affectation
quatre_string_un_entier& operator= (const quatre_string_un_entier& de)
Quatre_string_un_entier& operator= (const Quatre_string_un_entier& de)
{ nom1 = de.nom1; nom2 = de.nom2; nom3 = de.nom3;nom4 = de.nom4;n=de.n;
return (*this);};
// surcharge de l'operator de lecture
friend istream & operator >> (istream & ent, quatre_string_un_entier & de)
friend istream & operator >> (istream & ent, Quatre_string_un_entier & de)
{ ent >> de.nom1 >> de.nom2 >> de.nom3>> de.nom4>> de.n; return ent;};
// surcharge de l'operator d'ecriture
friend ostream & operator << (ostream & sort , const quatre_string_un_entier & de)
friend ostream & operator << (ostream & sort , const Quatre_string_un_entier & de)
{ sort << de.nom1 <<" " << de.nom2 << " "<< de.nom3 << " "<< de.nom4 << " "<< de.n << " "; return sort;};
// surcharge de lecture en XML
istream & LectXML_quatre_string_un_entier(istream & ent);
istream & LectXML_Quatre_string_un_entier(istream & ent);
// surcharge d'ecriture en XML
ostream & EcritXML_quatre_string_un_entier(ostream & sort);
ostream & EcritXML_Quatre_string_un_entier(ostream & sort);
//Surcharge d'operateurs logiques
bool operator == (const quatre_string_un_entier& a) const
bool operator == (const Quatre_string_un_entier& a) const
{ if (( nom1 == a.nom1) && (nom2 == a.nom2)&& (nom3 == a.nom3)&& (nom4 == a.nom4)&& (n == a.n))
return true; else return false;};
bool operator != (const quatre_string_un_entier& a) const { return !(*this == a);};
bool operator != (const Quatre_string_un_entier& a) const { return !(*this == a);};
// sortie du schemaXML: en fonction de enu
void SchemaXML_quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const ;
void SchemaXML_Quatre_string_un_entier(ofstream& sort,const Enum_IO_XML enu) const ;
// surchage de l'opérateur de comparaison : ici elle se fait par decroissance
// est uniquement intéressante pour classer,
bool operator > (const quatre_string_un_entier& a) const
bool operator > (const Quatre_string_un_entier& a) const
{ if (this->nom1 > a.nom1)
{return true;}
else if (this->nom1 < a.nom1)
@ -530,7 +530,7 @@ class quatre_string_un_entier
}
}
};
bool operator >= (const quatre_string_un_entier& a) const
bool operator >= (const Quatre_string_un_entier& a) const
{ if (this->nom1 > a.nom1)
{return true;}
else if (this->nom1 < a.nom1)
@ -567,7 +567,7 @@ class quatre_string_un_entier
}
};
bool operator < (const quatre_string_un_entier& a) const
bool operator < (const Quatre_string_un_entier& a) const
{ if (this->nom1 < a.nom1)
{return true;}
else if (this->nom1 > a.nom1)
@ -604,7 +604,7 @@ class quatre_string_un_entier
}
};
bool operator <= (const quatre_string_un_entier& a) const
bool operator <= (const Quatre_string_un_entier& a) const
{ if (this->nom1 < a.nom1)
{return true;}
else if (this->nom1 > a.nom1)
@ -687,7 +687,7 @@ class TroisEntiers
{ ent >> de.un >> de.deux >> de.trois; return ent;};
// surcharge de l'operator d'ecriture
friend ostream & operator << (ostream & sort , const TroisEntiers & de)
{ sort << de.un <<" " << de.deux << " "<<" "<< de.trois; return sort;};
{ sort << de.un <<" " << de.deux << " "<< de.trois<< " "; return sort;};
// surcharge de lecture en XML
istream & LectXML_TroisEntiers(istream & ent);
// surcharge d'ecriture en XML
@ -937,4 +937,356 @@ class Deux_String_un_entier
};
/// @} // end of group
/// @addtogroup Les_conteneurs_ultra_basiques
/// @{
///
/// cas de 4 entiers
class QuatreEntiers
{
public :
// VARIABLES PUBLIQUES :
int un,deux,trois,quatre;
// gestion schéma XML
static short int impre_schem_XML;
#ifdef UTILISATION_MPI
private:
friend class boost::serialization::access;
// When the class Archive corresponds to an output archive, the
// & operator is defined similar to <<. Likewise, when the class Archive
// is a type of input archive the & operator is defined similar to >>.
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{ ar & un; ar & deux; ar & trois; ar & quatre;}
#endif
public :
// CONSTRUCTEURS :
QuatreEntiers() : un(0),deux(0),trois(0),quatre(0) {};
QuatreEntiers(int u, int v,int w,int ww) : un(u),deux(v),trois(w),quatre(ww) {};
QuatreEntiers(const QuatreEntiers & de) : un(de.un),deux(de.deux),trois(de.trois),quatre(de.quatre) {};
// DESTRUCTEUR :
~QuatreEntiers() {};
// METHODES PUBLIQUES :
// surcharge de l'affectation
QuatreEntiers& operator= (const QuatreEntiers& de)
{ un = de.un; deux = de.deux;trois = de.trois; quatre = de.quatre; return (*this);};
// surcharge de l'operator de lecture
friend istream & operator >> (istream & ent, QuatreEntiers & de)
{ ent >> de.un >> de.deux >> de.trois >> de.quatre; return ent;};
// surcharge de l'operator d'ecriture
friend ostream & operator << (ostream & sort , const QuatreEntiers & de)
{ sort << de.un <<" " << de.deux << " "<< de.trois<< " "<<de.quatre << " "; return sort;};
// surcharge de lecture en XML
istream & LectXML_QuatreEntiers(istream & ent);
// surcharge d'ecriture en XML
ostream & EcritXML_QuatreEntiers(ostream & sort);
//Surcharge d'operateurs logiques
bool operator == (const QuatreEntiers& a) const
{ if (( un==a.un) && (deux==a.deux) && (trois == a.trois)&& (quatre == a.quatre)) return true; else return false;};
bool operator != (const QuatreEntiers& a) const { return !(*this == a);};
// surchage de l'opérateur de comparaison
bool operator > (const QuatreEntiers& a) const
{ if (un > a.un)
{return true;}
else if (un < a.un)
{return false;}
else // egalité, on test le suivant
{if (deux > a.deux)
{return true;}
else if (deux < a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois > a.trois)
{return true;}
else if (trois < a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre > a.quatre)
{return true;}
else if (quatre < a.quatre)
{return false;}
else // egalité, on test le suivant
{return false;} // car c'est l'égalité parfaite donc pas supérieur
}
}
}
};
bool operator >= (const QuatreEntiers& a) const
{ if (un > a.un)
{return true;}
else if (un < a.un)
{return false;}
else // egalité, on test le suivant
{if (deux > a.deux)
{return true;}
else if (deux < a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois > a.trois)
{return true;}
else if (trois < a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre > a.quatre)
{return true;}
else if (quatre < a.quatre)
{return false;}
else // egalité, on test le suivant
{return true;} // car c'est l'égalité parfaite
}
}
}
};
bool operator < (const QuatreEntiers& a) const
{ if (un < a.un)
{return true;}
else if (un > a.un)
{return false;}
else // egalité, on test le suivant
{if (deux < a.deux)
{return true;}
else if (deux > a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois < a.trois)
{return true;}
else if (trois > a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre < a.quatre)
{return true;}
else if (quatre > a.quatre)
{return false;}
else // egalité, on test le suivant
{return false;} // car c'est l'égalité parfaite donc pas inférieur
}
}
}
};
bool operator <= (const QuatreEntiers& a) const
{ if (un < a.un)
{return true;}
else if (un > a.un)
{return false;}
else // egalité, on test le suivant
{if (deux < a.deux)
{return true;}
else if (deux > a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois < a.trois)
{return true;}
else if (trois > a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre < a.quatre)
{return true;}
else if (quatre > a.quatre)
{return false;}
else // egalité, on test le suivant
{return true;} // car c'est l'égalité parfaite
}
}
}
};
// sortie du schemaXML: en fonction de enu
void SchemaXML_QuatreEntiers(ofstream& sort,const Enum_IO_XML enu) const ;
};
/// @} // end of group
/// @addtogroup Les_conteneurs_ultra_basiques
/// @{
///
/// cas de 5 entiers
class CinqEntiers
{
public :
// VARIABLES PUBLIQUES :
int un,deux,trois,quatre,cinq;
// gestion schéma XML
static short int impre_schem_XML;
#ifdef UTILISATION_MPI
private:
friend class boost::serialization::access;
// When the class Archive corresponds to an output archive, the
// & operator is defined similar to <<. Likewise, when the class Archive
// is a type of input archive the & operator is defined similar to >>.
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{ ar & un; ar & deux; ar & trois; ar & quatre; ar & cinq;}
#endif
public :
// CONSTRUCTEURS :
CinqEntiers() : un(0),deux(0),trois(0),quatre(0),cinq(0) {};
CinqEntiers(int u, int v,int w1,int w2,int w3) : un(u),deux(v),trois(w1),quatre(w2),cinq(w3) {};
CinqEntiers(const CinqEntiers & de) : un(de.un),deux(de.deux),trois(de.trois),quatre(de.quatre)
,cinq(de.cinq) {};
// DESTRUCTEUR :
~CinqEntiers() {};
// METHODES PUBLIQUES :
// surcharge de l'affectation
CinqEntiers& operator= (const CinqEntiers& de)
{ un = de.un; deux = de.deux;trois = de.trois; quatre = de.quatre;
cinq = de.cinq; return (*this);};
// surcharge de l'operator de lecture
friend istream & operator >> (istream & ent, CinqEntiers & de)
{ ent >> de.un >> de.deux >> de.trois >> de.quatre >> de.cinq; return ent;};
// surcharge de l'operator d'ecriture
friend ostream & operator << (ostream & sort , const CinqEntiers & de)
{ sort << de.un <<" " << de.deux << " "<< de.trois<< " "<<de.quatre << " "
<< de.cinq << " "; return sort;};
// surcharge de lecture en XML
istream & LectXML_CinqEntiers(istream & ent);
// surcharge d'ecriture en XML
ostream & EcritXML_CinqEntiers(ostream & sort);
//Surcharge d'operateurs logiques
bool operator == (const CinqEntiers& a) const
{ if (( un==a.un) && (deux==a.deux) && (trois == a.trois)&& (quatre == a.quatre)
&& (cinq == a.cinq) ) return true; else return false;};
bool operator != (const CinqEntiers& a) const { return !(*this == a);};
// surchage de l'opérateur de comparaison
bool operator > (const CinqEntiers& a) const
{ if (un > a.un)
{return true;}
else if (un < a.un)
{return false;}
else // egalité, on test le suivant
{if (deux > a.deux)
{return true;}
else if (deux < a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois > a.trois)
{return true;}
else if (trois < a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre > a.quatre)
{return true;}
else if (quatre < a.quatre)
{return false;}
else // egalité, on test le suivant
{if (cinq > a.cinq)
{return true;}
else if (cinq < a.cinq)
{return false;}
else // egalité, on test le suivant
{return false;} // car c'est l'égalité parfaite donc pas supérieur
}
}
}
}
};
bool operator >= (const CinqEntiers& a) const
{ if (un > a.un)
{return true;}
else if (un < a.un)
{return false;}
else // egalité, on test le suivant
{if (deux > a.deux)
{return true;}
else if (deux < a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois > a.trois)
{return true;}
else if (trois < a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre > a.quatre)
{return true;}
else if (quatre < a.quatre)
{return false;}
else // egalité, on test le suivant
{if (cinq > a.cinq)
{return true;}
else if (cinq < a.cinq)
{return false;}
else // egalité, on test le suivant
{return true;} // car c'est l'égalité parfaite
}
}
}
}
};
bool operator < (const CinqEntiers& a) const
{ if (un < a.un)
{return true;}
else if (un > a.un)
{return false;}
else // egalité, on test le suivant
{if (deux < a.deux)
{return true;}
else if (deux > a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois < a.trois)
{return true;}
else if (trois > a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre < a.quatre)
{return true;}
else if (quatre > a.quatre)
{return false;}
else // egalité, on test le suivant
{if (cinq < a.cinq)
{return true;}
else if (cinq > a.cinq)
{return false;}
else // egalité, on test le suivant
{return false;} // car c'est l'égalité parfaite donc pas inférieur
}
}
}
}
};
bool operator <= (const CinqEntiers& a) const
{ if (un < a.un)
{return true;}
else if (un > a.un)
{return false;}
else // egalité, on test le suivant
{if (deux < a.deux)
{return true;}
else if (deux > a.deux)
{return false;}
else // egalité, on test le suivant
{if (trois < a.trois)
{return true;}
else if (trois > a.trois)
{return false;}
else // egalité, on test le suivant
{if (quatre < a.quatre)
{return true;}
else if (quatre > a.quatre)
{return false;}
else // egalité, on test le suivant
{if (cinq < a.cinq)
{return true;}
else if (cinq > a.cinq)
{return false;}
else // egalité, on test le suivant
{return true;} // car c'est l'égalité parfaite
}
}
}
}
};
// sortie du schemaXML: en fonction de enu
void SchemaXML_CinqEntiers(ofstream& sort,const Enum_IO_XML enu) const ;
};
/// @} // end of group
#endif

View file

@ -52,7 +52,7 @@
#include <stdlib.h>
#include <list>
#include <iomanip>
#include "LaLIST.h"
#include "LaLIST.H"
#include "Sortie.h"
#include "ParaGlob.h"
using namespace std; //introduces namespace std

View file

@ -123,6 +123,9 @@ LesContacts::LesContacts () :
,nb_contact_actif(0),indice(),cont_solide_defor(),liQ_en_sortie()
,t_connectionCLL()
,liste_elemens_front(),tempsContact()
#ifdef UTILISATION_MPI
,temps_transfert_court(),temps_transfert_long(),temps_attente()
#endif
{};
// constructeur de copie
LesContacts::LesContacts (const LesContacts& a):
@ -137,6 +140,10 @@ LesContacts::LesContacts (const LesContacts& a):
,nb_contact_actif(a.nb_contact_actif),indice(a.indice),cont_solide_defor(a.cont_solide_defor)
,liste_elemens_front(a.liste_elemens_front),liQ_en_sortie(),tempsContact(a.tempsContact)
,t_connectionCLL(a.t_connectionCLL)
#ifdef UTILISATION_MPI
,temps_transfert_court(a.temps_transfert_court)
,temps_transfert_long(a.temps_transfert_long),temps_attente(a.temps_attente)
#endif
{};
// DESTRUCTEUR :
LesContacts::~LesContacts ()
@ -310,7 +317,7 @@ void LesContacts::Init_contact(LesMaillages& lesMail
else
{ // cas d'une zone restreinte de contact
// on va iterer sur les noeuds esclaves pour savoir s'ils appartiennent à la zone de contact potentiel
list <quatre_string_un_entier>::iterator il,ilfin=nom_ref_zone_contact.end();
list <Quatre_string_un_entier>::iterator il,ilfin=nom_ref_zone_contact.end();
int nb_zone = nom_ref_zone_contact.size();
if (niveau_commentaire_lescontacts >2 )
cout << "\n --> nombre de zone de contact: " << nb_zone;
@ -1996,7 +2003,7 @@ void LesContacts::Affiche() const
};
cout << "\n 3) liste des references de zones succeptibles d'entrer en contact";
list <quatre_string_un_entier>::const_iterator ill,illfin=nom_ref_zone_contact.end();
list <Quatre_string_un_entier>::const_iterator ill,illfin=nom_ref_zone_contact.end();
cout << "\n";
for (ill=nom_ref_zone_contact.begin();ill != illfin; ill++)
{ if ((*ill).nom1.length()) cout << " mail= " << (*ill).nom1 << " ";
@ -2248,7 +2255,7 @@ void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesRefere
if (niveau_commentaire_lescontacts >= 4) cout << " debut de la lecture des zones de contact possibles " << endl;
while (!motCle.SimotCle(entreePrinc.tablcar))
{ // on lit 2 par deux: une ref de noeud + une ref de frontière
quatre_string_un_entier quatre_inter; // une grandeur de travail
Quatre_string_un_entier quatre_inter; // une grandeur de travail
quatre_inter.n = indic_glue; // on stocke la glue éventuelle
for (int nr=1;nr<=2;nr++)
{// on commence par regarder si le nom du maillage est définit pour la référence

View file

@ -242,6 +242,13 @@ class LesContacts
// retourne temps cumulé pour imposer les CL imposées
const Temps_CPU_HZpp& Temps_cpu_Contact() const {return tempsContact;};
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
const Temps_CPU_HZpp& Temps_transfert_court() const {return temps_transfert_court;} ;
const Temps_CPU_HZpp& Temps_transfert_long() const {return temps_transfert_long;} ;
const Temps_CPU_HZpp& Temps_attente() const {return temps_attente;} ;
#endif
//----- lecture écriture de restart -----
// cas donne le niveau de sauvegarde
void Ecri_base_info_LesContacts(ofstream& sort);
@ -298,10 +305,8 @@ class LesContacts
return niveau_commentaire_lescontacts;
};
// ne sert plus (à virer car problématique !! )
// mise à jour du stockage inter, pour prendre en
// compte une nouvelle numérotation des noeuds
// void Prise_en_compte_nouvelle_numerotation_noeud();
// initialisation de la liste de grandeurs qui sont effectivement gérées par le contact
// ok, mais à revoir sans doute cf. pense bete 14 oct
@ -355,7 +360,7 @@ class LesContacts
Tableau < const Tableau <List_io < Element* > > *> indice;
//--------- les tableaux de gestions pour la recherche de contact ----------------
list <quatre_string_un_entier> nom_ref_zone_contact; // liste des noms de références des zones de contact éventuelle
list <Quatre_string_un_entier> nom_ref_zone_contact; // liste des noms de références des zones de contact éventuelle
// cette liste peut être vide, dans ce cas cela signifie que toutes les frontières des pièces sont
// suceptible de rentrer en contact. Dans le cas où la liste n'est pas vide, seules les grandeurs
// référencées sont succeptibles de rentrer en contact
@ -437,6 +442,12 @@ class LesContacts
//------- temps cpu -----
// retourne temps cumulé pour imposer les CL imposées
Temps_CPU_HZpp tempsContact;
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
Temps_CPU_HZpp temps_transfert_court ;
Temps_CPU_HZpp temps_transfert_long ;
Temps_CPU_HZpp temps_attente ;
#endif
// METHODES PROTEGEES :
// mise à jour des boites d'encombrement pour les éléments qui contiennent une frontière

View file

@ -686,8 +686,8 @@ void LesContacts::Suppression_gap_pour_noeud_collant()
// on passe en revue les zones de contact et si nécessaire on supprime les gaps
// sinon retour
bool continuer = false; // init par défaut
// list <quatre_string_un_entier> nom_ref_zone_contact; // liste des noms de références des zones de contact
list <quatre_string_un_entier>::iterator iu,iufin = nom_ref_zone_contact.end();
// list <Quatre_string_un_entier> nom_ref_zone_contact; // liste des noms de références des zones de contact
list <Quatre_string_un_entier>::iterator iu,iufin = nom_ref_zone_contact.end();
for (iu = nom_ref_zone_contact.begin();iu != iufin; iu++)
if ((*iu).n == 2)
{continuer = true; break;};