// This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-2022 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . #include "LesContacts.h" #include #include "ReferenceNE.h" #include "ReferenceAF.h" #include "CharUtil.h" // --------------- variables statiques --------- MotCle LesContacts::motCle; // liste des mots clés Tableau LesContacts::tqi_const_fct_nD_niveau_commentaire; Tableau < TypeQuelconque * > LesContacts::tqi_fct_nD_niveau_commentaire; Tableau LesContacts::t_num_ordre_fct_nD_niveau_commentaire; //------------------------- la classe ReactCont ------------- // surcharge de l'operator de lecture //istream & operator >> (istream & ent, LesContacts::ReactCont & a) istream & operator >> (istream & ent, LesContacts::ReactCont & ) { // lecture du type et vérification string nom_type; ent >> nom_type; if (nom_type != "LesContacts::ReactCont") Sortie(1); // les infos **** pb de la reconnaissance du noeud *** /* EN CHANTIER ent >> a.noe->Num_Mail() >> a.noe->Num_noeud() << " "; // la force sort << a.force; // les noeuds de la frontière maitre int taille = tabNoeud.Taille(); for (int i=1;i<=taille;i++) sort << a.tabNoeud(i)->Num_Mail() << " " << a.tabNoeud(i)->Num_noeud() << " "; // les réactions de la frontière maître int taille2 = tabForce.Taille(); for (int i=1;i<=taille2;i++) sort << a.tabForce(i); */ return ent ; }; // surcharge de l'operator d'ecriture ostream & operator << (ostream & sort , const LesContacts::ReactCont & a) { // écriture du type sort << "LesContacts::ReactCont "; // les infos sort << a.noe->Num_Mail() << " " << a.noe->Num_noeud() << " "; // la force sort << a.force; // les noeuds de la frontière maitre int taille = a.tabNoeud.Taille(); for (int i=1;i<=taille;i++) sort << a.tabNoeud(i)->Num_Mail() << " " << a.tabNoeud(i)->Num_noeud() << " "; // les réactions de la frontière maître int taille2 = a.tabForce.Taille(); for (int i=1;i<=taille2;i++) sort << a.tabForce(i); return sort ; }; // constructeur par defaut LesContacts::ReactCont::ReactCont() : force(),tabNoeud(),tabForce() { noe = NULL; }; // constructeur en fonction des datas du noeud esclave seul LesContacts::ReactCont::ReactCont(Noeud* no,const Coordonnee& forc) : force(forc),tabNoeud(),tabForce() { noe = no;}; // constructeur en fonction des datas de tous les noeuds LesContacts::ReactCont::ReactCont (Noeud* no,const Coordonnee& forc,Tableau tN,const Tableau & tFor) : force(forc),tabNoeud(tN),tabForce(tFor) { noe = no;}; // constructeur de copie LesContacts::ReactCont::ReactCont(const ReactCont& a) : force(a.force),tabNoeud(a.tabNoeud),tabForce(a.tabForce) { noe = a.noe;}; // affectation LesContacts::ReactCont& LesContacts::ReactCont::operator = (const LesContacts::ReactCont& a) { force =a.force;noe = a.noe;tabNoeud = a.tabNoeud;tabForce = a.tabForce; return *this;}; // test bool LesContacts::ReactCont::operator == (const LesContacts::ReactCont& a) { if ((force == a.force) &&(noe == a.noe) && (tabNoeud == a.tabNoeud) &&(tabForce == a.tabForce)) return true; else return false;}; bool LesContacts::ReactCont::operator != (const LesContacts::ReactCont& a) { if (*this == a) return false; else return true; }; //------------------------- fin la classe ReactCont ------------- // CONSTRUCTEURS : // constructeur par defaut 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() ,t_connectionCLL() ,liste_elemens_front(),tempsContact() #ifdef UTILISATION_MPI ,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) ,liste_elemens_front(a.liste_elemens_front),liQ_en_sortie(),tempsContact(a.tempsContact) ,t_connectionCLL(a.t_connectionCLL) #ifdef UTILISATION_MPI ,temps_transfert_court(a.temps_transfert_court) ,temps_transfert_long(a.temps_transfert_long),temps_attente(a.temps_attente) ,inter_transfer(),inter_transfer2(),lesMaille(NULL) #endif {// on réaffecte les pointeurs pour la sortie spécifique noeud et ou element list ::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 & list_fronta = (t_listFront(i)(j)); // pour simplifier LaLIST_io ::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 () { }; // METHODES PUBLIQUES : // initialisation des zones de contacts éventuelles à partir des éléments de frontières et des noeuds esclaves // sauf les frontières qui sont les mêmes pendant tout le calcul // --- en entrée: // les maillages, les ref et les fonctions nD // -- en sortie: // cas du contact type 4 : on renseigne éventuellement une fonction de pilotage --> fct_pilotage_contact4 // récup de: nb_mail_Esclave, nbmailMaitre, // récup du tableau "indice" : = la liste pour chaque noeud, des éléments qui contient ce noeud // création des conteneurs internes : tesctotal, tesN_collant, t_listFront, tesN_encontact void LesContacts::Init_contact(LesMaillages& lesMail ,const LesReferences& lesRef ,LesFonctions_nD* lesFonctionsnD) { tempsContact.Mise_en_route_du_comptage(); // temps cpu // sauvegarde de la liste des fonctions nD sauve_lesFonctionsnD = lesFonctionsnD; // init éventuel du pilotage par fct nD du niveau de commentaire LesContacts::Init_fct_niveau_commentaire(); 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(); #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 // --- récup info maillage // tescin : a la dimension du nombre de maillage esclave // comme les maillages esclaves sont les premiers dans le .info, // tescin(i) correspond aux noeuds des frontières du maillage i // listFrontiere (i) : toutes les frontières des maillages, (peut-être vide pour certains maillages sans frontières) // correspond aux frontières du maillage i: dabord pour les esclaves puis les maîtres // nbEscla : nb de maillage esclave // ind : pour tous les maillages, la liste des éléments qui contiennent chaque noeud // (mis à jour lors de la création des frontières) Tableau < Tableau *> tescin = lesMail.Tab_noeud_frontiere_esclave(); Tableau *>& listFrontiere = lesMail.ListFrontiere(); const Tableau < const Tableau > *>& ind = lesMail.Indice(); // dans le cas d'un contact de type 4 on renseigne éventuellement une fonction de pilotage string nom_fct4 = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_bascul_contact_type_4(); if ((ParaGlob::param->ParaAlgoControleActifs().ContactType() == 4) && (nom_fct4 != "_") ) {// on va récupérer la fonction if (lesFonctionsnD->Existe(nom_fct4)) { Fonction_nD * pt_fonct = lesFonctionsnD->Trouve(nom_fct4); // on vérifie pour l'instant que c'est bien une fonction de grandeurs globales if (pt_fonct->NbVariable_locale() != 0) // cas où il n'y a pas que des variables globales #ifdef UTILISATION_MPI {if (ParaGlob::Monde()->rank() == 0) #endif { cout << "\n *** erreur dans la definition de la fonction nD de pilotage " << " du type de contact 4 : " << nom_fct4 << " n'utilise pas que des variables globales !! "; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); } #ifdef UTILISATION_MPI } #endif else if (pt_fonct->NbComposante() > 2) #ifdef UTILISATION_MPI {if (ParaGlob::Monde()->rank() == 0) #endif { cout << "\n *** erreur dans la definition de la fonction nD de pilotage " << " du type de contact 4 : " << nom_fct4 << " ramene plus de 2 composantes !! "; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); } #ifdef UTILISATION_MPI } #endif else // sinon ok {ElContact::Init_fct_pilotage_contact4(pt_fonct);} } else #ifdef UTILISATION_MPI {if (ParaGlob::Monde()->rank() == 0) #endif { cout << "\n *** erreur dans la definition de la fonction nD de pilotage " << " du type de contact 4 , le nom : " << nom_fct4 << " ne correspond pas a une fonction nD existante !! "; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; #ifdef UTILISATION_MPI }; #endif }; /* // ----pour le débug //{int nbMaillageTotal = listFrontiere.Taille(); //for (int nbmail=1;nbmail<=nbMaillageTotal;nbmail++) // {int nbfront = listFrontiere(nbmail)->size(); // cout << "\n maillage " << nbmail << " -------- "; // LaLIST ::iterator iff,iffin = listFrontiere(nbmail)->end(); // iff=listFrontiere(nbmail)->begin(); //// for (iff=listFrontiere(nbmail)->begin();iff !=iffin;iff++) // Front& titi = (*iff); // titi.Affiche(); cout << "\n"; // // }; // // Sortie(1); //}; //// fin débug */ // dans le tableau de listes de frontière on a d'abord les elements frontieres // esclaves puis les elements maitres int ntmail = listFrontiere.Taille(); // nb maxi de maillages nb_mail_Esclave = lesMail.NbEsclave(); // def du nombre de maillages esclaves // les maillages mixtes (ou en autocontact) font partie de la liste des nbEscla // d'où si par exemple tous les éléments peuvent entrer en auto-contact // -> nbEscla == ntmail == nbmailautocontact == nbmailMaitre nbmailMaitre = ntmail-(nb_mail_Esclave-nbmailautocontact); // def du nombre de maillage maitres // dans le cas d'auto-contact, on vérifie la cohérence #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (nbmailautocontact != 0) {if ((nbmailautocontact <1) || (nbmailautocontact > nb_mail_Esclave)) // nbmailautocontact doit etre >= 0 et < nb_mail_Esclave { cout << "\n ** incoherence dans le nombre de maillage en auto contact !! " << ", le nombre de maillage en auto contact lu : " << nbmailautocontact << ", n\'est pas acceptable, il est soit negatif soit superieur au nombre de maillage esclave ( " << nb_mail_Esclave << " ) " << endl; if (niveau_commentaire_lescontacts >= 0) cout << "\n LesContacts::Init_contact(... " << endl; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; }; // on récupère le tableau indice indice = ind; #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n >>>> Information : Initialisation du contact: "; // dimensionnement du premier niveau des tableaux tesctotal.Change_taille(nb_mail_Esclave); tesN_collant.Change_taille(nb_mail_Esclave); t_listFront.Change_taille(nbmailMaitre); // --- on s'occupe du deuxième niveau de tesN_encontact // une map vide par défaut std::map::iterator > > map_vide; tesN_encontact.Change_taille(nb_mail_Esclave,map_vide); // --- on s'occupe maintenant des niveaux 2 et 3 des tableaux tesctotal et tesN_collant // on regarde si la zone de contact est restreinte if (nom_ref_zone_contact.size() == 0) { // cas d'un contact non restreint // cela correspond finalement à une seule zone de contact // 1-- cas des noeuds esclaves for (int ii=1;ii<= nb_mail_Esclave;ii++) { int taille = tescin(ii)->Taille(); // nombre de noeuds esclave // tescin -> tous les noeuds possiblement en esclave donc en contact tesctotal(ii).Change_taille(1);tesctotal(ii)(1).Change_taille(taille); tesN_collant(ii).Change_taille(1);tesN_collant(ii)(1).Change_taille(taille); for (int itai=1;itai<=taille;itai++) {// ici, la seule zone c'est "tout" les noeuds esclaves, du coup le numéro d'ordre // de stockage c'est le numéro dans tescin(ii), c-a-d le numéro de classement des noeuds esclaves // pour le maillage ii tesctotal(ii)(1)(itai) = (*tescin(ii))(itai); tesN_collant(ii)(1)(itai) = 0; // pas de contact collant car le contact est non restreint }; #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n mail. esclave "< & lis_fronta = (t_listFront(ilistfront)(1)); LaLIST ::iterator iMi,iMifin=(*listFrontiere(jf)).end(); for (iMi = (*listFrontiere(jf)).begin();iMi != iMifin; iMi++) lis_fronta.push_back((*iMi)); #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n mail. maitre "<::iterator il,ilfin=nom_ref_zone_contact.end(); int nb_zone = nom_ref_zone_contact.size(); #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n --> nombre de zone de contact: " << nb_zone; // --- tout d'abord on s'occupe des noeuds esclaves // on va boucler sur les zones pour être sûr de définir complètement toutes les zones int izone=1; for (il=nom_ref_zone_contact.begin(); il!=ilfin;il++,izone++) // boucle sur les références de zone_contact { // recup de la reference correspondant au mot cle string * nom_mail_noe=NULL; string nom_inter; if ((*il).nom1.length()) {nom_inter = ((*il).nom1); nom_mail_noe = &nom_inter; } const Reference & ref = lesRef.Trouve((*il).nom2,nom_mail_noe); // on continue que si c'est une référence de noeud #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (ref.Indic() != 1) { // ce n'est pas normal -> message d'erreur cout << "\n *** erreur la reference de zone de contact n'est pas " << " une reference de noeud ! "; ref.Affiche(); cout << "\n LesContacts::Init_contact(..." << endl; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; // on peut maintenant utiliser de manière sûre une ref NE const ReferenceNE & refNE = ((ReferenceNE &) ref); // maintenant on va boucler sur les noeuds esclaves pour trouver // les noeuds de la ref bool zone_definie = false; for (int intot = 1;intot<= nb_mail_Esclave;intot++) {// on dimensionne le niveaux 2 des tableaux tesctotal(intot).Change_taille(nb_zone); tesN_collant(intot).Change_taille(nb_zone); // et maintenant le niveau 3 c-a-d le troisième niveau //Les zones définies sont prises telles qu'elle, elles peuvent donc // définir des noeuds potentiels au contact en dehors de ceux définis // par la construction automatique des frontières dans lesMaillages // -> donc ici on ne considère pas tescin (modif: 16 mai 2020) int nb_noe = refNE.Taille(); // init tesctotal(intot)(izone).Change_taille(nb_noe); tesN_collant(intot)(izone).Change_taille(nb_noe); // maintenant on va remplir for (int no_dans_ref = 1; no_dans_ref<= nb_noe;no_dans_ref++) {int num_noe_ref = refNE.Numero(no_dans_ref); tesctotal(intot)(izone)(no_dans_ref)= &(lesMail.Noeud_LesMaille(ref.Nbmaille(),num_noe_ref)); tesN_collant(intot)(izone)(no_dans_ref)= (*il).n; }; // -- fin de la boucle sur les noeuds de la référence #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (niveau_commentaire_lescontacts >2 ) cout << "\n maillage esclave "< " << nb_noe << " noeuds esclaves pour contact "; // arrivée ici, c'est que la zone a été définie zone_definie = true; }; // -- fin de la boucle sur intot c-a-d les maillages esclave // message d'erreur si la zone n'a pas été définie #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (!zone_definie) { cout << "\n *** erreur dans la construction de la zone de contact "< donc ici on ne considère pas "listFrontiere" (modif: 16 mai 2020) Tableau < int > zone_frontiere(nb_zone,0); // le nb d'elem dans chaque zone // on initialise la liste // on parcours les elements maitres int ilistfront = 1; // compteur pour le tableau t_listFront //à cause d'un auto contact éventuelle on peut avoir des maillages esclaves qui jouent le rôle également de // maillages maitres for (int jlf=ntmail-nbmailMaitre+1;jlf<=ntmail;jlf++,ilistfront++) // boucle sur les maillages maitres {// on dimensionne le niveaux 2 des tableaux t_listFront(ilistfront).Change_taille(nb_zone); int izone = 1; // init compteur de zone for (il=nom_ref_zone_contact.begin(); il!=ilfin;il++,izone++) // boucle sur les références de zone_contact { // recup de la reference correspondant au mot cle string * nom_mail_face=NULL; if (((*il).nom3.length())) nom_mail_face = &(*il).nom3; // on regarde si la référence existe string nom_ref = (*il).nom4; #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (!lesRef.Existe(nom_ref,nom_mail_face)) { cout << "\n *** erreur la reference "<< nom_ref; if (nom_mail_face != NULL) cout << " du maillage " << *nom_mail_face; cout << " n'existe pas !! "; cout << "\n LesContacts::Init_contact(..." << endl; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; const Reference & ref = lesRef.Trouve((*il).nom4,nom_mail_face); // on continue si le maillage de la ref est bien celui du maître que l'on consulte actuellement if (ref.Nbmaille() == jlf) {// --- on balaie les frontières potentielles LaLIST_io & list_fronta = (t_listFront(ilistfront)(izone)); // pour simplifier switch (ref.Indic()) {case 3: // cas d'une frontière de type surface, {const ReferenceAF & refAF = ((ReferenceAF &) ref); int nb_fr = refAF.Taille(); for (int i_fr = 1; i_fr <= nb_fr;i_fr++) {int num_fr = refAF.NumeroFA(i_fr); // le numéro de la frontière int num_ele = refAF.NumeroElem(i_fr); // le numéro de l'élément associé int num_mail = refAF.Nbmaille(); Element& ele = lesMail.Element_LesMaille(num_mail, num_ele); // récupération ou création de la frontière ElFrontiere* fro = ele.Frontiere_surfacique(num_fr); // création et ajout de la frontière list_fronta.push_back(Front (*fro,&ele,num_fr)) ; zone_frontiere(izone)++; }; break; } case 4: // cas d'une frontière de type arête {const ReferenceAF & refAF = ((ReferenceAF &) ref); int nb_fr = refAF.Taille(); for (int i_fr = 1; i_fr <= nb_fr;i_fr++) {int num_fr = refAF.NumeroFA(i_fr); // le numéro de la frontière int num_ele = refAF.NumeroElem(i_fr); // le numéro de l'élément associé int num_mail = refAF.Nbmaille(); Element& ele = lesMail.Element_LesMaille(num_mail, num_ele); // récupération ou création de la frontière ElFrontiere* fro = ele.Frontiere_lineique(num_fr); // création et ajout de la frontière list_fronta.push_back(Front (*fro,&ele,num_fr)) ; zone_frontiere(izone)++; }; break; } default: // ici la frontière peut-être n'importe quoi: point, arête, surface // on vérifie que ce ne sont pas des ref Indic 5 ou 6 ou plus ou 1 ou 2 #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif { cout << "\n *** erreur la reference de zone de frontiere de contact n'est pas " << " une reference acceptable ! " << " seules les ref d'aretes ou de surface sont possibles " ; ref.Affiche(); cout << "\n LesContacts::Init_contact(..." << endl; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; break; }; // fin du switch sur le type de frontière }; }; //-- fin de la boucle sur zone de contact }; //-- fin de la boucle sur les maillages maîtres // petit message si nécessaire #ifdef UTILISATION_MPI if (ParaGlob::Monde()->rank() == 0) #endif if (niveau_commentaire_lescontacts >2 ) //&& (list_fronta.size() > 0)) { for (int i=1;i<= nb_zone;i++) // boucle sur les références de zone_contact { cout << "\n zone de contact: " << i << " => " << zone_frontiere(i) << " frontieres prises en compte pour le contact "; if (zone_frontiere(i) == 0) cout << "\n *** warning c'est un peu etrange qu'il y ait 0 frontiere, cela veut dire " << " que cette zone ne sera pas utilisable !! "; }; }; }; //-- fin du else : cas d'une zone restreinte de contact // on définit et on ajoute les fronts des angles morts ElementAngleMort(lesMail); // 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()); for (int i=1;i<=nbmailMaitre;i++) { for (int j=1;j<=nb_zone;j++) { LaLIST_io & list_fronta = (t_listFront(i)(j)); // pour simplifier LaLIST ::iterator iM,iMfin=list_fronta.end(); for (iM = list_fronta.begin();iM != iMfin; iM++) // boucle sur les frontières enregistrées {Front & fronta = (*iM); // pour simplifier const Tableau * ta = fronta.TabMitoyen(); // récup des mitoyens if (ta != NULL) // cas où il y a des éléments voisins ! { const Tableau & taa = *ta; // pour simplifier int ta_taille = ta->Taille(); Tableau 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 & list_fronta = (t_listFront(i)(j)); // pour simplifier LaLIST ::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 liste_elemens_front.sort(); // ordonne liste_elemens_front.unique(); // supprime les doublons // --- cas des contacts collants avec suppression des gaps ---- // suppression du gap de contact pour les noeuds "collant avec suppression de gap" Suppression_gap_pour_noeud_collant(); ////--- debug //{ for (int jf=ntmail-nbmailMaitre+1;jf<=ntmail;jf++) // { LaLIST ::iterator iM,iMfin=(*listFrontiere(jf)).end(); // for (iM = (*listFrontiere(jf)).begin();iM != iMfin; iM++) // boucle sur les fronts maitres // { ElFrontiere* elemf = (*iM).Eleme(); // pour simplifier // if (((*iM).Num_frontiere() == 1) && ((*iM).PtEI()->Num_elt()== 3130) // && ((*iM).PtEI()->Num_maillage() == 4)) // { cout << "\n debug : frontiere 1 de l'element 3130"; // } // } // } //} ////-- 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 & list_fronta = (t_listFront(i)(j)); // pour simplifier LaLIST_io ::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 & list_fronta = (t_listFront(i)(j)); // pour simplifier // LaLIST_io ::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 * ta = fronta.TabMitoyen(); // récup des mitoyens // if (ta != NULL) // cas où il y a des éléments voisins ! // { const Tableau & 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 }; // verification qu'il n'y a pas de contact avant le premier increment de charge void LesContacts::Verification() { #ifdef UTILISATION_MPI // cas d'un calcul //, seule le CPU 0 est concernée if (ParaGlob::Monde()->rank() != 0) return ; #endif // on va iterer sur les noeuds esclaves pour savoir s'ils sont internes // a un element c-a-d a l'interieur d'un element qui contiend un element // frontiere int nb_zone = MaX(1,nom_ref_zone_contact.size()); int niveau_commentaire_lescontacts = Permet_affichage(); if (niveau_commentaire_lescontacts > 4) cout << "\n -- LesContacts::Verification: "; // mise à jour les boites d'encombrement des éléments frontière {LaLIST_io ::iterator iM,iMfin; for (int i=1;i<=nbmailMaitre;i++) for (int j=1;j<= nb_zone;j++) { iMfin=(t_listFront(i)(j)).end(); //debug //cout << "\n les elements frontières: " << t_listFront(jjf) << " "; // fin debug for (iM = (t_listFront(i)(j)).begin() ; iM != iMfin; iM++) (*iM).Boite_encombrement_frontiere(TEMPS_t,0.); // au début pas de déplacement -> 0. }; }; list ::iterator ilfele, ilfelefin = liste_elemens_front.end(); for (int intot = 1;intot<= nb_mail_Esclave;intot++) for (int j=1;j<= nb_zone;j++) { const Tableau & tesc= tesctotal(intot)(j); // pour simplifier la notation const Tableau tesN_col = tesN_collant(intot)(j); // pour simplifier int tesc_taille=tesc.Taille(); for (int inesc = 1;inesc<= tesc_taille;inesc++) { Noeud* noee = tesc(inesc); // pour simplifier const Coordonnee& pt_esc = noee->Coord1(); // position du noeud esclave à l'instant t //debug //cout << "\n pt_esc= " << pt_esc << " "<< endl ; // fin debug int num_mail_noe_esclave = noee->Num_Mail(); // on parcours les elements maitres for (ilfele = liste_elemens_front.begin(); ilfele != ilfelefin; ilfele++) { Element & elem = *(*ilfele); // l'element qui contiend la frontiere // dans le cas où l'élément et le noeud appartienne au même maillage, on est // dans le cas d'un auto-contact. Dans ce cas on ne considère que les éléments // qui ne contiennent pas le noeud esclave if (elem.Num_maillage() == num_mail_noe_esclave) { List_io < Element* > indice_m = (*indice(num_mail_noe_esclave))(noee->Num_noeud()); // pour simplifier if (find(indice_m.begin(),indice_m.end(),&elem) != indice_m.end()) break; // on arrête la boucle si on trouve l'élément parmi ceux contenant le noeud }; // on regarde si le noeud esclave est dans la boite d'encombrement de l'élément if (elem.In_boite_emcombrement_elem(pt_esc)) // on teste alors plus précisemment {//compteur++; 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 > 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() << " dans l'element " << elem.Num_elt() << " du maillage " << num_mail_elem ; if (tesN_col(inesc)) cout << " (contact collant) "; //elem.Interne_t(pt_esc); // debug //cout << endl; // elem.Affiche();tesc(inesc)->Affiche(); //--- on laisse pour voir continuer Sortie(1); }; }; }; // -- fin de la boucle sur ifele }; // -- fin de la boucle sur inesc }; //-- fin de la boucle sur les zones // cout << "\n compteur = " << compteur << endl; // Sortie(1); }; // definition des elements de contact eventuels // dep_max : déplacement maxi des noeuds du maillage // 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 bool retour = false; // init par défaut int niveau_commentaire_lescontacts = Permet_affichage(); #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); #endif if (niveau_commentaire_lescontacts > 4) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours << " -- LesContacts::Def Elem Cont, initialement "<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 LaLIST_io ::iterator iM,iMfin; // des itérator de travail // la mise à jour des boites d'encombrement n'est pas nécessaire car elle est faite dans l'algo avant le contact // *** si car ici on tient compte du déplacement et pas dans le prog principale // *** à voir si on ne peut pas le faire dans le prog princ, mais il faut faire un cas mini // car pour les points on se retrouve avec une boite de dim nulle !! // mise à jour les boites d'encombrement des éléments frontière {LaLIST_io ::iterator iM,iMfin; for (int i=1;i<=nbmailMaitre;i++) for (int j=1;j<= nb_zone;j++) { iMfin=(t_listFront(i)(j)).end(); for (iM = (t_listFront(i)(j)).begin() ; iM != iMfin; iM++) (*iM).Boite_encombrement_frontiere(TEMPS_t,dep_max_pratique); // au début pas de déplacement -> 0. }; }; LaLIST ::iterator icont_inter; // sert pour la recherche de doublon // list ::iterator inumtesN; // " " " for (int intot = 1;intot<= nb_mail_Esclave;intot++) // boucle sur les maillages esclaves for (int j_zone=1;j_zone<=nb_zone;j_zone++) {const Tableau & tesc= tesctotal(intot)(j_zone); // pour simplifier la notation: const Tableau tesN_col = tesN_collant(intot)(j_zone); // pour simplifier int tesc_taille=tesc.Taille(); // tab des noeuds esclaves à considérer for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves {Noeud* noee = tesc(inesc); // pour simplifier int num_mail_noe_esclave = noee->Num_Mail(); int n_noee = noee->Num_noeud(); {int nb_contact=0; //au début pas de contact pour le noeud (pour gérer les doublons en contact) const Coordonnee pt_esc = noee->Coord2(); // position du noeud esclave for (int jlf=1;jlf<=nbmailMaitre;jlf++) // boucle sur les maillages maitres {LaLIST_io & t_listFront_jlf_j = t_listFront(jlf)(j_zone); iMfin= t_listFront_jlf_j.end(); for (iM = t_listFront_jlf_j.begin() ; iM != iMfin; iM++) // boucle sur les front { bool a_considerer = true; // init par défaut #ifdef UTILISATION_MPI // dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu {Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere // on ne continue que si l'élément est concerné if (!(ParaGlob::param->Element_concerner(elem.Num_maillage(),elem.Num_elt_const()) )) a_considerer=false; }; #endif std::map::iterator > >& tesN_encontact_ii = tesN_encontact(num_mail_noe_esclave); // on regarde si la liste existe, si oui on peut tester les membres sinon, on ne fait rien // car autrement on crée automatiquement une liste avec un élément vide std::map::iterator > >::iterator it_liste; if (tesN_encontact_ii.find(noee) != tesN_encontact_ii.end()) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[noee]; LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); nb_contact = list_tesN.size(); for (pl = list_tesN.begin();pl != plfin;pl++) {ElContact& elc = (*(*pl)); if ( elc.Elfront()->MemeOrigine(*iM)) {a_considerer=false;break;} }; }; // donc on ne continue que si la face n'est pas déjà en contact avec le noeud if (a_considerer) {// on regarde si le noeud esclave est dans la boite d'encombrement de l'élément frontière Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere // dans le cas où l'élément et le noeud appartienne au même maillage, on est // dans le cas d'un auto-contact. Dans ce cas on ne considère que les éléments // qui ne contiennent pas le noeud esclave if (elem.Num_maillage() == num_mail_noe_esclave) { List_io < Element* > indice_m = (*indice(num_mail_noe_esclave))(n_noee); // pour simplifier if (find(indice_m.begin(),indice_m.end(),&elem) != indice_m.end()) break; // on arrête la boucle si on trouve l'élément parmi ceux contenant le noeud }; // ---- finalement on ne va pas considérer le point frontière comme particulier --- // du coup, il ne sera jamais pris en compte et on // bool dans_la_boite=false; // init // // on prend en compte le cas particulier de frontière point // if ((*iM)->Eleme()->Type_geom_front() == POINT_G) // // on utilise la boite d'encombrement de l'élément car pour l'instant // // je ne vois pas de solution plus pertinente // // bool In_boite_emcombrement_elem(const Coordonnee& M,double depass = 0.) // { dans_la_boite = elem.In_boite_emcombrement_elem(pt_esc);} // else // sinon c'est le cas normal, on test la boite de la frontière // { dans_la_boite = (*iM)->In_boite_emcombrement_front(pt_esc);}; // if (dans_la_boite) bool plus_en_avant = false; // init if (tesN_col(inesc)) // si collant: on projete systématiquement avec de grandes bornes { if ((*iM).In_boite_emcombrement_front(pt_esc,dist_max)) plus_en_avant = true; } else if ((*iM).In_boite_emcombrement_front(pt_esc)) // cas non collant { plus_en_avant = true;}; if (plus_en_avant) // on teste alors plus précisemment {// constitution d'un element de contact intermediaire 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 // cout << "\n LesContacts::DefElemCont *3* "<< flush; // elcont.Affiche(1); // //--- fin debug bool ret = elcont.Contact(init_inter); if (niveau_commentaire_lescontacts > 5) { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << " recherche du contact entre noeud " << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() << " et frontiere " << (*iM).Num_frontiere() << " de l'element " << elem.Num_elt() << " du maillage " << num_mail_elem; if (ret) cout << "\n --> contact trouve "; else cout << "\n --> pas de contact "; if ((niveau_commentaire_lescontacts > 6) && ((*iM).In_boite_emcombrement_front(pt_esc)) ) {Noeud* noeud = tesc(inesc); // --- sortie d'info pour vérifier l'appartenance à la boite ou non cout << ", coordonnee noeud esclave : " ; noeud->Coord2().Affiche(); cout << "\n boite d'encombrement de l'element qui contient la frontiere:\n mini -> "; elem.RecupBoite_encombre_element().Premier().Affiche(); cout << " maxi -> "; elem.RecupBoite_encombre_element().Second().Affiche(); cout << "\n boite d'encombrement de la frontiere:\n mini -> "; (*iM).Encom_mini_FR().Affiche(); cout << " maxi -> "; (*iM).Encom_maxi_FR().Affiche(); }; cout << endl; }; if (ret) //sauvegarde éventuelle de l'element contact {// on regarde s'il n'y a pas un autre élément de contact avec le même noeud if (nb_contact == 0) { // s'il existe déjà ce n'est pas normal #ifdef MISE_AU_POINT {if (Element_contact_deja_present(elcont) != NULL) { #ifdef UTILISATION_MPI cout << "\n *** erreur: proc " << proc_en_cours; #endif cout << "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal " << (elcont).Esclave()->Num_noeud() << " du maillage " << (elcont).Esclave()->Num_Mail() << " la suite n'est pas possible " << " LesContacts::DefElemCont(.. \n"; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; } #endif // c'est le premier élément en contact, on l'enregistre listContact.push_front(elcont); retour = true; listContact_nouveau_tatdt.push_front(listContact.begin()); // mémorisation // et ajout dans la liste associé au noeud esclave tesN_encontact_ii[noee].push_front(listContact.begin()); nb_contact++; if (niveau_commentaire_lescontacts > 3) { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << "contact entre noeud " ; if (tesN_col(inesc)) cout << " collant "; cout << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() << " et frontiere " << (*iM).Num_frontiere() << " de l'element " << elem.Num_elt() << " du maillage " << num_mail_elem << "(zone"< 6) {cout << "\n pt intersection: " << elcont.Point_intersection() ; elcont.Elfront()->Affiche(); cout << flush; }; }; } else { // on a déjà un élément en contact // on peut alors utiliser une ref sur l'élément de la map, sans craindre d'en créer // un nouveau LaLIST < LaLIST::iterator >::iterator pl = tesN_encontact_ii[noee].begin(); // le pointeur du premier de la liste ElContact& elc = (*(*pl)); // on va retenir l'élément dont le point de contact est le plus proche du point à t //***: on retient ici le plus proche, mais dans nouveau on gardera tous les contacts // ici il s'agit essentiellement de l'initialisation (à voir ensuite si c'est tenable !) // --> permet aussi de coller sur un élément bien déterminé, s'il s'agit d'un collage if ((elcont.Point_intersection()-pt_esc).Norme() < (elc.Point_intersection()-pt_esc).Norme()) {// cas où le nouvel élément en contact est plus proche que celui enregistré listContact_efface_tatdt.push_front(elc); // mémorise // il faut utiliser erase et non remove car il n'y a pas d'opérateur = // pour les éléments de contact listContact.erase(*pl); // on efface l'ancien listContact_nouveau_tatdt.remove(*pl); // il faut supprimer dans tesN_encontact tesN_encontact_ii[noee].erase(pl); // puis on met le nouveau s'il n'existe pas déjà ElContact* test_existance= Element_contact_deja_present(elcont); if (test_existance == NULL) // s'il n'existe pas, on le rajoute {listContact.push_front(elcont); retour = true; 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 > 3) { int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << " --- changement d'element en contact ---"; cout << "contact entre noeud " ; if (tesN_col(inesc)) cout << " collant "; cout << elcont.Esclave()->Num_noeud() << " du maillage " << elcont.Esclave()->Num_Mail() << " et frontiere " << (*iM).Num_frontiere() << " de l'element " << elem.Num_elt() << " du maillage " << num_mail_elem << "(zone"<Actif()) // s'il existe et est inactif on le rend actif (pour remplacer celui qui devrait être créé) {test_existance->Met_actif(); }; }; // sinon le nouvel élément est plus loin que l'ancien, on en tient pas compte }; }; // sinon il n'y a pas de contact }; //-- fin du test sur la boite_encombrement }; // -- fin du test : if (a_considerer) }; // -- fin de la boucle sur iM }; //-- fin de la boucle sur jlf }; //-- 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 #else cout << "\n" #endif << " apres Def Elem Cont: "<< listContact.size() << " elem contact "; if ( listContact_nouveau_tatdt.size()) cout <<", "<< listContact_nouveau_tatdt.size() << " nouveau(x) "; if (listContact_efface_tatdt.size()) cout <<", "<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 <<", "<> bilan des noeud(s) actuellement en contact: "; int nb_noe_en_contact = 0; for (int intot = 1;intot<= nb_mail_Esclave;intot++) // boucle sur les maillages esclaves for (int j=1;j<= nb_zone;j++) {const Tableau & tesc= tesctotal(intot)(j); // pout simplifier la notation const Tableau tesN_col = tesN_collant(intot)(j); // pour simplifier int tesc_taille=tesc.Taille(); 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 *(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) cout << "\n noeud " << no->Num_noeud() << " du maillage " << no->Num_Mail(); cout << " coord2= "; no->Coord2().Affiche_1(cout); // #ifdef MISE_AU_POINT // if (tesN_encontact(num_mail_noe_esclave).find(no) // == tesN_encontact(num_mail_noe_esclave).end() ) // { cout << "\n*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave " // << n_noee << " du maillage " << num_mail_noe_esclave // << " la suite n'est pas possible " // << " LesContacts::Nouveau(.. \n"; // tempsContact.Arret_du_comptage(); // fin cpu // Sortie(1); // }; // #endif std::map::iterator > >& tesN_encontact_ii = tesN_encontact(num_mail_noe_esclave); // on regarde si la liste existe, si oui on peut tester les membres sinon, on ne fait rien // car autrement on crée automatiquement une liste avec un élément vide std::map::iterator > >::iterator it_liste; if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end()) {//LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; // LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); cout << "\n --> noeud actuellement en contact "; nb_noe_en_contact++; if (tesN_collant(num_mail_noe_esclave)(j)(inesc)) cout << " collant "; } else {cout << "\n --> noeud actuellement pas en contact ";}; cout << flush; }; }; }; #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << " ->> bilan : " << nb_noe_en_contact << " noeud(s) actuellement en contact: "; }; if (niveau_commentaire_lescontacts > 4) // on va lister les éléments de contact { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << " >> liste des Elcontact au debut de LesContacts::Nouveau: (fct du niveau de commentaire des elcontact): "; LaLIST::iterator ipp,ippfin=listContact.end(); for (ipp=listContact.begin();ipp != ippfin; ipp++) {(*ipp).Affiche(2);}; cout << " fin liste "; #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << " ->> bilan : " << listContact.size() << " element(s) de contact: "; }; // on met à jour les boites des éléments qui contiennent les frontières // ?? on pourrait peut-être restreindre aux seuls éléments de frontières du cpu i , à voir où est utilisée la méthode ?? Mise_a_jour_boite_encombrement_element_contenant_front(); // on met à jour le déplacement maxi toléré pour la classe ElContact double coef_mult_dep_max = 3.; // comme un noeud peut se déplacer de dep_max et que l'on double dep_max_pratique = coef_mult_dep_max * dep_max; // peut avoir la cible "et" le noeud qui se déplace de dep_max, on doit considérer 2*dep_max // pour être sûr, on considère 3 fois ElContact::Change_dep_max(dep_max_pratique); // --- 1) on va tout d'abord parcourir les éléments inactifs et regarder s'ils sont en contact // si oui on les valide, sinon on les supprimes. Il faut le faire avant de prospecter car // ces éléments inactifs ne vont pas être pris en compte car tesN_encontact(num_mail_noe_esclave)(inesc) = 0 // mais ils pourraient redevenir actifs, dans ce cas on aurait un noeud avec deux contacts // dans le cas //, on considère que les contacts déjà calculés sont a considérer avec le cpu en cours // car les tests d'appartenance on déjà été effectué au moment de la création { // ++ encapsulage LaLIST ::iterator iE ; // on met .end(), car cette borne peut changer au gré des suppression for (iE = listContact.begin(); iE != listContact.end(); iE++) if (!((*iE).Actif()) // on intervient si le contact est déclaré inactif && !((*iE).Collant()) // et si ce n'est pas collant: si collant, on ne change rien ) { LaLIST ::iterator iiE = iE; if ((*iE).Contact()) { // on valide si le contact est ok (*iE).Met_actif(); *(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; }; } else { // sinon on supprime car il n'y a pas de contact iE--; // pointe sur le precedent element 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; *(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; }; listContact_efface_tatdt.push_front(*iiE); // mémorise #ifdef MISE_AU_POINT if (tesN_encontact(num_mail_esclave).find(noe_esclave) == tesN_encontact(num_mail_esclave).end() ) { cout << "\n*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave " << num_noeud << " du maillage " << num_mail_esclave << " la suite n'est pas possible " << " LesContacts::Nouveau(.. \n"; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; #endif LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact(num_mail_esclave)[noe_esclave]; list_tesN.remove(iiE); listContact.erase(iiE); // efface l'element }; }; }; // ++ fin encapsulage // --fin 1) // 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 retour = false; // init du retour LaLIST_io ::iterator iM,iMfin; LaLIST ::iterator icont_inter; // sert pour la recherche de doublon list ::iterator inumtesN; // " " " // tout d'abord on met à jour les boites d'encombrement des éléments frontière for (int jjf=1;jjf<=nbmailMaitre;jjf++) for (int j=1;j<= nb_zone;j++) { iMfin=(t_listFront(jjf)(j)).end(); for (iM = (t_listFront(jjf)(j)).begin() ; iM != iMfin; iM++) (*iM).Boite_encombrement_frontiere(TEMPS_tdt,dep_max); }; // parcours des noeuds esclaves for (int intot = 1;intot<= nb_mail_Esclave;intot++) // boucle sur les maillages esclaves {for (int j_zone=1;j_zone<= nb_zone;j_zone++) {const Tableau & tesc= tesctotal(intot)(j_zone); // pout simplifier la notation const Tableau tesN_col = tesN_collant(intot)(j_zone); // pour simplifier int tesc_taille=tesc.Taille(); for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves // si le noeud est collant on ne fait rien {if (!tesN_col(inesc)) {Noeud* no = tesc(inesc); int n_noee = no->Num_noeud(); int num_mail_noe_esclave = no->Num_Mail(); /* / #ifdef MISE_AU_POINT // if (tesN_encontact(num_mail_noe_esclave).find(no) // == tesN_encontact(num_mail_noe_esclave).end() ) // { cout << "\n*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave " // << n_noee << " du maillage " << num_mail_noe_esclave // << " la suite n'est pas possible " // << " LesContacts::Nouveau(.. \n"; // tempsContact.Arret_du_comptage(); // fin cpu // Sortie(1); // }; // #endif */ std::map::iterator > >& tesN_encontact_ii = tesN_encontact(num_mail_noe_esclave); // on regarde si la liste existe, si oui on peut tester les membres sinon, on ne fait rien // car autrement on crée automatiquement une liste avec un élément vide std::map::iterator > >::iterator it_liste; int nb_contact=0; if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end()) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; nb_contact = list_tesN.size(); }; *(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 #else cout << "\n " #endif << " (re) examen eventuel : contact du noeud " << n_noee << " du maillage " << num_mail_noe_esclave; cout << " coord2= "; no->Coord2().Affiche_1(cout); if (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"; }; // on dit si un des contacts est actif int actif = 0; if (nb_contact) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; LaLIST < LaLIST::iterator >::iterator il, ilfin = list_tesN.end(); for (il = list_tesN.begin();il != ilfin; il++) if ( (*(*il)).Actif() ) actif++; if (actif) {cout << "\n noeud actuellement en contact dans " << actif << " element(s) "; if (tesN_collant(num_mail_noe_esclave)(j_zone)(inesc)) cout << " collant "; } else cout << "\n noeud actuellement pas en contact "; int icont = 1; for (il = list_tesN.begin();il != ilfin; il++,icont++) {Front* elfront = (*(*il)).Elfront(); Element * elem = elfront->PtEI(); // l'element qui contiend la frontiere cout << "\n elem_contact: "<Num_frontiere() << " de l'element " << elem->Geometrie() << " : " << elfront->PtEI()->Num_elt() << ", type: " << Nom_type_geom(elfront->Eleme_const()->Type_geom_front()) << " du maillage :" << elfront->PtEI()->Num_maillage(); }; }; // il y a un pb, car un noeud pourrait-être collant pour une zone et non collant pour une autre // 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 int num_frontiere=1; // pour le debug for (int jlf=1;jlf<=nbmailMaitre;jlf++) // boucle sur les maillages maîtres {LaLIST_io & t_listFront_jlf_j = t_listFront(jlf)(j_zone); iMfin= t_listFront_jlf_j.end(); for (iM = t_listFront_jlf_j.begin() ; iM != iMfin; iM++,num_frontiere++) // boucle sur les front maitres // on parcours les elements maitres de la zone // si le noeud esclave est déjà en contact avec la frontière ce n'est pas la peine de tester {// donc on passe en revue les éléments en contact // si calcul // et élément déjà en contact c'est aussi vrai bool a_considerer = true; // init par défaut if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end()) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); for (pl = list_tesN.begin();pl != plfin;pl++) {ElContact& elc = (*(*pl)); Front& elfront = (*iM); Front* eltest = elc.Elfront(); if (eltest->MemeOrigine(elfront) ) {a_considerer=false; if (elc.Permet_affichage() > 6) {cout << "\n noeud esclave deja en contact "; elc.Affiche(1); }; break;} }; }; #ifdef UTILISATION_MPI // dans le cas // on ne continue que si la frontière est relative à un élément associé au cpu {Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere // on ne continue que si l'élément est concerné if (!(ParaGlob::param->Element_concerner(elem.Num_maillage(),elem.Num_elt_const()) )) a_considerer=false; }; #endif // donc on ne continue que si la face n'est pas déjà en contact avec le noeud // et dans le cas // que c'est ok if (a_considerer) {// on regarde si le noeud esclave est dans la boite d'encombrement de l'élément // qui contient l'élément frontière (car l'élément frontière à une épaisseur nulle!) Element & elem = *((*iM).PtEI()); // l'element qui contiend la frontiere Front& elfront = (*iM); *(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 #else cout << "\n" #endif << " rappel: coordonnee noeud esclave : " ; no->Coord2().Affiche_1(cout); cout << "\n boite d'encombrement de l'element maitre qui contient la frontiere:\n mini -> "; elem.RecupBoite_encombre_element().Premier().Affiche(); cout << " maxi -> "; elem.RecupBoite_encombre_element().Second().Affiche(); }; // dans le cas où l'élément et le noeud appartienne au même maillage, on est // dans le cas d'un auto-contact. Dans ce cas on ne considère que les éléments // qui ne contiennent pas le noeud esclave if (elem.Num_maillage() == num_mail_noe_esclave) { List_io < Element* > indice_m = (*indice(num_mail_noe_esclave))(n_noee); // pour simplifier if (find(indice_m.begin(),indice_m.end(),&elem) != indice_m.end()) break; // on arrête la boucle si on trouve l'élément parmi ceux contenant le noeud }; if (Permet_affichage(&li_pour_noeuds_element) > 6) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n " #endif << " frontiere: " << elfront.Num_frontiere() << " (nb loc: "<Type_geom_front()) << " de l'element " << elem.Geometrie() << " : " << elfront.PtEI()->Num_elt() << " du maillage :" << elfront.PtEI()->Num_maillage() ; }; if (elem.In_boite_emcombrement_elem(pt_esc,dep_max_pratique)) // on teste alors plus précisemment // on regarde si cela pourrait conduire à un élément de contact identique // à un élément que l'on vient juste d'effacer, si oui, on ne crée pas d'élément et // on attend un prochain incrément, si effectivement l'élément doit se créer, il sera alors créé // *** non, ça pose pb, on commente pour l'instant {//LaLIST ::iterator ila,ilafin=listContact_efface_tatdt.end(); bool vraiment_nouveau_element=true; // par défaut /* // for (ila = listContact_efface_tatdt.begin();ila != ilafin;ila++) // { if (((*ila).Esclave()->Num_noeud() == n_noee) // && ((*((*ila).Elfront()->Eleme())) == (*((*iM).Eleme()))) // && ((*ila).Esclave()->Num_Mail() == num_mail_noe_esclave)) // { vraiment_nouveau_element = false; // if ((*ila).Permet_affichage() > 5) // {cout << "\n element de contact venant juste d'etre supprime, on arrete la creation "; // (*ila).Affiche(1); // }; // break;}; // }; */ *(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 ::iterator ila,ilafin=listContact_efface_tatdt.end(); for (ila = listContact_efface_tatdt.begin();ila != ilafin;ila++) { cout << "\n " << n_noee << " " << (*ila).Esclave()->Num_noeud() << " " ; (*ila).Elfront()->Affiche(); (*iM).Affiche(); cout << "\n ((*ila).Esclave()->Num_noeud() == noee->Num_noeud()) " << ((*ila).Esclave()->Num_noeud() == n_noee); cout << "\n ((*((*ila).Elfront()->Eleme())) == (*((*iM)->Eleme()))) " << ((*((*ila).Elfront()->Eleme())) == (*((*iM).Eleme()))); cout << "\n ((*ila).Esclave()->Num_Mail() == noee->Num_Mail()) " << ((*ila).Esclave()->Num_Mail() == n_noee); cout << "\n vraiment_nouveau_element= " << vraiment_nouveau_element << endl; }; }; // on ne continue que si c'est un vrai nouvel élément if (vraiment_nouveau_element) { // on passe en revue les frontières de contact déjà existantes associées // et s'il y a déjà un élément qui correspond, on arête la création bool creation = true; // init if (nb_contact) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[no]; LaLIST < LaLIST::iterator >::iterator il, ilfin = list_tesN.end(); for (il = list_tesN.begin();il != ilfin; il++) { ElContact& con = (*(*il)); if (con.Elfront()->MemeOrigine(elfront)) {creation = false; if (con.Permet_affichage() > 5) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n " #endif << " frontiere en contact deja existante , on arrete la creation "; elfront.Affiche(1); }; } }; }; // on ne continue que s'il n'existe pas d'élément de contact du même type if (creation) { 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) || (elcont.Permet_affichage() > 5)) { Front* elfront = elcont.Elfront(); #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n " #endif << " test nouveau contact: examen plus precis: frontiere: " << elfront->Num_frontiere() << ", type: " << Nom_type_geom(elfront->Eleme_const()->Type_geom_front()) << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage " << elfront->PtEI()->Num_maillage() ; *(gr_pour_elem->ConteneurEntier()) = elfront->PtEI()->Num_elt(); if (Permet_affichage(&li_pour_noeuds_element) > 7) elcont.Affiche(); }; // calcul du contact, et translation éventuelle du noeud sur la surface // si le contact existe, ceci en fonction de la méthode de contact bool ret = elcont.Contact(); if (elcont.Permet_affichage() > 5) {cout << "\n retour de Contact: ret= " << ret; } if (ret) {//sauvegarde éventuelle de l'element contact ElContact* test_existance= Element_contact_deja_present(elcont); if (test_existance == NULL) { listContact.push_front(elcont); //numtesN.push_front(TroisEntiers(num_mail_noe_esclave,j,n_noee)); tesN_encontact_ii[no].push_front(listContact.begin()); listContact_nouveau_tatdt.push_front(listContact.begin()); // à ce stade le nouveau contact est actif retour=true; // on valide le retour if ((niveau_commentaire_lescontacts > 3) || (elcont.Permet_affichage() > 3)) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n " #endif << " newcontact: " ; if (tesN_col(inesc)) cout << " collant "; elcont.Affiche(1); }; } else if (!test_existance->Actif()) // s'il existe et est inactif on le rend actif (pour remplacer celui qui devrait être créé) {test_existance->Met_actif(); if ((niveau_commentaire_lescontacts > 5) || (elcont.Permet_affichage() > 5)) {cout << " remis en actif: "; elcont.Affiche(2); }; } else { if ((niveau_commentaire_lescontacts > 5) || (elcont.Permet_affichage() > 5)) cout << " --> contact deja enregistre " ; } ; } else { if ((niveau_commentaire_lescontacts > 5) || (elcont.Permet_affichage() > 5)) cout << " --> pas de contact " ; } ; // listContact.push_back(elcont);numtesN.push_back(DeuxEntiers(intot,inesc)); // if (niveau_commentaire_lescontacts >= 6) // { Enum_type_geom type_front; Element & elem = *elcont.Elfront()->PtEI(); // int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); // cout << "\nnewcontact 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 " // << num_mail_elem << flush; // } // retour = true; // break; // on arrête la boucle sur les fronts car on a trouvé un contact }; // fin du test if creation // sinon il n'y a pas de contact } // -- fin du test sur examen if (vraiment_nouveau_element) }; //-- fin du test sur la boite_encombrement }; // -- fin du test : if (a_considerer) }; // -- boucle sur iM }; // -- boucle sur jlf }; // -- fin du test tesN_encontact(intot)(inesc) } //-- fin du test non collant: if (!tesN_col(inesc)) };// -- boucle sur inesc }// -- fin de la boucle sur les zones for (int j=1;j<= nb_zone;j++) };// -- boucle sur intot #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 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) "; if (listContact_efface_tatdt.size()) cout <<", "< 4) // on va lister les éléments de contact { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << " liste des Elcontact a la fin de LesContacts::Nouveau: (fct du niveau de commentaire des elcontact): "; LaLIST::iterator ipp,ippfin=listContact.end(); for (ipp=listContact.begin();ipp != ippfin; ipp++) {(*ipp).Affiche(2);}; cout << " fin liste "; }; if (niveau_commentaire_lescontacts > 3) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n " #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 <<", "<::iterator iE ; 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 ) {(*iE).Met_actif(); // on valide l'activation } else if (!((*iE).Actif()) // on intervient si le contact est déclaré inactif && !((*iE).Collant()) // et si ce n'est pas collant: si collant, on ne change rien ) { LaLIST ::iterator iiE = iE; // list ::iterator iiden = iden; int num_mail_esclave = (*iiE).Esclave()->Num_Mail(); int num_noeud = (*iiE).Esclave()->Num_noeud(); if (niveau_commentaire_lescontacts > 3) { Element & elem = *(*iiE).Elfront()->PtEI(); int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail(); cout << "\neffacement contact:";(*iiE).Affiche(1); }; iE--; // pointe sur le precedent element listContact_efface_tatdt.push_front(*iiE); #ifdef MISE_AU_POINT if (tesN_encontact(num_mail_esclave).find((*iiE).Esclave()) == tesN_encontact(num_mail_esclave).end() ) { cout << "\n*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave " << (*iiE).Esclave()->Num_noeud() << " du maillage " << num_mail_esclave << " la suite n'est pas possible " << " LesContacts::SuppressionDefinitiveElemInactif(.. \n"; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; #endif LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact(num_mail_esclave)[(*iiE).Esclave()]; ////--- debug //{cout << "\n debug LesContacts::SuppressionDefinitiveElemInactif: "; // (*iiE).Affiche(1); // } // //--- fin debug list_tesN.remove(iiE); // tesN_encontact(num_mail_esclave)(num_noeud).remove(iiE); // mise à jour de l'indicateur listContact.erase(iiE); // efface l'element ////--- debug //{cout << "\n liste restante des elements de contact "; // LaLIST ::iterator iE ; // for (iE = listContact.begin(); iE != listContact.end(); iE++) // {cout << "\n";(*iE).Affiche(1);} //} ////--- fin debug nb_effacement++; change = true; // iden--; // numtesN.erase(iiden); } //**** j'ai l'impression que la ligne qui suit ne sert à rien, car le if précédent était uniquement pour les inactifs, donc si on va à la ligne qui suit // 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 "; }; }; 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 }; }; // 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 return change; }; // relachement des noeuds collés // ramène true s'il y a des noeuds qui ont été relachés bool LesContacts::RelachementNoeudcolle() { tempsContact.Mise_en_route_du_comptage(); // def deb compt int niveau_commentaire_lescontacts = Permet_affichage(); 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 #else cout << "\n" #endif << " -- LesContacts::RelachementNoeudcolle(): "; // return change; //------- pour le débug LaLIST ::iterator iE ; // list ::iterator iden = numtesN.begin(); // on met .end(), car cette borne peut changer au gré des suppression for (iE = listContact.begin(); iE != listContact.end(); iE++)//,iden++) // on ne test que les éléments actifs, pour lesquels les calculs sont à jour if ( ((*iE).Actif()) // on intervient si le contact est déclaré actif && !((*iE).Collant()) // et si ce n'est pas collant: si collant, on ne fait rien ) if ((*iE).Decol()) // le décolement est testé soit sur la réaction, qui a été calculée // au pas précédent, ou soit sur une position géométrique en dehors d'une zone d'accostage. //S'il y a décolement on ne doit plus tenir compte du contact et donc on inactive l'élément de contact { LaLIST ::iterator iiE = iE; // list ::iterator iiden = iden; if (niveau_commentaire_lescontacts > 2) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << "inactivation (relachement) pour cause de decollement du contact"; (*iiE).Affiche(1); cout << endl; ////------ debug //{cout << "\n debug: LesContacts::RelachementNoeudcolle() "; // (*iE).Decol(); //} //// ------- fin debug }; change = true; (*iE).Met_Inactif(); }; 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; }; // definition des conditions lineaires de contact // casAssemb : donne le cas d'assemblage a prendre en compte // et marquage des ddl imposé par le contact // Dans le cas d'un calcul parallèle, il y a transfert des conditions au cpu 0 // seules les cpu i calculent les conditions linéaires // NB: on ne met pas la liste en const car on a besoin de pouvoir modifier les infos à l'intérieur // des CL pour les utiliser, mais l'idée est la liste elle, reste constante list & LesContacts::ConditionLin(const Nb_assemb& casAssemb) { tempsContact.Mise_en_route_du_comptage(); // def deb compt #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); if (proc_en_cours != 0) { #endif // on crée des conditions linéaires dans le cas du type 1: contact cinématique // mais aussi dans les autres cas pour l'optimisation de largeur de bande par exemple {Calcul_Nb_contact_actif(); listCoLin.clear();// Change_taille(nb_contact_actif); //cout << "\n nb actif pour condlin = " << nb_contact_actif; // on boucle sur les elements de contact LaLIST ::iterator iE,iEfin=listContact.end() ; for (iE = listContact.begin(); iE != iEfin; iE++) if ((*iE).Actif()) // on n'intervient que si le contact est actif // appel de la fonction de construction de condition lineaire dans l'element de contact {listCoLin.push_front((*iE).ConditionLi(casAssemb.n)); }; tempsContact.Arret_du_comptage(); // fin cpu } #ifdef UTILISATION_MPI temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va les transmettres au cpu 0 // pour cela on va utiliser un conteneur intermédiaire // on calcul la taille nécessaire pour le conteneur (a découper éventuellement ??) int taille_conteneur=0; list ::iterator il,ilfin = listCoLin.end(); for (il = listCoLin.begin();il != ilfin;il++) taille_conteneur += (*il).Taille_Pack(); inter_transfer.Change_taille(taille_conteneur); // le conteneur // on rempli le conteneur int rang = 1; // init for (il = listCoLin.begin();il != ilfin;il++) rang = (*il).Pack_vecteur(inter_transfer,rang); temps_attente.Arret_du_comptage(); // on transfert mpi::request reqs1 = ParaGlob::Monde()->isend(0, 40, taille_conteneur); mpi::request reqs2 = inter_transfer.Ienvoi_MPI(0,41); // on attend pas temps_transfert_long.Arret_du_comptage(); // fin comptage cpu } else // cas du cpu 0 {// l'objectif ici est de récupérer les conditions linéaires tempsContact.Arret_du_comptage(); // fin cpu temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu int nb_proc_terminer = 0; // permettra de terminer listCoLin.clear();// Change_taille(nb_contact_actif); while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront { // on récupère un résultat de cpu i int taille_transfert; mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 40, taille_transfert); mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli inter_transfer.Change_taille(taille_transfert); // le conteneur int source = stat.source(); // récupération du numéro de la source // on récupère mpi::request reqs2 = inter_transfer.Irecup_MPI(source, 41); reqs2.wait(); // on attend que le conteneur soit rempli nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur // on va remplir la liste des conditions limites int rang = 1; // init while (rang != 0) { Condilineaire condi; // une condition intermédiaire rang = condi.UnPack_vecteur(*lesMaille,inter_transfer,rang, &LesMaillages::Noeud_LesMaille); listCoLin.push_back(condi); }; }; temps_transfert_long.Arret_du_comptage(); }; #endif // tempsContact.Arret_du_comptage(); // fin cpu // retour du tableau return listCoLin; }; // effacement du marquage de ddl bloque du au conditions lineaire de contact void LesContacts::EffMarque() { tempsContact.Mise_en_route_du_comptage(); // def deb compt // on parcours la liste des conditions lineaires list ::iterator il,ilfin = listCoLin.end(); for (il = listCoLin.begin();il != ilfin;il++) { // on libere la condition Condilineaire& C = (*il); C.Noe()->Change_fixe(C.Tab_Enum()(1),false); }; tempsContact.Arret_du_comptage(); // fin cpu }; // indique si les surfaces des maillages maîtres ont des déplacements fixés // c-a-d sont de type solide imposé // retourne true si les déplacements des maîtres sont imposés bool LesContacts::Maitres_avec_deplacement_imposer() const { bool retour = true; // init par défaut int dim = ParaGlob::Dimension(); int nb_zone = MaX(1,nom_ref_zone_contact.size()); // seule sont disponibles les zones de contact (restreintes éventuellement) // on passe en revue tous les noeuds des frontières for (int i=1; i<= nbmailMaitre;i++) for (int j=1;j<= nb_zone;j++) {LaLIST_io ::const_iterator il,ilfin = t_listFront(i)(j).end(); for (il = t_listFront(i)(j).begin(); il != ilfin; il++) {const Tableau & tn = (*il).Eleme_const()->TabNoeud_const(); int nb_noe = tn.Taille(); for (int n = 1;n<= nb_noe;n++) { const Noeud& noe = *tn(n); // pour simplifier switch(dim) {case 3: if (!(noe.Ddl_fixe(X3))) {retour=false; break;}; case 2: if (!(noe.Ddl_fixe(X2))) {retour=false; break;}; case 1: if (!(noe.Ddl_fixe(X1))) {retour=false; break;}; }; if (!retour) break; }; if (!retour) break; }; if (!retour) break; }; // retour return retour; }; // def de la largeur de bande des elements contacts // casAssemb : donne le cas d'assemblage a prendre en compte // les condi linéaires ne donnent pas des largeurs de bande sup et inf égales !!! // demi = la demi largeur de bande maxi , // total = le maxi = la largeur sup + la largeur inf +1 // cumule = la somme des maxis, ce qui donnera la largeur finale, due à des multiples multiplications: une par conditions linéaires // ceci dans le cas de la prise en compte par rotation (et uniquement dans ce cas) // = true : si la largeur de bande en noeud est supérieure à 1 (cas d'un contact avec une surface déformable) // = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur // en noeud (cas d'un contact avec une surface rigide) // dans le cas d'un calcul // seule le cpu 0 effectue la résolution, par contre tous les cpu i contribuent // ils vont donc transmettre les informations au cpu 0 bool LesContacts::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb,int& cumule) { tempsContact.Mise_en_route_du_comptage(); // def deb compt bool retour = false; // par défaut on se met dans le cas le plus simple : contact avec surface rigide // dans le cas d'un contact avec surface déformable, le contact modifie la largeur de bande demi = 0; total = 0; // c'est le plus important, car la bande sup réelle est en général différente // de la bande inf, mais ce qui sera utilisé pour le dimensionnement de la bande de la matrice // c'est le total: inf + sup + 1 (le 1 est pour la diagonale, il ne sert à rien) cumule = 0; #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); if (proc_en_cours != 0) { #endif // encapsulage de la partie hors calcul parallèle { LaLIST ::iterator iE,iEfin=listContact.end(); int nb_Assemb = casAssemb.n; // récup du numéro d'assemblage //------ debug // cout << "\n LesContacts::Largeur_Bande "; // ------ fin debug // on boucle sur les elements de contact for ( iE = listContact.begin(); iE !=iEfin; iE++) { //------ debug // (*iE).Affiche(); // ------ fin debug // on n'intervient que si le contact est actif et que ce n'est pas un contact solide déformable if (((*iE).Actif()) && ((*iE).Cas_solide() == 0)) { //on boucle sur les noeuds de l'element de contact const Tableau & tabnoeud = (*iE).TabNoeud(); int maxiPourLeContact=0; // stocke le maxi pour chaque condition linéaire retour = true; // ici la largeur de bande en noeud est augmenté, car le noeud en contact // est en relation avec des noeuds d'une surface déformable for (int noe=1; noe<= tabnoeud.Taille();noe++) for ( int no=noe+1; no<=tabnoeud.Taille();no++) { Noeud & nne = *tabnoeud(noe); Noeud & nno = *tabnoeud(no); int di; if (nne.PosiAssemb(nb_Assemb) >= nno.PosiAssemb(nb_Assemb)) di = nne.PosiAssemb(nb_Assemb) - nno.PosiAssemb(nb_Assemb) + nne.NB_ddl_actif_casAssemb(nb_Assemb); else di = nno.PosiAssemb(nb_Assemb) - nne.PosiAssemb(nb_Assemb) + nno.NB_ddl_actif_casAssemb(nb_Assemb); if ( di > demi) demi = di; if ( di > maxiPourLeContact) maxiPourLeContact = di; if ( 2*di > total) total = 2*di; }; cumule += maxiPourLeContact; }; }; total += 1; demi += 1; tempsContact.Arret_du_comptage(); // fin cpu } #ifdef UTILISATION_MPI temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va transmettre au cpu 0 // pour cela on va utiliser un conteneur intermédiaire QuatreEntiers inter_entiers(demi,total,cumule,retour); // on transmet les infos au proc 0 mpi::request reqs1 = ParaGlob::Monde()->isend(0, 44, inter_entiers); // on attend pas temps_transfert_court.Arret_du_comptage(); // fin comptage cpu } else // cas du cpu 0 {// l'objectif ici est de récupérer les infos tempsContact.Arret_du_comptage(); // fin cpu int nb_proc_terminer = 0; // permettra de terminer while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront { // on récupère un résultat de cpu i temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu QuatreEntiers inter_entiers; mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 44, inter_entiers); reqs1.wait(); // on attend que le conteneur soit rempli temps_transfert_court.Arret_du_comptage(); // fin comptage cpu tempsContact.Mise_en_route_du_comptage(); // def deb compt if (inter_entiers.un > demi) demi = inter_entiers.un; if (inter_entiers.deux > total) total = inter_entiers.deux; cumule += inter_entiers.trois; retour = (retour || ((bool)inter_entiers.quatre)); nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur tempsContact.Arret_du_comptage(); }; }; // 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 return retour; }; // actualisation du contact, on examine que les elements de contact, dont on // actualise la projection du noeud esclave en fonction de la position de l'element // maitre frontiere (mais la position finale du noeud n'est pas forcément changée, cela dépend du // modèle de contact (cinématique, pénalisation etc.) // ramène true si quelque chose à changé, false sinon // choix == 1 : les éléments actifs sont maintenu en contact même si l'intersection est hors frontière // si l'intersection n'est pas calculable, l'élément de contact est laissè inchangé // choix == 0 : les éléments actifs sont inactivés si l'intersection est hors frontière ou // si l'intersection n'est pas calculable, // NB: pour les deux choix, s'il y a doublon d'élément de contact, due à un changement de frontière // en cours d'actualisation, on inactive le(s) doublon(s) // dans le cas d'un calcul // chaque proc i effectue son actualisation, s'il y a changement de surface avec sortie // de la surface gérée par le proc i, cela sera vérifié au niveau de l'élément de contact // Le proc 0 se contente de récupérer et globaliser les retours des proc i bool LesContacts::Actualisation(int choix) { tempsContact.Mise_en_route_du_comptage(); // def deb compt bool retour = false; // init par défaut #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); if (proc_en_cours != 0) { #endif { // on boucle sur les elements de contact int i; LaLIST ::iterator iE,iEfin=listContact.end(); int niveau_commentaire_lescontacts = Permet_affichage(); if (niveau_commentaire_lescontacts > 4) #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours << ": -- LesContacts::Actualisation: choix: "<< choix; #else cout << "\n -- LesContacts::Actualisation: choix: "<< choix; #endif if (niveau_commentaire_lescontacts > 4) // on va lister les éléments de contact { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours << ": liste des Elcontact avant actualisation (fct du niveau de commentaire des elcontact): "; #else cout << "\n liste des Elcontact avant actualisation (fct du niveau de commentaire des elcontact): "; #endif LaLIST::iterator ipp,ippfin=listContact.end(); for (ipp=listContact.begin();ipp != ippfin; ipp++) {(*ipp).Affiche(2);}; cout << " fin liste "; }; for (i=1, iE = listContact.begin(); iE !=iEfin; iE++,i++)//,iden++) // appel de la fonction d'actualisation de chaque element de contact if ((*iE).Actif()) // on intervient si le contact est déclaré actif // on intervient également si c'est collant, car il faut quand même actualiser // le contact, { int test=0; // init { /* // Si le retour est négatif et que l'élément est actif, cela signifie que l'on ne peut pas calculer le contact // là on on se contente d'inactiver l'élément // si le retour == 0: on peut calculer mais on sort de l'élément et même des mitoyens // là aussi on se contente d'inactiver l'élément // durant l'actualisation, on peut changer d'élément frontière, du coup l'élément de contact résultant // peut être égale à un élément déjà existant, et cela va faire double emploi // dans ce cas précis on ne va pas valider l'actualisation, mais on se contente d'inactiver l'élément // actualisation de la projection du noeud esclave en fonction de la position de l'element // maitre frontiere. Lorsque le noeud change d'element fontiere, on change l'element // frontiere de l'element de contact en consequence // retourne: // 0 : dans le cas ou on ne trouve pas d'intersection, cas d'une intersection qui n'est pas calculable // 1 : contact ok, sur l'élément // -1 : contact ok, mais hors de l'élément (là, on a parcouru tous les mitoyens et aucun ne convient // du coup on utilise l'élément initial pour la projection // 2 : changement de frontière, et contact ok sur la nouvelle frontière // NB: sauf pour le cas 0, dans tous les autres cas, les grandeurs locales sont correctement calculées // c-a-d : la projection, la normale // en fonction de la méthode de contact, le noeud est ramené éventuellement sur la frontière */ test = (*iE).Actualisation(); ElContact* test_existance=NULL; if (test == 2) {// on a changé de frontière, on regarde si l'élément de contact avec la nouvelle frontière n'est pas //identique à un élément existant test_existance= Element_contact_deja_present(iE); }; if ( ((test < 0) && (choix == 0) && !((*iE).Collant())) // si c'est collant, on maintient le contact arbitrairement sauf si on // est arrivé sur un élément existant || (test == 0) // ou que l'on ne peut pas calculer une intersection ... ce qui fait que le // calcul des second membre et raideur ne sera pas possible ) // on inactive l'element de contact { LaLIST ::iterator iiE = iE; if (niveau_commentaire_lescontacts >= 3) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours<<": " #else cout << "\n" #endif << " inactivation contact (les_contacts) pour cause de perte de contact:"; #ifdef MISE_AU_POINT if (niveau_commentaire_lescontacts > 4) cout << " test= "<Actif()) { LaLIST ::iterator iiE = iE; if (niveau_commentaire_lescontacts >= 3) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours<<": " #else cout << "\n" #endif << "inactivation contact apres chgt de frontiere (les_contacts) pour cause de duplication:"; (*iiE).Affiche(1); }; (*iiE).Met_Inactif(); // inactive l'élément retour = true; // on signale le changement }; } else // arrivée ici cela veut dire que test > 0 ou que c'est collant et test n'est pas négatif // ou alors que test < 0 mais on a choix == 1, c-a-d que l'on veut maintenir le contact même en dehors de l'élément actuel // (c'est par exemple une situation transitoire pendant les itérations en implicite) { if (niveau_commentaire_lescontacts >= 7) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours<<": " #else cout << "\n" #endif << " contact maintenu: ";(*iE).Affiche(1); }; }; // si on a inactivé l'élément, on regarde s'il n'y a pas un autre contact, utilisant le même noeud // que l'on pourrait activer if (!(*iE).Actif()) {Noeud* noe = (*iE).Esclave(); int num_mail_noe_esclave = noe->Num_Mail(); std::map::iterator > >& tesN_encontact_ii = tesN_encontact(num_mail_noe_esclave); // pour simplifier // la liste doit exister ! car au moins (*iE) y appartient // Tableau < std::map::iterator > > > tesN_encontact; // tesN_encontact(numMail_esclave)[*pt_noeud] -> la liste des iterators d'élément en contact // avec le noeud // on regarde si la liste existe, si oui on peut tester les membres sinon, on ne fait rien // car autrement on crée automatiquement une liste avec un élément vide std::map::iterator > >::iterator it_liste; if (tesN_encontact_ii.find(noe) != tesN_encontact_ii.end()) {LaLIST < LaLIST::iterator > & list_tesN = tesN_encontact_ii[noe]; LaLIST < LaLIST::iterator >::iterator pl,plfin=list_tesN.end(); for (pl = list_tesN.begin();pl != plfin;pl++) if ((*pl) != iE) // on évite celui qu'on vient d'inactiver !! {ElContact& elc = (*(*pl)); // on ne continue que si l'élément est inactif, sinon il est étudié dans la boucle globale if (!(elc.Actif())) {// là on va faire une actualisation simplifiée: le cas collant n'est pas à prendre en compte // car on n'arrive jamais ici en collant elc.Met_actif(); // on doit activer l'élément pour utiliser Actualisation // cela veut dire que systématiquement on calcule comme si le noeud esclave se déplace en contact // (ce n'est pas une initialisation ) test = elc.Actualisation(); test_existance = NULL ; // init if (test == 2) {// on a changé de frontière, on regarde si l'élément de contact avec la nouvelle frontière n'est pas //identique à un élément existant test_existance= Element_contact_deja_present(iE); }; if ((test_existance == NULL) && (test > 0)) // arrivée ici cela veut dire que le contact est valide // on conserve l'élément actif { if (niveau_commentaire_lescontacts > 2) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours<<": " #else cout << "\n" #endif << "reactivation contact :";elc.Affiche(1); }; } else // sinon on inactive l'élément pour le ramener à l'état initial {elc.Met_Inactif(); if (elc.Permet_affichage() > 2) cout << " ===>> inactivation car element doublon "; }; }; }; }; } }; } // else // {nb_contact_actif++; }; // on sauvegarde l'activité if (niveau_commentaire_lescontacts > 4) // on va lister les éléments de contact { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours<<": " #else cout << "\n" #endif << " liste des Elcontact apres actualisation (fct du niveau de commentaire des elcontact): "; LaLIST::iterator ipp,ippfin=listContact.end(); for (ipp=listContact.begin();ipp != ippfin; ipp++) {(*ipp).Affiche(2);}; cout << " fin liste "; // on calcule et affiche le nombre de contact actif Calcul_Nb_contact_actif(); #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours<<": " #else cout << "\n" #endif << " nb_contact_actif= " << nb_contact_actif << endl; }; } #ifdef UTILISATION_MPI temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va transmettre au cpu 0 mpi::request reqs1 = ParaGlob::Monde()->isend(0, 45, retour); // on attend pas temps_transfert_court.Arret_du_comptage(); // fin comptage cpu } else // cas du cpu 0 {// l'objectif ici est de récupérer les infos tempsContact.Arret_du_comptage(); // fin cpu int nb_proc_terminer = 0; // permettra de terminer while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront { // on récupère un résultat de cpu i temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu bool inter_retour; mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 45, inter_retour); reqs1.wait(); // on attend que le conteneur soit rempli temps_transfert_court.Arret_du_comptage(); // fin comptage cpu tempsContact.Mise_en_route_du_comptage(); // def deb compt retour = (retour || (inter_retour)); nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur tempsContact.Arret_du_comptage(); }; }; #endif #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 return retour; }; // ramène une liste de noeuds dont la position a été perturbé par le contact // (dépend du type de contact : ex cas contact = 4) // la liste passée en paramètre est supprimée et remplacée par la liste résultat // dans le cas d'un calcul // chaque proc i calcule une liste et la transmet au proc 0 // Le proc 0 globalise toutes les liste void LesContacts::Liste_noeuds_position_changer(list & li_noe) { tempsContact.Mise_en_route_du_comptage(); // def deb compt // récup du type de contact int contact_type = ElContact::Recup_et_mise_a_jour_type_contact(); li_noe.clear(); // on vide la liste int niveau_commentaire_lescontacts = Permet_affichage(); #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); if (proc_en_cours != 0) { #endif { if (contact_type== 4) // pour l'instant c'est le seul type de contact qui est concerné { // on boucle sur les elements de contact int i; LaLIST ::iterator iE,iEfin=listContact.end(); #ifndef UTILISATION_MPI if (niveau_commentaire_lescontacts >= 7) cout << "\n -- LesContacts::Liste_noeuds_position_changer: "; #endif for (i=1, iE = listContact.begin(); iE !=iEfin; iE++,i++)//,iden++) if ((*iE).Actif()) // on intervient si le contact est déclaré actif {// récup du noeud esclave Noeud* noe = (*iE).Esclave(); li_noe.push_back(noe); }; }; tempsContact.Arret_du_comptage(); // fin cpu } #ifdef UTILISATION_MPI temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va transmettre au cpu 0 int taille_list = li_noe.size(); mpi::request reqs1 = ParaGlob::Monde()->isend(0, 46, taille_list); // on attend pas temps_transfert_court.Arret_du_comptage(); // fin comptage cpu temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu // maintenant on va transmettre au cpu 0 // on va se servir d'un conteneur intermédiaire union double_int { double x; int n[2]; } ; double_int xinter; Vecteur v_inter(taille_list); list ::iterator il,ilfin=li_noe.end(); int i=1; for (il = li_noe.begin();il !=ilfin;il++,i++) {xinter.n[0] = (*il)->Num_Mail(); xinter.n[1] = (*il)->Num_noeud(); v_inter(i)=xinter.x; }; // envoi v_inter.Ienvoi_MPI(0,47); // on attend pas temps_transfert_long.Arret_du_comptage(); // fin comptage cpu } else // cas du cpu 0 {// l'objectif ici est de récupérer les infos union double_int { double x; int n[2]; } ; double_int xinter; int nb_proc_terminer = 0; // permettra de terminer while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront { // on récupère un résultat de cpu i temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu int taille_list ; mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 46, taille_list ); mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli int source = stat.source(); // récupération du numéro de la source temps_transfert_court.Arret_du_comptage(); // fin comptage cpu temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu Vecteur v_inter(taille_list); mpi::request reqs2 = v_inter.Irecup_MPI(source, 47); reqs2.wait(); // on attend que le conteneur soit rempli temps_transfert_long.Arret_du_comptage(); // fin comptage cpu tempsContact.Mise_en_route_du_comptage(); // def deb compt // maintenant on abonde la liste for (int i=1;i<= taille_list;i++) {xinter.x = v_inter(i); li_noe.push_back(&(lesMaille->Noeud_LesMaille(xinter.n[0],xinter.n[1]))); }; nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur tempsContact.Arret_du_comptage(); }; if (niveau_commentaire_lescontacts >= 7) cout << "\n proc 0: -- LesContacts::Liste_noeuds_position_changer: "; }; #endif tempsContact.Arret_du_comptage(); // fin cpu }; // calcul des reactions de contact et stockage des valeurs // solution : le vecteur residu // test d'un decollement eventuelle, pour un noeud en contact // Dans le cas d'un calcul parallèle, tous les cpu calculent, mais seule le cpu 0 // affiche les messages normaux, mais tous les cpu affichent les messages d'erreur éventuels // et les messages pour les niveaux de commentaires > 4 void LesContacts::CalculReaction(Vecteur& residu,bool& decol,const Nb_assemb& casAssemb ,bool affiche) { tempsContact.Mise_en_route_du_comptage(); // def deb compt #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); #endif int niveau_commentaire_lescontacts = Permet_affichage(); #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif if (niveau_commentaire_lescontacts > 4) #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << " -- LesContacts::CalculReaction: \n"; int nb_Assemb = casAssemb.n; // récup du numéro d'assemblage // récup du type de contact int contact_type = ElContact::Recup_et_mise_a_jour_type_contact(); // mise a dimension du tableau de stockage // tabReacCont.Change_taille((int)listContact.size()); // on recalcule le nombre de contact actif car c'est mal géré, je ne sais pas pourquoi et ou Calcul_Nb_contact_actif(); tabReacCont.Change_taille(nb_contact_actif); int itab ; // indice du tableau decol = false; bool axi = false; // cas particulier de l'axi if (ParaGlob::AxiSymetrie()) axi = true; LaLIST ::iterator iE,iEfin = listContact.end(); // on boucle sur les elements de contact for ( itab=1,iE = listContact.begin(); iE != iEfin; iE++) {if ((*iE).Actif()) { Noeud* noe = (*iE).Esclave(); // le noeud esclave int posi = noe->Pointeur_assemblage(X1,nb_Assemb); // position du ddl X1 #ifdef MISE_AU_POINT if ( posi == -1 ) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << "Erreur : ddl X1 " << " inexistant pour le cas de charge " << nb_Assemb << '\n' << " LesContacts::CalculReaction( (1)\n"; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; #endif int dim = noe->Dimension(); // dimension // dans le cas où on est en axi-symétrie, le vecteur réaction est en 2D car le calcul au niveau de l'équilibre // global n'est fait qu'en x et y // donc on ne peut récupérer que du x et du y int nb_ddl_en_var = dim; // init if (axi) nb_ddl_en_var -= 1; Coordonnee force(dim); // on dimensionne à dim au cas où for (int i=1;i<=nb_ddl_en_var;i++) // je crois qu'il faut un - pour la force (??) 20 avril 2018 force(i) = -residu(posi+i-1); // si le type de contact est de type 1 -> c'est la réaction if ((contact_type==1)||(contact_type==3)) (*iE).Change_force(force); // mise à jour de la force dans l'élément de contact if (niveau_commentaire_lescontacts > 5) {if ((contact_type==1)||(contact_type==3)) {cout << "\n LesContacts::CalculReaction >> Details: residu totale = contact + CL + F_int (noeud:" << noe->Num_noeud() << " maillage:"<< noe->Num_Mail() << ")\nR=" << force << " gapTDT= " << (*iE).Gaptdt() << "\n dont F_contact= "<< (*iE).Force_contact() ; cout << "\n noeud: coor_tdt: "<Coord2() <<"\n delta: "<<(noe->Coord2()-noe->Coord1()); } else if ((contact_type == 2) || (contact_type == 4)|| (contact_type == 41)|| (contact_type == 42)) {cout << "\n LesContacts::CalculReaction >> Details: F_contact (noeud:" << noe->Num_noeud() // 19 juin 2018 << " maillage:"<< noe->Num_Mail() << ")\nF=" << force << " gapTDT= " << (*iE).Gaptdt() ; << " maillage:"<< noe->Num_Mail() << ")\nForce= " << (*iE).Force_contact() << " gapTDT= " << (*iE).Gaptdt() ; cout << "\n noeud: coor_tdt: "<Coord2() <<"\n delta: "<<(noe->Coord2()-noe->Coord1()); if (niveau_commentaire_lescontacts > 7) (*iE).Affiche(); } else {cout << "\n *** erreur, cas de type de contact= " << contact_type << " pas encore pris en compte " ; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; }; // on regarde si le noeud decolle if ((*iE).Decol()) decol = true; // puis les noeuds de l'element maitre //!!!!! il faudra prevoir un cas ou on ne sauvegarde pas les maitres Tableau & tabNoeud = (*iE).Elfront()->Eleme()->TabNoeud(); // le tableau // on cree un tableau de sauvegarde des forces int tail = tabNoeud.Taille(); // Dans le cas du type 1 de contact, c'est le retour du résidu qui permet de construire des // réaction, alors que dans le cas du type 2 c'est au contraire dans l'élément de contact // que les grandeurs ont déjà été calculées if ((contact_type==1)||(contact_type==3)) {Coordonnee ex(dim); // une position à la bonne dimmension Tableau tabForce(tail,ex); // dimmensionnement du tableau avec alocation for (int it=1;it<= tail;it++) { posi = tabNoeud(it)->Pointeur_assemblage(X1,nb_Assemb) ; // position du ddl X1 #ifdef MISE_AU_POINT if ( posi == -1 ) { #ifdef UTILISATION_MPI cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << "Erreur : ddl X1 " << " inexistant pour le cas de charge " << nb_Assemb << '\n' << " LesContacts::CalculReaction( (2)\n"; tempsContact.Arret_du_comptage(); // fin cpu Sortie(1); }; #endif for (int i=1;i<=nb_ddl_en_var;i++) tabForce(it)(i) = residu(posi+i-1); // la reaction }; tabReacCont(itab) = ReactCont(noe,force,tabNoeud,tabForce); } else {tabReacCont(itab) = ReactCont(noe,(*iE).Force_contact(),tabNoeud,(*iE).TabForce_cont()); }; itab++; }; }; // affichage éventuelle de la force maxi de contact Forces_contact_maxi(affiche); // idem pour les gap N et T Gap_contact_maxi(affiche); tempsContact.Arret_du_comptage(); // fin cpu }; // affichage des reactions de contact sur la sortie // il s'agit ici d'une sortie sur fichier : seule le cpu 0 l'effectue void LesContacts::Affiche(ofstream& sort) const { #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); if (proc_en_cours == 0) #endif // on balaie le tableau de reaction for (int i= 1; i<= tabReacCont.Taille();i++) { ReactCont & R = tabReacCont(i); sort << "\n================= noeud esclave =================="; sort << "\nmaillage " << (R.noe)->Num_Mail() <<", noeud " << (R.noe)->Num_noeud() << ", force = " << R.force ; sort << "\n---------------- noeuds de la frontiere maitre -------------"; int tail = R.tabNoeud.Taille(); for (int it=1;it<= tail;it++) { Noeud & no = *(R.tabNoeud(it)); Coordonnee& coor = R.tabForce(it); sort << "\nmaillage " << no.Num_Mail() <<", noeud " << no.Num_noeud() << ", force = " << coor << ", de norme =" << coor.Vect().Norme() ; }; }; }; // affichage à l'écran des informations liées au contact // cas d'un calcul parallèle, on considère qu'il s'agit d'un affichage volontaire // donc tous les cpu peuvent l'utiliser: on affiche en + le num du cpu void LesContacts::Affiche() const { #ifdef UTILISATION_MPI int proc_en_cours = ParaGlob::Monde()->rank(); cout << "\n proc " << proc_en_cours #else cout << "\n" #endif << "\n ---- affichage des informations liees au contact --------"; cout << "\n 1) liste des elements en contact"; LaLIST ::const_iterator il,ilfin=listContact.end(); for (il=listContact.begin();il != ilfin; il++) (*il).Affiche(); cout << "\n 2) reactions aux contact"; // on balaie le tableau de reaction for (int i= 1; i<= tabReacCont.Taille();i++) { ReactCont & R = tabReacCont(i); cout << "\n================= noeud esclave =================="; cout << "\nmaillage " << (R.noe)->Num_Mail() <<", noeud " << (R.noe)->Num_noeud() << ", force = " << R.force ; cout << "\n---------------- noeuds de la frontiere maitre -------------"; int tail = R.tabNoeud.Taille(); for (int it=1;it<= tail;it++) { Noeud & no = *(R.tabNoeud(it)); Coordonnee& coor = R.tabForce(i); cout << "\nmaillage " << no.Num_Mail() <<", noeud " << no.Num_noeud() << ", force = " << coor << ", de norme =" << coor.Vect().Norme() ; }; }; cout << "\n 3) liste des references de zones succeptibles d'entrer en contact"; list ::const_iterator ill,illfin=nom_ref_zone_contact.end(); cout << "\n"; for (ill=nom_ref_zone_contact.begin();ill != illfin; ill++) { if ((*ill).nom1.length()) cout << " mail= " << (*ill).nom1 << " "; cout << "ref de noeud esclave: " << (*ill).nom2; if ((*ill).n ==1) cout << " (contact collant) "; cout << ", "; if ((*ill).nom3.length()) cout << " mail= " << (*ill).nom3 << " "; cout << "ref des frontieres maitres : " << (*ill).nom4; }; }; // affichage et definition interactive des commandes void LesContacts::Info_commande_LesContacts(UtilLecture & entreePrinc) { #ifdef UTILISATION_MPI cout << "\n *** erreur , la methode LesContacts::Info_commande_LesContacts " << " n'est pas utilisable en exécution MPI !!! "; Sortie(1); #endif ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier //On va proposer un menu string rep=" "; sort << "\n# --- les contact ------- "; while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { try { cout << "\n -- definition de : --- " << "\n (0 ou f) (fin) " << "\n (1) auto_contact " << "\n (2) zone particuliere de contact " << "\n (3) contact solide-deformable " << "\n (4) contact collant " << "\n (5) contact collant avec suppression du gap" << "\n (6 ou ? ) informations " << "\n "; // procédure de lecture avec prise en charge d'un retour chariot rep = lect_return_defaut(false,"f"); if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe break; int num = ChangeEntier(rep); if (Minuscules(rep) == "?") num = 6; bool choix_valide=false; if ((num >= 0)&&(num<=6)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 6 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; } string grandeur=" "; // init switch (num) { case 0: // sortie { break;} // normalement cela a déjà été filtré avant case 1: // auto_contact { sort << "\n auto_contact \n"; sort << "\n#--------------------------------------------------------------------------------"; sort << "\n# definition du nombre de domaine esclave en auto-contat |"; sort << "\n#--------------------------------------------------------------------------------"; cout << "\n nombre de maillage en autocontact (un entier) ? "; string nb_str; //int nb =0; nb_str = (int) lect_double(); if ((Minuscules(nb_str) == "f") || (Minuscules(nb_str) == "0"))// sortie directe break; int nb = ChangeEntier(nb_str); cout << " nom lu = "<< nb_str << " c-a-d le nombre "<rank(); #endif list li_lissage_de_la_normale; // stockage intermédiaire pour créer le tableau lissage_de_la_normale int niveau_commentaire_lescontacts = Permet_affichage(); while ( (strstr(entreePrinc.tablcar,"auto_contact")!=NULL) || (strstr(entreePrinc.tablcar,"zone_contact")!=NULL) || (strstr(entreePrinc.tablcar,"contact_solide_deformable")!=NULL) || (strstr(entreePrinc.tablcar,"glue_contact")!=NULL) || (strstr(entreePrinc.tablcar,"glue_contact_init_gap_zero")!=NULL) ) {// on regarde si la zone de contact est avec lissage de la normale int avec_lissage_de_la_normale = 0; if (strstr(entreePrinc.tablcar,"avec_lissage_de_la_normale")!=NULL) avec_lissage_de_la_normale = 1; // --- on examine le cas où il y a un marquage d'auto-contact if (strstr(entreePrinc.tablcar,"auto_contact")!=NULL) // cas ou l'on a des domaines esclaves en auto-contact, lecture du nombre { entreePrinc.NouvelleDonnee(); if (niveau_commentaire_lescontacts >= 4) #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif cout << " lecture du nombre de domaines esclaves en auto-contact " << endl; *(entreePrinc.entree) >> nbmailautocontact; // lecture du nombre if (niveau_commentaire_lescontacts >= 5) cout << nbmailautocontact << endl; if (niveau_commentaire_lescontacts >= 4) #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif cout << " fin de la lecture du nombre de domaines esclaves en auto-contact " << endl; entreePrinc.NouvelleDonnee(); // positionnement sur une nouvelle info }; // --- cas des zones particulières de contact if ( (strstr(entreePrinc.tablcar,"zone_contact")!=NULL) || (strstr(entreePrinc.tablcar,"glue_contact")!=NULL) || (strstr(entreePrinc.tablcar,"glue_contact_init_gap_zero")!=NULL) ) { int indic_glue = 0; // init de non glue a priori if (strstr(entreePrinc.tablcar,"glue_contact_init_gap_zero")!=NULL) {indic_glue = 2; }// cas particulier d'un contact collant avec suppression du gap else if (strstr(entreePrinc.tablcar,"glue_contact")!=NULL) {indic_glue = 1; }// cas particulier d'un contact collant // lecture tant qu'il n'y a pas de nouveau mot clé entreePrinc.NouvelleDonnee(); if (niveau_commentaire_lescontacts >= 4) #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif cout << " debut de la lecture des zones de contact possibles " << endl; while (!motCle.SimotCle(entreePrinc.tablcar)) { // on lit 2 par deux: une ref de noeud + une ref de frontière Quatre_string_un_entier quatre_inter; // une grandeur de travail quatre_inter.n = indic_glue; // on stocke la glue éventuelle for (int nr=1;nr<=2;nr++) {// on commence par regarder si le nom du maillage est définit pour la référence string nom_ref; // variables de travail string* nom_mail=NULL; string nom(""); if (strstr(entreePrinc.tablcar,"nom_mail=")!=NULL) { *(entreePrinc.entree) >> nom >> nom; nom_mail = & nom;} // lecture du nom d'une référence *(entreePrinc.entree) >> nom_ref; #ifdef ENLINUX if ((entreePrinc.entree)->rdstate() == 0) #else if (((entreePrinc.entree)->rdstate() == 0)||((entreePrinc.entree)->eof())) #endif // pour mémoire ici on a /* enum io_state { badbit = 1<<0, // -> 1 dans rdstate() eofbit = 1<<1, // -> 2 failbit = 1<<2, // -> 4 goodbit = 0 // -> O };*/ // lecture normale, vérification que la référence existe bien { if (!(lesRef.Existe(nom_ref,nom_mail))) { #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif cout << "\n erreur le nom de reference de zone de contact : " << nom_ref << " , n'existe pas !!" << "\n LesContacts::Lecture_zone_contact(.."; throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie (1); } else // enregistrement du nom de référence { if (nr==1) // premier passage on stocke {quatre_inter.nom1=nom;quatre_inter.nom2=nom_ref;} else // cas du deuxième passage on enregistre {quatre_inter.nom3=nom;quatre_inter.nom4=nom_ref; nom_ref_zone_contact.push_back(quatre_inter); li_lissage_de_la_normale.push_back(avec_lissage_de_la_normale); }; } #ifndef ENLINUX if ((entreePrinc.entree)->eof()) // on arrive à la fin de la ligne entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement #endif } //sinon il y a un pb ou, l'on est à la fin de la ligne et on passe à l'enregistrement suivant #ifdef ENLINUX else if ((entreePrinc.entree)->fail()) // on a atteind la fin de la ligne et on appelle un nouvel enregistrement { entreePrinc.NouvelleDonnee(); } // lecture d'un nouvelle enregistrement #endif else // cas d'une erreur de lecture { #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif { cout << "\n erreur de lecture inconnue au niveau des references de zone de contact"; entreePrinc.MessageBuffer("** LesContacts::Lecture_zone_contact(.. **"); Affiche(); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie (1); }; }; }; // -- fin for (int nr=1;nr<=2;nr++) }; //-- fin du while (!motCle.SimotCle(entreePrinc.tablcar)) if (niveau_commentaire_lescontacts >= 4) #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif cout << " fin de la lecture des zones de contact " << endl; }; // --- cas des contacts solide-deformable if (strstr(entreePrinc.tablcar,"contact_solide_deformable")!=NULL) { if (niveau_commentaire_lescontacts >= 4) #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif cout << " debut de la lecture des contacts solide-deformable " << endl; string toto; // variables de travail while (strstr(entreePrinc.tablcar,"fin_liste_des_couples_de_noms_solide_deformable")==NULL) // && (!motCle.SimotCle(entreePrinc.tablcar))) { Deux_String ie; // une variable de travail *(entreePrinc.entree) >> toto >> ie.nom1 >> toto >> ie.nom2; cont_solide_defor.push_back(ie); entreePrinc.NouvelleDonnee(); }; // on passe le mot clé de fin entreePrinc.NouvelleDonnee(); if (niveau_commentaire_lescontacts >= 4) #ifdef UTILISATION_MPI if (proc_en_cours == 0) #endif cout << " fin de la lecture des contacts solide-deformable " << endl; }; }; // création du tableau lissage_de_la_normale int nb_zone_lue = li_lissage_de_la_normale.size(); if (nb_zone_lue != 0) {lissage_de_la_normale.Change_taille(nb_zone_lue); // init list ::iterator il,ilfin=li_lissage_de_la_normale.end(); int iii=1; for (il = li_lissage_de_la_normale.begin();il != ilfin;il++,iii++) lissage_de_la_normale(iii) = (*il); } else // sinon on définie une seule zone et sans lissage {lissage_de_la_normale.Change_taille(1); lissage_de_la_normale(1)=0;}; };