- corr bug affichage intempestif contact

- fct nD: amélioration message d'erreur (arguments), et en fct du niveau géré par une fct nD
- première validation du fct. en // en implicite statique et en RD,
  nombreuses modifications et amélioration !

Signed-off-by: Gérard Rio <gerardrio56@free.fr>
This commit is contained in:
Gérard Rio 2024-03-24 11:43:58 +01:00
parent a317216f06
commit ea11c75ff8
52 changed files with 3452 additions and 1400 deletions

File diff suppressed because it is too large Load diff

View file

@ -739,20 +739,26 @@ class Algori
Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14)
Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
Temps_CPU_HZpp tempsCalMasse; // lesTempsCpu(17)
Temps_CPU_HZpp tempsCalViscoNum; // lesTempsCpu(18)
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(17)
Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18)
Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19)
Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20)
Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21)
Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22)
Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23)
Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24)
Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25)
Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26)
Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27)
Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28)
Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(19)
Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(20)
Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(21)
Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(22)
Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(23)
Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(24)
Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(25)
Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(26)
Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(27)
Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(28)
Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(29)
Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(30)
// des conteneurs de passage utilisés par Algori::Gestion_stockage_et_renumerotation_avec_contact
Vecteur inter_transfer; // un conteneur de transfert Algori::RaidSmEnerContact
Vecteur inter_transfer2; // un conteneur de transfert pour ConnectionCLL de contact
#endif
Tableau <Coordonnee3> lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties
@ -1303,6 +1309,8 @@ class Algori
// cas d'un calcul parallèle, passage des énergies, volumes
// a priori utilisée dans le calcul de raideur et second membres
void Passage_energiesEtVolumes();
// passage des énergies liées au contact
void Passage_energiesContact();
#endif

View file

@ -36,9 +36,13 @@
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "ExceptionsElemMeca.h"
#include "ExceptionsLoiComp.h"
#include "TypeQuelconqueParticulier.h"
#include "AlgoriCombine.h" // pour la sortie base_info
// cas eventuel d'un démarrage à partir de base_info
// si inc_voulu est négatif cela signifie que l'on est déjà positionné sur un
// incrément voulu et qu'il faut simplement faire la lecture des infos
@ -1025,6 +1029,10 @@ void Algori::LectureCommandeVisu(ParaGlob * paraGlob,LesMaillages * lesMaillages
return;
}
// écriture de l'en-tête
#ifdef UTILISATION_MPI
// cas d'un calcul //, seul le CPU 0 affiche
if (ParaGlob::Monde()->rank() == 0)
#endif
if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2))
cout << "\n ======== lecture du fichier de commande de visualisation ========\n";
// -- on définit l'ensemble des incréments possibles, ceci sont stocké dans .BI
@ -1176,6 +1184,10 @@ void Algori::LectureCommandeVisu(ParaGlob * paraGlob,LesMaillages * lesMaillages
// avertissement de la fin de lecture du fichier de commande
// if (ParaGlob::NiveauImpression() >= 0)
#ifdef UTILISATION_MPI
// cas d'un calcul //, pour l'instant seul le CPU 0 affiche
if (ParaGlob::Monde()->rank() == 0)
#endif
if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 0)) || (permet_affichage > 2))
cout << "\n ======== fin de la lecture du fichier de commande de visualisation ========\n";
// visualisation en fonction de l'activité des différents types de sortie
@ -1429,6 +1441,10 @@ void Algori::VisuAuFilDuCalcul(ParaGlob * paraGlob,LesMaillages * lesMaillages,L
<< "\n VisuAuFilDuCalcul(...";
return;
}
#ifdef UTILISATION_MPI
// cas d'un calcul //, seul le CPU 0 affiche
if (ParaGlob::Monde()->rank() == 0)
#endif
// écriture de l'en-tête
if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 1)) || (permet_affichage > 2))
{cout << "\n ======== lecture du fichier de commande "
@ -1575,6 +1591,10 @@ void Algori::VisuAuFilDuCalcul(ParaGlob * paraGlob,LesMaillages * lesMaillages,L
}
// avertissement de la fin de lecture du fichier de commande
// if (ParaGlob::NiveauImpression() >= 2)
#ifdef UTILISATION_MPI
// cas d'un calcul //, pour l'instant seul le CPU 0 affiche
if (ParaGlob::Monde()->rank() == 0)
#endif
if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2))
cout << "\n ======== fin de la lecture du fichier de commande de visualisation ========\n";
// initialisation de la sortie vrml (fichier) si la sortie vrml est valide
@ -1882,6 +1902,8 @@ void Algori::Ecriture_base_info
sort << "\n tps_SortieFilCalcul "<< tempsSortieFilCalcul;
sort << "\n tps_contactMatSmLoc "<< tempsRaidSmEnerContact;
sort << "\n tps_contactSmLoc "<< tempsSecondMembreEnergContact;
sort << "\n tempsCalMasse "<< tempsCalMasse;
sort << "\n tempsCalViscoNum "<< tempsCalViscoNum;
}
else
{ptalgocombi->AutreSortieTempsCPU(sort,cas); };
@ -2084,7 +2106,9 @@ void Algori::Lecture_base_info(ifstream& ent,const int cas)
ent >> nom1 >> tempsSortieFilCalcul;
ent >> nom1 >> tempsRaidSmEnerContact;
ent >> nom1 >> tempsSecondMembreEnergContact;
ent >> nom1 >> tempsCalMasse;
ent >> nom1 >> tempsCalViscoNum;
// --- b) parties extérieures à l'algo
ent >> nom1 >> temps_CL;
ent >> nom1 >> temps_CLL;

View file

@ -405,35 +405,39 @@ void Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(L
};
// //------- temps cpu -----
// Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1)
// Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2)
// Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3)
// Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4)
// Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5)
// Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6)
// Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7)
// Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8)
// Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9)
// Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10)
// Temps_CPU_HZpp temps_CL; // lesTempsCpu(11)
// Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12)
// Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13)
// Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14)
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
// si calcul //
//Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(17)
//Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(18)
//Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(19)
//Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(20)
//Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(21)
//Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(22)
//Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(23)
//Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(24)
//Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(25)
//Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(26)
//Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(27)
//Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(28)
// // ainsi en sortie on pourra différencier les temps totaux et les temps partiels
// Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1)
// Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2)
// Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3)
// Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4)
// Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5)
// Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6)
// Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7)
// Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8)
// Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9)
// Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10)
// Temps_CPU_HZpp temps_CL; // lesTempsCpu(11)
// Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12)
// Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13)
// Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14)
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
// Temps_CPU_HZpp tempsCalMasse; // lesTempsCpu(17)
// Temps_CPU_HZpp tempsCalViscoNum; // lesTempsCpu(18)
//#ifdef UTILISATION_MPI
// // cas d'un calcul parallèle: // passage des infos entre process
// Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(20)
// Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(21)
// Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(22)
// Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(23)
// Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(24)
// Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(25)
// Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(26)
// Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(27)
// Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(28)
// Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(29)
// Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(30)
//
// Tableau <Coordonnee3> lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties
@ -489,29 +493,31 @@ void Algori::Temps_CPU_HZpp_to_lesTempsCpu
lesTempsCpu(15)(1)= temps_chargement.Temps_CPU_User();
temps_rech_contact = contact.Temps_cpu_Contact();
lesTempsCpu(16)(1)= temps_rech_contact.Temps_CPU_User();
lesTempsCpu(17)(1)= tempsCalMasse.Temps_CPU_User();
lesTempsCpu(18)(1)= tempsCalViscoNum.Temps_CPU_User();
#ifdef UTILISATION_MPI
// cas des temps de l'algorithme
lesTempsCpu(17)(1)= temps_transfert_court_algo.Temps_CPU_User();
lesTempsCpu(18)(1)= temps_transfert_long_algo.Temps_CPU_User();
lesTempsCpu(19)(1)= temps_attente_algo.Temps_CPU_User();
lesTempsCpu(19)(1)= temps_transfert_court_algo.Temps_CPU_User();
lesTempsCpu(20)(1)= temps_transfert_long_algo.Temps_CPU_User();
lesTempsCpu(21)(1)= temps_attente_algo.Temps_CPU_User();
// des mat et SM locaux
lesTempsCpu(20)(1)= temps_transfert_court_matSm.Temps_CPU_User();
lesTempsCpu(21)(1)= temps_transfert_long_matSm.Temps_CPU_User();
lesTempsCpu(22)(1)= temps_attente_matSm.Temps_CPU_User();
lesTempsCpu(22)(1)= temps_transfert_court_matSm.Temps_CPU_User();
lesTempsCpu(23)(1)= temps_transfert_long_matSm.Temps_CPU_User();
lesTempsCpu(24)(1)= temps_attente_matSm.Temps_CPU_User();
// du chargement
temps_transfert_court_charge = charge.Temps_transfert_court();
lesTempsCpu(23)(1)= temps_transfert_court_charge.Temps_CPU_User();
lesTempsCpu(25)(1)= temps_transfert_court_charge.Temps_CPU_User();
temps_transfert_long_charge = charge.Temps_transfert_long();
lesTempsCpu(24)(1)= temps_transfert_long_charge.Temps_CPU_User();
lesTempsCpu(26)(1)= temps_transfert_long_charge.Temps_CPU_User();
temps_attente_charge = charge.Temps_attente();
lesTempsCpu(25)(1)= temps_attente_charge.Temps_CPU_User();
lesTempsCpu(27)(1)= temps_attente_charge.Temps_CPU_User();
// du contact
temps_transfert_court_contact = contact.Temps_transfert_court();
lesTempsCpu(26)(1)= temps_transfert_court_contact.Temps_CPU_User();
lesTempsCpu(28)(1)= temps_transfert_court_contact.Temps_CPU_User();
temps_transfert_long_contact = contact.Temps_transfert_long();
lesTempsCpu(27)(1)= temps_transfert_long_contact.Temps_CPU_User();
lesTempsCpu(29)(1)= temps_transfert_long_contact.Temps_CPU_User();
temps_attente_contact = contact.Temps_attente();
lesTempsCpu(28)(1)= temps_attente_contact.Temps_CPU_User();
lesTempsCpu(30)(1)= temps_attente_contact.Temps_CPU_User();
#endif
};
@ -522,9 +528,9 @@ void Algori::Temps_CPU_HZpp_to_lesTempsCpu
Tableau <Temps_CPU_HZpp> & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau <Temps_CPU_HZpp> & lesTsCpu)
{ // test éventuel de la taille du tableau
#ifdef MISE_AU_POINT
if (lesTsCpu.Taille() != 10)
if (lesTsCpu.Taille() != 18)
{cout << "\n erreur de dim de tableau: dim lesTsCpu= " << lesTsCpu.Taille()
<< " au lieu de 10 !! "
<< " au lieu de 18 !! "
<< "\n Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(... " ;
Sortie(1);
};
@ -541,19 +547,21 @@ Tableau <Temps_CPU_HZpp> & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau <
lesTsCpu(8) += tempsSortieFilCalcul; // conversion de long long en double
lesTsCpu(9) += tempsRaidSmEnerContact; // conversion de long long en double
lesTsCpu(10) += tempsSecondMembreEnergContact; // conversion de long long en double
lesTsCpu(17) += tempsCalMasse; // conversion de long long en double
lesTsCpu(18) += tempsCalViscoNum; // conversion de long long en double
#ifdef UTILISATION_MPI
lesTsCpu(17) += temps_transfert_court_algo;
lesTsCpu(18) += temps_transfert_long_algo;
lesTsCpu(19) += temps_attente_algo;
lesTsCpu(20) += temps_transfert_court_matSm;
lesTsCpu(21) += temps_transfert_long_matSm;
lesTsCpu(22) += temps_attente_matSm;
lesTsCpu(23) += temps_transfert_court_charge;
lesTsCpu(24) += temps_transfert_long_charge;
lesTsCpu(25) += temps_attente_charge;
lesTsCpu(26) += temps_transfert_court_contact;
lesTsCpu(27) += temps_transfert_long_contact;
lesTsCpu(28) += temps_attente_contact;
lesTsCpu(19) += temps_transfert_court_algo;
lesTsCpu(20) += temps_transfert_long_algo;
lesTsCpu(21) += temps_attente_algo;
lesTsCpu(22) += temps_transfert_court_matSm;
lesTsCpu(23) += temps_transfert_long_matSm;
lesTsCpu(24) += temps_attente_matSm;
lesTsCpu(25) += temps_transfert_court_charge;
lesTsCpu(26) += temps_transfert_long_charge;
lesTsCpu(27) += temps_attente_charge;
lesTsCpu(28) += temps_transfert_court_contact;
lesTsCpu(29) += temps_transfert_long_contact;
lesTsCpu(30) += temps_attente_contact;
#endif
// retour
return lesTsCpu;
@ -579,6 +587,8 @@ void Algori::Arret_du_comptage_CPU()
temps_metrique_K_SM.Arret_du_comptage();
temps_chargement.Arret_du_comptage();
temps_rech_contact.Arret_du_comptage();
tempsCalMasse.Arret_du_comptage();
tempsCalViscoNum.Arret_du_comptage();
#ifdef UTILISATION_MPI
temps_transfert_court_algo.Arret_du_comptage();
temps_transfert_long_algo.Arret_du_comptage();
@ -700,6 +710,14 @@ void Algori::Sortie_temps_cpu(const LesCondLim& lesCondLim
<< ".("<< std::setw(nbdigit) << (100*temps_CLL.Temps_CPU_User()/total_cpu) << " % ) "
<< temps_CLL.Temps_CPU_User_milli()
;
sort_cpu << "\n tempsCalMasse "
<< ".("<< std::setw(nbdigit) << (100*tempsCalMasse.Temps_CPU_User()/total_cpu) << " % ) "
<< tempsCalMasse.Temps_CPU_User_milli()
;
sort_cpu << "\n tempsCalViscoNum "
<< ".("<< std::setw(nbdigit) << (100*tempsCalViscoNum.Temps_CPU_User()/total_cpu) << " % ) "
<< tempsCalViscoNum.Temps_CPU_User_milli()
;
sort_cpu << "\n tps_ResSystLineaire "
<< "("<< std::setw(nbdigit) << (100*tempsResolSystemLineaire.Temps_CPU_User()/total_cpu) << " % ) "
@ -979,36 +997,82 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul
,Tableau <Mat_abstraite* >& tab_mato,const Nb_assemb& nb_casAssemb
,LesContacts* lescontacts,int niveau_substitution)
{
#ifdef UTILISATION_MPI
// cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées
// donc s'il s'agit d'un CPU différent, on revient immédiatement
if (ParaGlob::Monde()->rank() != 0)
return false;
#endif
bool retour = false; // init pas de changement a priori au niveau des matrices
// récup des connexions entre noeud dues aux contacts
list <Condilineaire>& listCondLine= lescontacts->ConnectionCLL();
int taille_listCondLine=listCondLine.size(); // init
#ifdef UTILISATION_MPI
// il faut que tous les proc effectuent la renumérotation, il faut donc transmettre les conditions linéaires de contact
int proc_en_cours = ParaGlob::Monde()->rank();
// seule le proc 0 a récupérer la liste complète des conditions linéaires
int taille_conteneur=0; // init
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
if (proc_en_cours == 0)
{ //transmission au cpu i >0
// pour cela on va utiliser un conteneur intermédiaire
// on calcul la taille nécessaire pour le conteneur (a découper éventuellement ??)
taille_conteneur=0;
list <Condilineaire>::iterator il,ilfin = listCondLine.end();
for (il = listCondLine.begin();il != ilfin;il++)
taille_conteneur += (*il).Taille_Pack();
inter_transfer2.Change_taille(taille_conteneur); // le conteneur
// on rempli le conteneur
int rang = 1; // init
for (il = listCondLine.begin();il != ilfin;il++)
rang = (*il).Pack_vecteur(inter_transfer2,rang);
};
// on transfert
broadcast(*ParaGlob::Monde(), taille_conteneur, 0);
if (proc_en_cours != 0)
inter_transfer2.Change_taille(taille_conteneur);
// le proc 0 transfert le tableau
inter_transfer2.Broadcast(0);
if (proc_en_cours != 0)
{// l'objectif ici est de récupérer les conditions linéaires
// pour chaque cpu i>0
listCondLine.clear();//
// on va remplir la liste des conditions limites
int rang = 1; // init
while (rang != 0)
{ Condilineaire condi; // une condition intermédiaire
rang = condi.UnPack_vecteur(*lesMail,inter_transfer2,rang,
&LesMaillages::Noeud_LesMaille);
listCondLine.push_back(condi);
};
// on met à jour la taille de la liste, car utilisée ensuite dans des tests
taille_listCondLine=listCondLine.size();
};
temps_transfert_court_algo.Arret_du_comptage(); // fin comptage cpu
#endif
TroisEntiers nevez_largeurs;
bool retour = false; // init pas de changement a priori au niveau des matrices
if (premier_calcul)
{// si demandé, renumérotation en fonction des éléments en contact
if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation())
{ // récup des connexions entre noeud dues aux contacts
list <Condilineaire>& listCondLine= lescontacts->ConnectionCLL();
if (listCondLine.size() > 0) //cas où il faut en tenir compte
{// récup des connexions entre noeuds dues aux CLL externes
if (taille_listCondLine > 0) //cas où il faut en tenir compte
{bool calcul_ok = false; // init
// récup des connexions entre noeuds dues aux CLL externes
Tableau <Tableau <Condilineaire> > tabCLL(lesCondLim->ConnectionCLL(lesMail,lesRef));
int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1);
// tabCLL(tailtabCLL+1) = listCondLine;
// ajout de la partie contact
Tableau <Condilineaire>& tabCLL_contact = tabCLL(tailtabCLL+1); // pour simplifier
tabCLL_contact.Change_taille(listCondLine.size());
tabCLL_contact.Change_taille(taille_listCondLine);
list <Condilineaire>::iterator il,ilfin = listCondLine.end();
int i=1;
for (il = listCondLine.begin();il != ilfin;il++,i++)
tabCLL_contact(i) = (*il);
#ifdef UTILISATION_MPI
// seule le proc 0 affiche
if (proc_en_cours == 0)
#endif
if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2))
cout << "\n -- renumerotation en tenant compte des elements de contact ";
// appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage
bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true);
calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true);
if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation
{//lesMail->MiseAJourPointeurAssemblage(nb_casAssemb);// mise a jour des pointeurs d'assemblage
// il faut regarder un peu partout: élément, frontière etc
@ -1036,9 +1100,9 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul
{if (nouvelle_situation_contact)
{if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation())
{ // récup des connexions entre noeud dues aux contacts
list <Condilineaire>& listCondLine= lescontacts->ConnectionCLL();
if (listCondLine.size() > 0) //cas où il faut en tenir compte
{// récup des connexions entre noeuds dues aux CLL externes: comme les cll ont été mises à jour
if (taille_listCondLine > 0) //cas où il faut en tenir compte
{ bool calcul_ok = false; // init
// récup des connexions entre noeuds dues aux CLL externes: comme les cll ont été mises à jour
// on récupère directement le tableau
Tableau <Tableau <Condilineaire> > tabCLL(lesCondLim->Tab_CLinApplique());
int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1);
@ -1049,10 +1113,14 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul
int i=1;
for (il = listCondLine.begin();il != ilfin;il++,i++)
tabCLL_contact(i) = (*il);
#ifdef UTILISATION_MPI
// seule le proc 0 affiche
if (proc_en_cours == 0)
#endif
if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2))
cout << "\n -- renumerotation en tenant compte d'un changement de contact ";
// appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage
bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true);
calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true);
if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation
{
// on met à jour le tableau indice pour LesContacts
@ -1078,8 +1146,9 @@ bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul
else
{retour = false; };
}; //-- fin du cas si ce n'est pas un premier calcul
// retour
return retour;
// retour
return retour; // correct uniquement pour le proc 0, les autres procs ne s'en servent pas à priori
};
@ -1440,7 +1509,8 @@ Tableau <Algori *> Algori::New_tous_les_Algo
// cas d'un calcul parallèle, passage des énergies, volumes
// a priori utilisée dans le calcul de raideur et second membres
void Algori::Passage_energiesEtVolumes()
{ mpi::request reqs1;
{ tempsRaidSmEner.Mise_en_route_du_comptage(); // fin comptage cpu
mpi::request reqs1;
bool premier_passage = true;
// récupération de toutes les énergies par le cpu 0
@ -1457,6 +1527,7 @@ Tableau <Algori *> Algori::New_tous_les_Algo
dim_tav_double += vol_total2D_avec_plan_ref(i).Dimension();
Vecteur v_val_inter(8+dim_tav_double);
int num_process = ParaGlob::Monde()->rank();
tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu
if (num_process != 0)
{temps_transfert_court_matSm.Mise_en_route_du_comptage(); // comptage cpu
//on rempli le vecteur de passage
@ -1531,6 +1602,71 @@ Tableau <Algori *> Algori::New_tous_les_Algo
//
////------------- fin debug --------
};
// passage des énergies liées au contact
void Algori::Passage_energiesContact()
{ mpi::request reqs1;
bool premier_passage = true;
// récupération de toutes les énergies par le cpu 0
// on dit à tous les process d'attendre sauf le master
// on crée un vecteur intermédiaire pour le passage d'information
Vecteur v_val_inter(4);
int num_process = ParaGlob::Monde()->rank();
if (num_process != 0)
{temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu
//on rempli le vecteur de passage
v_val_inter(1) =energFrottement.EnergieElastique();
v_val_inter(2) =energFrottement.DissipationPlastique();
v_val_inter(3) =energFrottement.DissipationVisqueuse();
v_val_inter(4)=energPenalisation;
// //------------- debug --------
// cout << "\n debug Algori::Passage_energiesContact() num_process= "<< num_process;
// cout << "\n v_val_inter= "<<v_val_inter;
//
// //------------- fin debug --------
temps_transfert_court_contact.Arret_du_comptage();
// on récupère un signal du process 0
temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu
if (premier_passage) {premier_passage = false;}
else // on attend que les transferts soient finis
{reqs1.wait();
};
temps_attente_contact.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_contact.Mise_en_route_du_comptage(); // comptage cpu
// on transmet le vecteur intermédiaire
reqs1 = v_val_inter.Ienvoi_MPI(0,270);
temps_transfert_court_contact.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_contact.Mise_en_route_du_comptage(); // comptage cpu
reqs1 = v_val_inter.Irecup_MPI(mpi::any_source, 270);
temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu
temps_attente_contact.Mise_en_route_du_comptage(); // comptage cpu
reqs1.wait(); // on attend que le conteneur soit rempli
temps_attente_contact.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court_contact.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));
energFrottement += inter;
energPenalisation += v_val_inter(4);
temps_transfert_court_contact.Arret_du_comptage(); // fin comptage cpu
};
};
////------------- debug --------
//cout << "\n debug Algori::Passage_energiesContact() ";
//cout << "\n energFrottement "<<energFrottement
// << " energPenalisation "<< energPenalisation;
//
////------------- fin debug --------
};
#endif

View file

