Herezh_dev/contact/LesContacts.cc
Gérard Rio a317216f06 V 7.021 - 7.023
- modification des sorties post pour loi hypo 2D_C et 1D_C
- corr bug lecture fct_nD avec toutes les lois hypo isotropes
- corr bug sur le calcul de la compressibilité pour les loi hypo 2D_C
- première mise en place du calcul parallèle sur le contact
- ajout d'une fct nD pour gérer le niveau de commentaire sur LesContacts (indépendante de celle qui gère le niveau de commentaire concernant les éléments de contact)
- amélioration de la méthode d'initialisation du contact, utilisée en début d'incrément
2024-01-30 20:55:48 +01:00

2921 lines
146 KiB
C++

// 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) <https://www.irdl.fr/>.
//
// 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 <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "LesContacts.h"
#include <vector>
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "CharUtil.h"
#include "Enum_TypeQuelconque.h"
#include "TypeQuelconqueParticulier.h"
// --------------- variables statiques ---------
MotCle LesContacts::motCle; // liste des mots clés
Tableau <const TypeQuelconque * > LesContacts::tqi_const_fct_nD_niveau_commentaire;
Tableau < TypeQuelconque * > LesContacts::tqi_fct_nD_niveau_commentaire;
Tableau <int> 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 <Noeud *> tN,const Tableau <Coordonnee>& 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()
,listContact_nouveau_tatdt(),listContact_efface_tatdt()
,nom_ref_zone_contact(),lissage_de_la_normale()
,t_listFront(),nb_mail_Esclave(),nbmailautocontact(0),nbmailMaitre()
,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
{};
// 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)
,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)
,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
{};
// 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();
if (niveau_commentaire_lescontacts > 4)
#ifdef UTILISATION_MPI
// on sauvegarde un pointeur sur les maillages
lesMaille = &lesMail;
if (ParaGlob::Monde()->rank() == 0)
#endif
cout << "\n -- LesContacts::Init_contact: ";
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 <Noeud*> *> tescin = lesMail.Tab_noeud_frontiere_esclave();
Tableau <LaLIST <Front>*>& listFrontiere = lesMail.ListFrontiere();
const Tableau < const Tableau <List_io < Element* > > *>& 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 <Front>::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<Noeud*,LaLIST < LaLIST<ElContact>::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 "<<ii<<" : "<<taille << " noeuds esclaves pour contact ";
};
// 2-- pour les éléments
int ilistfront = 1; // compteur pour le tableau t_listFront
// on parcours les elements maitres: à cause d'un auto contact
// éventuelle on peut avoir des maillages esclaves qui jouent le rôle également de
// maillages maitres
for (int jf=ntmail-nbmailMaitre+1;jf<=ntmail;jf++,ilistfront++)
{ t_listFront(ilistfront).Change_taille(1); // une seule zone de contact
LaLIST_io <Front> & lis_fronta = (t_listFront(ilistfront)(1));
LaLIST <Front>::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 "<<ilistfront<<" : "<<lis_fronta.size()
<< " frontieres pour contact ";
};
}
else
{ // cas d'une zone restreinte de contact
// on va iterer sur les noeuds esclaves pour savoir s'ils appartiennent à la zone de contact potentiel
list <Quatre_string_un_entier>::iterator il,ilfin=nom_ref_zone_contact.end();
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 "<<intot<< " : zone de contact: " << izone
<<" => " << 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 "<<izone
<< " on ne trouve pas le maillage esclave correspondant ! ";
refNE.Affiche();
cout << "\n LesContacts::Init_contact(..." << endl;
tempsContact.Arret_du_comptage(); // fin cpu
Sortie(1);
};
}; //-- fin de la boucle sur les zones de contact
// --- maintenant on s'occupe des frontières des maillages maîtres
//Les zones définies sont prises telles qu'elle, elles peuvent donc
// définir des frontières potentielles au contact en dehors de ceux définis
// par la construction automatique des frontières dans lesMaillages
// -> 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 <Front> & 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);
// Pour diminuer le temps de recherche, et aussi les messages on va constituer une liste des éléments
// qui contiennent les frontières
int nb_zone = MaX(1,nom_ref_zone_contact.size());
liste_elemens_front.clear(); // init de la liste
for (int i=1;i<=nbmailMaitre;i++)
{ for (int j=1;j<=nb_zone;j++)
{ LaLIST_io <Front> & list_fronta = (t_listFront(i)(j)); // pour simplifier
LaLIST <Front>::iterator iM,iMfin=list_fronta.end();
for (iM = list_fronta.begin();iM != iMfin; iM++) // boucle sur les frontières enregistrées
liste_elemens_front.push_back((*iM).PtEI());
};
};
// 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 <Front>::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
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 <Front>::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 <Element *>::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 <Noeud*>& tesc= tesctotal(intot)(j); // pour simplifier la notation
const Tableau <int> 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 > 2)
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
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 "<<listContact.size() << " elem contact ";
#else
cout << "\n -- LesContacts::Def Elem Cont, initialement "<<listContact.size() << " elem contact ";
#endif
};
// on initialise les listes transitoires
listContact_nouveau_tatdt.clear();
listContact_efface_tatdt.clear();
// on met à jour le déplacement maxi toléré pour la classe ElContact
double coef_mult_dep_max = 2.; // 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
// on met à jour le déplacement maxi pour la class
ElContact::Change_dep_max(dep_max_pratique);
int nb_zone = MaX(1,nom_ref_zone_contact.size());
double dist_max = Dabs(ParaGlob::param->ParaAlgoControleActifs().DistanceMaxiAuPtProjete());
// 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 <Front>::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 <Front>::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 <ElContact>::iterator icont_inter; // sert pour la recherche de doublon
// list <TroisEntiers>::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 <Noeud*>& tesc= tesctotal(intot)(j_zone); // pour simplifier la notation:
const Tableau <int> 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 <Front>& 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<Noeud*,LaLIST < LaLIST<ElContact>::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<Noeud*,LaLIST < LaLIST<ElContact>::iterator > >::iterator it_liste;
if (tesN_encontact_ii.find(noee) != tesN_encontact_ii.end())
{LaLIST < LaLIST<ElContact>::iterator > & list_tesN = tesN_encontact_ii[noee];
LaLIST < LaLIST<ElContact>::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
// 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
<< "\ncontact 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"<<j_zone<<")"<< flush;
if (niveau_commentaire_lescontacts > 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<ElContact>::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 > 2)
{ 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 << "\ncontact 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"<<j_zone<<")"<< flush;
};
}
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();
};
};
// 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
// retour
if (niveau_commentaire_lescontacts > 2) // ==> LesContacts::
{
#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 <<", "<<listContact_efface_tatdt.size() << " effacement(s) ";
cout << flush;
};
tempsContact.Arret_du_comptage(); // fin cpu
return retour;
};
// reexamen du contact pour voir s'il n'y a pas de nouveau element de contact
// ramene false s'il n'y a pas de nouveau element de contact
// true sinon
// dep_max : déplacement maxi des noeuds du maillage
bool LesContacts::Nouveau(double dep_max)
{
tempsContact.Mise_en_route_du_comptage(); // def deb compt
int niveau_commentaire_lescontacts = Permet_affichage();
list <TypeQuelconque> li_pour_noeuds; // pour une sortie spécifique noeud
Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques
li_pour_noeuds.push_front(TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier));
Grandeur_scalaire_entier& gr_pour_noeud
= *((Grandeur_scalaire_entier*) (*li_pour_noeuds.begin()).Grandeur_pointee());
list <TypeQuelconque> li_pour_elcont; // pour une sortie spécifique élément finis
li_pour_elcont.push_front(TypeQuelconque(NUM_ELEMENT,EPS11,grand_courant_entier));
#ifdef UTILISATION_MPI
int proc_en_cours = ParaGlob::Monde()->rank();
#endif
int nb_zone = MaX(1,nom_ref_zone_contact.size());
// on sauvegarde la liste au départ
int taille_list_contact_nouveau_au_debut = listContact_nouveau_tatdt.size();
if (niveau_commentaire_lescontacts > 3)
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n"
#endif
<< " -- LesContacts::Nouveau: temps= " << ParaGlob::Variables_de_temps().TempsCourant();
// on montre les noeuds actuellement en contact
if (Permet_affichage() > 4)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n"
#endif
<< " >> 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 <Noeud*>& tesc= tesctotal(intot)(j); // pout simplifier la notation
const Tableau <int> 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
if (Permet_affichage(&li_pour_noeuds) > 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<Noeud*,LaLIST < LaLIST<ElContact>::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<Noeud*,LaLIST < LaLIST<ElContact>::iterator > >::iterator it_liste;
if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end())
{//LaLIST < LaLIST<ElContact>::iterator > & list_tesN = tesN_encontact_ii[no];
// LaLIST < LaLIST<ElContact>::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<ElContact>::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 <ElContact>::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 <ElContact>::iterator iiE = iE;
if ((*iE).Contact())
{ // on valide si le contact est ok
(*iE).Met_actif();
(*gr_pour_noeud.ConteneurEntier()) = (*iE).Esclave()->Num_noeud();
if (Permet_affichage(&li_pour_noeuds) > 3)
{ 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;
if (Permet_affichage(&li_pour_noeuds) > 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<ElContact>::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
bool retour = false; // init du retour
LaLIST_io <Front>::iterator iM,iMfin;
LaLIST <ElContact>::iterator icont_inter; // sert pour la recherche de doublon
list <TroisEntiers>::iterator inumtesN; // " " "
// 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 <Noeud*>& tesc= tesctotal(intot)(j_zone); // pout simplifier la notation
const Tableau <int> 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<Noeud*,LaLIST < LaLIST<ElContact>::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<Noeud*,LaLIST < LaLIST<ElContact>::iterator > >::iterator it_liste;
int nb_contact=0;
if (tesN_encontact_ii.find(no) != tesN_encontact_ii.end())
{LaLIST < LaLIST<ElContact>::iterator > & list_tesN = tesN_encontact_ii[no];
nb_contact = list_tesN.size();
};
(*gr_pour_noeud.ConteneurEntier()) = n_noee;
if (Permet_affichage(&li_pour_noeuds) > 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) > 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<ElContact>::iterator > & list_tesN = tesN_encontact_ii[no];
LaLIST < LaLIST<ElContact>::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: "<<icont<<" avec frontiere: " << elfront->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;
};
{
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 <Front>& 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<ElContact>::iterator > & list_tesN = tesN_encontact_ii[no];
LaLIST < LaLIST<ElContact>::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();
if (Permet_affichage(&li_pour_noeuds) > 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) > 6)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n "
#endif
<< " frontiere: " << elfront.Num_frontiere() << " (nb loc: "<<num_frontiere<<") "
<< ", type: " << Nom_type_geom(elfront.Eleme_const()->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 <ElContact>::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;
if (Permet_affichage(&li_pour_noeuds) > 7)
{cout << "\n liste des contacts sur le noeud " << n_noee
<< " qui est prevu en effacement sur l'increment " ;
LaLIST <ElContact>::iterator ila,ilafin=listContact_efface_tatdt.end();
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<ElContact>::iterator > & list_tesN = tesN_encontact_ii[no];
LaLIST < LaLIST<ElContact>::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
// 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() ;
if (Permet_affichage(&li_pour_noeuds) > 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
if (niveau_commentaire_lescontacts > 3)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n "
#endif
<< " en fin de au debut de LesContacts::Nouveau: bilan: "<< listContact.size() << " elem(s) contact ";
if ( listContact_nouveau_tatdt.size())
cout <<", "<< (listContact_nouveau_tatdt.size()-taille_list_contact_nouveau_au_debut)
<< " nouveau(x) ";
if (listContact_efface_tatdt.size())
cout <<", "<<listContact_efface_tatdt.size() << " effactement(s) ";
};
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 a la fin de LesContacts::Nouveau: (fct du niveau de commentaire des elcontact): ";
LaLIST<ElContact>::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 " ;
};
tempsContact.Arret_du_comptage(); // fin cpu
//cout << "\n tempsContact.Temps_CPU_User = " << tempsContact.Temps_CPU_User() << flush;
return retour;
};
// suppression définitive, si le contact à disparu, des éléments inactifs
// ramène false si aucun élément n'est finalement supprimé
bool LesContacts::SuppressionDefinitiveElemInactif()
{
tempsContact.Mise_en_route_du_comptage(); // def deb compt
int niveau_commentaire_lescontacts = Permet_affichage();
#ifdef UTILISATION_MPI
int proc_en_cours = ParaGlob::Monde()->rank();
#endif
if (niveau_commentaire_lescontacts > 4)
{
#ifdef UTILISATION_MPI
cout << "\n proc " << proc_en_cours
#else
cout << "\n"
#endif
<< " -- LesContacts::SuppressionDefinitiveElemInactif: ";
};
bool change = false;
int nb_effacement=0;
// return change;
//------- pour le débug
LaLIST <ElContact>::iterator iE ;
// list <TroisEntiers>::iterator iden = numtesN.begin();
// on met .end(), car cette borne peut changer au gré des suppressions
for (iE = listContact.begin(); iE != listContact.end(); iE++)//,iden++)
{if (!((*iE).Actif()) // on intervient si le contact est déclaré inactif
&& ((*iE).Collant()) // et si c'est collant: ce n'est pas normal, on le remet actif
)
{(*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 <ElContact>::iterator iiE = iE;
// list <TroisEntiers>::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<ElContact>::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 <ElContact>::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 ";
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();
#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
#else
cout << "\n"
#endif
<< " -- LesContacts::RelachementNoeudcolle(): ";
bool change = false;
// return change; //------- pour le débug
LaLIST <ElContact>::iterator iE ;
// list <TroisEntiers>::iterator iden = numtesN.begin();
// on met .end(), car cette borne peut changer au gré des suppression
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 <ElContact>::iterator iiE = iE;
// list <TroisEntiers>::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 ";
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 <Condilineaire>& 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 <ElContact>::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 <Condilineaire>::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 <Condilineaire>::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 <Front>::const_iterator il,ilfin = t_listFront(i)(j).end();
for (il = t_listFront(i)(j).begin(); il != ilfin; il++)
{const Tableau <Noeud *>& 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 <ElContact>::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 <Noeud*>& tabnoeud = (*iE).TabNoeud();
int maxiPourLeContact=0; // stocke le maxi pour chaque condition linéaire
retour = true; // ici la largeur de bande en noeud est augmenté, car le noeud en contact
// est en relation avec des noeuds d'une surface déformable
for (int noe=1; noe<= tabnoeud.Taille();noe++)
for ( int no=noe+1; no<=tabnoeud.Taille();no++)
{ Noeud & nne = *tabnoeud(noe);
Noeud & nno = *tabnoeud(no);
int di;
if (nne.PosiAssemb(nb_Assemb) >= nno.PosiAssemb(nb_Assemb))
di = nne.PosiAssemb(nb_Assemb) - nno.PosiAssemb(nb_Assemb)
+ nne.NB_ddl_actif_casAssemb(nb_Assemb);
else
di = nno.PosiAssemb(nb_Assemb) - nne.PosiAssemb(nb_Assemb)
+ nno.NB_ddl_actif_casAssemb(nb_Assemb);
if ( di > demi) demi = di;
if ( di > maxiPourLeContact) maxiPourLeContact = di;
if ( 2*di > total) total = 2*di;
};
cumule += maxiPourLeContact;
};
};
total += 1;
demi += 1;
tempsContact.Arret_du_comptage(); // fin cpu
}
#ifdef UTILISATION_MPI
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
// maintenant on va transmettre au cpu 0
// pour cela on va utiliser un conteneur intermédiaire
QuatreEntiers inter_entiers(demi,total,cumule,retour);
// on transmet les infos au proc 0
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 44, inter_entiers);
// on attend pas
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
}
else // cas du cpu 0
{// l'objectif ici est de récupérer les infos
tempsContact.Arret_du_comptage(); // fin cpu
int nb_proc_terminer = 0; // permettra de terminer
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
{ // on récupère un résultat de cpu i
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
QuatreEntiers inter_entiers;
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 44, inter_entiers);
reqs1.wait(); // on attend que le conteneur soit rempli
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
tempsContact.Mise_en_route_du_comptage(); // def deb compt
if (inter_entiers.un > demi) demi = inter_entiers.un;
if (inter_entiers.deux > total) total = inter_entiers.deux;
cumule += inter_entiers.trois;
retour = (retour || ((bool)inter_entiers.quatre));
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
tempsContact.Arret_du_comptage();
};
};
#endif
// retour de l'indicateur
return retour;
};
// 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 <ElContact>::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<ElContact>::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 <ElContact>::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= "<<test;
#endif
(*iiE).Affiche(1);
};
(*iiE).Met_Inactif(); // inactive l'élément
retour = true; // on signale le changement
}
else if (test_existance != NULL)
// cas où test est forcément == 2 (car on a calculé test_existance) et on est arrivé sur un élément existant qui est actif
// on inactive l'element de contact
{if (test_existance->Actif())
{ LaLIST <ElContact>::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<Noeud*,LaLIST < LaLIST<ElContact>::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<Noeud*,LaLIST < LaLIST<ElContact>::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<Noeud*,LaLIST < LaLIST<ElContact>::iterator > >::iterator it_liste;
if (tesN_encontact_ii.find(noe) != tesN_encontact_ii.end())
{LaLIST < LaLIST<ElContact>::iterator > & list_tesN = tesN_encontact_ii[noe];
LaLIST < LaLIST<ElContact>::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<ElContact>::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
// 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 <Noeud * >& 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 <ElContact>::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 <Noeud * >::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 <ElContact>::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: "<<noe->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: "<<noe->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 <Noeud *>& 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 <Coordonnee> 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
#ifdef UTILISATION_MPI
if (proc_en_cours == 0)
#endif
{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 <ElContact>::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 <Quatre_string_un_entier>::const_iterator ill,illfin=nom_ref_zone_contact.end();
cout << "\n";
for (ill=nom_ref_zone_contact.begin();ill != illfin; ill++)
{ if ((*ill).nom1.length()) cout << " mail= " << (*ill).nom1 << " ";
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 "<<nb ;
sort << "\n "<< nb <<endl ;
break;
}
case 2: // zone particuliere de contact
{ cout << "\n def d'une ref de noeuds esclave ";
string nom_mail1="";
cout << "\n nom du maillage ? ";
nom_mail1= lect_chaine(); cout << " nom lu = "<< nom_mail1;
cout << "\n nom de la reference de noeud ? ";
string nom_ref=" ";
nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref;
if (nom_ref.at(0) != 'N')
{cout << "\n *** erreur, la premiere lettre de la ref de noeud "
<< " doit etre N et non "<< nom_ref.at(0)<< " !!";
break;
};
cout << "\n def d'une ref de faces maitres ";
string nom_mail_face="";
cout << "\n nom du maillage ? ";
nom_mail_face= lect_chaine(); cout << " nom lu = "<< nom_mail_face;
cout << "\n nom de la reference de face ? ";
string nom_ref_face="";
nom_ref_face= lect_chaine();cout << " nom lu = "<< nom_ref_face;
if (nom_ref_face.at(0) != 'F')
{cout << "\n *** erreur, la premiere lettre de la ref de face "
<< " doit etre F et non "<< nom_ref_face.at(0)<< " !!";
break;
};
sort << "\n\n zone_contact #------------- ";
sort << "\n#----------------------------------------------------"
<< "\n# ref noeuds | ref face |"
<< "\n#----------------------------------------------------";
sort << "\n nom_mail= "<< nom_mail1<< " "<< nom_ref << " "
<< " nom_mail= "<< nom_mail_face << " "<< nom_ref_face <<endl;
break;
}
case 3: // contact solide-deformable
{ cout << "\n def de contact de type solide-deformable ";
sort << "\n\n contact_solide_deformable #------------- ";
sort << "\n#----------------------------------------------------"
<< "\n# maillage solide | maillage deformable |"
<< "\n#----------------------------------------------------";
sort << "\n debut_liste_des_couples_de_noms_solide_deformable ";
string nom_mailsolide="";
do {
cout << "\n nom du maillage considere solide ? (ou f pour finir) ";
nom_mailsolide= lect_chaine(); cout << " nom lu = "<< nom_mailsolide;
if (Minuscules(nom_mailsolide) == "f")
break;
cout << "\n nom du maillage considere deformable ";
string nom_maildeformable="";
cout << "\n nom du maillage ? ";
nom_maildeformable= lect_chaine(); cout << " nom lu = "<< nom_maildeformable;
sort << "\n solide= "<< nom_mailsolide<< " "
<< " deformable= "<< nom_maildeformable << " " <<endl;
} while (Minuscules(nom_mailsolide) != "f");
sort << "\n fin_liste_des_couples_de_noms_solide_deformable ";
break;
}
case 4: case 5: // zone contact collant
{ cout << "\n def d'une ref de noeuds esclave ";
string nom_mail1="";
cout << "\n nom du maillage ? ";
nom_mail1= lect_chaine(); cout << " nom lu = "<< nom_mail1;
cout << "\n nom de la reference de noeud ? ";
string nom_ref=" ";
nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref;
if (nom_ref.at(0) != 'N')
{cout << "\n *** erreur, la premiere lettre de la ref de noeud "
<< " doit etre N et non "<< nom_ref.at(0)<< " !!";
break;
};
cout << "\n def d'une ref de faces maitres ";
string nom_mail_face="";
cout << "\n nom du maillage ? ";
nom_mail_face= lect_chaine(); cout << " nom lu = "<< nom_mail_face;
cout << "\n nom de la reference de face ? ";
string nom_ref_face="";
nom_ref_face= lect_chaine();cout << " nom lu = "<< nom_ref_face;
if (nom_ref_face.at(0) != 'F')
{cout << "\n *** erreur, la premiere lettre de la ref de face "
<< " doit etre F et non "<< nom_ref_face.at(0)<< " !!";
break;
};
if (num==4)
{sort << "\n\n glue_contact #------------- ";}
else {sort << "\n\n glue_contact_init_gap_zero #------------- ";};
sort << "\n#----------------------------------------------------"
<< "\n# ref noeuds | ref face |"
<< "\n#----------------------------------------------------";
sort << "\n nom_mail= "<< nom_mail1<< " "<< nom_ref << " "
<< " nom_mail= "<< nom_mail_face << " "<< nom_ref_face <<endl;
break;
}
case 6: // information
{ cout << "\n -- Concernant l'auto-contact, le nombre demande indique "
<< "\n le nombre de maillages en auto-contact, compte parmi les maillages"
<< "\n esclaves, donc doit etre <= au nombre de maillages esclaves ! "
<< "\n -- Concernant les zones de contact, indique les ref de noeuds esclaves"
<< "\n qui doivent etre consideres potentiellement en contact avec les ref "
<< "\n de faces. Si un (ou les deux) des deux mots cles zone_contact et/ou glue_contact "
<< "\n existe, seules les zones definies sont prises en compte."
<< "\n -- Concernant le contact solide deformable "
<< "\n le maillage indique comme solide doit etre un maillage maitre "
<< "\n ou un maillage en auto-contact "
<< "\n le maillage deformable doit-etre un maillage esclave ou en auto-contact "
<< "\n le noeud en contact du solide deformable est systematiquement deplace "
<< "\n sur la surface du solide deformable, cette condition se substitue donc "
<< "\n a une condition de penalisation si celle-ci est en oeuvre "
<< "\n -- Concernant les zones de contact collant, indique les ref de noeuds esclaves"
<< "\n qui seront imposes en contact avec les ref "
<< "\n de faces. Si un (ou les deux) des deux mots cles zone_contact et/ou glue_contact "
<< "\n existe, seules les zones definies sont prises en compte."
<< "\n "<<endl ;
}
default:
cout << "\n le cas "<<rep<<" n'est pas traite !!, bizarre, il faut se plaindre !! ";
};
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
{ cout << "\n Erreur on attendait un des mots cles proposes !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour sortir ";
};
}; //-- fin du while
sort << flush;
};
// lecture éventuelle des zones où le contact doit être recherché, à l'exclusion de tout
// autre zone, ainsi que la définition de l'auto-contact éventuel
// ainsi que des contacts solide-deformables éventuel
// cas d'un calcul parallèle, tous les proc utilisent la méthode, seule le proc 0 affiche
void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesReferences& lesRef)
{
#ifdef UTILISATION_MPI
int proc_en_cours = ParaGlob::Monde()->rank();
#endif
list <int> 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 <int>::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;};
};