2343 lines
124 KiB
C++
2343 lines
124 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
|
|
|
|
//------------------------- 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 () :
|
|
tabCoLin(),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()
|
|
{};
|
|
// constructeur de copie
|
|
LesContacts::LesContacts (const LesContacts& a):
|
|
tabCoLin(a.tabCoLin),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)
|
|
{};
|
|
// 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
|
|
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)
|
|
cout << "\n -- LesContacts::Init_contact: ";
|
|
|
|
// sauvegarde de la liste des fonctions nD
|
|
sauve_lesFonctionsnD = lesFonctionsnD;
|
|
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
|
|
{ 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);
|
|
}
|
|
else if (pt_fonct->NbComposante() > 2)
|
|
{ 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);
|
|
}
|
|
else // sinon ok
|
|
{ElContact::Init_fct_pilotage_contact4(pt_fonct);}
|
|
}
|
|
else
|
|
{ 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);
|
|
};
|
|
};
|
|
|
|
/* // ----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
|
|
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;
|
|
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
|
|
};
|
|
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));
|
|
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();
|
|
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
|
|
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
|
|
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
|
|
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;
|
|
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
|
|
{ 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
|
|
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)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //,
|
|
// pour l'instant seule le CPU 0 est concernée
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return false;
|
|
#endif
|
|
|
|
tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
bool retour = false; // init par défaut
|
|
int niveau_commentaire_lescontacts = Permet_affichage();
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
cout << "\n ==> LesContacts::Def Elem Cont, initialement "<<listContact.size() << " elem contact ";
|
|
// 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
|
|
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
|
|
{
|
|
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;
|
|
bool a_considerer = true; // init par défaut
|
|
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();
|
|
cout << "\n 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)
|
|
{ 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();
|
|
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;
|
|
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();
|
|
cout << "\n --- 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::
|
|
{ cout << "\n 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();
|
|
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)
|
|
cout << "\n ==> LesContacts::Nouveau: temps= " << ParaGlob::Variables_de_temps().TempsCourant();
|
|
// on montre les noeuds actuellement en contact
|
|
if (niveau_commentaire_lescontacts > 5)
|
|
{cout << "\n >> bilan des noeud(s) actuellement en contact: ";
|
|
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
|
|
{if (niveau_commentaire_lescontacts > 4)
|
|
{ Noeud* no = tesc(inesc);
|
|
// int n_noee = no->Num_noeud();
|
|
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 ";
|
|
if (tesN_collant(num_mail_noe_esclave)(j)(inesc)) cout << " collant ";
|
|
}
|
|
else {cout << "\n --> noeud actuellement pas en contact ";};
|
|
cout << flush;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
// on va lister les éléments de contact
|
|
{ cout << "\n 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);};
|
|
};
|
|
|
|
// on met à jour les boites des éléments qui contiennent les frontières
|
|
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
|
|
{ // ++ 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
|
|
// int num_mail = (*iE).Esclave()->Num_Mail();
|
|
// int num_noeud = (*iE).Esclave()->Num_noeud();
|
|
// tesN_encontact(num_mail)(num_noeud) += 1; // mise à jour de l'indicateur
|
|
(*iE).Met_actif();
|
|
if (niveau_commentaire_lescontacts > 3)
|
|
{ Element & elem = *(*iiE).Elfront()->PtEI();
|
|
int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail();
|
|
cout << "\nreactivation (dans newcontact) contact: ";
|
|
(*iiE).Affiche(1); cout << endl;
|
|
};
|
|
}
|
|
else
|
|
{ // sinon on supprime car il n'y a pas de contact
|
|
iE--; // pointe sur le precedent element
|
|
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 (dans newcontact): ";
|
|
(*iiE).Affiche(1);cout << endl;
|
|
};
|
|
listContact_efface_tatdt.push_front(*iiE); // mémorise
|
|
#ifdef MISE_AU_POINT
|
|
if (tesN_encontact((*iiE).Esclave()->Num_Mail()).find((*iiE).Esclave())
|
|
== tesN_encontact((*iiE).Esclave()->Num_Mail()).end() )
|
|
{ cout << "\n*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave "
|
|
<< (*iiE).Esclave()->Num_noeud()
|
|
<< " du maillage " << (*iiE).Esclave()->Num_Mail()
|
|
<< " 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((*iiE).Esclave()->Num_Mail())[(*iiE).Esclave()];
|
|
// tesN_encontact(num_mail_esclave)(num_noeud).remove(iiE);
|
|
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; // " " "
|
|
for (int jjf=1;jjf<=nbmailMaitre;jjf++)
|
|
for (int j=1;j<= nb_zone;j++)
|
|
{ iMfin=(t_listFront(jjf)(j)).end();
|
|
// tout d'abord on met à jour les boites d'encombrement des éléments frontière
|
|
for (iM = (t_listFront(jjf)(j)).begin() ; iM != iMfin; iM++)
|
|
(*iM).Boite_encombrement_frontiere(TEMPS_tdt,dep_max);
|
|
};
|
|
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];
|
|
// LaLIST < LaLIST<ElContact>::iterator >::iterator pl,plfin=list_tesN.end();
|
|
nb_contact = list_tesN.size();
|
|
};
|
|
if (niveau_commentaire_lescontacts > 5)
|
|
{ cout << "\n (re) examen eventuel : contact du noeud " << n_noee << " du maillage " << num_mail_noe_esclave;
|
|
cout << " coord2= "; no->Coord2().Affiche_1(cout);
|
|
if (niveau_commentaire_lescontacts > 5)
|
|
{cout << " num_mail_dans_contact = " << num_mail_noe_esclave <<" inesc(num N local)= " << inesc
|
|
// << "\n tesN_encontact= " << tesN_encontact(num_mail_noe_esclave)(n_noee).size()
|
|
<< "\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
|
|
|
|
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() > 5)
|
|
{cout << "\n noeud esclave deja en contact "; elc.Affiche(1);
|
|
};
|
|
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
|
|
// 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);
|
|
if (niveau_commentaire_lescontacts > 5)
|
|
{// --- sortie d'info pour vérifier l'appartenance à la boite ou non
|
|
cout << "\n 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 (niveau_commentaire_lescontacts > 5)
|
|
{ cout << "\n 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;};
|
|
// };
|
|
|
|
if (niveau_commentaire_lescontacts > 5)
|
|
{//cout << "\n 2debug LesContacts::Nouveau( " ;
|
|
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)
|
|
{ cout << "\n 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();
|
|
cout << "\n 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 (niveau_commentaire_lescontacts > 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))
|
|
{ int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail();
|
|
cout << "\n 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)
|
|
{ cout << "\nbilan: "<< listContact.size() << " elem 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) ";
|
|
cout << "\n <== fin LesContacts::Nouveau " ;
|
|
};
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
// on va lister les éléments de contact
|
|
{ cout << "\n 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);};
|
|
};
|
|
|
|
|
|
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();
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
cout << "\n -- 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)
|
|
cout << "\n 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();
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
cout << "\n -- 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;
|
|
int num_mail_esclave = (*iiE).Esclave()->Num_Mail();
|
|
int num_noeud = (*iiE).Esclave()->Num_noeud();
|
|
if (niveau_commentaire_lescontacts > 2)
|
|
{ Element & elem = *(*iiE).Elfront()->PtEI();
|
|
int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail();
|
|
cout << "\ninactivation (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
|
|
const Tableau <Condilineaire>& LesContacts::ConditionLin(const Nb_assemb& casAssemb)
|
|
{
|
|
tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
// 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
|
|
// if (ParaGlob::param->ParaAlgoControleActifs().ContactType() == 1)
|
|
// definition du tableau
|
|
// int tail = listContact.size();//(int) listContact.size();
|
|
// tabCoLin.Change_taille(tail);
|
|
{Calcul_Nb_contact_actif();
|
|
tabCoLin.Change_taille(nb_contact_actif);
|
|
//cout << "\n nb actif pour condlin = " << nb_contact_actif;
|
|
// on boucle sur les elements de contact
|
|
int i=1;
|
|
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
|
|
{tabCoLin(i) = (*iE).ConditionLi(casAssemb.n);i++;
|
|
//cout << " i="<<i;
|
|
};
|
|
}
|
|
// else
|
|
// { tabCoLin.Change_taille(0);};
|
|
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
// retour du tableau
|
|
return tabCoLin;
|
|
};
|
|
|
|
// 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 le tableau des conditions lineaires
|
|
int tailletabcolin = tabCoLin.Taille();
|
|
for (int i=1;i<=tailletabcolin;i++)
|
|
{ // on libere la condition
|
|
Condilineaire& C = tabCoLin(i);
|
|
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 nb_maitre = t_listFront.Taille(); // le nombre de maîtres
|
|
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)
|
|
bool LesContacts::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb,int& cumule)
|
|
{
|
|
tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
// 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;
|
|
bool retour = false; // par défaut on se met dans le cas le plus simple : contact avec surface rigide
|
|
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
|
|
// 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)
|
|
bool LesContacts::Actualisation(int choix)
|
|
{
|
|
tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
bool retour = false; // init par défaut
|
|
// 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)
|
|
cout << "\n -- LesContacts::Actualisation: choix: "<< choix;
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
// on va lister les éléments de contact
|
|
{ cout << "\n liste des Elcontact avant 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);};
|
|
};
|
|
|
|
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;
|
|
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 << "\ninactivation 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) il 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;
|
|
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 << "\ninactivation 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)
|
|
{ Element & elem = *(*iE).Elfront()->PtEI();
|
|
int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail();
|
|
cout << "\n 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();
|
|
int nb_contact = list_tesN.size();
|
|
for (pl = list_tesN.begin();pl != plfin;pl++)
|
|
{ElContact& elc = (*(*pl));
|
|
// 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
|
|
bool actif_transitoire = true;
|
|
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
|
|
{ actif_transitoire=false; // active l'élément
|
|
if (niveau_commentaire_lescontacts > 2)
|
|
{ Element & elem = *(*iE).Elfront()->PtEI();
|
|
int num_mail_elem = (elem.Tab_noeud())(1)->Num_Mail();
|
|
cout << "\nreactivation contact :";elc.Affiche(1);
|
|
|
|
};
|
|
}
|
|
else // sinon on inactive l'élément ;
|
|
elc.Met_Inactif();
|
|
};
|
|
};
|
|
|
|
}
|
|
};
|
|
}
|
|
// else
|
|
// {nb_contact_actif++; }; // on sauvegarde l'activité
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
// on va lister les éléments de contact
|
|
{ cout << "\n 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);};
|
|
// on calcule et affiche le nombre de contact actif
|
|
Calcul_Nb_contact_actif();
|
|
cout << "\n nb_contact_actif= " << nb_contact_actif << endl;
|
|
};
|
|
// 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
|
|
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
|
|
|
|
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();
|
|
|
|
int niveau_commentaire_lescontacts = Permet_affichage();
|
|
if (niveau_commentaire_lescontacts >= 7)
|
|
cout << "\n -- LesContacts::Liste_noeuds_position_changer: ";
|
|
|
|
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
|
|
};
|
|
|
|
// calcul des reactions de contact et stockage des valeurs
|
|
// solution : le vecteur residu
|
|
// test d'un decollement eventuelle, pour un noeud en contact
|
|
void LesContacts::CalculReaction(Vecteur& residu,bool& decol,const Nb_assemb& casAssemb
|
|
,bool affiche)
|
|
{
|
|
tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
int niveau_commentaire_lescontacts = Permet_affichage();
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
cout << "\n -- LesContacts::CalculReaction: ";
|
|
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 )
|
|
{ cout << "\nErreur : 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 )
|
|
{ cout << "\nErreur : ddl X1 "
|
|
<< " inexistant pour le cas de charge " << nb_Assemb << '\n'
|
|
<< " LesContacts::CalculReaction( (2)\n";
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
for (int i=1;i<=nb_ddl_en_var;i++)
|
|
tabForce(it)(i) = residu(posi+i-1); // la reaction
|
|
};
|
|
tabReacCont(itab) = ReactCont(noe,force,tabNoeud,tabForce);
|
|
}
|
|
else
|
|
{tabReacCont(itab) = ReactCont(noe,(*iE).Force_contact(),tabNoeud,(*iE).TabForce_cont());
|
|
};
|
|
itab++;
|
|
};
|
|
};
|
|
// affichage éventuelle de la force maxi de contact
|
|
Forces_contact_maxi(affiche);
|
|
// idem pour les gap N et T
|
|
Gap_contact_maxi(affiche);
|
|
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
};
|
|
|
|
// affichage des reactions de contact sur la sortie
|
|
void LesContacts::Affiche(ofstream& sort) const
|
|
{ // 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
|
|
void LesContacts::Affiche() const
|
|
{ cout << "\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)
|
|
{ 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
|
|
void LesContacts::Lecture_zone_contact(UtilLecture & entreePrinc,const LesReferences& lesRef)
|
|
{ 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)
|
|
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)
|
|
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) 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)))
|
|
{ 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
|
|
{ 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) 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) 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) 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;};
|
|
};
|
|
|
|
|
|
|