@ -893,7 +893,7 @@ void AlgoriCombine::Lecture_algo_interne(const bool avec_typeDeCal
// sortie des temps cpu cumulées de tous les algos
void AlgoriCombine::AutreSortieTempsCPU(ofstream& sort,const int ) const
{ // on commence par cumuler tous les temps de calcul
Tableau <Temps_CPU_HZpp> lesTsCpu(10); // init
Tableau <Temps_CPU_HZpp> lesTsCpu(18); // init
// on passe en revue tous les algorithmes et on cumule les temps cpu
int nb_algo = tab_algo.Taille();
@ -909,32 +909,40 @@ void AlgoriCombine::AutreSortieTempsCPU(ofstream& sort,const int ) const
//Algori::Ecriture_base_info(ofstream& sort,const int cas
/// ----> pour rappel:
// //------- temps cpu -----
// Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1)
// Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2)
// Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3)
// Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4)
// Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5)
// Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6)
// Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7)
// Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8)
// Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9)
// Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10)
// Temps_CPU_HZpp temps_CL; // lesTempsCpu(11)
// Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12)
// Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13)
// Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14)
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
// cas d'un calcul parallèle: // passage des infos entre process
// Temps_CPU_HZpp temps_transfert_court ; // lesTempsCpu(17)
// Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(18)
// Temps_CPU_HZpp temps_attente ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(20)
// Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(21)
// Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(22)
// Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(23)
// Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(24)
// Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(25)
// // ainsi en sortie on pourra différencier les temps totaux et les temps partiels
// Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1)
// Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2)
// Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3)
// Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4)
// Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5)
// Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6)
// Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7)
// Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8)
// Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9)
// Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10)
// Temps_CPU_HZpp temps_CL; // lesTempsCpu(11)
// Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12)
// Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13)
// Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14)
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
// Temps_CPU_HZpp tempsCalMasse; // lesTempsCpu(17)
// Temps_CPU_HZpp tempsCalViscoNum; // lesTempsCpu(18)
//#ifdef UTILISATION_MPI
// // cas d'un calcul parallèle: // passage des infos entre process
// Temps_CPU_HZpp temps_transfert_court_algo ; // lesTempsCpu(19)
// Temps_CPU_HZpp temps_transfert_long_algo ; // lesTempsCpu(20)
// Temps_CPU_HZpp temps_attente_algo ; // lesTempsCpu(21)
// Temps_CPU_HZpp temps_transfert_court_matSm ; // lesTempsCpu(22)
// Temps_CPU_HZpp temps_transfert_long_matSm ; // lesTempsCpu(23)
// Temps_CPU_HZpp temps_attente_matSm ; // lesTempsCpu(24)
// Temps_CPU_HZpp temps_transfert_court_charge ; // lesTempsCpu(25)
// Temps_CPU_HZpp temps_transfert_long_charge ; // lesTempsCpu(26)
// Temps_CPU_HZpp temps_attente_charge ; // lesTempsCpu(27)
// Temps_CPU_HZpp temps_transfert_court_contact ; // lesTempsCpu(28)
// Temps_CPU_HZpp temps_transfert_long_contact ; // lesTempsCpu(29)
// Temps_CPU_HZpp temps_attente_contact ; // lesTempsCpu(30)
sort << "\n tps_InitAlgo " << lesTsCpu(1);
sort << "\n tps_MiseAJourAlgo "<< lesTsCpu(2);
sort << "\n tps_CalEquilibre "<< lesTsCpu(3);
@ -945,6 +953,8 @@ void AlgoriCombine::AutreSortieTempsCPU(ofstream& sort,const int ) const
sort << "\n tps_SortieFilCalcul "<< lesTsCpu(8);
sort << "\n tps_contactMatSmLoc "<< lesTsCpu(9);
sort << "\n tps_contactSmLoc "<< lesTsCpu(10);
sort << "\n tempsCalMasse "<< lesTsCpu(17);
sort << "\n tempsCalViscoNum "<< lesTsCpu(18);
};

View file

@ -51,7 +51,7 @@ void AlgoriCombine::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

View file

@ -961,7 +961,7 @@ void AlgoriRungeKutta::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

View file

@ -803,7 +803,7 @@ void AlgoriDynaExpli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

View file

@ -294,7 +294,7 @@ void AlgoriDynaExpli_zhai::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * les
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

View file

@ -283,7 +283,7 @@ void Algori_chung_lee::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

File diff suppressed because it is too large Load diff

View file

@ -872,7 +872,7 @@ void AlgoriTchamwa::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

View file

@ -50,7 +50,7 @@ void AlgoriNewmark::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

View file

@ -51,7 +51,7 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
tempsInitialisation.Arret_du_comptage(); // temps cpu
temps_transfert_court_algo.Mise_en_route_du_comptage(); // comptage cpu
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
@ -71,8 +71,6 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
//cout << endl;
////-------- fin debug
// avant toute chose, au cas où l'algo interviendrait après un autre algo
// on inactive tous les ddl existants
lesMail->Inactive_ddl();
@ -139,7 +137,8 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
int nbddl_X = lesMail->NbTotalDdlActifs(); // nb total de ddl
// choix de la matrice de raideur du système linéaire (calcul éventuellement d'une largeur de bande ad oc)
Choix_matriciel(nbddl_X,tab_mato,lesMail,lesRef,Ass.Nb_cas_assemb(),lesCondLim);
// ici, au niveau init, on démarre sans contact, son action sera ensuite rajoutée
Choix_matriciel(nbddl_X,tab_mato,lesMail,lesRef,Ass.Nb_cas_assemb(),lesCondLim,NULL);
matglob = tab_mato(1); // par défaut c'est la première matrice
// dans le cas où l'on veut également utiliser du Newton modifié, on definit la matrice de sauvegarde
if (deb_newton_modifie >= 0)
@ -242,7 +241,7 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
// initi boucle sur les increments de charge
icharge = 0;
// definition des elements de frontiere, ces elements sont utilises pour le contact
lesMail->CreeElemFront();
// calcul éventuel des normales aux noeuds -> init des normales pour t=0
@ -274,6 +273,31 @@ void AlgoriNonDyna::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
// definition des elements de contact eventuels
// et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact)
bool nevez_contact = lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul
// #ifdef UTILISATION_MPI
// if (ParaGlob::Monde()->rank() == 0)
// { cout << "\n debug AlgoriNonDyna::InitAlgorithme fin transitoire proc 0";
// cout << "\n taper une lettre pour stopper ";
// string toto;
// cin >> toto;
// int nb_process = ParaGlob::Monde()->size();
// for (int i=1;i<nb_process;i++) // < absolu, donc le max c'est nb_process-1
// { // on envoie un signal de re démarrage au process i
// ParaGlob::Monde()->send(i, 100, std::string("redemarrage"));
// };
// Sortie(1);
// }
// else
// { cout << "\n debug AlgoriNonDyna::InitAlgorithme fin transitoire proc " << ParaGlob::Monde()->rank();
// // on attend le message de redémarrage du proc 0
// std::string msg;
// ParaGlob::Monde()->recv(0, 100, msg);
// Sortie(1);
// };
// #endif
int niveau_substitution = 0; // on intervient sur toutes les matrices
bool premier_calcul = true;
// mise à jour éventuelle de la matrice de raideur en fonction du contact
@ -719,7 +743,10 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
//--fin-debug
// affichage ou non de l'itération
bool aff_iteration = (pa.freq_affich_iter() > 0) ?
(aff_incr && (compteur % pa.freq_affich_iter()==0) &&(compteur!=0)) : false ;
(aff_incr && (compteur % pa.freq_affich_iter()==0) &&(compteur!=0))
: (pa.freq_affich_iter() < 0) ? // dans le cas < 0 on affiche également l'itération 0
(aff_incr && (compteur % pa.freq_affich_iter()==0))
:false ;
// utilisation d'un comportement tangent simplifié si nécessaire
if (compteur <= pa.Init_comp_tangent_simple() )
lesLoisDeComp->Loi_simplifie(true);
@ -732,6 +759,12 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
if (pa.ContactType())
{ int niveau_substitution = 0; // on intervient sur toutes les matrices
bool a_changer = lescontacts->Actualisation(1);
#ifdef UTILISATION_MPI
// if faut que tous les proc aient le résultat final qui peut être différent pour chaque proc
// due au fait que chaque proc ne traite pas les mêmes éléments de contact
broadcast(*ParaGlob::Monde(), a_changer, 0);
#endif
// mise à jour éventuelle des matrices de raideur en fonction du contact
if (a_changer)
{//bool changement_sur_matrice =
@ -824,8 +857,14 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
// calcul des maxi des puissances internes
maxPuissInt = vglobin.Max_val_abs();
////------- debug
//#ifdef UTILISATION_MPI
// // cas d'un calcul //, pour l'instant seul le CPU 0 sont concerné
// if (ParaGlob::Monde()->rank() == 0)
//#endif
//cout << "\n debug AlgoNonDyna::CalEquilibre: maxPuissInt => "<<maxPuissInt
// << " compteur= " << compteur <<flush;
////--- fin debug
// dans le cas où l'on utilise de l'amortissement numérique le second membre
// et la matrice de raideur sont modifiés
@ -848,7 +887,16 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
(Ass,lesMail,lesRef,vglobex,*matglob,assembMat,pa,lesCourbes1D,lesFonctionsnD)))
{ Change_PhaseDeConvergence(-10);break;};
//cout << "\n debug AlgoNonDyna::CalEquilibre: vglobex => "; vglobex.Affiche();
////cout << "\n debug AlgoNonDyna::CalEquilibre: vglobex => "; vglobex.Affiche();
////------- debug
// #ifdef UTILISATION_MPI
// // cas d'un calcul //, pour l'instant seul le CPU 0 sont concerné
// if (ParaGlob::Monde()->rank() == 0)
// #endif
// { cout << "\n debug AlgoriNonDyna::CalEquilibre";
// cout << "\n debug AlgoNonDyna::CalEquilibre: maxPuissext sans contact => "<<vglobex.Max_val_abs();
// };
////--- fin debug
// cas des efforts de contact, contribution second membre et matrice,
// suivant le type de contact on utilise ou on recalcule les reactions de contact éventuelles (contact et frottement)
@ -862,6 +910,17 @@ void AlgoriNonDyna::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
// dans le cas où le calcul est inexploitable (pb dans le calcul) arrêt de la boucle
if (!RaidSmEnerContact(lescontacts,Ass,vcontact,(*matglob))) break;
//cout << "\n debug AlgoNonDyna::CalEquilibre: vcontact => "; vcontact.Affiche();
// //------- debug
// #ifdef UTILISATION_MPI
// // cas d'un calcul //, pour l'instant seul le CPU 0 sont concerné
// if (ParaGlob::Monde()->rank() == 0)
// #endif
// { cout << "\n debug AlgoriNonDyna::CalEquilibre";
// cout << "\n max forces de contact " << vcontact.Max_val_abs();
// };
// //--- fin debug
// on globalise tout pour les forces externes généralisées
#ifdef UTILISATION_MPI
temps_transfert_long_algo.Mise_en_route_du_comptage(); // comptage cpu
@ -1034,6 +1093,14 @@ decol = false; // pour debugger
};
residu_final = vglobaal; // sauvegarde pour le post-traitement
////------- debug
//cout << "\n debug AlgoriNonDyna::CalEquilibre";
// { string entete = " affichage de la matrice de raideur (puissance interne) avant resolution";
// tab_mato(1)->Affichage_ecran(entete);
// entete = " affichage du second membre (puissance interne) avant resolution ";
// residu_final.Affichage_ecran(entete);
// };
////--- fin debug
try
{// ici sol en fait = vecglob qui est ecrase par la resolution
sol = &(tab_mato(niveau_substitution)->Resol_systID

View file

@ -650,7 +650,7 @@ void AlgoBonelli::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
#ifdef UTILISATION_MPI
// calcul de l'équilibrage initiale par le cpu 0
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
,distribution_CPU_algo.Tab_indique_CPU_en_cours()

View file

@ -219,7 +219,7 @@ Charge::Charge () : // constructeur par defaut
tabV_transfert.Change_taille(taille_passage);
tabMat_transfert.Change_taille(taille_passage);
tab_six_faux_entiers.Change_taille(taille_passage);
for (int i=1;i<=taille_passage;i++)tab_six_faux_entiers(i).Change_taille(6);
for (int i=1;i<=taille_passage;i++) tab_six_faux_entiers(i).Change_taille(6);
#endif
}
@ -1355,11 +1355,11 @@ void Charge::Transfert_SM(bool& premier_passage,
// on transmet les numéros d'élément et de maillage etc.
reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
// puis on transmets le vecteur résidu sauf si tyfront est négatif
if (tyfront > 0)
{temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM_transfert.Ienvoi_MPI(0,35);
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
{reqs2 = SM_transfert.Ienvoi_MPI(0,35);
// // debug
// cout << "\n debug Charge::Transfert_SM( proc= "<< ParaGlob::Monde()->rank()
// << " six_faux_entiers= " << six_faux_entiers
@ -1371,6 +1371,7 @@ void Charge::Transfert_SM(bool& premier_passage,
index_transfert++;
if (index_transfert > taille_tableau) // on fait une permutation circulaire
index_transfert = 1;// on revient au premier élément des tableaux de transfert
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
};
// transfert du second membre "SM_transfert" et de la matrice "MAT_transfert" et mise à jour
@ -1406,7 +1407,8 @@ void Charge::Transfert_MatSm(bool& premier_passage,
six_faux_entiers(3) = (double) tyfront;
six_faux_entiers(4) = (double) num_front;
six_faux_entiers(5) = (double) SM_transfert.Taille();
six_faux_entiers(6) = (double) index_transfert;
int indique_matrice = (MAT_transfert != NULL);
six_faux_entiers(6) = (double) indique_matrice;
// on transmet les numéros d'élément et de maillage etc.
reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34);
// // debug
@ -1415,12 +1417,15 @@ void Charge::Transfert_MatSm(bool& premier_passage,
// << " SM_transfert= " << SM_transfert << flush;
// // fin debug
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
// puis on transmets le vecteur résidu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM_transfert.Ienvoi_MPI(0,35);
// puis on transmets éventuellementla matrice de raideur
if (MAT_transfert != NULL)
// puis on transmets le vecteur résidu sauf si tyfront est négatif
if (tyfront > 0)
{reqs2 = SM_transfert.Ienvoi_MPI(0,35);
// puis on transmets éventuellementla matrice de raideur
if (MAT_transfert != NULL)
reqs3 = MAT_transfert->Ienvoi_MPI(0,36);
};
// ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore
// en transfert vers le proc 0
index_transfert++;
@ -1429,6 +1434,7 @@ void Charge::Transfert_MatSm(bool& premier_passage,
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
};
#endif

View file

@ -354,7 +354,7 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
#ifdef UTILISATION_MPI
// on définit les conteneurs de passage d'info
int proc_en_cours = ParaGlob::Monde()->rank();
int index_transfert; // index pour incrémenter dans les tableaux
int index_transfert = 1; // index pour incrémenter dans les tableaux
bool premier_passage = true;
if (proc_en_cours != 0)
@ -467,8 +467,6 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
};
#ifdef UTILISATION_MPI
// appel du calcul du second membre correspondant à la charge de type pression
// appel du calcul du second membre correspondant à la charge surfacique
Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier
int num_face = ref.NumeroFA(ns);
SM_transfert = elem.SM_charge_surfacique_E_tdt(vforce,pt_fonct,num_face,pa);
@ -1388,6 +1386,10 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
// le signe - indique une fin
// appel du transfert et mise à jour de l'index des tableaux
Vecteur& SM_transfert = tabV_transfert(index_transfert); // ne sert pas ici
// il faut que le vecteur ne soit pas vide, s'il a une taille nulle on modifie arbitrairement
// c'est le cas qui arrive s'il n'y a aucun chargement
if (SM_transfert.Taille() == 0)
SM_transfert.Change_taille(1); // le vecteur ne sert pas ici
Transfert_SM(premier_passage,tyfront,
0,SM_transfert,
index_transfert,0,0
@ -1540,11 +1542,11 @@ bool Charge::ChargeSecondMembre_Ex_mecaSolid
retour = false;
};
temps_cpu_chargement.Arret_du_comptage();
#ifdef UTILISATION_MPI
temps_attente.Mise_en_route_du_comptage();
ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
temps_attente.Arret_du_comptage();
#endif
//#ifdef UTILISATION_MPI
// temps_attente.Mise_en_route_du_comptage();
// ParaGlob::Monde()->barrier(); // synchronisation ici de tous les process
// temps_attente.Arret_du_comptage();
//#endif
return retour;
};
@ -1886,13 +1888,12 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
#ifdef UTILISATION_MPI
// on définit les conteneurs de passage d'info
int proc_en_cours = ParaGlob::Monde()->rank();
int index_transfert; // index pour incrémenter dans les tableaux
int index_transfert = 1; // index pour incrémenter dans les tableaux
bool premier_passage = true;
if (proc_en_cours != 0)
{
#endif
// $$$--- cas des forces surfaciques ---$$$
// il y a une implication éventuelle sur la raideur
int tabsurfactaille = tabFsurfac.Taille();
@ -2003,8 +2004,7 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
Element::ResRaid resu = elem.SMR_charge_surfacique_I(vforce,pt_fonct,ref.NumeroFA(ns),pa);
#ifdef UTILISATION_MPI
// appel du calcul du second membre correspondant à la charge de type pression
// appel du calcul du second membre correspondant à la charge surfacique
// transfert
Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier
Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert);
Mat_pleine* pt_MAT = NULL;
@ -2143,8 +2143,6 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
Element::ResRaid resu = elem.SMR_charge_pression_I(press_ac,pt_fonct,ref.NumeroFA(ns),pa);
#ifdef UTILISATION_MPI
// appel du calcul du second membre correspondant à la charge de type pression
// appel du calcul du second membre correspondant à la charge surfacique
Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier
Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert);
Mat_pleine* pt_MAT = NULL;
@ -2170,6 +2168,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
pt_MAT,index_transfert,
num_mail,num_elem
);
// //-------debug
// cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< ParaGlob::Monde()->rank()
// << "\n SM= " << SM_transfert << flush;
// cout << "\n mat= "<<*pt_MAT;
// //-------fin debug
temps_cpu_chargement.Mise_en_route_du_comptage();
}
};
@ -2186,6 +2189,11 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
if (avec_raid)
// appel de la fonction adoc, via le pointeur de fonction
(assemb.*assembMat) (matglob,*(resu.raid),elfront->DdlElem_const(),elfront->TabNoeud_const());
// //-------debug
// cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid "
// << "\n SM= " << *(resu.res) << flush;
// cout << "\n mat= "<<*(resu.raid);
// //-------fin debug
}
#endif
};
@ -2307,8 +2315,6 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
#ifdef UTILISATION_MPI
// appel du calcul du second membre correspondant à la charge de type pression
// appel du calcul du second membre correspondant à la charge surfacique
Vecteur& SM_transfert = tabV_transfert(index_transfert); // pour simplifier
Mat_pleine& MAT_transfert = tabMat_transfert(index_transfert);
Mat_pleine* pt_MAT = NULL;
@ -3024,6 +3030,10 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
// le signe - indique une fin
// appel du transfert et mise à jour de l'index des tableaux
Vecteur& SM_transfert = tabV_transfert(index_transfert); // ne sert pas ici
// il faut que le vecteur ne soit pas vide, s'il a une taille nulle on modifie arbitrairement
// c'est le cas qui arrive s'il n'y a aucun chargement
if (SM_transfert.Taille() == 0)
SM_transfert.Change_taille(1); // le vecteur ne sert pas ici
Transfert_SM(premier_passage,tyfront,
0,SM_transfert,
index_transfert,0,0
@ -3058,7 +3068,7 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
tyfront = (int) six_faux_entiers(3);
num_front = (int) six_faux_entiers(4);
taille_SM = (int) six_faux_entiers(5);
index_transfert = six_faux_entiers(6);
int indique_matrice = (int) six_faux_entiers(6);
source = stat.source();
////-------debug
@ -3071,19 +3081,24 @@ bool Charge::ChargeSMembreRaideur_Im_mecaSolid
{Element& elem = lesMail->Element_LesMaille(nbMail,ne);
// def de SM et MAT avec la bonne dimension
SM_transfert.Change_taille(taille_SM);
if (MAT_transfert.Nb_ligne () != taille_SM)
if (indique_matrice)
if (MAT_transfert.Nb_ligne () != taille_SM)
MAT_transfert.Initialise(taille_SM,taille_SM);
// récupération des conteneurs ad hoc vecteur et raideur
temps_cpu_chargement.Arret_du_comptage(); // fin comptage cpu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM_transfert.Irecup_MPI(source, 35);
reqs2.wait(); // on attend que le conteneur soit rempli
// idem pour la matrice
reqs3 = MAT_transfert.Irecup_MPI(source,36);
// idem pour la matrice éventuelle
if (indique_matrice)
{reqs3 = MAT_transfert.Irecup_MPI(source,36);
reqs3.wait();
}
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
////-------debug
//cout << "\n debug Charge::ChargeSMembreRaideur_Im_mecaSolid proc= "<< ParaGlob::Monde()->rank()
// << " SM= " << SM << flush;
// << "\n SM= " << SM_transfert << flush;
//cout << "\n mat= "<<MAT_transfert;
////-------fin debug
// assemblage

View file

@ -788,10 +788,6 @@ Element::operator= (Element& elt)
// calcul d'une longueur géométrique mini représentative de l'élément
// cas = 1: correspond à la distance mini entre deux noeuds coins de l'élément
// cas = 2: dans le cas 1D -> distance mini entre noeuds extrèmes
// en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface
// en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol
// cas = 3: 1D idem cas 2, 2D: distance mini noeud arrête opposée, 3D: distance mini noeud face opposé
double Element::LongueurGeometrique_mini(int cas) const
{ double longueur=0.; // valeur de retour
switch (cas)
@ -843,6 +839,81 @@ double Element::LongueurGeometrique_mini(int cas) const
//cout << " longueur= "<< longueur << endl;
return longueur;
};
// ramène la coordonnée maxi dans la direction i de l'ensemble des noeuds de l'élément
// à l'instant tdt, ou t ou t=0 en fonction de temps
double Element::Maxi_xi_noeud(int i_dir, Enum_dure temps)
{double maxi_xi =0; // init
int nbne = tab_noeud.Taille(); // récup du nombre de noeud
switch (temps)
{ case TEMPS_0:
{for (int i=1;i<= nbne;i++)
{ double xi = tab_noeud(i)->Coord0()(i_dir);
if (maxi_xi < xi) maxi_xi = xi;
};
break;
}
case TEMPS_t:
{for (int i=1;i<= nbne;i++)
{ double xi = tab_noeud(i)->Coord1()(i_dir);
if (maxi_xi < xi) maxi_xi = xi;
};
break;
}
case TEMPS_tdt:
{for (int i=1;i<= nbne;i++)
{ double xi = tab_noeud(i)->Coord2()(i_dir);
if (maxi_xi < xi) maxi_xi = xi;
};
break;
}
};
return maxi_xi;
};
// calcul d'une longueur géométrique caractéristique représentative de l'élément
// cas = 1: correspond à la distance moyenne entre deux noeuds coins de l'élément
// cas = 2: dans le cas 1D -> distance moyenne entre noeuds extrèmes
// en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface
// en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol
double Element::LongueurGeometrique_caracteristique(int cas) const
{ double longueur=0.; // valeur de retour
switch (cas)
{ case 1:
{ int nbne = tab_noeud.Taille(); // récup du nombre de noeud
if (nbne > 1) // si on a qu'un seul noeud, on ne peut rien calculer
{ // tout d'abord l'objectif est de déterminer la distance moyenne entre les différents noeuds
// initialisation de la distance entre les deux noeuds
double dist = 0.;
int nb_dist = 0; // init
if (tab_noeud(1)->ExisteCoord1())
{// cas où les coordonnées à t sont définies
for (int i=1;i<= nbne;i++)
// on itère sur les noeuds restants
for (int j=i+1;j<= nbne;j++,nb_dist++)
dist += (tab_noeud(i)->Coord1() - tab_noeud(j)->Coord1()).Norme();
}
else
{// cas où seules les coordonnées à 0 sont définit
for (int i=1;i<= nbne;i++)
// on itère sur les noeuds restants
for (int j=i+1;j<= nbne;j++,nb_dist++)
dist += (tab_noeud(i)->Coord0() - tab_noeud(j)->Coord0()).Norme();
};
longueur = dist / nb_dist;
};
break;
}
default :
cout << "\nErreur : cas:" << cas <<" non encore traite !\n"
<< "Element::LongueurGeometrique_caracteristique(int cas) ) \n";
Sortie(1);
};
//cout << " longueur= "<< longueur << endl;
return longueur;
};
// calcul le volume entre l'élément (=surface2D) et les plans de ref: yz, xz, xy, dans cet ordre
// valable uniquement pour les éléments 2D dans un espace 3D, ramène une dim nulle sinon

View file

@ -335,14 +335,23 @@ class Element
// ramene l'element geometrique
virtual ElemGeomC0& ElementGeometrique() const =0;
// ramene l'element geometrique en constant
virtual const ElemGeomC0& ElementGeometrique_const() const =0;
virtual const ElemGeomC0& ElementGeometrique_const() const =0;
// calcul d'une longueur géométrique mini représentative de l'élément
// cas = 1: correspond à la distance mini entre deux noeuds coins de l'élément
// cas = 2: dans le cas 1D -> distance mini entre noeuds extrèmes
// en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface
// en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol
// cas = 3: 1D idem cas 2, 2D: distance mini noeud arrête opposée, 3D: distance mini noeud face opposé
double LongueurGeometrique_mini(int cas) const;
double LongueurGeometrique_mini(int cas) const;
// ramène la coordonnée maxi dans la direction i de l'ensemble des noeuds de l'élément
// à l'instant tdt, ou t ou t=0 en fonction de temps
double Maxi_xi_noeud(int i, Enum_dure temps);
// calcul d'une longueur géométrique moyenne représentative de l'élément
// cas = 1: correspond à la distance moyenne entre deux noeuds coins de l'élément
// cas = 2: dans le cas 1D -> distance moyenne entre noeuds extrèmes
// en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface
// en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol
double LongueurGeometrique_caracteristique(int cas) const;
// récupération du volume de l'élément (qui doit avoir été calculé dans une des classes dérivées
// par exemple en mécanique via un calcul explicite ou implicite d'équilibre mécanique
// pour un élément 3D: le volume au sens classique

View file

@ -34,12 +34,18 @@
// constructeur
//par defaut
Front::Front() :
boite_Front(),num_frontiere(0),elem(NULL)
boite_Front(),num_frontiere(0),elem(NULL),angle_mort(0)
#ifdef UTILISATION_MPI
,num_unique(0)
#endif
{ptEl = NULL; tabmitoyen=NULL; };
// normal
Front::Front ( const ElFrontiere& el, Element * pt, int num_front ,int ang_mort) :
boite_Front(ParaGlob::Dimension()),num_frontiere(num_front)
,angle_mort(ang_mort)
#ifdef UTILISATION_MPI
,num_unique(0)
#endif
,elem(el.NevezElemFront())
{ ptEl =(Element *) pt;
tabmitoyen=NULL;
@ -53,6 +59,9 @@ Front::Front ( const ElFrontiere& el, Element * pt, int num_front ,int ang_mort
Front::Front ( const Front& a) :
boite_Front(a.boite_Front),num_frontiere(a.num_frontiere)
,elem(a.elem->NevezElemFront()),angle_mort(a.angle_mort)
#ifdef UTILISATION_MPI
,num_unique(a.num_unique)
#endif
{ ptEl = (Element *) a.ptEl;
if (a.tabmitoyen != NULL)
{ int tabtaille = (a.tabmitoyen)->Taille();
@ -146,6 +155,9 @@ Front& Front::operator = ( const Front& a)
boite_Front = a.boite_Front;
// angle mort
angle_mort = a.angle_mort;
#ifdef UTILISATION_MPI
num_unique = a.num_unique;
#endif
return *this;
};

View file

@ -180,6 +180,13 @@ class Front
int Angle_mort() const {return angle_mort;};
// changement de l'indicateur d'angle mort
void Change_angle_mort(int new_angle_mort) {angle_mort= new_angle_mort;};
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
int NumUnique() const {return num_unique;}; // s'il est attribué (c-a-d != 0) donne un numéro unique de référencement
// est mis à jour et utilisé par les classes appelantes
void ChangeNumUnique(int num) {num_unique = num;};
#endif
// test si la position d'un point est du bon cote ( c-a-d hors matiere) ou non
// si le point est sur la surface, ramène false
@ -215,6 +222,12 @@ class Front
int angle_mort; // indicateur par défaut = 0, ==1 s'il s'agit d'un front
// qui est construit pour représenter un angle mort
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
int num_unique; // s'il est attribué (c-a-d != 0) donne un numéro de référencement
// est mis à jour et utilisé par les classes appelantes
#endif
// fonctions internes
static double prop_mini; // mini proportion à ajouter à l'encombrement

View file

@ -756,6 +756,17 @@ int ElemMeca::Interne(Enum_dure temps,const Coordonnee& M,Coordonnee* coor_local
Sortie(1);
};
#endif
////----- debug
//if ((Num_elt() == 3) && (Num_maillage() == 2))
// {cout << "\n debug ElemMeca::Interne(...";
// Tableau<Noeud *>& tan = Tab_noeud();
//
// for (int i = 1;i<= tan.Taille();i++)
// {cout << " noeud ("<<i<<")";
// tan(i)->Coord2().Affiche();
// };
// };
////---- fin debug
// la methode consiste tout d'abord a calculer les coordonnees locales correspondants
// a M. Pour cela on utilise un processus iteratif
// ---- 1 :init de la recherche
@ -860,56 +871,64 @@ int ElemMeca::Interne(Enum_dure temps,const Coordonnee& M,Coordonnee* coor_local
{retour = 2;} // !-! à l'erreur près, le point est sur la frontière
else {retour = 1;}; // !-! point à l'intérieur
}
else {return 0;}; // !-! point à l'extérieur -> retour directe
// --- cas particuliers ---
// -- dans le cas où "retour" est différent de 0, on regarde les cas particuliers
switch (dim_glob)
{case 3:
{switch (dim_loc)
{ case 3: break; // cas pas de pb
case 2: // cas des "coques ou plaques" on regarde si le point est réellement à l'intérieur (+- 1/2 épaisseur)
{ double epaisseur = Epaisseurs(temps,theta);
A = (met->*PointM) (tab_noeud,ph_i); // le point projeté sur la surface de l'élément
AM = M-A; double delta_hauteur = 0.5 * epaisseur - AM.Norme();
if (Dabs(delta_hauteur) <= prec_tehetai_interne)
{retour = 2;} // !-! à l'erreur près, le point est sur la frontière
else if (delta_hauteur < 0.)
{retour = 0;} // !-! point externe
else {retour = 1;}; // !-! point à l'intérieur
break;
}
default:
cout << " \n *** erreur : cas non implemente pour l'instant "
<< " dim_glob= " << dim_glob << " dim_loc= " << dim_loc
<< "\n ElemMeca::Interne(... ";
Sortie(1);
};// -- fin du switch dim_loc pour dim_glob=3
break;
} // fin dim_glob=3
case 2:
{switch (dim_loc)
{case 2: break; // pas de pb
case 1: case 3: // cas des poutres et volume (pb non consistance) pour l'instant non traité
// donc on laisse aller à la valeur par défaut
default:
cout << " \n *** erreur : cas non implemente pour l'instant "
<< " dim_glob= " << dim_glob << " dim_loc= " << dim_loc
<< "\n ElemMeca::Interne(... ";
Sortie(1);
};// -- fin du switch dim_loc pour dim_glob=3
break;
} // fin dim_glob=2
case 1: // la dimension locale est forcément 1, et pas de pb
{break;
}
default: // default pour le switch sur di_glob
cout << " \n *** erreur : cas non implemente pour l'instant "
<< " dim_glob= " << dim_glob << " dim_loc= " << dim_loc
<< "\n ElemMeca::Interne(... ";
Sortie(1);
break;
}; // -- fin du switch sur dim_glob
// retour
else {retour = 0;}; // !-! point à l'extérieur -> retour directe
if (!retour)
{// --- cas particuliers ---
// -- dans le cas où "retour" est différent de 0, on regarde les cas particuliers
switch (dim_glob)
{case 3:
{switch (dim_loc)
{ case 3: break; // cas pas de pb
case 2: // cas des "coques ou plaques" on regarde si le point est réellement à l'intérieur (+- 1/2 épaisseur)
{ double epaisseur = Epaisseurs(temps,theta);
A = (met->*PointM) (tab_noeud,ph_i); // le point projeté sur la surface de l'élément
AM = M-A; double delta_hauteur = 0.5 * epaisseur - AM.Norme();
if (Dabs(delta_hauteur) <= prec_tehetai_interne)
{retour = 2;} // !-! à l'erreur près, le point est sur la frontière
else if (delta_hauteur < 0.)
{retour = 0;} // !-! point externe
else {retour = 1;}; // !-! point à l'intérieur
break;
}
default:
cout << " \n *** erreur : cas non implemente pour l'instant "
<< " dim_glob= " << dim_glob << " dim_loc= " << dim_loc
<< "\n ElemMeca::Interne(... ";
Sortie(1);
};// -- fin du switch dim_loc pour dim_glob=3
break;
} // fin dim_glob=3
case 2:
{switch (dim_loc)
{case 2: break; // pas de pb
case 1: case 3: // cas des poutres et volume (pb non consistance) pour l'instant non traité
// donc on laisse aller à la valeur par défaut
default:
cout << " \n *** erreur : cas non implemente pour l'instant "
<< " dim_glob= " << dim_glob << " dim_loc= " << dim_loc
<< "\n ElemMeca::Interne(... ";
Sortie(1);
};// -- fin du switch dim_loc pour dim_glob=3
break;
} // fin dim_glob=2
case 1: // la dimension locale est forcément 1, et pas de pb
{break;
}
default: // default pour le switch sur di_glob
cout << " \n *** erreur : cas non implemente pour l'instant "
<< " dim_glob= " << dim_glob << " dim_loc= " << dim_loc
<< "\n ElemMeca::Interne(... ";
Sortie(1);
break;
}; // -- fin du switch sur dim_glob
};
// //----- debug
// if ((Num_elt() == 3) && (Num_maillage() == 2))
// {cout << "\n debug ElemMeca::Interne(...)";
// cout << " retour = "<<retour<< flush;
// };
// //---- fin debug
// retour
return retour;
};
@ -1136,6 +1155,9 @@ void ElemMeca::Cal_implicit (DdlElement & tab_ddl
}; // fin boucle sur les points d'intégration
#ifdef MISE_AU_POINT
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() != 0)
#endif
if (ParaGlob::NiveauImpression() > 9)
{ cout << "\n Raideur et second membre locaux: ? (o/n) "; string rep(" ");
// procédure de lecture avec prise en charge d'un retour chariot
@ -1163,6 +1185,10 @@ void ElemMeca::Cal_implicit (DdlElement & tab_ddl
else {Cal_implicit_StabMembBiel(-1,*ex_final, nbint,volume,NULL);} ;
};
#ifdef MISE_AU_POINT
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() != 0)
#endif
if (ParaGlob::NiveauImpression() > 9)
{ if ((type_stabHourglass)||(pt_StabMembBiel != NULL))
{cout << "\n apres stabilisation: Raideur et second membre locaux: ? (o/n) "; string rep(" ");

View file

@ -980,6 +980,10 @@ if ((*residu)(jloc) > 10.)
}; // fin boucle sur les points d'intégration
#ifdef MISE_AU_POINT
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() == 0)
#endif
if (ParaGlob::NiveauImpression() > 9)
{ cout << "\n Raideur et second membre locaux: ? (o/n) "; string rep(" ");
// procédure de lecture avec prise en charge d'un retour chariot
@ -1009,6 +1013,9 @@ if ((*residu)(jloc) > 10.)
(-1,*ex_final, nbtotsurf,volume,unefois->doCoMemb->noeud_a_prendre_en_compte);} ;
};
#ifdef MISE_AU_POINT
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() == 0)
#endif
if (ParaGlob::NiveauImpression() > 9)
{ if ((type_stabHourglass)||(pt_StabMembBiel != NULL))
{cout << "\n apres stabilisation: Raideur et second membre locaux: ? (o/n) "; string rep(" ");

View file

@ -36,7 +36,7 @@ namespace mpi = boost::mpi;
// constructeur par défaut
Distribution_CPU::Distribution_CPU():
tab_list_maillage_element(),tab_indic()
,total_elem(0)
,total_elem(0),total_elem_maitre(0)
,tab_vide_list_maillage_element()
,tab_list_maillage_noeud(),tab_indic_noeud()
,total_noeud(0)
@ -46,7 +46,8 @@ Distribution_CPU::Distribution_CPU():
// constructeur de copie
Distribution_CPU::Distribution_CPU (const Distribution_CPU& a):
tab_list_maillage_element(a.tab_list_maillage_element)
,tab_indic(a.tab_indic),total_elem(a.total_elem)
,tab_indic(a.tab_indic)
,total_elem(a.total_elem),total_elem_maitre(a.total_elem_maitre)
,tab_vide_list_maillage_element()
,tab_list_maillage_noeud(a.tab_list_maillage_noeud)
,tab_indic_noeud(a.tab_indic_noeud),total_noeud(a.total_noeud)
@ -54,7 +55,7 @@ Distribution_CPU::Distribution_CPU (const Distribution_CPU& a):
{};
// calcul de l'équilibrage initiale
void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMaillages)
void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMaillages, LesContacts * lesContacts)
{
if (ParaGlob::Monde()->rank() == 0)
{ // on équilibre sur tous les cpu excepté le maître, qui lui ne calcule pas
@ -104,6 +105,7 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai
int nb_elem_un_cpu = total_elem/nb_proc_calcul; // arrondi inférieur
// on adapte le tableau de liste
tab_list_maillage_element.Change_taille(nb_proc_calcul);
tab_list_maillage_noeud.Change_taille(nb_proc_calcul);
for (int iproc =1;iproc <= nb_proc_calcul; iproc++)
{tab_list_maillage_element(iproc).Change_taille(nb_mail);
tab_list_maillage_noeud(iproc).Change_taille(nb_mail);
@ -112,40 +114,170 @@ void Distribution_CPU::Calcul_Equilibrage_initiale(const LesMaillages * lesMai
tab_list_maillage_noeud(iproc)(imail).clear();
};
};
// on parcours tous les éléments et on remplit les tableaux
int iproc = 1; // le num du proc en cours
int nb_ele_enreg_iproc = 1; // init le nombre d'élément enregistré pour le proc
for (int imail=1;imail<=nb_mail;imail++)
{
int nb_ele = lesMaillages->Nombre_element(imail);
{list <int > * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init
list <int > * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init
// de la liste courante
for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++)
{ li_maillage_element->push_back(ile);
tab_indic(iproc)(imail)(ile)=true; // on signale
// idem pour les noeuds
Element& ele = lesMaillages->Element_LesMaille(imail,ile);
Tableau<Noeud *>& tab_N = ele.Tab_noeud();
int nb_N = tab_N.Taille();
for (int ne =1;ne<=nb_N;ne++)
{int num_noeud = tab_N(ne)->Num_noeud();
tab_indic_noeud(iproc)(imail)(num_noeud)=true;
li_maillage_noeud->push_back(num_noeud);
};
// on regarde s'il faut changer de cpu
// si c'est le dernier cpu, on ne change pas -> pour éviter
// les pb d'arrondi
if ((nb_ele_enreg_iproc > nb_elem_un_cpu)
&& (iproc < nb_proc_calcul) )
{iproc++;
nb_ele_enreg_iproc=1; // reinit du compteur
li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée
li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail);
};
};
};
};
// on différencie le cas sans et avec contact
// dans le cas sans contact on parcours linéairement tous les maillages successivement
int nb_mail_Esclave = lesMaillages->NbEsclave(); // def du nombre de maillages esclaves
// si aucun esclave
if (nb_mail_Esclave==0)
{// on parcours tous les éléments et on remplit les tableaux
int iproc = 1; // le num du proc en cours
int nb_ele_enreg_iproc = 1; // init le nombre d'élément enregistré pour le proc
for (int imail=1;imail<=nb_mail;imail++)
{
int nb_ele = lesMaillages->Nombre_element(imail);
{list <int > * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init
list <int > * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init
// de la liste courante
for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++)
{ li_maillage_element->push_back(ile);
tab_indic(iproc)(imail)(ile)=true; // on signale
// idem pour les noeuds
Element& ele = lesMaillages->Element_LesMaille(imail,ile);
Tableau<Noeud *>& tab_N = ele.Tab_noeud();
int nb_N = tab_N.Taille();
for (int ne =1;ne<=nb_N;ne++)
{int num_noeud = tab_N(ne)->Num_noeud();
tab_indic_noeud(iproc)(imail)(num_noeud)=true;
li_maillage_noeud->push_back(num_noeud);
};
// on regarde s'il faut changer de cpu
// si c'est le dernier cpu, on ne change pas -> pour éviter
// les pb d'arrondi
if ((nb_ele_enreg_iproc > nb_elem_un_cpu)
&& (iproc < nb_proc_calcul) )
{iproc++;
nb_ele_enreg_iproc=1; // reinit du compteur
li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée
li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail);
};
};
};
};
}
else // cas où on a des maillages maîtres particuliers donc du contact
{// l'idée est de tout d'abord, ventiler les éléments des maillages maîtres ou en autocontact
// de manière à l'exécution qu'il y ait une ventilation:
// 1) de la recherche du contact
// 2) potentiellement (si contact il y a) d'élément de contact
int iproc = 1; // le num du proc en cours
// on va calculer le nb d'éléments maitres (environ) qui doivent être attribué à chaque cpu
int nbmailautocontact = lesContacts->NbmailAutoContact();
// int nbmailMaitre = nb_mail-(nb_mail_Esclave-nbmailautocontact); // def du nombre de maillage maitres
// ce sont les derniers maillages
total_elem_maitre = 0; // init
for (int i=1+nb_mail_Esclave-nbmailautocontact;i<=nb_mail;i++)
{int nb_elem_mail = lesMaillages->Nombre_element(i);
total_elem_maitre += nb_elem_mail;
};
int nb_elem_maitre_un_cpu = total_elem_maitre/nb_proc_calcul; // arrondi inférieur
// // --- debug
// cout << "\n *** debug Distribution_CPU::Calcul_Equilibrage_initiale"
// << "\n total_elem_maitre= "<< total_elem_maitre
// << " nb_elem_maitre_un_cpu= "<< nb_elem_maitre_un_cpu;
// //--- fin debug
// on distribue en parcourant les maillages maîtres
int nb_ele_enreg_iproc = 1; // init le nombre d'élément enregistré pour le proc
for (int imail=1+nb_mail_Esclave-nbmailautocontact;imail<=nb_mail;imail++)
{
int nb_ele = lesMaillages->Nombre_element(imail);
{list <int > * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init
list <int > * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init
// de la liste courante
for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++)
{ li_maillage_element->push_back(ile);
tab_indic(iproc)(imail)(ile)=true; // on signale
// idem pour les noeuds
Element& ele = lesMaillages->Element_LesMaille(imail,ile);
Tableau<Noeud *>& tab_N = ele.Tab_noeud();
int nb_N = tab_N.Taille();
for (int ne =1;ne<=nb_N;ne++)
{int num_noeud = tab_N(ne)->Num_noeud();
tab_indic_noeud(iproc)(imail)(num_noeud)=true;
li_maillage_noeud->push_back(num_noeud);
};
// on regarde s'il faut changer de cpu
// si c'est le dernier cpu, on ne change pas -> pour éviter
// les pb d'arrondi
if ((nb_ele_enreg_iproc > nb_elem_maitre_un_cpu)
&& (iproc < nb_proc_calcul) )
{iproc++;
nb_ele_enreg_iproc=1; // reinit du compteur
li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée
li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail);
};
};
};
};
//// --- debug
//cout << "\n *** debug Distribution_CPU::Calcul_Equilibrage_initiale";
//cout << "\n 1) elements maitres pour chaque proc : ";
//for (int iproc = 1;iproc <= nb_proc_calcul; iproc++)
// {for (int imail=1+nb_mail_Esclave-nbmailautocontact;imail<=nb_mail;imail++)
// {list <int > * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init
// list <int >::iterator il,ilfin = li_maillage_element->end();
// for (il = li_maillage_element->begin();il != ilfin; il++)
// cout << "\n proc("<<iproc<<") mail= "<<imail<< ", elem= "<< (*il)<< flush;
// }
// }
////--- fin debug
// puis on distribue en parcourant les maillages esclaves
// le nombre théorique d'élément par cpu
int nb_elem_esclave_un_cpu = (total_elem-total_elem_maitre)/nb_proc_calcul; // arrondi inférieur
//// --- debug
//cout << "\n *** debug Distribution_CPU::Calcul_Equilibrage_initiale"
// << "\n total_elem= "<< total_elem
// << " nb_elem_esclave_un_cpu= "<< nb_elem_esclave_un_cpu;
////--- fin debug
nb_ele_enreg_iproc = 1; // on réinit
iproc = 1;// réinit
for (int imail=1;imail<=nb_mail_Esclave-nbmailautocontact;imail++)
{
int nb_ele = lesMaillages->Nombre_element(imail);
{list <int > * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init
list <int > * li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail); // init
// de la liste courante
for (int ile = 1; ile<=nb_ele;ile++,nb_ele_enreg_iproc++)
{ li_maillage_element->push_back(ile);
tab_indic(iproc)(imail)(ile)=true; // on signale
// idem pour les noeuds
Element& ele = lesMaillages->Element_LesMaille(imail,ile);
Tableau<Noeud *>& tab_N = ele.Tab_noeud();
int nb_N = tab_N.Taille();
for (int ne =1;ne<=nb_N;ne++)
{int num_noeud = tab_N(ne)->Num_noeud();
tab_indic_noeud(iproc)(imail)(num_noeud)=true;
li_maillage_noeud->push_back(num_noeud);
};
// on regarde s'il faut changer de cpu
// si c'est le dernier cpu, on ne change pas -> pour éviter
// les pb d'arrondi
if ((nb_ele_enreg_iproc > nb_elem_esclave_un_cpu)
&& (iproc < nb_proc_calcul) )
{iproc++;
nb_ele_enreg_iproc=1; // reinit du compteur
li_maillage_element = & tab_list_maillage_element(iproc)(imail); // pointage liste associée
li_maillage_noeud = & tab_list_maillage_noeud(iproc)(imail);
};
};
};
};
//// --- debug
//cout << "\n *** debug Distribution_CPU::Calcul_Equilibrage_initiale";
//cout << "\n 2) au final les elements pour chaque proc : ";
//for (int iproc = 1;iproc <= nb_proc_calcul; iproc++)
// {for (int imail=1;imail<=nb_mail;imail++)
// {list <int > * li_maillage_element = & tab_list_maillage_element(iproc)(imail); // init
// list <int >::iterator il,ilfin = li_maillage_element->end();
// for (il = li_maillage_element->begin();il != ilfin; il++)
// cout << "\n proc("<<iproc<<") mail= "<<imail<< ", elem= "<< (*il)<< flush;
// }
// }
////--- fin debug
}
//// ----- debug
//cout << "\n debug Distribution_CPU::Calcul_Equilibrage_initiale ";
//Distribution_CPU::Affiche();

View file

@ -49,6 +49,7 @@
#include "LesMaillages.h"
#include "LesContacts.h"
#include "Basiques.h"
/**
@ -84,7 +85,7 @@ class Distribution_CPU
// METHODES PUBLIQUES :
// calcul de l'équilibrage initiale par le cpu 0
void Calcul_Equilibrage_initiale(const LesMaillages * lesMaillages);
void Calcul_Equilibrage_initiale(const LesMaillages * lesMaillages, LesContacts * lesContacts);
// passage de l'équilibrage à tous les cpu autres que 0
void Passage_Equilibrage_aux_CPU();
// retour de tab_list_maillage_element(i)(j) contient la liste
@ -177,6 +178,7 @@ class Distribution_CPU
Tableau <Tableau < Tableau <bool > > > tab_indic;
int total_elem ; // nombre total d'éléments cumulé sur tous les maillages
int total_elem_maitre; // nombre total d'éléments maitres cumulé sur tous les maillages;
// tab_list_maillage_noeud(i)(j) contient la liste
// pour le maillage j des num <noeud> associés au cpu i

View file

@ -437,6 +437,16 @@ try
#endif
//#ifdef UTILISATION_MPI
// if (world.rank() == 0)
// { cout << "\n debug Herezh.cc fin transitoire de lecture proc 0";
// cout << "\n taper une lettre pour stopper ";
// string toto;
// cin >> toto;
// Sortie(1);
// };
//#endif
do
{ projet.Calcul(); // 2- calcul

View file

@ -3361,10 +3361,23 @@ Ddl LesMaillages::NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage, double&
return noe.Ddl_noeud_t(a.Const_Enu());
};
// creation des elements frontiere
// creation des elements frontiere: cela n'a lieu qu'une seule fois
// si les frontières existent déjà, --> aucune action, --> ramène 0
// sinon il y a réellement création, et --> ramène 1
// NB: il s'agit ici des frontière minimales permettant de représenter toute la frontière
// Ainsi:
// en 1D on retrouve:
// - des points uniquement
// en 2D on retrouve :
// - des segments dans le cas d'une surface (les noeuds sont exclus car intégrés aux lignes)
// - points et segment pour les lignes
// en 2D axi, on retrouve :
// - des segments dans le cas d'une surface (les noeuds sont exclus car intégrés aux lignes)
// - points et segment pour les lignes
// en 3D, on retrouve
// - des faces pour les éléments volumique (noeuds et lignes sont exclus)
// - une face et des lignes pour les éléments 2D (pas de noeuds)
int LesMaillages::CreeElemFront()
{ int retour = 0;
@ -3414,10 +3427,16 @@ int LesMaillages::CreeElemFront()
// ramene le tableau des noeuds des frontières des maillages esclaves
Tableau < Tableau <Noeud*> *> LesMaillages::Tab_noeud_frontiere_esclave()
{ Tableau < Tableau <Noeud*> *> ret(domEsclave);
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() == 0)
#endif
if ((domEsclave)&&(ParaGlob::NiveauImpression()>2))
cout << "\n >>>> Information maillages : ";
for (int i=1;i<=domEsclave;i++)
{ret(i) = tt_noeud_front(i);
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank() == 0)
#endif
if (ParaGlob::NiveauImpression()>2)
cout << "\n il y a "<<ret(i)->Taille()
<< " noeuds esclaves possible sur front. du maillage " << i ;

View file

@ -647,7 +647,7 @@ class LesMaillages
int CreeElemFront();
// ramene le nombre de maillage esclave
inline int NbEsclave() { return domEsclave;};
inline int NbEsclave() const { return domEsclave;};
// ramene le tableau des list des elements frontiere minimales (cf. explication dans CreeElemFront())
inline Tableau <LaLIST <Front>*>& ListFrontiere() { return listFrontiere;};
// ramene un tableau des noeuds des frontières des maillages esclaves

View file

@ -2179,7 +2179,7 @@ void LesMaillages::Integration()
// };
};
// maintenant il s'agit d'alimenter les grandeurs globales
// maintenant il s'agit d'alimenter les grandeurs globales (du proc i en //)
// on récupère le pointeur correspondant à la grandeur correspondant au nom
// de référence
@ -2206,14 +2206,15 @@ void LesMaillages::Integration()
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
*(gr_quelc->Grandeur_pointee()) = *(g_TG);
#ifdef UTILISATION_MPI
#ifdef UTILISATION_MPI
};
#endif
#endif
};
// même chose pour les intégrales en volume et en temps
int taill1 = ref_integ_vol_t.Taille();
for (int rang_integ =1;rang_integ<= taill1;rang_integ++)
if (ref_integ_vol_t(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas
// même chose pour les intégrales en volume et en temps
int taill1 = ref_integ_vol_t.Taille();
for (int rang_integ =1;rang_integ<= taill1;rang_integ++)
if (ref_integ_vol_t(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas
// l'intégrale stockée reste fixe pendant le calcul
{ const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol_t(rang_integ));
// initialisation du conteneur relatif à chaque ref
@ -2258,7 +2259,7 @@ void LesMaillages::Integration()
// };
// };
};
// maintenant il s'agit d'alimenter les grandeurs globales
// maintenant il s'agit d'alimenter les grandeurs globales (des proc i en //)
// on récupère le pointeur correspondant à la grandeur correspondant au nom
// de référence
@ -2285,11 +2286,16 @@ void LesMaillages::Integration()
// on l'affecte
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
*(gr_quelc->Grandeur_pointee()) = *(g_TG);
#ifdef UTILISATION_MPI
};
#endif
#ifdef UTILISATION_MPI
};
#endif
};
#ifdef UTILISATION_MPI
// on ne continue que s'il y a quelque chose à transmettre
if (taill_v != 0)
{
if (ParaGlob::Monde()->rank() != 0)
{temps_serialisation.Mise_en_route_du_comptage(); // comptage cpu
// on va transmettre au proc 0 les résultats pour que celui-ci globalise les informations
@ -2325,7 +2331,7 @@ void LesMaillages::Integration()
temps_serialisation.Arret_du_comptage(); // fin comptage cpu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
// 4) transfert sans attente au proc 0
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 50, v_integ);
mpi::request reqs1 = v_integ.Ienvoi_MPI(0,50);
temps_transfert_long.Arret_du_comptage(); // comptage cpu
}
else // cas du proc 0
@ -2472,7 +2478,7 @@ void LesMaillages::Integration()
};
temps_serialisation.Arret_du_comptage(); // fin comptage cpu
}
}; // fin cu cas (taill_v != 0)
#endif

View file

@ -2007,7 +2007,7 @@ pour le calcul des frontières donc on met en stand by pour l'instant, si pas de
// definition des elements mitoyens aux elements de frontiere
// definition des elements frontières mitoyens aux elements de frontiere
MitoyenFront();
// ==== définition du tableau des noeuds frontières =====
// 1) on définit un tableau de numéro de noeuds qui sont utilisés
@ -2736,7 +2736,7 @@ Tableau <Vecteur> Maillage::Taille_boiteMail()
//========================== fonction protegee =============================
// definition des elements mitoyens aux elements de frontiere
// definition des elements frontières mitoyens aux elements de frontiere
// à la fin du programme tous les éléments mitoyens sont stocké dant les éléments front
// la manip est de créer des éléments frontières aux éléments frontières existant
// ensuite deux éléments sont mitoyens s'il ont la même frontière

View file

@ -1804,6 +1804,11 @@ void Maillage::AffichageNoeudNonReferencer()
{ //if (ParaGlob::NiveauImpression() > 2)
// cout << "\n print nodes which are not referred in the mesh "
// << nomDuMaillage << endl;
#ifdef UTILISATION_MPI
// cas d'un calcul //, seul le CPU 0 affiche
if (ParaGlob::Monde()->rank() != 0)
return ;
#endif
// on commence par chercher les noeuds non référencés
int taille_tabnoeud=tab_noeud.Taille();
Tableau <bool> non_referencer(taille_tabnoeud,true);

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.023" ; // numéro de version du logiciel
string ParaGlob::nbVersion = "7.028" ; // numéro de version du logiciel
string ParaGlob::NbVersionsurfichier = ""; // numéro de version lue en entrée fichier
int ParaGlob::nb_diggit_double_calcul= 17; // nombre de chiffre significatifs utilisé pour
// l'affichage des double précision pour l'archivage

View file

@ -201,6 +201,7 @@ ParaAlgoControle::ParaAlgoControle() :
nbDecolAutorise = 1; // nb de fois un noeud décolle pour n'être plus considéré en contact
typeDeDecolement = 0; // type par défaut sur la réaction
nb_glissant = 1; // par défaut il n'y a pas de moyenne glissante
nb_change_frontiere_max = 4; // nb de changement maxi de frontière
niveau_commentaire_lescontacts = 0; // par défaut c'est le général qui commande
fct_niveau_commentaire_lescontacts = "_";// pas de fonction par défaut
@ -316,7 +317,8 @@ ParaAlgoControle::ParaAlgoControle(const ParaAlgoControle& p) :
force_tangentielle_noeud_maxi(p.force_tangentielle_noeud_maxi),
fct_nD_force_tangentielle_noeud_maxi(p.fct_nD_force_tangentielle_noeud_maxi),
nb_boucle_newton_position_frontiere(p.nb_boucle_newton_position_frontiere),
nbDecolAutorise(p.nbDecolAutorise),typeDeDecolement(p.typeDeDecolement),nb_glissant(p.nb_glissant),
nbDecolAutorise(p.nbDecolAutorise),typeDeDecolement(p.typeDeDecolement),
nb_glissant(p.nb_glissant),nb_change_frontiere_max(p.nb_change_frontiere_max),
niveau_commentaire_lescontacts(p.niveau_commentaire_lescontacts),
fct_niveau_commentaire_lescontacts(p.fct_niveau_commentaire_lescontacts),
niveau_commentaire_contact(p.niveau_commentaire_contact),
@ -429,7 +431,8 @@ ParaAlgoControle& ParaAlgoControle::operator= (const ParaAlgoControle& p)
fct_nD_force_tangentielle_noeud_maxi = p.fct_nD_force_tangentielle_noeud_maxi;
nb_boucle_newton_position_frontiere = p.nb_boucle_newton_position_frontiere;
nbDecolAutorise = p.nbDecolAutorise; typeDeDecolement = p.typeDeDecolement; nb_glissant = p.nb_glissant;
nbDecolAutorise = p.nbDecolAutorise; typeDeDecolement = p.typeDeDecolement;
nb_glissant = p.nb_glissant;nb_change_frontiere_max = p.nb_change_frontiere_max;
niveau_commentaire_lescontacts = p.niveau_commentaire_lescontacts;
fct_niveau_commentaire_lescontacts = p.fct_niveau_commentaire_lescontacts;
@ -1110,6 +1113,9 @@ void ParaAlgoControle::Lecture_paraAlgoControle(UtilLecture & entreePrinc)
{typeDeDecolement= (int) entreePrinc.lect_avec_const_double_utilisateur("TYPE_DE_DECOLLEMENT ");}
else if (nom == "NB_MOY_GLISSANT")
{nb_glissant= (int) entreePrinc.lect_avec_const_double_utilisateur("NB_MOY_GLISSANT ");}
else if (nom == "NB_CHANGE_FRONTIERE_MAX")
{nb_change_frontiere_max = (int) entreePrinc.lect_avec_const_double_utilisateur("NB_CHANGE_FRONTIERE_MAX ");}
else if (nom == "NIVEAU_COMMENTAIRE_LESCONTACTS")
{if (strstr(entreePrinc.tablcar,"FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACTS")!=NULL)
{*(entreePrinc.entree) >> nom_inter >> fct_niveau_commentaire_lescontacts;
@ -1133,7 +1139,7 @@ void ParaAlgoControle::Lecture_paraAlgoControle(UtilLecture & entreePrinc)
else if (nom == "OPTIMISATION_NUMEROTATION")
{optimisation_numerotation= (int) entreePrinc.lect_avec_const_double_utilisateur("OPTIMISATION_NUMEROTATION ");}
else
{ cout << "\n ** erreur en lecture des parametres de contact" << nom;
{ cout << "\n ** erreur en lecture des parametres de contact: " << nom;
entreePrinc.MessageBuffer
("** lecture des parametres des parametres de contact **");
Affiche();
@ -1470,6 +1476,8 @@ void ParaAlgoControle::Ecriture_base_info_Para
sort << "NB_DECOLLEMENT_MAXI " << nbDecolAutorise << "\n";
sort << "TYPE_DE_DECOLLEMENT " << typeDeDecolement << "\n";
sort << "NB_MOY_GLISSANT " << nb_glissant << "\n";
sort << "NB_CHANGE_FRONTIERE_MAX " << nb_glissant << "\n";
sort << "NIVEAU_COMMENTAIRE_LESCONTACTS "<< niveau_commentaire_lescontacts
<< "FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACT"<< fct_niveau_commentaire_lescontacts << "\n";
sort << "NIVEAU_COMMENTAIRE_CONTACT "<< niveau_commentaire_contact
@ -1682,6 +1690,8 @@ void ParaAlgoControle::Lecture_base_info_Para(ifstream& ent,const int cas)
ent >> toto >> nbDecolAutorise ;
ent >> toto >> typeDeDecolement ;
ent >> toto >> nb_glissant ;
ent >> toto >> nb_glissant ;
ent >> toto >> niveau_commentaire_lescontacts >> toto >> fct_niveau_commentaire_lescontacts;
ent >> toto >> niveau_commentaire_contact >> toto >> fct_niveau_commentaire_contact;
ent >> toto >> optimisation_numerotation;
@ -1890,6 +1900,8 @@ void ParaAlgoControle::Affiche() const
cout << "NB_DECOLLEMENT_MAXI " << nbDecolAutorise << "\n";
cout << "TYPE_DE_DECOLLEMENT " << typeDeDecolement << "\n";
cout << "NB_MOY_GLISSANT " << nb_glissant << "\n";
cout << "NB_CHANGE_FRONTIERE_MAX " << nb_glissant << "\n";
cout << "NIVEAU_COMMENTAIRE_LESCONTACTS " << niveau_commentaire_lescontacts
<< "FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACTS"<< fct_niveau_commentaire_lescontacts << "\n";
cout << "NIVEAU_COMMENTAIRE_CONTACT " << niveau_commentaire_contact
@ -2540,7 +2552,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
<< "\n#--------------------------- "
<< "\n# PARAMETRE | VALEUR | "
<< "\n#--------------------------- ";
Tableau<bool> tab_modif(37,false); // indique qu'est-ce qui a été modifié
Tableau<bool> tab_modif(38,false); // indique qu'est-ce qui a été modifié
//On va proposer un menu
string repa=" ";
cout << "\n --- controle generaux ------ ";
@ -2585,16 +2597,17 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
<< "\n (34) FCT_ND_FORCE_TANGENTIELLE_NOEUD_MAXI "
<< "\n (35) FCT_ND_NIVEAU_COMMENTAIRE_CONTACT "
<< "\n (36) FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACTS "
<< "\n (37 ou h ou ? ) informations "
<< "\n (37) NB_CHANGE_FRONTIERE_MAX "
<< "\n (38 ou h ou ? ) informations "
<< "\n ";
repa = lect_return_defaut(false,"f");
if ((Minuscules(repa) == "f") || (Minuscules(repa) == "0"))// sortie directe
break;
int numa = ChangeEntier(repa);
if (repa == "?") numa = 37;
if (repa == "?") numa = 38;
if (!((numa >= 0)&&(numa<=37)))
{ cout << "\n Erreur on attendait un entier entre 0 et 37 !!, "
if (!((numa >= 0)&&(numa<=38)))
{ cout << "\n Erreur on attendait un entier entre 0 et 38 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour arreter le programme";
};
@ -2606,7 +2619,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
switch (numa)
{ case 0: // sortie
{ break;} // normalement cela a déjà été filtré avant
case 6: case 8: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 25:
case 6: case 8: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 25: case 37:
{ cout << "\n nouvelle valeur (un entier ) ? ";
string_inter= lect_chaine();cout << " valeur lue ="<<string_inter;
// on test si c'est numérique
@ -2633,7 +2646,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
break;
}
case 37:
case 38:
{ cout << "\n PRECISION_POINT_INTERNE_DEBUT: precision du test: point interieur ?, "
<< " avant le debut des calculs "
<< "\n FACT_POUR_RAYON_ACCOSTAGE: facteur multiplicatif du deplacement maxi entre t et tdt"
@ -2667,6 +2680,9 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
<< "\n d'element de contact"
<< "\n FCT_ND_BASCUL_CONTACT_TYPE_4: nom d'une fonction nD permettant de piloter "
<< "\n le basculement du type de contact 4 a 2 (cf. doc) "
<< "\n et tous les mots clef type FCT_ND_... representent des fonctions qui permettent "
<< "\n de moduler une grandeur (cf. doc) "
<< "\n NB_CHANGE_FRONTIERE_MAX : le nombre maximum de changement de frontiere "
<< endl;
break;
}
@ -2712,6 +2728,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
case 34: { fct_nD_force_tangentielle_noeud_maxi = val_string;tab_modif(numa)=true;break;}
case 35: { fct_niveau_commentaire_contact = val_string;tab_modif(numa)=true;break;}
case 36: { fct_niveau_commentaire_lescontacts = val_string;tab_modif(numa)=true;break;}
case 37: { nb_change_frontiere_max = val_int;tab_modif(numa)=true;break;}
default: break;
};
@ -2731,7 +2748,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
};
}; //-- fin du while interne
// écriture des paramètres de contrôle
for (int i=1;i<=36;i++)
for (int i=1;i<=37;i++)
if (tab_modif(i))
{switch (i)
{ case 1: { sort << "\n PRECISION_POINT_INTERNE_DEBUT "<< prec_pt_int_deb;break;}
@ -2771,6 +2788,7 @@ void ParaAlgoControle::Info_commande_ParaAlgoControle(UtilLecture& entreePrinc)
case 35: { sort << "\n NIVEAU_COMMENTAIRE_CONTACT FCT_ND_NIVEAU_COMMENTAIRE_CONTACT "<< fct_niveau_commentaire_contact ;break;}
case 36: { sort << "\n NIVEAU_COMMENTAIRE_LESCONTACTS FCT_ND_NIVEAU_COMMENTAIRE_LESCONTACTS "
<< fct_niveau_commentaire_lescontacts ;break;}
case 37: { sort << "\n NB_CHANGE_FRONTIERE_MAX " << nb_change_frontiere_max;break;}
default: break;
};
};

View file

@ -388,6 +388,8 @@ class ParaAlgoControle
int TypeDeDecolement() const {return typeDeDecolement;};
// retourne le nombre de positions successives, utilisé pour faire une moyenne glissante de ces positions
int Nb_moy_glissant() const {return nb_glissant;};
// retourne le nb de changement maxi de frontière toléré
int NB_change_frontiere_max() const {return nb_change_frontiere_max;};
// retourne le niveau de commentaire entre 0 et 10, pour la gestion globale
// du contact (class LesContacts)
@ -658,6 +660,7 @@ class ParaAlgoControle
int nbDecolAutorise;// nb de fois un noeud décolle pour n'être plus considéré en contact
int typeDeDecolement; // indique le type de méthode utilisée pour gérer le décollement
int nb_glissant; // le nombre de positions successives du noeud esclave, utilisé pour faire une moyenne glissante
int nb_change_frontiere_max = 4; // nb de changement maxi de frontière
int niveau_commentaire_lescontacts; // de 0 à 10: niveau des commentaires pour la gestion globale du contact: i.e. LesContacts
string fct_niveau_commentaire_lescontacts; // fct nD dans le cas d'une valeur pilotée

View file

@ -68,10 +68,20 @@ void Banniere::Sortie_banniere(ofstream & sort)
for (int i=1;i<= taille;i++)
sort << la_banniere(i);
#ifndef MISE_AU_POINT
#ifdef UTILISATION_MPI
sort << "\n# (version parallele la plus rapide )";
#else
sort << "\n# (version la plus rapide )";
#endif
#endif
#ifdef MISE_AU_POINT
#ifdef UTILISATION_MPI
sort << "\n# (version parallele avec le plus de verifications pendant le calcul et les I/O ) ";
#else
sort << "\n# (version avec le plus de verifications pendant le calcul et les I/O ) ";
#endif
#endif
};
// affichage de la banniere sur cout
@ -83,7 +93,11 @@ void Banniere::Sortie_banniere()
cout << "\n# (version la plus rapide )";
#endif
#ifdef MISE_AU_POINT
cout << "\n# (version avec le plus de verifications pendant le calcul et les I/O ) ";
#ifdef UTILISATION_MPI
cout << "\n# (version parallele avec le plus de verifications pendant le calcul et les I/O ) ";
#else
cout << "\n# (version avec le plus de verifications pendant le calcul et les I/O ) ";
#endif
#endif
};

View file

@ -193,14 +193,60 @@ void Condilineaire::Ecriture_base_info(ofstream& sort)
// ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v
// dans ce cas ramène 0
int Condilineaire::Pack_vecteur(Vecteur& v,int rang) const
{ // le tableau de pointeurs
{
////debug Condilineaire::Pack_vecteur
//{ int rang_inter = rang;
// cout << "\n debug Condilineaire::Pack_vecteur ";
// // le tableau de pointeurs
// int taille_pt = pt.Taille();
// cout << "\n taille_pt "<<taille_pt << " rang= " << rang_inter;
// rang_inter++;
// for (int i=1;i<=taille_pt;i++)
// {cout << " pt(i)= "<<pt(i) << " rang= " << rang_inter;
// rang++;};
// // le vecteur val
// int taille_val = val.Taille();
// cout << "\n taille_val "<<taille_val << " rang= " << rang_inter;
// v(rang) = taille_val;
// for (int i=1;i<=taille_val;i++)
// {v(rang)= val(i);rang++;};
// // beta
// v(rang)=beta; rang++;
// // Uk_impose
// v(rang)=Uk_impose; rang++;
// // le cas d'assemblage associé
// rang = casAssemb.Pack_vecteur(v,rang);
// // le tableau t_enu
// int taille_t_enu = t_enu.Taille();
// v(rang) = taille_t_enu;rang++;
// for (int i=1;i<=taille_t_enu;i++)
// {v(rang)= t_enu(i);rang++;};
// // iddl
// v(rang)=iddl; rang++;
// // le taleau t_noeud
// // on considère que la numérotation est la même pour tous les cpu
// // du coup on sauvegarde le numéro de maillage et le numéro de noeud
// int taille_t_noeud = t_noeud.Taille();rang++;
// v(rang)= taille_t_noeud;
// for (int i=1;i<=taille_t_noeud;i++)
// {v(rang)= t_noeud(i)->Num_Mail();rang++;
// v(rang)= t_noeud(i)->Num_noeud();rang++;
// };
// if (rang > v.Taille()) rang = 0;
//
//
//}
//fin debug Condilineaire::Pack_vecteur
// le tableau de pointeurs
int taille_pt = pt.Taille();
v(rang) = taille_pt;rang++;
for (int i=1;i<=taille_pt;i++)
{v(rang)= pt(i);rang++;};
// le vecteur val
int taille_val = val.Taille();
v(rang) = taille_val;
v(rang) = taille_val;rang++;
for (int i=1;i<=taille_val;i++)
{v(rang)= val(i);rang++;};
// beta
@ -219,13 +265,17 @@ void Condilineaire::Ecriture_base_info(ofstream& sort)
// le taleau t_noeud
// on considère que la numérotation est la même pour tous les cpu
// du coup on sauvegarde le numéro de maillage et le numéro de noeud
int taille_t_noeud = t_noeud.Taille();rang++;
v(rang)= taille_t_noeud;
int taille_t_noeud = t_noeud.Taille();
v(rang)= taille_t_noeud;rang++;
for (int i=1;i<=taille_t_noeud;i++)
{v(rang)= t_noeud(i)->Num_Mail();rang++;
v(rang)= t_noeud(i)->Num_noeud();rang++;
};
if (rang > v.Taille()) rang = 0;
return rang;
};
@ -234,10 +284,10 @@ void Condilineaire::Ecriture_base_info(ofstream& sort)
{int taille_pack = 0; // init
taille_pack += pt.Taille() + 1;
taille_pack += val.Taille() + 1;
taille_pack += 2;
taille_pack += 2; // beta et Uk
taille_pack += casAssemb.Taille_Pack();
taille_pack += t_enu.Taille()+1;
taille_pack += 1;
taille_pack += 1; // iddl
taille_pack += 2*t_noeud.Taille()+1;
return taille_pack;
};

View file

@ -89,7 +89,7 @@ class Condilineaire
// par defaut
Condilineaire () :
pt(),val(),beta(0.),t_noeud(),t_enu(),casAssemb()
,Uk_impose(ConstMath::tresgrand)
,Uk_impose(ConstMath::tresgrand),iddl(0)
{} ;
// cas ou l'on connait toutes les infos, sauf Uk_impose, qui est une variable de stockage gérée indépendament
Condilineaire (Tableau <Enum_ddl>& t_enuu, const Tableau<int> & ptt, const Vecteur& vall
@ -101,6 +101,8 @@ class Condilineaire
// cas ou l'on connait les infos relatives uniquements aux noeuds, aux enum ddl
Condilineaire(Tableau <Enum_ddl>& t_enuu, const Tableau < Noeud *>& t_n) :
t_noeud(t_n),t_enu(t_enuu),casAssemb()
,pt(),val(),beta(0.)
,Uk_impose(ConstMath::tresgrand),iddl(0)
{};
// de copie
Condilineaire (const Condilineaire& a) :

View file

@ -193,7 +193,7 @@ class Tableau
// opération inverse: remplissage d'une liste à partir du tableau
// premier de la liste == premier du tableau
void Init_list(std::list<T> & liste );
void Init_list(std::list<T> & liste ) const;
// opération de lecture sur un flot d'entrée
// les données sont le type puis la dimension puis les datas
@ -220,7 +220,11 @@ class Tableau
// test si la valeur passée en argument apartient au tableau
// ramène 0 si ne contient pas
// ramène l'indice dans le tableau de la grandeur si appartenance
// il s'agit du premier élément trouvé à partir de l'élément 1
int Contient(const T& e) const;
// idem mais dans un intervalle de 1 à max d'indice
int Contient(const T& e,int max) const;
// initialisation avec la valeur passée en argument
bool Inita(const T& e) ;
@ -685,7 +689,7 @@ inline Tableau<T>::Init_from_list(const std::list<T> & liste )
}
template <class T> void
inline Tableau<T>::Init_list(std::list<T> & liste )
inline Tableau<T>::Init_list(std::list<T> & liste ) const
// initialisation d'une liste à partir du tableau
// premier de la liste == premier du tableau
{ liste.clear(); // on initialise la liste
@ -861,6 +865,7 @@ inline ostream & Tableau<T>::Sortir_sansRet( ostream & sort) const
// test si la valeur passée en argument apartient au tableau
// ramène 0 si n'appartient pas sinon ramène l'indice dans le tableau
// du premier élément trouvé à partir de l'élément 1
// t(i) = t[i+1]
template <class T>
inline int Tableau<T>::Contient(const T& e) const
@ -869,7 +874,14 @@ inline int Tableau<T>::Contient(const T& e) const
return 0;
}
// idem mais dans un intervalle de 1 à max d'indice
template <class T>
inline int Tableau<T>::Contient(const T& e,int max) const
{ for (int i=0;i<max;i++)
if (t[i] == e) {return (i+1);}
return 0;
}
// initialisation avec la valeur passée en argument
template <class T>
inline bool Tableau<T>::Inita(const T& e)

View file

@ -208,8 +208,22 @@ void Fonc_scal_combinees_nD::Affiche(int niveau) const
};
// --- les variables dans l'ensemble
cout << "\n -- vue d'ensemble des variables: --- "
<< " \n arguments= " << nom_variables
<< " \n variables_globales_en_enumere= " ;
<< " \n arguments= " ; //<< nom_variables
{ // l'objectif est d'afficher le tableau nom_variables
// du fait qu'il peut y avoir (due aux fct internes) une redondance des noms de variables
// on va trier et ne garder qu'un seul exemplaire de chaque variable, pour cela on passe par une liste
// intermédiaire
list <string > li_inter; // init
nom_variables.Init_list(li_inter); // on remplit la liste
li_inter.sort(); // ordonne la liste
li_inter.unique(); // supprime les redondances
// affichage
list <string >::iterator il,ilfin=li_inter.end();
for (il = li_inter.begin();il != ilfin; il++)
cout << (*il) << " ";
};
cout << " \n variables_globales_en_enumere= " ;
int nb_enu = enu_variables_globale.Taille();
cout << "taille " << nb_enu << " ";
for (int i=1;i<= nb_enu;i++)
@ -318,7 +332,8 @@ void Fonc_scal_combinees_nD::LectDonnParticulieres_Fonction_nD(const string& nom
entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne
} while (strstr(entreePrinc->tablcar,"fin_fcts_interne_fonction_combinee_")==0);
// on passe à la ligne suivante
entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne
// on lit sans tenir compte des < éventuelles
{entreePrinc->NouvelleDonneeSansInf();};
// on met en tableau
int tai = li_Fi.size();
Fi.Change_taille(tai);
@ -1053,7 +1068,8 @@ Tableau <double> & Fonc_scal_combinees_nD::Valeur_FnD_interne(Tableau <double >*
int tail_enu = enu_variables_globale_int.Taille(); // les variables globales
for (int i=1;i<= tail_enu;i++,i_fval_int++)
int index_glob=1; // init
for (int i=1;i<= tail_enu;i++,i_fval_int++,index_glob++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale_int(i)));
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
@ -1107,10 +1123,12 @@ Tableau <double> & Fonc_scal_combinees_nD::Valeur_FnD_interne(Tableau <double >*
this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
};
};
// on remplit également le tableau de stockage
x_glob(index_glob)=tab_fVal_int(i_fval_int);
};
// idem pour les variables globales indiçées par des strings
int tail_nom = nom_variables_globales_int.Taille(); // idem avec des noms
for (int i=1;i<= tail_nom;i++,i_fval_int++)
for (int i=1;i<= tail_nom;i++,i_fval_int++,index_glob++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales_int(i)));
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
@ -1217,6 +1235,8 @@ Tableau <double> & Fonc_scal_combinees_nD::Valeur_FnD_interne(Tableau <double >*
this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
};
};
// on remplit également le tableau de stockage
x_glob(index_glob)=tab_fVal_int(i_fval_int);
};
// appel de la fonction maître
@ -2055,6 +2075,63 @@ void Fonc_scal_combinees_nD::Init_fonction_analytique()
// affichage des arguments xi internes en supprimant les redondances,
// utilisée par les fonctions dérivées
// tab_ret: le retour qui a été calculé par la fonction
// decal: donne le nombre de blanc à insérer avant l'affichage
// niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage
void Fonc_scal_combinees_nD::Affiche_interne_valeurs_et_arguments
(int& decal,const Tableau <double >* xi,const Tableau <double>& tab_ret,int niveau) const
{int decal_initial = decal;
//--- debug
//if (nom_ref == "fct_reso_valPropre_coef_B_MAT_1")
// {cout << " debug ";//Fonc_scal_combinees_nD::Affiche_interne_valeurs_et_arguments";
// int toto;
// cin >> toto;
// }
//--- fin debug
if (niveau > 3)
{Fonction_nD::Affiche_interne_valeurs_et_arguments(decal,xi,tab_ret,niveau);
decal++; // +=2; // on décale pour le cas de fct emboitée
// if (permet_affichage > 4)
// {cout << "\n";SortBlanc(decal);cout << " --- fonction composee : Fonc_scal_combinees_nD : nom_ref= " << nom_ref;
// cout << "\n";SortBlanc(decal);cout << " 1) -- vue d'ensemble des variables: --- ";};
if ((niveau > 5) && (niveau < 8))
// --- les variables dans l'ensemble
{ cout << "\n";SortBlanc(decal);cout << " --- fonction composee : Fonc_scal_combinees_nD : nom_ref= " << nom_ref;
// maintenant on s'intéresse à chaque fonction membre
cout << " >>>> fct membres dont le retour sert d'argument: --- ";
int tail = Fi.Taille();
for (int i=1; i<= tail; i++)
{ decal++; // 2;
Fi(i)->Affiche_interne_valeurs_et_arguments(decal,&tab_fVal_Fi(i),tab_ret_Fi(i),niveau);
decal--;// -= 2;
// cout << "\n";SortBlanc(decal);cout << " retour fct (" <<Fi(i)->NomFonction() << ") qui sert d'argument: ";
// int nb_val = tab_ret_Fi(i).Taille();
// for (int j=1;j<=nb_val;j++)
// cout << " val("<<j<<")= "<<tab_ret_Fi(i)(j);
};
};
if (niveau == 8 )
{ // maintenant on s'intéresse à chaque fonction membre
int tail = Fi.Taille();
int decal_deb = decal;
for (int i=1; i<= tail; i++)
{ decal++;
cout << "\n";SortBlanc(decal);
// on impose l'affichage de même type pour avoir tout l'arbre d'appel
Fi(i)->Affiche_interne_valeurs_et_arguments(decal,&tab_fVal_Fi(i),tab_ret_Fi(i),8);
decal = decal_deb;
};
};
};
decal = decal_initial; // retour au décalage initiale
};

View file

@ -265,6 +265,15 @@ class Fonc_scal_combinees_nD : public Fonction_nD
// sont des grandeurs globales
virtual Tableau <double> & Valeur_pour_variables_globales_interne();
// affichage des arguments xi internes en supprimant les redondances,
// utilisée par les fonctions dérivées
// tab_ret: le retour qui a été calculé par la fonction
// decal: donne le nombre de blanc à insérer avant l'affichage
// niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage
virtual void Affiche_interne_valeurs_et_arguments
(int& decal, const Tableau <double >* xi,const Tableau <double>& tab_ret,int niveau) const;
};
/// @} // end of group

View file

@ -124,7 +124,7 @@ Fonction_nD& Fonction_expression_litterale_nD::operator= (const Fonction_nD& elt
return *this;
};
// affichage de la courbe
// affichage de la fonction
void Fonction_expression_litterale_nD::Affiche(int niveau) const
{ cout << " Fonction_expression_litterale_nD " << nom_ref ;
cout << " \n arguments= " << nom_variables
@ -450,6 +450,7 @@ void Fonction_expression_litterale_nD::Info_commande_Fonctions_nD(UtilLecture &
};
// calcul des valeurs de la fonction, retour d'un tableau de scalaires
// pas d'affichage sauf s'il y a une erreur
Tableau <double> & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau <double >* xi)
{ int i_in_xi=1; // indice pour se déplacer dans xi
// int i_in_tab_coor=1;// indice pour se déplacer dans tab_coor
@ -471,10 +472,8 @@ Tableau <double> & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau
int tail_enu = enu_variables_globale.Taille(); // les variables globales
int tail_nom = nom_variables_globales.Taille(); // idem avec des noms
#ifdef MISE_AU_POINT
// if (tab_fVal.Taille() != (taille_xi+taille_totale_coor+tail_enu))
if (tab_fVal.Taille() != (taille_xi+tail_enu+tail_nom))
{ cout << "\n *** pb de dimensions d'argument non coherentes !! "
// << " taille_xi+taille_totale_coor "<<taille_xi+taille_totale_coor
<< " taille_xi "<<taille_xi
<< ", tab_fVal.Taille()= "<<tab_fVal.Taille()
<< " enu_variables_globale.Taille()= "<<enu_variables_globale
@ -523,236 +522,6 @@ Tableau <double> & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau
for (int i=1;i<= taille;i++,i_fval++)
tab_fVal(i_fval) = x_glob(i);
/*
// 2) puis les valeurs globales éventuelles typées énuméré
if (tail_enu>0)
{
// en debug on vérifie que les grandeurs globales sont présentent
#ifdef MISE_AU_POINT
try
{ int taille = enu_variables_globale.Taille();
for (int i=1;i<= taille;i++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i)));
if (pointe == NULL)
{ cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! "
<< " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i))
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
}
catch(...)
{ cout << "\n ** erreur dans l'appel de la fonction "
<< nom_ref << " d'expression " << expression_fonction;
cout << " verifier la presence des grandeurs globales voulues "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
// on parcours les variables globales
int taille = enu_variables_globale.Taille();
for (int i=1;i<= taille;i++,i_fval++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i)));
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie())
{ case TYPE_SIMPLE:
{ switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
{case PARTICULIER_SCALAIRE_ENTIER:
{Grandeur_scalaire_entier& gr
= *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurEntier());
break;
}
case PARTICULIER_SCALAIRE_DOUBLE:
{Grandeur_scalaire_double& gr
= *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurDouble());
break;
}
case PARTICULIER_DDL_ETENDU:
{Grandeur_Ddl_etendu& gr
= *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i))
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
}
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i))
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
};
};
// 3) idem pour les globaux en nom c-a-d typées sous forme de string
if (tail_nom>0)
{
// en debug on vérifie que les grandeurs globales sont présentent
#ifdef MISE_AU_POINT
try
{ for (int i=1;i<= tail_nom;i++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i)));
if (pointe == NULL)
{ cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! "
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
}
catch(...)
{ cout << "\n ** erreur dans l'appel de la fonction "
<< nom_ref << " d'expression " << expression_fonction;
cout << " verifier la presence des grandeurs globales voulues "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
// on parcours les variables globales
int taille = nom_variables_globales.Taille();
for (int i=1;i<= taille;i++,i_fval++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i)));
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie())
{ case TYPE_SIMPLE:
{ switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
{case PARTICULIER_SCALAIRE_ENTIER:
{Grandeur_scalaire_entier& gr
= *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurEntier());
break;
}
case PARTICULIER_SCALAIRE_DOUBLE:
{Grandeur_scalaire_double& gr
= *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurDouble());
break;
}
case PARTICULIER_DDL_ETENDU:
{Grandeur_Ddl_etendu& gr
= *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
break;
}
case PARTICULIER_VECTEUR_NOMMER:
{Grandeur_Vecteur_Nommer& gr
= *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
#ifdef MISE_AU_POINT
// on vérifie qu'une seule grandeur est stockée
if (gr.NbMaxiNumeroOrdre() > 1)
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
<< " compte pour l'intant, on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
}
break;
}
case TABLEAU_T: // valable uniquement pour les vecteur nommer
// dans ce cas on n'utilise pour l'instant que la première valeur
{ switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
{ case PARTICULIER_VECTEUR_NOMMER:
{Grandeur_Vecteur_Nommer& gr
= *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
#ifdef MISE_AU_POINT
// on vérifie qu'une seule grandeur est stockée
if (gr.NbMaxiNumeroOrdre() > 1)
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
<< " compte pour l'intant, on ne peut pas continuer "
<< "\n grandeur= "<<gr<< " NbMaxiNumeroOrdre()= "<< gr.NbMaxiNumeroOrdre()
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
}
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_FnD_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
};
};
*/
// on peut maintenant appeler la fonction
int nNum;
double * v = p.Eval(nNum);
@ -774,7 +543,6 @@ Tableau <double> & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau
cout <<"\n >>> arbre d'appel : fonction this : ";
this->Affiche(5);
cout << endl;
// p.Eval(nNum);
// on génère une interruption ce qui permettra de dépiler les appels
ErrCalculFct_nD toto;throw (toto);Sortie(1);
};
@ -818,251 +586,8 @@ Tableau <double> & Fonction_expression_litterale_nD::Valeur_FnD_interne(Tableau
// sont toutes des grandeurs globales: pour l'instant que pour des variables scalaires
Tableau <double> & Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne()
{
/* // en debug on vérifie que les grandeurs globales sont présentent
#ifdef MISE_AU_POINT
try
{ // on vérifie tout d'abord que toutes les variables sont globales
if (nom_variables.Taille() != 0)
{ cout << "\n ** erreur dans l'appel de la fonction "
<< nom_ref << " d'expression " << expression_fonction;
cout << " toutes les variables ne sont pas globales !! "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<<endl;
this->Affiche();
// on génère une interruption ce qui permettra de dépiler les appels
ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
// maintenant on vérifie la présence des variables globales
int taille = enu_variables_globale.Taille();
for (int i=1;i<= taille;i++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i)));
if (pointe == NULL)
{ cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! "
<< " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i))
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<<endl;
this->Affiche();
// on génère une interruption ce qui permettra de dépiler les appels
ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
}
catch(...)
{ cout << "\n ** erreur dans l'appel de la fonction "
<< nom_ref << " d'expression " << expression_fonction;
cout << " verifier la presence des grandeurs globales voulues "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<<endl;
this->Affiche();
// on génère une interruption ce qui permettra de dépiler les appels
ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
// idem pour les grandeurs indicées avec des string
#ifdef MISE_AU_POINT
try
{ int tail_nom = nom_variables_globales.Taille();
for (int i=1;i<= tail_nom;i++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i)));
if (pointe == NULL)
{ cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! "
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
}
catch(...)
{ cout << "\n ** erreur dans l'appel de la fonction "
<< nom_ref << " d'expression " << expression_fonction;
cout << " verifier la presence des grandeurs globales voulues "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."<<endl;
this->Affiche();
// on génère une interruption ce qui permettra de dépiler les appels
ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
*/
// arrivée ici toutes les grandeurs existent
try
{
/* // on parcours les variables globales
int i_fval=1; // indice pour se déplacer dans plusieurs boucles
int taille = enu_variables_globale.Taille();
for (int i=1;i<= taille;i++,i_fval++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i)));
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie())
{ case TYPE_SIMPLE:
{ switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
{case PARTICULIER_SCALAIRE_ENTIER:
{Grandeur_scalaire_entier& gr
= *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurEntier());
break;
}
case PARTICULIER_SCALAIRE_DOUBLE:
{Grandeur_scalaire_double& gr
= *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurDouble());
break;
}
case PARTICULIER_DDL_ETENDU:
{Grandeur_Ddl_etendu& gr
= *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i))
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
}
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i))
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
};
// idem mais typées sous forme de string
{// on parcours les variables globales
int taille = nom_variables_globales.Taille();
for (int i=1;i<= taille;i++,i_fval++)
{// on récupère le pointeur correspondant à la grandeur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i)));
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie())
{ case TYPE_SIMPLE:
{ switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
{case PARTICULIER_SCALAIRE_ENTIER:
{Grandeur_scalaire_entier& gr
= *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurEntier());
break;
}
case PARTICULIER_SCALAIRE_DOUBLE:
{Grandeur_scalaire_double& gr
= *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = *(gr.ConteneurDouble());
break;
}
case PARTICULIER_DDL_ETENDU:
{Grandeur_Ddl_etendu& gr
= *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
break;
}
case PARTICULIER_VECTEUR_NOMMER:
{Grandeur_Vecteur_Nommer& gr
= *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
#ifdef MISE_AU_POINT
// on vérifie qu'une seule grandeur est stockée
if (gr.NbMaxiNumeroOrdre() > 1)
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
<< " compte pour l'intant, on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
}
break;
}
case TABLEAU_T: // valable uniquement pour les vecteur nommer
// dans ce cas on n'utilise pour l'instant que la première valeur
{ switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
{ case PARTICULIER_VECTEUR_NOMMER:
{Grandeur_Vecteur_Nommer& gr
= *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
tab_fVal(i_fval) = (gr.GrandeurNumOrdre(1));
#ifdef MISE_AU_POINT
// on vérifie qu'une seule grandeur est stockée
if (gr.NbMaxiNumeroOrdre() > 1)
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
<< " compte pour l'intant, on ne peut pas continuer "
<< "\n grandeur= "<<gr<< " NbMaxiNumeroOrdre()= "<< gr.NbMaxiNumeroOrdre()
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
#endif
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
}
break;
}
default:
{ cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
<< " la variable globale "<< nom_variables_globales(i)
<< ", n'est pas prise en compte actuellement , on ne peut pas continuer "
<< "\n Fonction_expression_litterale_nD::Valeur_pour_variables_globales_interne(..."
<<endl;
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche();ErrCalculFct_nD toto;throw (toto);
Sortie(1);
};
};
};
};
*/
// on récupère les grandeurs globales
Fonction_nD::Recup_Grandeurs_globales();
// on affecte les grandeurs
@ -1097,7 +622,6 @@ Tableau <double> & Fonction_expression_litterale_nD::Valeur_pour_variables_globa
cout <<"\n >>> arbre d'appel : fonction this : ";
this->Affiche(5);
cout << endl;
// p.Eval(nNum);
// on génère une interruption ce qui permettra de dépiler les appels
this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
};

View file

@ -164,6 +164,7 @@ class Fonction_expression_litterale_nD : public Fonction_nD
// METHODES PROTEGEES :
// calcul des valeurs de la fonction, retour d'un tableau de scalaires
// pas d'affichage sauf s'il y a une erreur
virtual Tableau <double> & Valeur_FnD_interne(Tableau <double >* xi);
// calcul des valeurs de la fonction, dans le cas où les variables

View file

@ -38,6 +38,8 @@
#include "Fonction_expression_litterale_nD.h"
#include "Fonction_externe_nD.h"
#include "MotCle.h"
#include "CharUtil.h"
// CONSTRUCTEURS :
// par défaut
@ -887,7 +889,8 @@ void Fonction_nD::Construction_index_conteneurs_evoluees()
posi_ddl_enum(i)=position;
// maintenant il faut récupérer la position = l'indice, de l'enu dans le tenseur
// erreur : 18 mars 2023 Deuxentiers_enu deux = IJind(ddl_de_service.Enum(),dim);
Deuxentiers_enu deux = IJind(ddenumetendu.Enum(),dim);
// on considère qu'il s'agit de composantes de tenseur en absolu
Deuxentiers_enu deux = IJind(ddenumetendu.Enum(),ParaGlob::NbCompTens());
ind_tens(i) = deux;
break;
}
@ -1122,11 +1125,12 @@ Tableau <double > & Fonction_nD::Vers_tab_double(Tableau <double > & di
di(num_variable) = (*(*tens_ddl_enum)(j))(k,l);
#ifdef MISE_AU_POINT
if (permet_affichage > 9)
cout << "\n num_variable= "<<num_variable
{cout << "\n num_variable= "<<num_variable
<< " di (num_variable)= "<<di(num_variable)
<< " posi_ddl_enum(ienu)= "<<posi_ddl_enum(ienu)
<< " indices dans tenseur: (k,l)= ("<<k<<","<<l<<")"
<< "\n tensBB= ";(*tens_ddl_enum)(j)->Ecriture(cout) ;
};
#endif
break;}
default:
@ -1279,11 +1283,12 @@ Tableau <double > & Fonction_nD::Vers_tab_double(Tableau <double > & di
di(num_variable) = tensBB(k,l);
#ifdef MISE_AU_POINT
if (permet_affichage > 9)
cout << "\n num_variable= "<<num_variable
{cout << "\n num_variable= "<<num_variable
<< " di (num_variable)= "<<di(num_variable)
<< " posi_ddl_enum(ienu)= "<<posi_ddl_enum(ienu)
<< " indices dans tenseur: (k,l)= ("<<k<<","<<l<<")"
<< "\n tensBB= ";tensBB.Ecriture(cout) ;
};
#endif
i_evol++;
break;}
@ -1369,7 +1374,7 @@ double Fonction_nD::Val_avec_nbArgVariable(double x,...)
// méthode utilisée par les classes dérivées, pour transférer les infos qui sont
// gérées au niveau de Fonction_nD
Fonction_nD& Fonction_nD::Transfert_info(const Fonction_nD& elt)
void Fonction_nD::Transfert_info(const Fonction_nD& elt)
{ // on reprend toutes les données gérées par Fonction_nD
typeFonction = elt.typeFonction;
nom_ref = elt.nom_ref;
@ -1413,43 +1418,75 @@ void Fonction_nD::Affiche_interne(int niveau) const
{ if (niveau > 0)
{ cout << "\n type_de_fonction: "<< Nom_Fonction_nD(typeFonction)
<< " nom_ref= " << nom_ref
<< "\n les_variables_lues: " << nom_variables ;
<< "\n les_variables_lues: (nb total avec redondance= "<< nom_variables.Taille()<<") " ;//<< nom_variables ;
{ // l'objectif est d'afficher le tableau nom_variables
// du fait qu'il peut y avoir (due aux fct internes) une redondance des noms de variables
// on va trier et ne garder qu'un seul exemplaire de chaque variable, pour cela on passe par une liste
// intermédiaire
list <string > li_inter; // init
nom_variables.Init_list(li_inter); // on remplit la liste
li_inter.sort(); // ordonne la liste
li_inter.unique(); // supprime les redondances
// affichage
list <string >::iterator il,ilfin=li_inter.end();
for (il = li_inter.begin();il != ilfin; il++)
cout << (*il) << " ";
};
if (niveau > 1)
{ // les énumérés globaux éventuels
int taille_enu_variables_globale= enu_variables_globale.Taille();
if (taille_enu_variables_globale != 0)
{ cout << "\n enumeres_globaux:_taille " << enu_variables_globale.Taille();
{ cout << "\n enumeres_globaux: (nb total avec redondance= "<< enu_variables_globale.Taille()<<") " ; // << enu_variables_globale.Taille();
for (int i=1;i<= taille_enu_variables_globale;i++)
cout << " " << Nom_GrandeurGlobale(enu_variables_globale(i));
{// on regarde si un élément de même type à déjà été affiché
int posi = enu_variables_globale.Contient(enu_variables_globale(i),i-1);
if (posi == 0)
cout << " " << Nom_GrandeurGlobale(enu_variables_globale(i));
};
};
// les noms de variables globales éventuelles
int taille_nom_variables_globales= nom_variables_globales.Taille();
if (taille_nom_variables_globales != 0)
{ cout << "\n noms_variables_globales:_taille " << nom_variables_globales.Taille();
{ cout << "\n noms_variables_globales: (nb total avec redondance= "<< nom_variables_globales.Taille()<<") " ;// << nom_variables_globales.Taille();
for (int i=1;i<= taille_nom_variables_globales;i++)
cout << " " << nom_variables_globales(i);
{// on regarde si un élément de même type à déjà été affiché
int posi = nom_variables_globales.Contient(nom_variables_globales(i),i-1);
if (posi == 0)
cout << " " << nom_variables_globales(i);
};
};
// enu étendu équivalent aux variables non globales
int taille_tab_enu_etendu= tab_enu_etendu.Taille();
if (taille_tab_enu_etendu != 0)
{ cout << "\n enum_etendu_locaux:_taille " << tab_enu_etendu.Taille();
{ cout << "\n enum_etendu_locaux equivalent : (nb total avec redondance= "<< taille_tab_enu_etendu<<") " ; // << taille_tab_enu_etendu;
// l'objectif est d'afficher le tableau tab_enu_etendu
// du fait qu'il peut y avoir (due aux fct internes) une redondance
// on fait une manip pour n'afficher qu'un seul exemplaire
for (int i=1;i<= taille_tab_enu_etendu;i++)
{cout << " " << tab_enu_etendu(i).Nom_plein();
int j = posi_ddl_enum(i);
switch (type_des_variables(i))
{case 1: cout << " type scalaire: valeur actuelle= "
<< val_ddl_enum(j) ;
break;
case 2: cout << " type coordonnees: valeur actuelle= "
<< coor_ddl_enum(j)(num_dans_coor(j));
break;
case 3: cout << " type tenseur: valeur actuelle= "
<< (*tens_ddl_enum(j))(ind_tens(j).i,ind_tens(j).j) ;
break;
default: cout << "\n type non reconnue= " << type_des_variables(i)
<< "\n Fonction_nD::Affiche_interne( ";
Sortie(1);
};
{// on regarde si un élément de même type à déjà été affiché
int posi = tab_enu_etendu.Contient(tab_enu_etendu(i),i-1);
if ((posi == 0)
|| ((posi !=0)&&(posi_ddl_enum(i) != posi_ddl_enum(posi)))
)
{cout << " " << tab_enu_etendu(i).Nom_plein();
int j = posi_ddl_enum(i);
switch (type_des_variables(i))
{case 1: cout << " type scalaire: valeur actuelle= "
<< val_ddl_enum(j) ;
break;
case 2: cout << " type coordonnees: valeur actuelle= "
<< coor_ddl_enum(j)(num_dans_coor(j));
break;
case 3: cout << " type tenseur: valeur actuelle= "
<< (*tens_ddl_enum(j))(ind_tens(j).i,ind_tens(j).j) ;
break;
default: cout << "\n type non reconnue= " << type_des_variables(i)
<< "\n Fonction_nD::Affiche_interne( ";
Sortie(1);
};
};
};
// bilan des variables évoluées
cout << "\n il y a: "
@ -1461,7 +1498,7 @@ void Fonction_nD::Affiche_interne(int niveau) const
// grandeurs quelconques équivalentes aux variables non globales
int taille_tab_enu_quelconque= tab_enu_quelconque.Taille();
if (taille_tab_enu_quelconque != 0)
{ cout << "\n enum_quelconque:_taille " << tab_enu_quelconque.Taille()
{ cout << "\n enum_quelconque (equivalent aux variables non globales):_taille " << tab_enu_quelconque.Taille()
<< "\n liste: ";
for (int i=1;i<= taille_tab_enu_quelconque;i++)
cout << NomTypeQuelconque(tab_enu_quelconque(i)) << ", ";
@ -1632,11 +1669,13 @@ void Fonction_nD::Lecture_variables(string& nom_lu,UtilLecture * entreePrinc)
nom_variables.Init_list(list_de_variables);
bool lecture_effective = false; // init
while (( (strstr(entreePrinc->tablcar,"un_argument=")==0)
&& (strstr(entreePrinc->tablcar,"deb_list_var_")==0)
)
|| (nom_lu == "un_argument=")
|| (nom_lu == "deb_list_var_")
while ( ( (strstr(entreePrinc->tablcar,"un_argument=")!=0)
|| (strstr(entreePrinc->tablcar,"deb_list_var_")!=0)
|| (nom_lu == "un_argument=")
|| (nom_lu == "deb_list_var_")
)
&& (nom_lu != "fin_list_var_")
// || (lecture_effective)
)
{
// si on a un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur
@ -1687,7 +1726,7 @@ void Fonction_nD::Lecture_variables(string& nom_lu,UtilLecture * entreePrinc)
Sortie(1);
};
lecture_effective = false; // on réinit
// cas de la lecture d'une variable
if(nom_lu == "un_argument=")
{*(entreePrinc->entree) >> nom_lu;
@ -1699,6 +1738,27 @@ void Fonction_nD::Lecture_variables(string& nom_lu,UtilLecture * entreePrinc)
{ list_de_variables_nom_globales.push_back(nom_lu);}
else // sinon ce n'est pas une grandeur globale
{list_de_variables.push_back(nom_lu);};
// on gère le fait que l'on peut être à la fin de la ligne
if ((entreePrinc->entree)->rdstate() == 0)
{} // lecture normale on ne fait rien
#ifdef ENLINUX
else if ((entreePrinc->entree)->fail())
// on a atteind la fin de la ligne et on appelle un nouvel enregistrement
{ // on lira sans tenir compte des < éventuelles
entreePrinc->NouvelleDonneeSansInf();
}
#else
else if ((entreePrinc->entree)->eof())
// la lecture est bonne mais on a atteind la fin de la ligne
{ entreePrinc->NouvelleDonneeSansInf();
}
#endif
else // cas d'une erreur de lecture
{ cout << "\n erreur de lecture inconnue ";
entreePrinc->MessageBuffer("** erreur3 des parametres d'une fonction nD **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
// on signale que la lecture a été effective
lecture_effective = true;
}
@ -2047,6 +2107,97 @@ void Fonction_nD::Recup_Grandeurs_globales()
};
// affichage des arguments xi internes en supprimant les redondances,
// utilisée par les fonctions dérivées
// tab_ret: le retour qui a été calculé par la fonction
// decal: donne le nombre de blanc à insérer avant l'affichage
// niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage
void Fonction_nD::Affiche_interne_valeurs_et_arguments
(int& decal,const Tableau <double >* xi,const Tableau <double>& tab_ret,int niveau) const
{ int taille_nom_variables = nom_variables.Taille();
int taille_enu_variables_globale= enu_variables_globale.Taille();
int taille_nom_variables_globales= nom_variables_globales.Taille();
#ifdef MISE_AU_POINT
// vérif de démarrage
if (xi == NULL)
{ if (taille_nom_variables != 0)
{cout << "\n *** erreur d'appel de fonction nD, on ne devrait pas avoir de variables autre que globales !! "
<< "\n Fonction_nD::Affiche_interne_valeurs_arguments(...";
Affiche(2);
Sortie(1);
};
}
else
{ if (xi->Taille() != taille_nom_variables)
{cout << "\n *** erreur d'appel de fonction nD, le nombre d'arguments ("<< xi->Taille()
<<") n'est pas coherent avec les arguments lues (avec redondance) !! "
<< "\n Fonction_nD::Affiche_interne_valeurs_arguments(...";
Affiche(2);
Sortie(1);
};
};
#endif
if (niveau > 3)
{
if (niveau < 8)
{cout << "\n";SortBlanc(decal);cout << " --- fonction: "<<nom_ref<<" : ";
if (niveau > 4)
if (taille_nom_variables > 0)
{cout << "\n";SortBlanc(decal);cout << " les_variables_lues: " ;// nom_variables
// l'objectif est d'afficher le tableau nom_variables et les valeurs correspondantes
for (int i = 1; i<= taille_nom_variables;i++)
{// on regarde si un élément de même type à déjà été affiché
int posi = nom_variables.Contient(nom_variables(i),i-1);
if (posi == 0) // pas encore affiché, on l'affiche
cout << " " << nom_variables(i) << " = " << (*xi)(i);
};
};
if (niveau > 6)
{// les énumérés globaux éventuels
if (taille_enu_variables_globale != 0)
{ cout << "\n";SortBlanc(decal);cout << " enumeres_globaux: "; // << enu_variables_globale.Taille();
for (int i=1;i<= taille_enu_variables_globale;i++)
{// on regarde si un élément de même type à déjà été affiché
int posi = enu_variables_globale.Contient(enu_variables_globale(i),i-1);
if (posi == 0)
cout << " " << Nom_GrandeurGlobale(enu_variables_globale(i))
<< " = " << x_glob(i);
};
};
// les noms de variables globales éventuelles
if (taille_nom_variables_globales != 0)
{ cout << "\n";SortBlanc(decal);cout << " noms_variables_globales: ";// << nom_variables_globales.Taille();
for (int i=1;i<= taille_nom_variables_globales;i++)
{// on regarde si un élément de même type à déjà été affiché
int posi = nom_variables_globales.Contient(nom_variables_globales(i),i-1);
if (posi == 0)
cout << " " << nom_variables_globales(i)
<< " = " << x_glob(i+taille_enu_variables_globale);
};
};
};
SortBlanc(decal);cout << " ==>> retour fonction: ";
int nb_val = tab_ret.Taille();
for (int i=1;i<=nb_val;i++)
cout << " val("<<i<<")= "<<tab_ret(i);
}
else
{ if (decal == 0)
cout << "\n"; // juste au début
SortBlanc(decal);cout << "--f:"<<nom_ref<<" : "<< "=>";
int nb_val = tab_ret.Taille();
for (int i=1;i<=nb_val;i++)
cout << " val("<<i<<")= "<<tab_ret(i);
};
};
};

View file

@ -275,27 +275,12 @@ class Fonction_nD
// retour d'un tableau de scalaires
Tableau <double> & Valeur_FnD_tab_scalaire(Tableau <double >* val_double)
{try
{
// #ifdef MISE_AU_POINT
if (permet_affichage > 4)
{
cout << "\n fonction: "<<nom_ref<<" : ";
if (permet_affichage > 5)
{cout << "\n parametres d'appel: ";
int nb_var = val_double->Taille();
for (int j=1;j<=nb_var;j++)
{ cout << " para("<<j<<")= "<< (*val_double)(j);}
};
Tableau <double> & inter = Valeur_FnD_interne(val_double);
cout << "\n retour fonction: ";
int nb_val = inter.Taille();
for (int i=1;i<=nb_val;i++)
cout << " val("<<i<<")= "<<inter(i);
return inter;
}
else
// #endif
return Valeur_FnD_interne(val_double);
{ // on commence par le calcul se qui permet pour des fonctions complexes (ex: combinées)
// de remplir les tableaux internes nécessaires pour l'affichage locale éventuelles (fct propres)
Tableau <double> & inter = Valeur_FnD_interne(val_double);
int decal = 0;
Affiche_interne_valeurs_et_arguments(decal,val_double,inter,permet_affichage);
return inter;
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
@ -330,25 +315,12 @@ class Fonction_nD
{try
{ Vers_tab_double(t_inter_double,val_ddl_enum,coor_ddl_enum,tens_ddl_enum
,tqi,t_num_ordre);
// #ifdef MISE_AU_POINT
if (permet_affichage > 4)
{cout << "\n fonction: "<<nom_ref<<" : ";
if (permet_affichage > 5)
{cout << "\n parametres d'appel: ";
int nb_var = t_inter_double.Taille();
for (int j=1;j<=nb_var;j++)
{ cout << " para("<<j<<")= "<< t_inter_double(j);}
};
Tableau <double> & inter = Valeur_FnD_interne(&t_inter_double);
cout << "\n retour fonction: ";
int nb_val = inter.Taille();
for (int i=1;i<=nb_val;i++)
cout << " val("<<i<<")= "<<inter(i);
return inter;
}
else
// #endif
return Valeur_FnD_interne(&t_inter_double);
// on commence par le calcul se qui permet pour des fonctions complexes (ex: combinées)
// de remplir les tableaux internes nécessaires pour l'affichage locale éventuelles (fct propres)
Tableau <double> & inter = Valeur_FnD_interne(&t_inter_double);
int decal = 0;
Affiche_interne_valeurs_et_arguments(decal,&t_inter_double,inter,permet_affichage);
return inter;
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
@ -417,25 +389,12 @@ class Fonction_nD
{ if (equivalence_nom_enu_etendu_et_enu_quelconque)
{ try
{Vers_tab_double(t_inter_double,val_ddl_enum,li_evolue_scalaire,li_evoluee_non_scalaire,tqi,t_num_ordre);
// #ifdef MISE_AU_POINT
if (permet_affichage > 4)
{cout << "\n fonction: "<<nom_ref<<" : ";
if (permet_affichage > 5)
{cout << "\n parametres d'appel: ";
int nb_var = t_inter_double.Taille();
for (int j=1;j<=nb_var;j++)
{ cout << " para("<<j<<")= "<< t_inter_double(j);}
};
Tableau <double> & inter = Valeur_FnD_interne(&t_inter_double);
cout << "\n retour fonction: ";
int nb_val = inter.Taille();
for (int i=1;i<=nb_val;i++)
cout << " val("<<i<<")= "<<inter(i);
return inter;
}
else
// #endif
return Valeur_FnD_interne(&t_inter_double);
// on commence par le calcul se qui permet pour des fonctions complexes (ex: combinées)
// de remplir les tableaux internes nécessaires pour l'affichage locale éventuelles (fct propres)
Tableau <double> & inter = Valeur_FnD_interne(&t_inter_double);
int decal = 0;
Affiche_interne_valeurs_et_arguments(decal,&t_inter_double,inter,permet_affichage);
return inter;
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
@ -485,19 +444,12 @@ class Fonction_nD
Tableau <double> & Valeur_pour_variables_globales()
{ try
{
// #ifdef MISE_AU_POINT
if (permet_affichage > 4)
{cout << "\n fonction: "<<nom_ref<<" : ";
Tableau <double> & inter = Valeur_pour_variables_globales_interne();
cout << "\n retour fonction: ";
int nb_val = inter.Taille();
for (int i=1;i<=nb_val;i++)
cout << " val("<<i<<")= "<<inter(i);
return inter;
}
else
// #endif
return Valeur_pour_variables_globales_interne();
// on commence par le calcul se qui permet pour des fonctions complexes (ex: combinées)
// de remplir les tableaux internes nécessaires pour l'affichage locale éventuelles (fct propres)
Tableau <double> & inter = Valeur_pour_variables_globales_interne();
int decal = 0; // init
Affiche_interne_valeurs_et_arguments(decal,NULL,inter,permet_affichage);
return inter;
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
@ -518,7 +470,15 @@ class Fonction_nD
// elles sont mises en public, pour pouvoir être appelées par les classes dérivées
// sans avoir à déclarer en friend les classes dérivées, sinon cela fait une boucle
// sans fin, d'où la solution choisit pour éviter ce pb
// affichage des arguments xi internes en supprimant les redondances,
// utilisée par les fonctions dérivées
// tab_ret: le retour qui a été calculé par la fonction
// decal: donne le nombre de blanc à insérer avant l'affichage
// niveau: permet pour certaines valeurs (ex=8) d'imposer le niveau d'affichage
virtual void Affiche_interne_valeurs_et_arguments
(int& decal, const Tableau <double >* xi,const Tableau <double>& tab_ret,int niveau) const;
// calcul des valeurs de la fonction, retour d'un tableau de scalaires
virtual Tableau <double> & Valeur_FnD_interne(Tableau <double >* val_ddl_enum) = 0;
@ -554,7 +514,8 @@ class Fonction_nD
// ramène le type de la Fonction
EnumFonction_nD Type_Fonction() const { return typeFonction;};
// recup du niveau d'affichage
int Permet_affichage() const {return permet_affichage;};
protected :
@ -751,7 +712,7 @@ class Fonction_nD
// méthode utilisée par les classes dérivées, pour transférer les infos qui sont
// gérées au niveau de Fonction_nD
Fonction_nD& Transfert_info(const Fonction_nD& elt);
void Transfert_info(const Fonction_nD& elt);
// affichage des données internes, utilisée par les fonctions dérivées
// niveau donne le degré d'affichage
@ -785,7 +746,7 @@ class Fonction_nD
// affichage des variables de la fonction, dépend du niveau d'impression
void Affichage_variables() const;
// récupération des valeurs des variables globales et stockage dans le tableau
// interne x_glob
void Recup_Grandeurs_globales();

View file

@ -530,6 +530,9 @@ void LesLoisDeComp::LecMateriaux(UtilLecture& entreePrinc,LesReferences&
entreePrinc.NouvelleDonnee(); // prepa du flot de lecture
pt->LectureDonneesParticulieres (&entreePrinc,lesCourbes1D,lesFonctionsnD);
// on enregistre et on signale si la loi est inutilisée via un warning
#ifdef UTILISATION_MPI
if (ParaGlob::Monde()->rank()==0) // seule le proc 0 afficher
#endif
if (!ex && (ParaGlob::NiveauImpression()>1))
{ cout << "\n Warning, le nom de materiau = " << st1
<< " , ne correspond pas a une"

View file

@ -451,13 +451,14 @@ ElContact::ElContact ( const Front * elf, const Noeud * noe, Fct_nD_contact & fc
// pour stocker les info specifique aux intersections et tangence
// par contre les info generique (noeuds etc) sont identiques
Construction_TabNoeud(); // on construit le tableau de noeud global
tabNoeud_t = tabNoeud; // init
tabForce_cont.Change_taille(tabNoeud.Taille()-1);
tabForce_cont_t.Change_taille(tabNoeud.Taille()-1);
};
// de copie
ElContact::ElContact ( const ElContact & a):
tabNoeud(),tabNoeud_t()
tabNoeud(a.tabNoeud),tabNoeud_t(a.tabNoeud_t)
,Mtdt(a.Mtdt),Mt(a.Mt),M_noeud_tdt_avant_projection(a.M_noeud_tdt_avant_projection)
,phi_theta_0(a.phi_theta_0)
,force_contact(a.force_contact),tabForce_cont(a.tabForce_cont)
@ -496,7 +497,7 @@ ElContact::ElContact ( const ElContact & a):
// on cree un nouvelle element generique frontiere identique
// pour stocker les info specifique aux intersections et tangence
// par contre les info generique (noeuds etc) sont identiques
Construction_TabNoeud(); // on construit le tableau de noeud global
// non, car normalement toutes les initialisation on déjà été faites dans "a" Construction_TabNoeud(); // on construit le tableau de noeud global
};
// DESTRUCTEUR :
ElContact::~ElContact ()
@ -504,7 +505,45 @@ ElContact::~ElContact ()
};
// METHODES PUBLIQUES :
// affectation de toute les donnees
ElContact& ElContact::operator = ( const ElContact& a)
{ tabNoeud=a.tabNoeud;tabNoeud_t=a.tabNoeud_t;
Mtdt=a.Mtdt;Mt=a.Mt;M_noeud_tdt_avant_projection=a.M_noeud_tdt_avant_projection;
phi_theta_0=a.phi_theta_0;
force_contact=a.force_contact;tabForce_cont=a.tabForce_cont;
force_contact_t=a.force_contact_t;tabForce_cont_t=a.tabForce_cont_t;
F_N_max=a.F_N_max;F_T_max=a.F_T_max;
F_N_max_t=a.F_N_max_t;F_T_max_t=a.F_T_max_t;
ddlElement_assemblage=a.ddlElement_assemblage;
raideur=a.raideur;residu=a.residu;
energie_penalisation=a.energie_penalisation;
energie_frottement=a.energie_frottement;
num_zone_contact=a.num_zone_contact;normale_lisser=a.normale_lisser;
nb_decol_t=a.nb_decol_t;nb_decol_tdt=a.nb_decol_tdt;
gap_t=a.gap_t;gap_tdt=a.gap_tdt;nb_pene_t=a.nb_pene_t;nb_pene_tdt=a.nb_pene_tdt;
dep_T_t=a.dep_T_t;dep_T_tdt=a.dep_T_tdt;
mult_pene_t=a.mult_pene_t;mult_pene_tdt=a.mult_pene_tdt;
mult_tang_t=a.mult_tang_t;mult_tang_tdt=a.mult_tang_tdt;
actif=a.actif;type_trajectoire_t=a.type_trajectoire_t;
type_trajectoire_tdt=a.type_trajectoire_tdt;
cas_solide=a.cas_solide;cas_collant=a.cas_collant;nb_change_frontiere=a.nb_change_frontiere;
tabNoeud_pour_assemblage=a.tabNoeud_pour_assemblage;tab_posi_esclave=a.tab_posi_esclave;
nb_posi_esclave_stocker_t=a.nb_posi_esclave_stocker_t;nb_posi_esclave_stocker_tdt=a.nb_posi_esclave_stocker_tdt;
indice_stockage_glissant_t=a.indice_stockage_glissant_t;indice_stockage_glissant_tdt=a.indice_stockage_glissant_t;
penalisation=a.penalisation;penalisation_tangentielle=a.penalisation_tangentielle;
penalisation_t=a.penalisation_t;penalisation_tangentielle_t=a.penalisation_tangentielle_t;
// utilisation éventuelle de fonction nD
fct_nD_contact=a.fct_nD_contact;
N=a.N;dep_tangentiel=a.dep_tangentiel;
// pour le contact 4, pour le calcul de la pénalisation avec une moyenne glissante
val_penal=a.val_penal;pt_dans_val_penal=a.pt_dans_val_penal;
noeud = a.noeud;noeud_t = noeud;
elfront = new Front(*(a.Elfront()));
elfront_t=elfront;
return *this;
};
// affichage à l'écran des informations liées au contact
// cas = 0 : affichage en fonction du niveau de commentaire voulu
// cas = 1 : affichage minimal nécessaire pour repérer l'élément
@ -717,16 +756,48 @@ bool ElContact::Contact( bool init)
int dim = noeud->Dimension();
Plan pl(dim); Droite dr(dim); int indic; // def des variables de tangence
N = Calcul_Normale(dim,pl,dr,indic);
int permet_affiche = Permet_affichage();
// la seule chose que l'on peut faire pour valider le fait qu'il y a contact ou pas
// c'est de tester si le noeud est à l'intérieur de l'élément d'angle mort ou pas
// c'est plus long qu'un test de surface mais il n'y a pas vraiment d'autre solution
int cas = elfront->PtEI()->Interne_tdt(noeud->Coord2());
if (Permet_affichage() > 5)
if (permet_affiche > 5)
{cout << "\n -- ElContact::Contact: ";
cout << " Interne_tdt ? cas= " << cas <<", ";
this->Affiche(1);
};
return cas; // si != 0 le point est interne
// retour : =0 le point est externe, =1 le point est interne ,
// = 2 le point est sur la frontière à la précision près
if (cas == 0)
return cas;
// sinon on continue à tester
// on déclare le noeud pas en contact si la distance entre le noeud et la frontière est trop grande:
double dmax = ParaGlob::param->ParaAlgoControleActifs().DistanceMaxiAuPtProjete();
// pour cela il nous faut le point d'impact
// calcul de la trajectoire a utiliser
Coordonnee V = Trajectoire(test);
Coordonnee M1(dim);
if (init)
{M1 = Intersection(V,true);
}
else
{M1 = Intersection(V,false);};
// dans le cas ou M1 a une dimension nulle, signifie qu'il n'y a pas d'intersection,
// on peut alors dire qu'il ne peut pas y avoir contact donc retour
if (M1.Dimension() == 0)
return false;
// on regarde la distance d'impact
double d_MM1 = (M1-noeud->Coord2()).Norme();
if (permet_affiche > 6)
{cout << " intersection= ";M1.Affiche();
cout << " d_MM1= "<<d_MM1<<", dmax= "<<dmax<<flush;
this->Affiche(1);
};
if (d_MM1 > dmax)
{return false;}
else
{return true;};
};
// 2) === suite pour le cas différent des angles morts
@ -1785,7 +1856,7 @@ int ElContact::Actualisation()
// donc on cherche la projection du point sur la surface. Pour cela on calcule l'intersection d'une trajectoire qui a
// comme direction, la normale à la surface
// dans le cas d'un point avec ligne c'est idem
int nb_change_frontiere_max = 4; // **** à mettre ensuite en paramètre
int nb_change_frontiere_max = ParaGlob::param->ParaAlgoControleActifs().NB_change_frontiere_max();
#ifdef MISE_AU_POINT
if (!actif)
{cout << "\n ElContact::Actualisation(., actif= "<< actif
@ -1845,7 +1916,7 @@ int ElContact::Actualisation()
// pour éviter les flip flop, si on a eu trop de changement de frontière
// on valide de manière arbitraire le choix actuel
if (nb_change_frontiere > nb_change_frontiere_max)
if (nb_change_frontiere > abs(nb_change_frontiere_max))
{cas = 1;
if (Permet_affichage() > 5)
{cout << "\n >> nb_change_frontiere: " << nb_change_frontiere
@ -1861,6 +1932,13 @@ int ElContact::Actualisation()
{ int ta_taille_et1 = 1+ta->Taille();
for (int i=1; i < ta_taille_et1; i++)
{
#ifdef UTILISATION_MPI
// dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu
Element & elem11 = *((*ta)(i)->PtEI()); // l'element qui contiend la frontiere
// on ne continue que si l'élément est concerné
if (ParaGlob::param->Element_concerner(elem11.Num_maillage(),elem11.Num_elt_const()) )
{
#endif
if (Permet_affichage() > 5)
cout << "\n >> test de l'element voisin "<<i <<" : " ;
cas = (*ta)(i)->PtEI()->Interne_tdt(noeud->Coord2());
@ -1891,6 +1969,12 @@ int ElContact::Actualisation()
// on commence par sauvegarder (*ta)(i) en créant une copie
Front* newelfront = new Front(*((*ta)(i)));
////----- debug
//if (newelfront->NumUnique()==0)
// {cout << "\ndebug Elcontact::Actualisation , ***** NumUnique est nulle !! erreur ";
// cout << "\n (*ta)(i)->Unique() = "<<(*ta)(i)->NumUnique();
// }
////----- fin debug
// Libere(); // on supprime le elfront actuel, donc le tableau ta
// on ne peut pas supprimer le elfront, car il est également pointé par elfront_t
// du coup ce sera fait dans la méthode ElContact::TdtversT()
@ -1906,6 +1990,9 @@ int ElContact::Actualisation()
};
if (intersec == 2)
break;
#ifdef UTILISATION_MPI
};
#endif
};
};
}
@ -1946,12 +2033,12 @@ int ElContact::Actualisation()
// int contactType =
ElContact::Recup_et_mise_a_jour_type_contact();
if ((elfro.InSurf(extra_in_surface))
|| (nb_change_frontiere > nb_change_frontiere_max) // pour limiter les flip-flop
|| (nb_change_frontiere > abs(nb_change_frontiere_max)) // pour limiter les flip-flop
)
// l'intersection est ok pour l'element
// cote droite : contrairement a Intersection() , on oblige ici éventuellement en fonction du modèle de contact
// le point a etre sur la surface, car a priori il y a toujours contact
{ intersec = 1;
{ if (nb_change_frontiere_max > 0) intersec = 1; else { intersec = 0;};
}
else
// l'intersection est en dehors de la surface ou courbe maitre, on essaie une projection sur
@ -1961,6 +2048,14 @@ int ElContact::Actualisation()
if (ta != NULL) // cas où il y a des éléments voisins !
{for (int i=1; i<= ta->Taille(); i++)
{ bool mitoyen_valider = false;
#ifdef UTILISATION_MPI
// dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu
Element & elem11 = *((*ta)(i)->PtEI()); // l'element qui contiend la frontiere
// on ne continue que si l'élément est concerné
if (ParaGlob::param->Element_concerner(elem11.Num_maillage(),elem11.Num_elt_const()) )
{
#endif
if (Permet_affichage() > 5)
cout << "\n >> test de l'element voisin "<<i <<" : " ;
// le cas des angles morts est particulier, on commence par le traiter
@ -2006,6 +2101,7 @@ int ElContact::Actualisation()
}
else // ---- la suite concerne des éléments autres que ceux d'angle mort
{ElContact elct((*ta)(i),noeud,fct_nD_contact); // on cree un element contact pour utiliser ses methodes
Coordonnee M1_new;
M1_new = elct.Intersection(V,true);
// ici on recherche avec une précision donnée
@ -2023,11 +2119,14 @@ int ElContact::Actualisation()
};
};
};
#ifdef UTILISATION_MPI
};
#endif
// si le mitoyen est validé on change de Front pour l'élément de contact
if (mitoyen_valider)
{ // --- changement d'element frontiere
if (Permet_affichage() > 2)
if (Permet_affichage() > 3)
{cout << "\n change front. du noeud "<< noeud->Num_noeud() <<" mail= " << noeud->Num_Mail()
<< " == ";
elfront->Affiche(1);
@ -2037,6 +2136,14 @@ int ElContact::Actualisation()
// on commence par sauvegarder (*ta)(i)
Front* newelfront = new Front(*((*ta)(i)));
// //----- debug
// if (newelfront->NumUnique()==0)
// {cout << "\ndebug Elcontact::Actualisation , ***** NumUnique est nulle !! erreur 2 ";
// cout << "\n (*ta)(i)->Unique() = "<<(*ta)(i)->NumUnique();
// }
// //----- fin debug
// Libere(); // on supprime le elfront actuel, donc le tableau ta
// on ne peut pas supprimer le elfront, car il est également pointé par elfront_t
// du coup ce sera fait dans la méthode ElContact::TdtversT()

View file

@ -171,15 +171,18 @@ class ElContact
// du fait éventuel qu'il peut-être collant ou pas
ElContact ( const Front * elfront, const Noeud * noeud, Fct_nD_contact & fct_contact_, int collant = 0);
// de copie
ElContact ( const ElContact & a);
ElContact ( const ElContact & a);
// DESTRUCTEUR :
~ElContact ();
// METHODES PUBLIQUES :
// test d'egalite sur les éléments originaux :
// l'élément de frontière front, le noeud esclave, même zone de contact
inline bool MemeOrigine( const ElContact& a) const
// affectation de toute les donnees
ElContact& operator = ( const ElContact& a);
// test d'egalite sur les éléments originaux :
// l'élément de frontière front, le noeud esclave, même zone de contact
inline bool MemeOrigine( const ElContact& a) const
{ if ( (this->elfront->MemeOrigine(*a.Elfront()))
&& (this->noeud->Num_noeud() == a.Const_Esclave()->Num_noeud())
&& (this->noeud->Num_Mail() == a.Const_Esclave()->Num_Mail())
@ -347,6 +350,11 @@ class ElContact
virtual Vecteur* SM_charge_contact();
// -> implicite,
virtual Element::ResRaid SM_K_charge_contact();
// récup uniquement des conteneurs raideurs et résidu (pas forcément remplis, mais de la bonne taille)
Element::ResRaid Conteneur_ResRaid();
// récup uniquement du conteneur résidu (pas forcément rempli, mais de la bonne taille)
Vecteur* Conteneur_Residu();
// récupération des énergies intégrées sur l'éléments, résultants d'un précédent calcul
// explicite, ou implicite:
// 1- il s'agit ici de l'énergie développée par le frottement glissant ou pas
@ -398,7 +406,28 @@ class ElContact
void Lec_base_info_ElContact(ifstream& ent);
void Ecri_base_info_ElContact(ofstream& sort);
#ifdef UTILISATION_MPI // spécifique au calcul parallèle
// stockage dans un unique vecteur, des infos à partir de l'indice rang inclus
// correspond à une sérialisation des infos
// ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v
// dans ce cas ramène 0
// niveau: == 1 -> niveau minimum de sauvegarde, concerne uniquement la structure de l'élément
int Pack_vecteur(int niveau, Vecteur& v,int rang) const;
// taille du conteneur actuel de la condition linéaire
// dépend du niveau de sauvegarde
int Taille_Pack(int niveau) const;
// modification des infos à partir de l'indice rang inclus en fonction du vecteur passé en paramètre
// correspond à une désérialisation
// ramène le positionnement dans v pour un prochain enreg, sauf si > à la taille de v
// dans ce cas ramène 0
// on passe un pointeur de fonctions qui ramène un noeud en fonction d'un numéro de maillage et d'un
// numéro de noeud, ceci pour éviter de passer toute l'instance de la classe Les_maillages
// niveau: == 1 -> niveau minimum de sauvegarde, concerne uniquement la structure de l'élément
template <class T> int UnPack_vecteur(T& instance,int niveau,const Vecteur& v,int rang,
Noeud & (T::*Ptfonc) (int num_mail,int num_noeud) const );
#endif
protected :
// VARIABLES PROTEGEES :
int actif; // un indicateur, disant si le contact est actif ou pas
@ -543,4 +572,9 @@ protected :
};
/// @} // end of group
// pour faire de l'inline: nécessaire avec les templates
// on n'inclut que les méthodes templates
#include "ElContact_3.cc"
#define ElContact_deja_inclus
#endif

View file

@ -1437,6 +1437,35 @@ Element::ResRaid ElContact::SM_K_charge_contact()
return el;
};
// récup uniquement des conteneurs raideurs et résidu (pas forcément remplis, mais de la bonne taille)
Element::ResRaid ElContact::Conteneur_ResRaid()
{ Mise_a_jour_ddlelement_cas_solide_assemblage(); // mise à jour de ddl element et de cas_solide
// def de quelques dimensions pour simplifier
int dima = ParaGlob::Dimension();
int tab_taille = tabNoeud.Taille();
int nbddl = ddlElement_assemblage->NbDdl();
// récup d'une place pour le résidu local et mise à jour de list_SM éventuellement
RecupPlaceResidu(nbddl);
// idem pour la raideur
RecupPlaceRaideur(nbddl);
// préparation du retour
Element::ResRaid el;
el.res = residu;
el.raid = raideur;
return el;
};
// récup uniquement du conteneur résidu (pas forcément rempli, mais de la bonne taille)
Vecteur* ElContact::Conteneur_Residu()
{Mise_a_jour_ddlelement_cas_solide_assemblage(); // mise à jour de ddl element et de cas_solide
// def de quelques dimensions pour simplifier
int dima = ParaGlob::Dimension();
int tab_taille = tabNoeud.Taille();
int nbddl = ddlElement_assemblage->NbDdl();
// récup d'une place pour le résidu local et mise à jour de list_SM éventuellement
RecupPlaceResidu(nbddl);
return residu;
};
//================================= methodes privées ===========================
@ -1936,7 +1965,7 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
case 2: case 3: case 4: case 5: case 6: case 7: case 8:// calcul du type ls-dyna avec la compressibilité du maître
{ // on choisit en fonction de la géométrie si il existe une compressibilité
ElFrontiere* elfrontiere = elfront->Eleme(); // pour simplifier l'écriture
const Element * elem = elfront->PtEI(); // idem
Element * elem = elfront->PtEI(); // idem
if (((const ElemMeca*) elem)->CompressibiliteMoyenne() > 0.)
{ switch (elfrontiere->Type_geom_front())
{ case SURFACE:
@ -1954,6 +1983,8 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
}
else // sinon c'est bon
{facteur = surf*surf/volume;}
if (Permet_affichage() > 4)
cout << "\n SURFACE d'un volume: facteur = "<< facteur;
}
else if (elem->ElementGeometrie(X1).Dimension()==2)
{ // cas d'une surface frontière d'un élément coque ou plaque
@ -1969,25 +2000,47 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
}
else // sinon c'est bon
{facteur = surf/maxdiag;}
if (Permet_affichage() > 4)
cout << "\n SURFACE d'une coque ou plaque: facteur = "<< facteur;
};
break;
// pour mémoire pour la suite POINT_G = 1 , LIGNE , SURFACE, VOLUME, RIEN_TYPE_GEOM
//******** partie en construction
case LIGNE:
// --- on traite les cas particuliers des éléments d'angle mort
if (elfront->Angle_mort())
{ // il n'y a pas de notion de surface de contact et l'idée est de récupérer
// une grandeur du type module de compressibilité * une longueur caractéristique de l'élément
// on retient une expression simple
double longueur = elem->LongueurGeometrique_mini(1);
facteur = longueur;
//%%%% essai %%%%
longueur = elem->LongueurGeometrique_mini(1);
double volume = elem->Volume();
facteur = volume / (longueur * longueur);
//%%%% fin essai %%%%
{
// il n'y a pas de notion de surface de contact et l'idée est de récupérer
// // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément
// // on retient une expression simple
// double longueur = elem->LongueurGeometrique_caracteristique(1);
// facteur = longueur;
// if (Permet_affichage() > 4)
// cout << "\n angle mort: facteur1 = "<< facteur;
// //%%%% essai %%%%
// longueur = elem->LongueurGeometrique_caracteristique(1);
// double volume = elem->Volume();
// facteur = volume / (longueur * longueur);
// if (Permet_affichage() > 4)
// cout << "\n angle mort: facteur2 = "<< facteur;
//
// //%%%% fin essai %%%%
double longueur = elem->LongueurGeometrique_caracteristique(1);
double volume = elem->Volume();
if (Dabs(volume) <= ConstMath::pasmalpetit)
{ if (Permet_affichage() > 1)
cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage "
<< elem->Num_maillage() << " est nul, on utilise le max de diagonal ";
if (Permet_affichage() > 4)
cout << "\n ElContact::CalFactPenal()";
facteur = elfrontiere->MaxDiagonale_tdt();
}
else // sinon c'est bon
{facteur = volume/longueur/longueur;};
if (Permet_affichage() > 4)
cout << "\n LIGNE angle mort: facteur = "<< facteur;
}
else
{// --- cas d'un élément de contact autre que d'angle mort
@ -1997,7 +2050,7 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
if (elem->ElementGeometrie(X1).Dimension()==2)
// élément 2D en axi donc 3D en réalité
{ // récup de la longueur de la frontière
double longueur = elfrontiere->LongueurApprox();
// double longueur = elfrontiere->LongueurApprox();
// on calcul la surface associée
// M_impact(1) = x donc = le rayon car on est axi autour de y
//// double surf = longueur * M_impact(1) * ConstMath::Pi * 2.;
@ -2005,19 +2058,49 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
// donc il ne faut pas tenir compte du point d'impact ?? sinon par exemple si le point est au centre
// M_impact(1) = 0 et on n'a pas de surf !!
// mais plus généralement, le pt d'impact ne doit pas interférer à mon avis
double surf = longueur * ConstMath::Pi * 2.;
// 3 fevr 2023 : c'est incohérent, car surf n'a pas la dimension d'une surface
// du coup avec le volume qui est vraiment de dim 3 on aura une grandeur non cohérente
// par rapport à la formule de base double surf = longueur * ConstMath::Pi * 2.;
// du coup on va utiliser la surface de l'élément
#ifdef MISE_AU_POINT
if (!(elem->SurfExiste(1)))
{cout << "\n *** erreur la surface l'element axi " << elem->Num_elt_const() << " du maillage "
<< elem->Num_maillage() << " n'est pas disponible, on stop ";
Sortie(1);
};
#endif
// on récupère la surface de l'élément qui a créé la frontière
double volume = elem->Volume();
if (Dabs(volume) <= ConstMath::pasmalpetit)
{ if (Permet_affichage() > 1)
cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage "
<< elem->Num_maillage() << " est nul, on utilise le max de diagonal ";
if (Permet_affichage() > 4)
cout << "\n ElContact::CalFactPenal()";
facteur = elfrontiere->MaxDiagonale_tdt();
}
else // sinon c'est bon
{facteur = surf*surf/volume;}
ElFrontiere* const elfro_elem = elem->Frontiere_surfacique(1,false);
double surf = elfro_elem->SurfaceApprox(); // là on a bien la surface approximative de l'élément de surface axi
double longueur = elfrontiere->MaxDiagonale_tdt();
facteur = surf / longueur;
// comme on est en axisymétrie, la force résultante doit-être multipliée par la circonférence du point d'application
// pour être cohérente avec les forces internes de réaction des éléments maîtres, qui eux sont relatives à des volumes
// pour maximiser la force: on utilise la coordonnée x maxi des noeuds de l'élément maître, et on évite la coordonnée x du point
// d'impact qui est nulle pour le centre par exemple
double maxi_x1 = elem->Maxi_xi_noeud(1, TEMPS_t);// on se contente de la valeur à t, car il s'agit d'une approximation et cela évite l'instabilité
facteur *= maxi_x1 * ConstMath::Pi * 2.; // on se contente de la valeur à t, car il s'agit d'une approximation et cela évite l'instabilité
//
//
//
// double volume = elem->Volume(); // là il s'agit du volume totale
// if (Dabs(volume) <= ConstMath::pasmalpetit)
// { if (Permet_affichage() > 1)
// cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage "
// << elem->Num_maillage() << " est nul, on utilise le max de diagonal ";
// if (Permet_affichage() > 4)
// cout << "\n ElContact::CalFactPenal()";
// facteur = elfrontiere->MaxDiagonale_tdt();
// }
// else // sinon c'est bon
// {facteur = surf*surf/volume;}
if (Permet_affichage() > 4)
cout << "\n LIGNE en axi: facteur = "<< facteur
<< ", surface= " << surf <<", longueur= " << longueur;
}
else // sinon ce n'est pas pris en charge
{cout << "\n *** erreur: cas non pris en charge pour l'instant: "
@ -2028,17 +2111,9 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
};
}
else if (elem->ElementGeometrie(X1).Dimension()==3)
// cas d'une ligne frontière d'un élément coque ou plaque
{
// il faut finir la fonction ElFrontiere::LongueurApprox()
// cf le laïus qui est écrit dans la méthode
double surf = elfrontiere->SurfaceApprox();
// cas d'une ligne frontière d'un élément volumique
{ double longueur = elem->LongueurGeometrique_caracteristique(1);
double volume = elem->Volume();
// virtual double EpaisseurMoyenne(Enum_dure )
if (Dabs(volume) <= ConstMath::pasmalpetit)
{ if (Permet_affichage() > 1)
cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage "
@ -2048,11 +2123,13 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
facteur = elfrontiere->MaxDiagonale_tdt();
}
else // sinon c'est bon
{facteur = surf*surf/volume;}
{facteur = volume/longueur/longueur;}
if (Permet_affichage() > 4)
cout << "\n LIGNE d'un volume: facteur = "<< facteur;
}
else if (elem->ElementGeometrie(X1).Dimension()==2)
// cas d'une ligne frontière d'une plaque
{ double longueur = elfrontiere->LongueurApprox();
{ double longueur = elfrontiere->LongueurApprox();
double epais = 0.; // init
if (!ParaGlob::AxiSymetrie()) // si on n'est pas en axi
{epais = ((ElemMeca*) elem)->EpaisseurMoyenne(TEMPS_tdt );}
@ -2060,24 +2137,43 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
{epais = 1.;};
double surf = elem->Volume() / epais;
facteur = surf/longueur;
if (Permet_affichage() > 4)
cout << "\n LIGNE d'une plaque: facteur = "<< facteur;
};
};
break;
//******** fin partie en construction
case POINT_G:
// --- on traite les cas particuliers des éléments d'angle mort
if (elfront->Angle_mort())
{ // il n'y a pas de notion de surface de contact et l'idée est de récupérer
// une grandeur du type module de compressibilité * une longueur caractéristique de l'élément
// on retient une expression simple
double longueur = elem->LongueurGeometrique_mini(1);
facteur = longueur;
//%%%% essai %%%%
longueur = elem->LongueurGeometrique_mini(1);
double volume = elem->Volume();
facteur = volume / (longueur * longueur);
//%%%% fin essai %%%%
{
// // il n'y a pas de notion de surface de contact et l'idée est de récupérer
// // une grandeur du type module de compressibilité * une longueur caractéristique de l'élément
// // on retient une expression simple
// double longueur = elem->LongueurGeometrique_caracteristique(1);
// facteur = longueur;
// if (Permet_affichage() > 4)
// cout << "\n angle mort: facteur1 = "<< facteur;
// //%%%% essai %%%%
// double volume = elem->Volume();
// facteur = volume / (longueur * longueur);
// //%%%% fin essai %%%%
// if (Permet_affichage() > 4)
// cout << "\n angle mort: facteur2 = "<< facteur;
double longueur = elem->LongueurGeometrique_caracteristique(1);
double volume = elem->Volume();
if (Dabs(volume) <= ConstMath::pasmalpetit)
{ if (Permet_affichage() > 1)
cout << "\n *** attention, le volume de l'element " << elem->Num_elt_const() << " du maillage "
<< elem->Num_maillage() << " est nul, on utilise le max de diagonal ";
if (Permet_affichage() > 4)
cout << "\n ElContact::CalFactPenal()";
facteur = elfrontiere->MaxDiagonale_tdt();
}
else // sinon c'est bon
{facteur = volume/longueur/longueur;};
if (Permet_affichage() > 4)
cout << "\n POINT_G angle mort: facteur = "<< facteur
<< ", volume = " << volume << ", longueur = " << longueur;
}
else
{ // --- cas d'un élément de contact autre que d'angle mort
@ -2088,9 +2184,12 @@ double ElContact::CalFactPenal(const double& gap,double & d_beta_gap,int contact
{// on veut calculer Ke * Ae * Ae / vol , comme on est dans le cas d'une barre
// vol = long * section, et Ae = section , du coup:
// Ke * Ae * Ae / vol = Ke * vol / (long * long) avec long = la longueur de l'élément
double longueur = elem->LongueurGeometrique_mini(1);
double longueur = elem->LongueurGeometrique_caracteristique(1);
double volume = elem->Volume();
facteur = volume / (longueur * longueur);
if (Permet_affichage() > 4)
cout << "\n POINT_G en dim espace 1D: facteur = "<< facteur
<< ", volume = " << volume << ", longueur = " << longueur;
}
else
{cout << "\n *** erreur: cas non pris en charge pour l'instant: "
@ -2411,10 +2510,10 @@ double ElContact::CalFactPenalTangentiel(const double& dep_T,double & d_beta_dep
{ // il n'y a pas de notion de surface de contact et l'idée est de récupérer
// une grandeur du type module de compressibilité * une longueur caractéristique de l'élément
// on retient une expression simple
double longueur = elem->LongueurGeometrique_mini(1);
double longueur = elem->LongueurGeometrique_caracteristique(1);
facteur = longueur;
//%%%% essai %%%%
longueur = elem->LongueurGeometrique_mini(1);
longueur = elem->LongueurGeometrique_caracteristique(1);
double volume = elem->Volume();
facteur = volume / (longueur * longueur);
//%%%% fin essai %%%%
@ -2495,7 +2594,7 @@ double ElContact::CalFactPenalTangentiel(const double& dep_T,double & d_beta_dep
{ // il n'y a pas de notion de surface de contact et l'idée est de récupérer
// une grandeur du type module de compressibilité * une longueur caractéristique de l'élément
// on retient une expression simple
double longueur = elem->LongueurGeometrique_mini(1);
double longueur = elem->LongueurGeometrique_caracteristique(1);
facteur = longueur;
}
else
@ -2507,7 +2606,7 @@ double ElContact::CalFactPenalTangentiel(const double& dep_T,double & d_beta_dep
{// on veut calculer Ke * Ae * Ae / vol , comme on est dans le cas d'une barre
// vol = long * section, et Ae = section , du coup:
// Ke * Ae * Ae / vol = Ke * vol / (long * long) avec long = la longueur de l'élément
double longueur = elem->LongueurGeometrique_mini(1);
double longueur = elem->LongueurGeometrique_caracteristique(1);
double volume = elem->Volume();
facteur = volume / (longueur * longueur);
}

View file

@ -34,8 +34,6 @@
#include "ReferenceAF.h"
#include "CharUtil.h"
#include "Enum_TypeQuelconque.h"
#include "TypeQuelconqueParticulier.h"
// --------------- variables statiques ---------
@ -119,9 +117,13 @@ bool LesContacts::ReactCont::operator != (const LesContacts::ReactCont& a)
LesContacts::LesContacts () :
listCoLin(),tabReacCont(),listContact()//,numtesN()
,sauve_lesFonctionsnD(NULL),fct_nD_contact()
,fct_niveau_commentaire(NULL),li_pour_noeuds_element(),gr_pour_noeud(NULL),gr_pour_elem(NULL)
,listContact_nouveau_tatdt(),listContact_efface_tatdt()
,nom_ref_zone_contact(),lissage_de_la_normale()
,t_listFront(),nb_mail_Esclave(),nbmailautocontact(0),nbmailMaitre()
#ifdef UTILISATION_MPI
,pointe_t_listFront(),v_interProc_contact_actif()
#endif
,tesctotal(),tesN_encontact()
,tesN_collant()
,nb_contact_actif(0),indice(),cont_solide_defor(),liQ_en_sortie()
@ -131,15 +133,26 @@ LesContacts::LesContacts () :
,temps_transfert_court(),temps_transfert_long(),temps_attente()
,inter_transfer(),inter_transfer2(),lesMaille(NULL)
#endif
{};
{// pour une sortie spécifique noeud et ou element
Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques
li_pour_noeuds_element.push_front(TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier));
gr_pour_noeud = ((Grandeur_scalaire_entier*) (*li_pour_noeuds_element.begin()).Grandeur_pointee());
li_pour_noeuds_element.push_front(TypeQuelconque(NUM_ELEMENT,EPS11,grand_courant_entier));
gr_pour_elem = ((Grandeur_scalaire_entier*) (*li_pour_noeuds_element.begin()).Grandeur_pointee());
};
// constructeur de copie
LesContacts::LesContacts (const LesContacts& a):
listCoLin(a.listCoLin),tabReacCont(a.tabReacCont)
,sauve_lesFonctionsnD(a.sauve_lesFonctionsnD),fct_nD_contact(a.fct_nD_contact)
,fct_niveau_commentaire(a.fct_niveau_commentaire),li_pour_noeuds_element(a.li_pour_noeuds_element)
,gr_pour_noeud(a.gr_pour_noeud),gr_pour_elem(a.gr_pour_elem)
,listContact(a.listContact)//,numtesN(a.numtesN)
,listContact_nouveau_tatdt(a.listContact_nouveau_tatdt),listContact_efface_tatdt(a.listContact_efface_tatdt)
,nom_ref_zone_contact(a.nom_ref_zone_contact),lissage_de_la_normale(a.lissage_de_la_normale)
,t_listFront(a.t_listFront),nb_mail_Esclave(a.nb_mail_Esclave),nbmailautocontact(a.nbmailautocontact)
#ifdef UTILISATION_MPI
,pointe_t_listFront(),v_interProc_contact_actif()
#endif
,nbmailMaitre(a.nbmailMaitre),tesctotal(a.tesctotal),tesN_encontact(a.tesN_encontact)
,tesN_collant(a.tesN_collant)
,nb_contact_actif(a.nb_contact_actif),indice(a.indice),cont_solide_defor(a.cont_solide_defor)
@ -150,7 +163,29 @@ LesContacts::LesContacts (const LesContacts& a):
,temps_transfert_long(a.temps_transfert_long),temps_attente(a.temps_attente)
,inter_transfer(),inter_transfer2(),lesMaille(NULL)
#endif
{};
{// on réaffecte les pointeurs pour la sortie spécifique noeud et ou element
list <TypeQuelconque>::iterator ili = li_pour_noeuds_element.begin();
gr_pour_elem = ((Grandeur_scalaire_entier*) (*ili).Grandeur_pointee());
ili++;
gr_pour_noeud = ((Grandeur_scalaire_entier*) (*ili).Grandeur_pointee());
#ifdef UTILISATION_MPI
// on redéfini le tableau pointe_t_listFront() et la numérotation unique dans les fronts stockés
pointe_t_listFront.Change_taille(a.pointe_t_listFront.Taille());
int nb_zone = MaX(1,nom_ref_zone_contact.size());
int inum = 1;
for (int i=1;i<=nbmailMaitre;i++)
{ for (int j=1;j<=nb_zone;j++)
{ LaLIST_io <Front> & list_fronta = (t_listFront(i)(j)); // pour simplifier
LaLIST_io <Front>::iterator il,ilfin = list_fronta.end();
for (il = list_fronta.begin();il != ilfin; il++,inum++)
{pointe_t_listFront(inum) = &(*il);
(*il).ChangeNumUnique(inum);
};
};
};
#endif
};
// DESTRUCTEUR :
LesContacts::~LesContacts ()
{ };
@ -179,13 +214,13 @@ void LesContacts::Init_contact(LesMaillages& lesMail
int niveau_commentaire_lescontacts = Permet_affichage();
// on met à jour le niveau de commentaire dans les éléments de contact
ElContact::Mise_a_jour_niveau_commentaire();
if (niveau_commentaire_lescontacts > 4)
#ifdef UTILISATION_MPI
// on sauvegarde un pointeur sur les maillages
lesMaille = &lesMail;
if (ParaGlob::Monde()->rank() == 0)
#endif
if (niveau_commentaire_lescontacts > 4)
cout << "\n -- LesContacts::Init_contact: ";
Creation_Fct_nD_contact(); // récupération des fonctions de pilotage éventuelles
@ -551,17 +586,55 @@ void LesContacts::Init_contact(LesMaillages& lesMail
// on définit et on ajoute les fronts des angles morts
ElementAngleMort(lesMail);
// Pour diminuer le temps de recherche, et aussi les messages on va constituer une liste des éléments
// qui contiennent les frontières
// il faut mettre à jour les mitoyens des Front: c-a-d il faut que les mitoyens
// soient eux-même des fronts de t_listFront
int nb_zone = MaX(1,nom_ref_zone_contact.size());
liste_elemens_front.clear(); // init de la liste
for (int i=1;i<=nbmailMaitre;i++)
{ for (int j=1;j<=nb_zone;j++)
{ LaLIST_io <Front> & list_fronta = (t_listFront(i)(j)); // pour simplifier
LaLIST <Front>::iterator iM,iMfin=list_fronta.end();
for (iM = list_fronta.begin();iM != iMfin; iM++) // boucle sur les frontières enregistrées
liste_elemens_front.push_back((*iM).PtEI());
{Front & fronta = (*iM); // pour simplifier
const Tableau <Front*>* ta = fronta.TabMitoyen(); // récup des mitoyens
if (ta != NULL) // cas où il y a des éléments voisins !
{ const Tableau <Front*>& taa = *ta; // pour simplifier
int ta_taille = ta->Taille();
Tableau <Front*> inter(ta_taille);// un tableau inter de travail
for (int i=1; i <= ta_taille; i++)
// on récupère l'élément ad hoc
{Front* froon = Front_de_meme_origine(taa(i),j);
if (froon != NULL)
{inter(i)=froon;}
else // sinon c'est un pb pour la suite
{cout << "\n *** erreur dans la definition des mitoyens pour l'initialisation des frontieres de contact "
<< " on n'a pas trouve dans la zone de contact une frontiere adequate : arret ";
Sortie(1);
};
};
// on peut maintenant remplacer le tableau de mitoyen
fronta.DefMitoyen(inter);
};
};
};
};
// Pour diminuer le temps de recherche, et aussi les messages on va constituer une liste des éléments
// qui contiennent les frontières
liste_elemens_front.clear(); // init de la liste
#ifdef UTILISATION_MPI
int nb_total_front=0; // permet ensuite de dimensionner le tableau pointe_t_listFront
#endif
for (int i=1;i<=nbmailMaitre;i++)
{ for (int j=1;j<=nb_zone;j++)
{ LaLIST_io <Front> & list_fronta = (t_listFront(i)(j)); // pour simplifier
LaLIST <Front>::iterator iM,iMfin=list_fronta.end();
for (iM = list_fronta.begin();iM != iMfin; iM++) // boucle sur les frontières enregistrées
{liste_elemens_front.push_back((*iM).PtEI());
#ifdef UTILISATION_MPI
nb_total_front++;
#endif
};
};
};
// on ordonne la liste puis on supprime les doublons
@ -585,6 +658,52 @@ void LesContacts::Init_contact(LesMaillages& lesMail
// }
//}
////-- fin debug
#ifdef UTILISATION_MPI
// on défini le tableau pointe_t_listFront et on définit le numéro associé unique dans les fronts
pointe_t_listFront.Change_taille(nb_total_front);
int inum = 1;
for (int i=1;i<=nbmailMaitre;i++)
{ for (int j=1;j<=nb_zone;j++)
{ LaLIST_io <Front> & list_fronta = (t_listFront(i)(j)); // pour simplifier
LaLIST_io <Front>::iterator il,ilfin = list_fronta.end();
for (il = list_fronta.begin();il != ilfin; il++,inum++)
{pointe_t_listFront(inum) = &(*il);
(*il).ChangeNumUnique(inum);
};
};
};
// //--- debug
// {cout << "\n debug : LesContacts::Init_contact ";
// for (int i=1;i<=nbmailMaitre;i++)
// { for (int j=1;j<=nb_zone;j++)
// { LaLIST_io <Front> & list_fronta = (t_listFront(i)(j)); // pour simplifier
// LaLIST_io <Front>::iterator il,ilfin = list_fronta.end();
// for (il = list_fronta.begin();il != ilfin; il++)
// {if ((*il).NumUnique() == 0)
// cout << "\n debug : LesContacts::Init_contact "
// << " ***** erreur numunique == 0 !!" ;
// // maintenant on s'occupe des mitoyens
// {Front & fronta = (*il); // pour simplifier
// const Tableau <Front*>* ta = fronta.TabMitoyen(); // récup des mitoyens
// if (ta != NULL) // cas où il y a des éléments voisins !
// { const Tableau <Front*>& taa = *ta; // pour simplifier
// int ta_taille = ta->Taille();
// for (int i=1; i <= ta_taille; i++)
// {if (taa(i)->NumUnique() == 0)
// cout << "\n debug : LesContacts::Init_contact "
// << " ***** erreur dans les mitoyens : numunique == 0 !!" ;
// };
// };
// };
//
// };
// };
// };
// }
// //-- fin debug
#endif
tempsContact.Arret_du_comptage(); // fin cpu
};
@ -651,7 +770,7 @@ void LesContacts::Verification()
if ((elem.Interne_t(pt_esc)==1) && (niveau_commentaire_lescontacts >= 3))
{ cout << "\n attention, noeud esclave dans elem. "
<< "avant incre. 1 charge";
if (niveau_commentaire_lescontacts > 2)
if (niveau_commentaire_lescontacts > 3)
cout << "\n LesContacts::Verification(..)";
int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail();
cout << "\n -> noeud " << tesc(inesc)->Num_noeud() << " du maillage " << tesc(inesc)->Num_Mail()
@ -676,6 +795,8 @@ void LesContacts::Verification()
// cette méthode est utilisée au début du calcul, ensuite c'est Nouveau()
// qui prend le relais
// ramène true s'il y a effectivement création d'élément de contact
// en parallèle seules les proc i>0 définissent des éléments de contact
// le proc 0 ne fait rien, il récupère le retour et fait le bilan
bool LesContacts::DefElemCont(double dep_max)
{
tempsContact.Mise_en_route_du_comptage(); // def deb compt
@ -706,7 +827,11 @@ bool LesContacts::DefElemCont(double dep_max)
int nb_zone = MaX(1,nom_ref_zone_contact.size());
double dist_max = Dabs(ParaGlob::param->ParaAlgoControleActifs().DistanceMaxiAuPtProjete());
#ifdef UTILISATION_MPI
if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact
{
#endif
// on va iterer sur les noeuds esclaves pour savoir s'ils ont une trajectoire
// qui cree un contact avec les elements maitres, ou l'inverse, c-a-d s'ils sont
// dans de la matiere
@ -811,6 +936,10 @@ bool LesContacts::DefElemCont(double dep_max)
ElContact elcont(&(*iM),tesc(inesc),fct_nD_contact,tesN_col(inesc));
elcont.Num_zone_contact()=j_zone; // affectation du numéro de zone
elcont.Change_lissage_normale(lissage_de_la_normale(j_zone)); // affectation du lissage
#ifdef UTILISATION_MPI
// on attribue au front de l'élément de contact, le numéro unique utilisable pour le tableau pointe_t_listFront
elcont.Elfront()->ChangeNumUnique((*iM).NumUnique());
#endif
// calcul du contact, et translation (éventuelle) du noeud sur la surface si le contact existe
bool init_inter = true; // on est en phase d'initialisation
// //--- debug
@ -825,7 +954,7 @@ bool LesContacts::DefElemCont(double dep_max)
#else
cout << "\n"
#endif
<< " recherche du contact entre noeud " << elcont.Esclave()->Num_noeud()
<< " recherche du contact entre noeud " << elcont.Esclave()->Num_noeud()
<< " du maillage " << elcont.Esclave()->Num_Mail()
<< " et frontiere " << (*iM).Num_frontiere()
<< " de l'element " << elem.Num_elt() << " du maillage "
@ -885,7 +1014,7 @@ bool LesContacts::DefElemCont(double dep_max)
#else
cout << "\n"
#endif
<< "\ncontact entre noeud " ;
<< "contact entre noeud " ;
if (tesN_col(inesc)) cout << " collant ";
cout << elcont.Esclave()->Num_noeud()
<< " du maillage " << elcont.Esclave()->Num_Mail()
@ -930,7 +1059,7 @@ bool LesContacts::DefElemCont(double dep_max)
listContact_nouveau_tatdt.push_front(listContact.begin());
tesN_encontact_ii[noee].push_front(listContact.begin());
// on n'intervient pas sur tesN_encontact, car ça ne change pas
if (niveau_commentaire_lescontacts > 2)
if (niveau_commentaire_lescontacts > 3)
{ int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail();
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
@ -938,7 +1067,7 @@ bool LesContacts::DefElemCont(double dep_max)
cout << "\n"
#endif
<< " --- changement d'element en contact ---";
cout << "\ncontact entre noeud " ;
cout << "contact entre noeud " ;
if (tesN_col(inesc)) cout << " collant ";
cout << elcont.Esclave()->Num_noeud()
<< " du maillage " << elcont.Esclave()->Num_Mail()
@ -965,8 +1094,19 @@ bool LesContacts::DefElemCont(double dep_max)
}; //-- fin du test if (!tesN_encontact(intot)(n_noee))
}; //-- fin de la boucle sur inesc
}; //-- fin de la boucle sur les zones
#ifdef UTILISATION_MPI
}; // fin du cas des proc i > 0
#endif
// retour
#ifdef UTILISATION_MPI
if (proc_en_cours != 0)
{
if (niveau_commentaire_lescontacts > 4) // ==> LesContacts::
#else
if (niveau_commentaire_lescontacts > 2) // ==> LesContacts::
#endif
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
@ -980,6 +1120,53 @@ bool LesContacts::DefElemCont(double dep_max)
cout <<", "<<listContact_efface_tatdt.size() << " effacement(s) ";
cout << flush;
};
#ifdef UTILISATION_MPI
};
if (proc_en_cours != 0) // on transmet à proc 0
{temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
// pour cela on va utiliser un conteneur intermédiaire
QuatreEntiers inter_entiers(retour,listContact.size(),listContact_nouveau_tatdt.size(),listContact_efface_tatdt.size());
// on transmet les infos au proc 0
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 61, inter_entiers);
// on attend pas
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
else // cas du cpu 0
{// l'objectif ici est de récupérer les infos
tempsContact.Arret_du_comptage(); // fin cpu
int nb_contact=0;int nb_new_contact = 0;int nb_efface_contact = 0; // que l'on va cumuler
int nb_proc_terminer = 0; // permettra de terminer
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1))
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
QuatreEntiers inter_entiers;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 61, inter_entiers );
reqs1.wait(); // on attend que le conteneur soit rempli
// on cumule
nb_contact += inter_entiers.deux;
nb_new_contact += inter_entiers.trois;
nb_efface_contact += inter_entiers.quatre;
if (inter_entiers.un) // si un seul des retour s est bon on passe à true
retour = true;
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
};
if (niveau_commentaire_lescontacts > 2) // ==> LesContacts::
{cout << "\n apres Def Elem Cont: "<< nb_contact << " elem contact ";
if ( nb_new_contact)
cout <<", "<< nb_new_contact << " nouveau(x) ";
if (nb_efface_contact)
cout <<", "<<nb_efface_contact << " effacement(s) ";
cout << flush;
};
};
// il faut que tous les proc aient le retour global, car le retour sert dans l'algo général
broadcast(*ParaGlob::Monde(), retour, 0);
#endif
tempsContact.Arret_du_comptage(); // fin cpu
return retour;
@ -993,20 +1180,24 @@ bool LesContacts::Nouveau(double dep_max)
{
tempsContact.Mise_en_route_du_comptage(); // def deb compt
int niveau_commentaire_lescontacts = Permet_affichage();
list <TypeQuelconque> li_pour_noeuds; // pour une sortie spécifique noeud
Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques
li_pour_noeuds.push_front(TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier));
Grandeur_scalaire_entier& gr_pour_noeud
= *((Grandeur_scalaire_entier*) (*li_pour_noeuds.begin()).Grandeur_pointee());
list <TypeQuelconque> li_pour_elcont; // pour une sortie spécifique élément finis
li_pour_elcont.push_front(TypeQuelconque(NUM_ELEMENT,EPS11,grand_courant_entier));
////--- debug
//cout << "\n debug LesContacts::Nouveau "<< " niveau_commentaire_lescontacts = "<< niveau_commentaire_lescontacts<< flush;
////--- fin debug
// list <TypeQuelconque> li_pour_noeuds; // pour une sortie spécifique noeud
// Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques
// li_pour_noeuds.push_front(TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier));
// Grandeur_scalaire_entier& gr_pour_noeud
// = *((Grandeur_scalaire_entier*) (*li_pour_noeuds.begin()).Grandeur_pointee());
// list <TypeQuelconque> li_pour_elcont; // pour une sortie spécifique élément finis
// li_pour_elcont.push_front(TypeQuelconque(NUM_ELEMENT,EPS11,grand_courant_entier));
#ifdef UTILISATION_MPI
int proc_en_cours = ParaGlob::Monde()->rank();
#endif
int nb_zone = MaX(1,nom_ref_zone_contact.size());
bool retour = false; // init du retour
// on sauvegarde la liste au départ
int taille_list_contact_nouveau_au_debut = listContact_nouveau_tatdt.size();
@ -1017,6 +1208,11 @@ bool LesContacts::Nouveau(double dep_max)
cout << "\n"
#endif
<< " -- LesContacts::Nouveau: temps= " << ParaGlob::Variables_de_temps().TempsCourant();
#ifdef UTILISATION_MPI
if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact
{
#endif
// on montre les noeuds actuellement en contact
if (Permet_affichage() > 4)
{
@ -1035,8 +1231,9 @@ bool LesContacts::Nouveau(double dep_max)
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
{Noeud* no = tesc(inesc);
int n_noee = no->Num_noeud();
(*gr_pour_noeud.ConteneurEntier()) = n_noee; // pour l'affichage
if (Permet_affichage(&li_pour_noeuds) > 5)
*(gr_pour_noeud->ConteneurEntier()) = n_noee; // pour l'affichage
*(gr_pour_elem->ConteneurEntier()) = 0; //pas d'élément ici
if (Permet_affichage(&li_pour_noeuds_element) > 5)
{
int num_mail_noe_esclave = no->Num_Mail();
// if (no->Num_noeud()==495)
@ -1124,8 +1321,9 @@ bool LesContacts::Nouveau(double dep_max)
if ((*iE).Contact())
{ // on valide si le contact est ok
(*iE).Met_actif();
(*gr_pour_noeud.ConteneurEntier()) = (*iE).Esclave()->Num_noeud();
if (Permet_affichage(&li_pour_noeuds) > 3)
*(gr_pour_noeud->ConteneurEntier()) = (*iE).Esclave()->Num_noeud();
*(gr_pour_elem->ConteneurEntier()) = (*iE).Elfront()->PtEI()->Num_elt();
if (Permet_affichage(&li_pour_noeuds_element) > 3)
{ cout << "\n reactivation (dans LesContacts::Nouveau) contact: ";
(*iiE).Affiche(1); cout << endl;
};
@ -1136,8 +1334,9 @@ bool LesContacts::Nouveau(double dep_max)
Noeud* noe_esclave = (*iiE).Esclave();
int num_mail_esclave = noe_esclave->Num_Mail();
int num_noeud = noe_esclave->Num_noeud();
(*gr_pour_noeud.ConteneurEntier()) = num_noeud;
if (Permet_affichage(&li_pour_noeuds) > 3)
*(gr_pour_noeud->ConteneurEntier()) = num_noeud;
*(gr_pour_elem->ConteneurEntier()) = (*iE).Elfront()->PtEI()->Num_elt();
if (Permet_affichage(&li_pour_noeuds_element) > 3)
{ cout << "\n effacement contact (dans LesContacts::Nouveau): ";
(*iiE).Affiche(1);cout << endl;
};
@ -1164,7 +1363,7 @@ bool LesContacts::Nouveau(double dep_max)
// on va iterer sur les noeuds esclaves pour savoir s'ils ont une trajectoire
// qui cree un contact avec les elements maitres, ou l'inverse, c-a-d s'ils sont
// dans de la matiere
bool retour = false; // init du retour
retour = false; // init du retour
LaLIST_io <Front>::iterator iM,iMfin;
LaLIST <ElContact>::iterator icont_inter; // sert pour la recherche de doublon
list <TroisEntiers>::iterator inumtesN; // " " "
@ -1210,8 +1409,9 @@ bool LesContacts::Nouveau(double dep_max)
nb_contact = list_tesN.size();
};
(*gr_pour_noeud.ConteneurEntier()) = n_noee;
if (Permet_affichage(&li_pour_noeuds) > 6)
*(gr_pour_noeud->ConteneurEntier()) = n_noee;
*(gr_pour_elem->ConteneurEntier()) = 0; // pas de numéro d'élément à prendre en compte pour la visu
if (Permet_affichage(&li_pour_noeuds_element) > 6)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
@ -1220,7 +1420,7 @@ bool LesContacts::Nouveau(double dep_max)
#endif
<< " (re) examen eventuel : contact du noeud " << n_noee << " du maillage " << num_mail_noe_esclave;
cout << " coord2= "; no->Coord2().Affiche_1(cout);
if (Permet_affichage(&li_pour_noeuds) > 7)
if (Permet_affichage(&li_pour_noeuds_element) > 7)
{cout << " num_mail_dans_contact = " << num_mail_noe_esclave <<" inesc(num N local)= " << inesc
<< "\n tesN_encontact= " << nb_contact
<< " contacts enregistres";
@ -1252,7 +1452,8 @@ bool LesContacts::Nouveau(double dep_max)
// ce n'est peut-être pas un pb, mais il faudra peut-être avoir le niveau de zone en plus dans tesN_encontact ??
// cout << endl;
};
// on ne continue que si le noeud n'est pas entièrement bloqué
// si c'est le cas .... à finir !
{
Coordonnee pt_esc = no->Coord2(); // position du noeud esclave
// maintenant on regarde les frontieres maitres
@ -1297,8 +1498,9 @@ bool LesContacts::Nouveau(double dep_max)
Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere
Front& elfront = (*iM);
(*gr_pour_noeud.ConteneurEntier()) = no->Num_noeud();
if (Permet_affichage(&li_pour_noeuds) > 7)
*(gr_pour_noeud->ConteneurEntier()) = no->Num_noeud();
*(gr_pour_elem->ConteneurEntier()) = elem.Num_elt();
if (Permet_affichage(&li_pour_noeuds_element) > 7)
{// --- sortie d'info pour vérifier l'appartenance à la boite ou non
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
@ -1322,7 +1524,7 @@ bool LesContacts::Nouveau(double dep_max)
break; // on arrête la boucle si on trouve l'élément parmi ceux contenant le noeud
};
if (Permet_affichage(&li_pour_noeuds) > 6)
if (Permet_affichage(&li_pour_noeuds_element) > 6)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
@ -1357,8 +1559,9 @@ bool LesContacts::Nouveau(double dep_max)
// break;};
// };
*/
(*gr_pour_noeud.ConteneurEntier()) = n_noee;
if (Permet_affichage(&li_pour_noeuds) > 7)
*(gr_pour_noeud->ConteneurEntier()) = n_noee;
*(gr_pour_elem->ConteneurEntier()) = 0; // pas de filtre sur les nb elem
if (Permet_affichage(&li_pour_noeuds_element) > 7)
{cout << "\n liste des contacts sur le noeud " << n_noee
<< " qui est prevu en effacement sur l'increment " ;
LaLIST <ElContact>::iterator ila,ilafin=listContact_efface_tatdt.end();
@ -1407,6 +1610,10 @@ bool LesContacts::Nouveau(double dep_max)
{ ElContact elcont(&(*iM),tesc(inesc),fct_nD_contact);
elcont.Num_zone_contact()=j_zone; // affectation du numéro de zone
elcont.Change_lissage_normale(lissage_de_la_normale(j_zone)); // affectation du lissage
#ifdef UTILISATION_MPI
// on attribue au front de l'élément de contact, le numéro unique utilisable pour le tableau pointe_t_listFront
elcont.Elfront()->ChangeNumUnique((*iM).NumUnique());
#endif
// vérification que l'on a bien les frontières bien connectées
if ((niveau_commentaire_lescontacts > 5)
@ -1421,7 +1628,8 @@ bool LesContacts::Nouveau(double dep_max)
<< ", type: " << Nom_type_geom(elfront->Eleme_const()->Type_geom_front())
<< " de l'element " << elfront->PtEI()->Num_elt() << " du maillage "
<< elfront->PtEI()->Num_maillage() ;
if (Permet_affichage(&li_pour_noeuds) > 7)
*(gr_pour_elem->ConteneurEntier()) = elfront->PtEI()->Num_elt();
if (Permet_affichage(&li_pour_noeuds_element) > 7)
elcont.Affiche();
};
@ -1500,14 +1708,20 @@ bool LesContacts::Nouveau(double dep_max)
};// -- boucle sur inesc
}// -- fin de la boucle sur les zones for (int j=1;j<= nb_zone;j++)
};// -- boucle sur intot
if (niveau_commentaire_lescontacts > 3)
#ifdef UTILISATION_MPI
// affichage pour les proc != 0
if (niveau_commentaire_lescontacts > 4)
#else
if (niveau_commentaire_lescontacts > 3) // ==> LesContacts::
#endif
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n "
#endif
<< " en fin de au debut de LesContacts::Nouveau: bilan: "<< listContact.size() << " elem(s) contact ";
<< " en fin de LesContacts::Nouveau: bilan: "<< listContact.size() << " elem(s) contact ";
if ( listContact_nouveau_tatdt.size())
cout <<", "<< (listContact_nouveau_tatdt.size()-taille_list_contact_nouveau_au_debut)
<< " nouveau(x) ";
@ -1537,6 +1751,58 @@ bool LesContacts::Nouveau(double dep_max)
#endif
<< " <== fin LesContacts::Nouveau " ;
};
#ifdef UTILISATION_MPI
}; // fin de la recherche de nouveaux contact pour proc != 0
#endif
#ifdef UTILISATION_MPI
if (proc_en_cours != 0) // on transmet à proc 0
{temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
// pour cela on va utiliser un conteneur intermédiaire
QuatreEntiers inter_entiers(retour,listContact.size(),listContact_nouveau_tatdt.size(),listContact_efface_tatdt.size());
// on transmet les infos au proc 0
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 62, inter_entiers);
// on attend pas
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
else // cas du cpu 0
{// l'objectif ici est de récupérer les infos
tempsContact.Arret_du_comptage(); // fin cpu
int nb_contact=0;int nb_new_contact = 0;int nb_efface_contact = 0; // que l'on va cumuler
int nb_proc_terminer = 0; // permettra de terminer
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1))
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
QuatreEntiers inter_entiers;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 62, inter_entiers );
reqs1.wait(); // on attend que le conteneur soit rempli
// on cumule
nb_contact += inter_entiers.deux;
nb_new_contact += inter_entiers.trois;
nb_efface_contact += inter_entiers.quatre;
if (inter_entiers.un) // si un seul des retour s est bon on passe à true
retour = true;
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
};
if (retour)
if (niveau_commentaire_lescontacts > 3) // ==> LesContacts::
{cout << "\n en fin de LesContacts::Nouveau: bilan: "<< nb_contact << " elem(s) contact ";
if ( nb_new_contact)
cout <<", "<< nb_new_contact << " nouveau(x) ";
if (nb_efface_contact)
cout <<", "<<nb_efface_contact << " effacement(s) ";
cout << flush;
};
};
// il faut que tous les proc aient le retour global, car le retour sert dans l'algo général
broadcast(*ParaGlob::Monde(), retour, 0);
#endif
tempsContact.Arret_du_comptage(); // fin cpu
//cout << "\n tempsContact.Temps_CPU_User = " << tempsContact.Temps_CPU_User() << flush;
@ -1550,8 +1816,13 @@ bool LesContacts::SuppressionDefinitiveElemInactif()
{
tempsContact.Mise_en_route_du_comptage(); // def deb compt
int niveau_commentaire_lescontacts = Permet_affichage();
bool change = false;
int nb_effacement=0;
#ifdef UTILISATION_MPI
int proc_en_cours = ParaGlob::Monde()->rank();
if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact
{
#endif
if (niveau_commentaire_lescontacts > 4)
{
@ -1562,13 +1833,7 @@ bool LesContacts::SuppressionDefinitiveElemInactif()
#endif
<< " -- LesContacts::SuppressionDefinitiveElemInactif: ";
};
bool change = false;
int nb_effacement=0;
// return change;
//------- pour le débug
LaLIST <ElContact>::iterator iE ;
// list <TroisEntiers>::iterator iden = numtesN.begin();
// on met .end(), car cette borne peut changer au gré des suppressions
for (iE = listContact.begin(); iE != listContact.end(); iE++)//,iden++)
{if (!((*iE).Actif()) // on intervient si le contact est déclaré inactif
&& ((*iE).Collant()) // et si c'est collant: ce n'est pas normal, on le remet actif
@ -1628,20 +1893,46 @@ bool LesContacts::SuppressionDefinitiveElemInactif()
// c'est que l'élément est actif, donc cela ne sert à rien de le réactiver ???? ceci dit cela ne génère pas une erreur a priori
else {/*(*iE).Met_actif();*/}; // on valide l'activation
};
// info
if (niveau_commentaire_lescontacts > 2)
{ if (nb_effacement)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n"
#endif
<< " sup: "<< nb_effacement << " effacement(s) definitif(s) de contact ";
// info
if (niveau_commentaire_lescontacts > 2)
{ if (nb_effacement)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n"
#endif
<< " sup: "<< nb_effacement << " effacement(s) definitif(s) de contact ";
};
};
if ((niveau_commentaire_lescontacts > 6) && (nb_effacement==0))
cout << " aucun effacement ";
#ifdef UTILISATION_MPI
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 610, change);
// on attend pas
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
else // cas du cpu 0
{// l'objectif ici est de récupérer les infos
tempsContact.Arret_du_comptage(); // fin cpu
int nb_proc_terminer = 0; // permettra de terminer
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1))
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
bool change_i;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 610, change_i );
reqs1.wait(); // on attend que le conteneur soit rempli
if (change_i) // si un seul des retour s est bon on passe à true
change = true;
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
};
};
if ((niveau_commentaire_lescontacts > 6) && (nb_effacement==0))
cout << " aucun effacement ";
};
// il faut que tous les proc aient le retour global, car le retour sert dans l'algo général
broadcast(*ParaGlob::Monde(), change, 0);
#endif
tempsContact.Arret_du_comptage(); // fin cpu
// retour du tableau
@ -1654,9 +1945,13 @@ bool LesContacts::RelachementNoeudcolle()
{
tempsContact.Mise_en_route_du_comptage(); // def deb compt
int niveau_commentaire_lescontacts = Permet_affichage();
#ifdef UTILISATION_MPI
int proc_en_cours = ParaGlob::Monde()->rank();
#endif
bool change = false;
#ifdef UTILISATION_MPI
int proc_en_cours = ParaGlob::Monde()->rank();
if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact
{
#endif
if (niveau_commentaire_lescontacts > 4)
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
@ -1664,8 +1959,7 @@ bool LesContacts::RelachementNoeudcolle()
cout << "\n"
#endif
<< " -- LesContacts::RelachementNoeudcolle(): ";
bool change = false;
// return change; //------- pour le débug
// return change; //------- pour le débug
LaLIST <ElContact>::iterator iE ;
// list <TroisEntiers>::iterator iden = numtesN.begin();
// on met .end(), car cette borne peut changer au gré des suppression
@ -1700,7 +1994,32 @@ bool LesContacts::RelachementNoeudcolle()
};
if ((!change)&& (niveau_commentaire_lescontacts > 6))
cout << " aucun noeud relache ";
#ifdef UTILISATION_MPI
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 6100, change);
// on attend pas
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
else // cas du cpu 0
{// l'objectif ici est de récupérer les infos
tempsContact.Arret_du_comptage(); // fin cpu
int nb_proc_terminer = 0; // permettra de terminer
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1))
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
bool change_i;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 6100, change_i );
reqs1.wait(); // on attend que le conteneur soit rempli
if (change_i) // si un seul des retour s est bon on passe à true
change = true;
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
};
};
// il faut que tous les proc aient le retour global, car le retour sert dans l'algo général
broadcast(*ParaGlob::Monde(), change, 0);
#endif
tempsContact.Arret_du_comptage(); // fin cpu
// retour
return change;
@ -1765,7 +2084,6 @@ list <Condilineaire>& LesContacts::ConditionLin(const Nb_assemb& casAssemb)
listCoLin.clear();// Change_taille(nb_contact_actif);
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
{ // on récupère un résultat de cpu i
int taille_transfert;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 40, taille_transfert);
mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
@ -1942,6 +2260,8 @@ else // cas du cpu 0
tempsContact.Arret_du_comptage();
};
};
// il faut que tous les proc aient le retour global, car le retour sert dans l'algo général
broadcast(*ParaGlob::Monde(), retour, 0);
#endif
// retour de l'indicateur
@ -2206,6 +2526,10 @@ bool LesContacts::Actualisation(int choix)
};
};
#endif
#ifdef UTILISATION_MPI
// il faut que tous les proc aient le retour global, car le retour sert dans l'algo général
broadcast(*ParaGlob::Monde(), retour, 0);
#endif
// retour
tempsContact.Arret_du_comptage(); // fin cpu
@ -2455,13 +2779,9 @@ void LesContacts::CalculReaction(Vecteur& residu,bool& decol,const Nb_assemb& ca
};
};
// affichage éventuelle de la force maxi de contact
#ifdef UTILISATION_MPI
if (proc_en_cours == 0)
#endif
{Forces_contact_maxi(affiche);
// idem pour les gap N et T
Gap_contact_maxi(affiche);
};
Forces_contact_maxi(affiche);
// idem pour les gap N et T
Gap_contact_maxi(affiche);
tempsContact.Arret_du_comptage(); // fin cpu
};

View file

@ -64,6 +64,9 @@
#include "Basiques.h"
#include "TypeQuelconque.h"
#include "Temps_CPU_HZpp.h"
#include "Enum_TypeQuelconque.h"
#include "TypeQuelconqueParticulier.h"
#include <stdlib.h>
#ifdef UTILISATION_MPI
#include <boost/serialization/split_member.hpp>
@ -94,6 +97,10 @@ class LesContacts
~LesContacts ();
// METHODES PUBLIQUES :
// ramène le nombre de maillages esclaves en auto contact, donc qui joue le rôle esclave et maître, ou maillages mixte: dépend de la manière dont les zones de contact ont été
// est définit en lecture des données
int NbmailAutoContact() const {return nbmailautocontact;};
// ramène la liste des éléments de contact
LaLIST <ElContact>& LesElementsDeContact() {return listContact;};
@ -261,6 +268,9 @@ class LesContacts
void TdtversT();
// actualisation des ddl et des grandeurs actives de t vers tdt
void TversTdt();
// ramène le nombre de contacts actifs actuel
int Nb_actifs() const {return nb_contact_actif;};
//------- temps cpu -----
// retourne temps cumulé pour imposer les CL imposées
@ -271,6 +281,19 @@ class LesContacts
const Temps_CPU_HZpp& Temps_transfert_court() const {return temps_transfert_court;} ;
const Temps_CPU_HZpp& Temps_transfert_long() const {return temps_transfert_long;} ;
const Temps_CPU_HZpp& Temps_attente() const {return temps_attente;} ;
// mise à jour list contact pour proc 0: il s'agit des infos minimales
void Mise_a_jour_liste_contacts_actif_interProc();
// on définit une méthode qui permet de retrouver un élément à partir d'infos minimales
ElContact* RecupElContactActif( int num_mailEsclave, int num_noeudEsclave, int numUnique)
{LaLIST <ElContact>::iterator ili,ilifin = listContact.end();
for (ili = listContact.begin();ili != ilifin;ili++)
if ( ((*ili).Esclave()->Num_Mail() == num_mailEsclave)
&& ((*ili).Esclave()->Num_noeud() == num_noeudEsclave)
&& ((*ili).Elfront()->NumUnique() == numUnique)
)
return (&(*ili));
return NULL;
} ;
#endif
//----- lecture écriture de restart -----
@ -326,7 +349,7 @@ class LesContacts
// li si non nulle permet d'indiquer spécifiquement quelle grandeur on veut
// sortir
int Permet_affichage(list <TypeQuelconque> * li = NULL ) const
{ int niveau_commentaire_lescontacts;
{ int niveau_commentaire_lescontacts = ParaGlob::param->ParaAlgoControleActifs().Niveau_commentaire_LesContact();
return( (fct_niveau_commentaire == NULL) ?
(niveau_commentaire_lescontacts == 0) ? ParaGlob::NiveauImpression() : niveau_commentaire_lescontacts
: Valeur_fct_nD_LesContacts(fct_niveau_commentaire, li
@ -375,6 +398,9 @@ class LesContacts
static Tableau <const TypeQuelconque * > tqi_const_fct_nD_niveau_commentaire;
static Tableau < TypeQuelconque * > tqi_fct_nD_niveau_commentaire;
static Tableau <int> t_num_ordre_fct_nD_niveau_commentaire;
list <TypeQuelconque> li_pour_noeuds_element; // pour une sortie spécifique noeud et ou élément fini contenant la frontière
Grandeur_scalaire_entier* gr_pour_noeud; // contient le numéro de noeud esclave éventuel
Grandeur_scalaire_entier* gr_pour_elem; // contient le numéro éventuel de l'élément fini contenant la frontière
// -- fin partie affichage éventuellement piloté
@ -421,6 +447,17 @@ class LesContacts
// ** mais uniquement un numéro locale d'ordre
// ** mais on a: les éléments de frontière de t_listFront(i) font partie du maillage
// i + (nb_mail_Esclave-nbmailautocontact)
#ifdef UTILISATION_MPI
// cas d'un calcul parallèle: // passage des infos entre process
Tableau <Front *> pointe_t_listFront; // pointe_t_listFront(i_num) permet de repérer un élément unique
// dans t_listFront
// à l'inverse, chaque Front stocke son numéro i_num
// pointe_t_listFront est défini dans LesContacts::Init_contact
Vecteur v_interProc_contact_actif; // conteneur de travail utilisé pour le passage d'infos
// entre proc , par la méthode Mise_a_jour_liste_contacts_actif_interProc()
#endif
// les noeuds esclaves potentiels
Tableau < Tableau < Tableau < Noeud*> > > tesctotal;
@ -535,7 +572,13 @@ class LesContacts
return (&(*ili));
return NULL;
} ;
// recherche dans les Front enregistrés de la zone , c-a-d dans t_listFront(i)(zone)
// un Front de même origine , c-a-d sans les mitoyens
// si aucun résultat retourne NULL
// sinon ramène l'élément de t_listFront de même origine
Front* Front_de_meme_origine(Front* fro, int zone) const;
// init éventuel du pilotage par fct nD du niveau de commentaire
void Init_fct_niveau_commentaire();
// définition des conteneurs des TypeQuelconque pour fct nD de LesContacts

View file

@ -176,6 +176,10 @@ void LesContacts::Lec_base_info_LesContacts(ifstream& ent
// mis à jour du numéro de zone
courant.Num_zone_contact() = num_zone;
courant.Change_lissage_normale(lissage_de_la_normale(num_zone)); // affectation du lissage
#ifdef UTILISATION_MPI
// on attribue au front de l'élément de contact, le numéro unique utilisable pour le tableau pointe_t_listFront
courant.Elfront()->ChangeNumUnique(froant->NumUnique());
#endif
// sauvegarde si l'élément de contact n'existe pas déjà
ElContact* test_existance= Element_contact_deja_present(courant);
if (test_existance == NULL)

View file

@ -98,24 +98,32 @@ void LesContacts::TversTdt()
Noeud* no = elc.Esclave();
int n_noee = no->Num_noeud();
int num_mail_noe_esclave = no->Num_Mail();
#ifdef MISE_AU_POINT
if (Element_contact_deja_present(*al))
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n"
#endif
<< "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal "
<< (*al).Esclave()->Num_noeud()
<< " du maillage " << (*al).Esclave()->Num_Mail()
<< " la suite n'est pas possible "
<< " LesContacts::TversTdt(.. \n";
tempsContact.Arret_du_comptage(); // fin cpu
Sortie(1);
};
#endif
listContact.push_front(*al);
// je supprime le test suivant, car on pourrait peut-être avoir en début d'incrément précédent,
// deux elements de contact avec le même noeud esclave mais pas la même frontière
// qui ensuite à cause d'un changement de frontière, deviennent identique -> un des deux est inactivé
// mais il y en a deux identiques.
// du coup si on revient en arrière c'est de ne pas tenir compte du doublon et s'il y a besoin, au niveau de Nouveau
// on aura une création d'un nouvel élément
// #ifdef MISE_AU_POINT
// if (Element_contact_deja_present(*al))
// {
// #ifdef UTILISATION_MPI
// cout << "\n proc " << proc_en_cours
// #else
// cout << "\n"
// #endif
// << "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal "
// << (*al).Esclave()->Num_noeud()
// << " du maillage " << (*al).Esclave()->Num_Mail()
// << " la suite n'est pas possible "
// << " LesContacts::TversTdt(.. \n";
// tempsContact.Arret_du_comptage(); // fin cpu
// Sortie(1);
// };
// #endif
if (!(Element_contact_deja_present(*al)))
listContact.push_front(*al);
// on met à jour le tableau tesN_encontact
#ifdef MISE_AU_POINT
if (tesN_encontact(num_mail_noe_esclave).find(no)
@ -188,7 +196,7 @@ double LesContacts::Pas_de_temps_ideal()
#ifdef UTILISATION_MPI
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
// maintenant on va transmettre au cpu 0
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 56, delta_optimal);
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 48, delta_optimal);
// on attend pas
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
@ -200,12 +208,14 @@ double LesContacts::Pas_de_temps_ideal()
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
double dtelem_optimal ;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 56, dtelem_optimal );
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 48, dtelem_optimal );
reqs1.wait(); // on attend que le conteneur soit rempli
delta_optimal = MiN(delta_optimal, dtelem_optimal);
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
};
};
// il faut que tous les proc aient le retour global, car le retour sert dans l'algo général
broadcast(*ParaGlob::Monde(), delta_optimal, 0);
#endif
return delta_optimal;
@ -1033,11 +1043,11 @@ list <Condilineaire>& LesContacts::ConnectionCLL()
int rang = 1; // init
for (il = t_connectionCLL.begin();il != ilfin;il++)
rang = (*il).Pack_vecteur(inter_transfer2,rang);
temps_attente.Arret_du_comptage();
// on transfert
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 42, taille_conteneur);
mpi::request reqs2 = inter_transfer2.Ienvoi_MPI(0,43);
// si la taille du conteneur est nulle, on ne le transfert pas
if (taille_conteneur > 0)
mpi::request reqs2 = inter_transfer2.Ienvoi_MPI(0,43);
// on attend pas
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
}
@ -1053,19 +1063,22 @@ list <Condilineaire>& LesContacts::ConnectionCLL()
int taille_transfert;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 42, taille_transfert);
mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
inter_transfer2.Change_taille(taille_transfert); // le conteneur
int source = stat.source(); // récupération du numéro de la source
// on récupère
mpi::request reqs2 = inter_transfer2.Irecup_MPI(source, 43);
reqs2.wait(); // on attend que le conteneur soit rempli
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
// on va remplir la liste des conditions limites
int rang = 1; // init
while (rang != 0)
{ Condilineaire condi; // une condition intermédiaire
rang = condi.UnPack_vecteur(*lesMaille,inter_transfer2,rang,
// si la taille == 0, il n'y a rien à faire
if (taille_transfert > 0)
{inter_transfer2.Change_taille(taille_transfert); // le conteneur
int source = stat.source(); // récupération du numéro de la source
// on récupère
mpi::request reqs2 = inter_transfer2.Irecup_MPI(source, 43);
reqs2.wait(); // on attend que le conteneur soit rempli
// on va remplir la liste des conditions limites
int rang = 1; // init
while (rang != 0)
{ Condilineaire condi; // une condition intermédiaire
rang = condi.UnPack_vecteur(*lesMaille,inter_transfer2,rang,
&LesMaillages::Noeud_LesMaille);
t_connectionCLL.push_back(condi);
t_connectionCLL.push_back(condi);
};
};
};
temps_transfert_long.Arret_du_comptage();
@ -1483,7 +1496,7 @@ DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche)
if ((affiche && (ParaGlob::NiveauImpression() > 2))
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
)
{ cout << "\n F_N => [" << retour_min.un << " : " << retour_max.un << "]"
{ cout << "\n contact: reaction ==> F_N => [" << retour_min.un << " : " << retour_max.un << "]"
<< ", F_T max = " << retour_max.deux;
};
if (niveau_commentaire_lescontacts > 6)
@ -1516,11 +1529,13 @@ DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche)
#ifdef UTILISATION_MPI
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
// maintenant on va transmettre au cpu 0
Vecteur v_inter(2);v_inter(1) = retour.un; v_inter(2) = retour.deux;
Vecteur v_inter(3);
v_inter(1) = retour_max.un; v_inter(2) = retour_max.deux;
v_inter(3) = retour_min.un;
// envoi
v_inter.Ienvoi_MPI(0,66);
v_inter.Ienvoi_MPI(0,49);
// on attend pas
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
else // cas du cpu 0
{// l'objectif ici est de récupérer les infos
@ -1529,22 +1544,26 @@ DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche)
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
Vecteur v_inter(2);
mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 66);
Vecteur v_inter(3);
mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 49);
reqs1.wait(); // on attend que le conteneur soit rempli
if (Dabs(v_inter(1)) > Dabs(retour.un) )
{retour.un = v_inter(1);};
if (Dabs(v_inter(2)) > Dabs(retour.deux) )
{retour.deux = v_inter(2);
if (v_inter(1) > retour_max.un)
{retour_max.un = v_inter(1);};
if (v_inter(2) > retour_max.deux)
{retour_max.deux = v_inter(2);
};
if (v_inter(3) < retour_min.un)
{retour_min.un = v_inter(3);};
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
};
if ((affiche && (ParaGlob::NiveauImpression() > 2))
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
)
cout << "\n contact: reaction ==> |F_N max| " << Dabs(retour_min.un) << " |F_T max| " << DabsMaX(retour_min.deux,retour_max.deux);
// cout << "\n contact: reaction ==> |F_N max| = " << Dabs(retour_min.un) << " |F_T max| = " << DabsMaX(retour_min.deux,retour_max.deux);
cout << "\n contact: reaction ==> F_N => [" << retour_min.un << " : " << retour_max.un << "]"
<< ", F_T max = " << retour_max.deux;
};
#endif
@ -1612,11 +1631,12 @@ DeuxDoubles LesContacts::Gap_contact_maxi(bool affiche)
#ifdef UTILISATION_MPI
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
// maintenant on va transmettre au cpu 0
Vecteur v_inter(2);v_inter(1) = retour.un; v_inter(2) = retour.deux;
Vecteur v_inter(4);v_inter(1) = retour_max.un; v_inter(2) = retour_max.deux;
v_inter(3) = retour_min.un;v_inter(4) = retour_min.deux;
// envoi
v_inter.Ienvoi_MPI(0,67);
v_inter.Ienvoi_MPI(0,60);
// on attend pas
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
else // cas du cpu 0
{// l'objectif ici est de récupérer les infos
@ -1625,15 +1645,19 @@ DeuxDoubles LesContacts::Gap_contact_maxi(bool affiche)
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
Vecteur v_inter(2);
mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 67);
Vecteur v_inter(4);
mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 60);
reqs1.wait(); // on attend que le conteneur soit rempli
if (Dabs(v_inter(1)) > Dabs(retour.un) )
{retour.un = v_inter(1);};
if (Dabs(v_inter(2)) > Dabs(retour.deux) )
{retour.deux = v_inter(2);
if (v_inter(1) > retour_max.un)
{retour_max.un = v_inter(1);};
if (v_inter(2) > retour_max.deux)
{retour_max.deux = v_inter(2);
};
if (v_inter(3) < retour_min.un)
{retour_min.un = v_inter(3);};
if (v_inter(4) < retour_min.deux)
{retour_min.deux = v_inter(4);};
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
};
@ -1909,6 +1933,10 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail)
{int i_noe = (*ih); // le num du noeud maître que l'on va tester
Tableau <Noeud *> ttn(1);
ttn(1)= &(lesMail.Noeud_LesMaille(jf,i_noe)); // récup du pointeur de noeud
////------ debug
//if (ttn(1)->Num_noeud() == 37 )
// cout << "\n debug LesContacts::ElementAngleMort(...";
//// fin debug
// récup de la liste pour le noeud i_noe, des éléments qui contient ce noeud : construite avec Init_contact
const List_io < Element* >& liel = (*indice(jf))(i_noe);
@ -1944,7 +1972,10 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail)
Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie());
if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE)))
{continuer = false;}
// b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
// b) si on est en axi et qu'il s'agit d'un élément surface, là c'est bon
else if (ParaGlob::AxiSymetrie() && (enu_type_geom_ele == SURFACE))
{continuer = true;}
// c) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
else if ((ParaGlob::Dimension() == 3)
&& ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE))
)
@ -2118,7 +2149,10 @@ void LesContacts::ElementAngleMort(LesMaillages& lesMail)
Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie());
if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE)))
{continuer = false;}
// b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
// b) si on est en axi et qu'il s'agit d'un élément surface, là c'est bon
else if (ParaGlob::AxiSymetrie() && (enu_type_geom_ele == SURFACE))
{continuer = true;}
// c) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
else if ((ParaGlob::Dimension() == 3)
&& ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE))
)
@ -2456,7 +2490,6 @@ void LesContacts::Init_fct_niveau_commentaire()
tqii(i) = tqi(i);
};
// calcul d'une fonction nD relative à des données de LesContacts
double LesContacts::Valeur_fct_nD_LesContacts
(Fonction_nD * pt_fonct,list<TypeQuelconque>* li
@ -2558,6 +2591,140 @@ double LesContacts::Valeur_fct_nD_LesContacts
// on récupère le premier élément du tableau uniquement
return tab_val(1);
};
// recherche dans les Front enregistrés de la zone , c-a-d dans t_listFront(i)(zone)
// un Front de même origine , c-a-d sans les mitoyens
// si aucun résultat retourne NULL
// sinon ramène l'élément de t_listFront de même origine
Front* LesContacts::Front_de_meme_origine(Front* fro, int zone) const
{ // on récupère le num de maillage associé
// récup du numero du maillage rattache
int numMail = fro->NumMail();
int i = numMail - (nb_mail_Esclave-nbmailautocontact);
// on va balayer dans la zone de contact
LaLIST_io <Front> & list_fronta = (t_listFront(i)(zone)); // pour simplifier
LaLIST_io <Front>::iterator il,ilfin = list_fronta.end();
for (il = list_fronta.begin();il != ilfin; il++)
if ((*il).MemeOrigine(*fro))
return &((*il));
// arrivée ici, cela veut dire que l'on n'a rien trouvé
return NULL;
// la liste des éléments frontières succeptibles d'entrer en contact
// ces Front (qui contiennent que des pointeurs sauf une boite d'encombrement)
// sont différents de ceux des maillages, et sont donc stocké en interne
// Tableau < Tableau < LaLIST_io <Front> > > t_listFront;
// t_listFront(i)(j)(k) : maillage maître (i)
// zone de contact (j)
// (K) = kième frontière (dans l'ordre de la liste)
// ** pour le tableaux t_listFront, le numéros dit de maillage, n'est pas le numéro
// ** intrinsèque de maillage (telle que ceux associés aux noeuds et éléments)
// ** mais uniquement un numéro locale d'ordre
// ** mais on a: les éléments de frontière de t_listFront(i) font partie du maillage
// i + (nb_mail_Esclave-nbmailautocontact)
};
#ifdef UTILISATION_MPI
// mise à jour list contact pour proc 0:
// il s'agit des infos minimales
void LesContacts::Mise_a_jour_liste_contacts_actif_interProc()
{ temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
// on va se servir d'un conteneur intermédiaire
union double_int
{ double x;
int n[2];
} ;
double_int xinter;
int proc_en_cours = ParaGlob::Monde()->rank();
if (proc_en_cours != 0) // seules les proc i>0 définissent des éléments de contact
// on boucle sur les elements de contact du proc i pour les transmettres à proc 0
{ int nb_contact_actif = Calcul_Nb_contact_actif();
// on a besoin de 8 entiers pour repérer un élément de contact, on va transmettre
// un vecteur contenant ces infos
////---debug
//cout << "\n LesContacts::Mise_a_jour_liste_contacts_actif_interProc "
// << " proc "<< proc_en_cours << ", nb_contact= "<< listContact.size();
////--fin debug
v_interProc_contact_actif.Change_taille(4*nb_contact_actif);
int rang=1; // init
LaLIST <ElContact>::iterator il,ilfin = listContact.end();
for (il = listContact.begin();il != ilfin; il++)
if ((*il).Actif())
{xinter.n[0] = (*il).Actif(); xinter.n[1] = (*il).Cas_solide();
v_interProc_contact_actif(rang) = xinter.x;rang++;
xinter.n[0] = (*il).Esclave()->Num_Mail(); xinter.n[1] = (*il).Esclave()->Num_noeud();
v_interProc_contact_actif(rang) = xinter.x;rang++;
xinter.n[0] = (*il).Elfront()->NumUnique(); xinter.n[1] = (*il).Const_Num_zone_contact();
v_interProc_contact_actif(rang) = xinter.x;rang++;
xinter.n[0] = (*il).Lissage_normale(); xinter.n[1] = (*il).Collant();
v_interProc_contact_actif(rang) = xinter.x;rang++;
};
// on transmet à proc 0
// tout d'abord la taille
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 63, 4*nb_contact_actif);
// puis le conteneur
mpi::request reqs2 = v_interProc_contact_actif.Ienvoi_MPI(0,64);
}
else
// cas du proc 0
{ int nb_proc_terminer = 0; // permettra de terminer
// on supprime la liste existante car:
// - si on teste l'existance d'un élément à chaque ajout => il faut parcourir la liste qui peut être longue
// - il faut y adjoindre une méthode pour supprimer les éléments qui ont été supprimés par un proc
// => c'est plus simple de repartir d'une liste vide,
listContact.clear(); // init
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1))
{ // on récupère un résultat de cpu i
int taille_transfert;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 63, taille_transfert);
mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
v_interProc_contact_actif.Change_taille(taille_transfert); // le conteneur
int source = stat.source(); // récupération du numéro de la source
// on récupère
mpi::request reqs2 = v_interProc_contact_actif.Irecup_MPI(source, 64);
reqs2.wait(); // on attend que le conteneur soit rempli
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
// on va remplir la liste des contacts actifs
int rang = 1; // init
while (rang < taille_transfert+1)
{ // récup des infos pour le contact
xinter.x = v_interProc_contact_actif(rang);rang++;
int actif = xinter.n[0]; int casSolide = xinter.n[1];
xinter.x = v_interProc_contact_actif(rang);rang++;
int num_mail = xinter.n[0]; int num_noeud = xinter.n[1];
xinter.x = v_interProc_contact_actif(rang);rang++;
int numUnique = xinter.n[0]; int numZoneContact = xinter.n[1];
xinter.x = v_interProc_contact_actif(rang);rang++;
int lissageNormale = xinter.n[0]; int collant = xinter.n[1];
// on crée un élément de contact
ElContact elcont(pointe_t_listFront(numUnique)
,&(lesMaille->Noeud_LesMaille(num_mail,num_noeud))
,fct_nD_contact,collant);
elcont.Num_zone_contact()=numZoneContact; // affectation du numéro de zone
elcont.Change_lissage_normale(lissageNormale); // affectation du lissage
if (actif) elcont.Met_actif();
else elcont.Met_Inactif();
listContact.push_front(elcont);
};
};
// //---debug
// cout << "\n LesContacts::Mise_a_jour_liste_contacts_actif_interProc "
// << " proc "<< proc_en_cours << ", nb_contact= "<< listContact.size();
// //--fin debug
Calcul_Nb_contact_actif(); // mise à jour
};
temps_transfert_long.Arret_du_comptage();
};
#endif