Herezh_dev/contact/LesContacts_3.cc

1861 lines
93 KiB
C++
Raw Normal View History

// 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.
//
2023-05-03 17:23:49 +02:00
// 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"
2023-05-03 17:23:49 +02:00
#include "FrontPointF.h"
// récupération des ddl ou des grandeurs actives de tdt vers t
void LesContacts::TdtversT()
{ LaLIST <ElContact>::iterator il,ilfin=listContact.end();
for (il=listContact.begin();il != ilfin; il++)
(*il).TdtversT();
// on nettoie les indicateurs transitoires
listContact_nouveau_tatdt.clear();
listContact_efface_tatdt.clear();
};
// actualisation des ddl et des grandeurs actives de t vers tdt
void LesContacts::TversTdt()
{ // on essaie de mettre la situation de contact comme elle était à t
// a) on supprime les nouveaux contacts
{LaLIST <LaLIST <ElContact>::iterator>::iterator al,alfin=listContact_nouveau_tatdt.end();
for (al=listContact_nouveau_tatdt.begin();al != alfin; al++)
{ ElContact& elc = (*(*al));
Noeud* no = elc.Esclave();
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::TversTdt(.. \n";
Sortie(1);
};
#endif
LaLIST < LaLIST<ElContact>::iterator > & list_tesN
= tesN_encontact(num_mail_noe_esclave)[no];
list_tesN.remove(*al);
// tesN_encontact(num_mail_noe_esclave)(n_noee).remove(*al);
listContact.erase(*al);
// cout << "\n debug toto ";
};
};
// b) on rajoute les contacts supprimés
{LaLIST <ElContact>::iterator al,alfin=listContact_efface_tatdt.end();
for (al=listContact_efface_tatdt.begin();al != alfin; al++)
{ ElContact& elc = (*al);
Noeud* no = elc.Esclave();
int n_noee = no->Num_noeud();
int num_mail_noe_esclave = no->Num_Mail();
2023-05-03 17:23:49 +02:00
#ifdef MISE_AU_POINT
if (Element_contact_deja_present(*al))
{ cout << "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal "
<< (*al).Esclave()->Num_noeud()
<< " du maillage " << (*al).Esclave()->Num_Mail()
<< " la suite n'est pas possible "
<< " LesContacts::TversTdt(.. \n";
tempsContact.Arret_du_comptage(); // fin cpu
Sortie(1);
};
#endif
listContact.push_front(*al);
// on met à jour le tableau tesN_encontact
#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::TversTdt(.. \n";
Sortie(1);
};
#endif
tesN_encontact(num_mail_noe_esclave)[no].push_front(listContact.begin());
};
};
// c) on nettoie les indicateurs transitoires
listContact_nouveau_tatdt.clear();
listContact_efface_tatdt.clear();
// d) on revient à t pour les éléments en contact
{LaLIST <ElContact>::iterator il,ilfin=listContact.end();
for (il=listContact.begin();il != ilfin; il++)
(*il).TversTdt();
};
2023-05-03 17:23:49 +02:00
Calcul_Nb_contact_actif();
if ((ParaGlob::NiveauImpression() > 4) || (Permet_affichage() > 4 ))
cout << "\n >> LesContacts::TversTdt : nb contact actif = "<< nb_contact_actif << endl ;
};
// cas d'une méthode avec pénalisation: calcul éventuel d'un pas de temps idéal,
// si oui retour de la valeur delta_t proposé
// sinon dans tous les autres cas retour de 0.
// le calcul se fait en fonction du pas de temps courant et de la pénétration
// donc nécessite que le contact ait déjà été étudié
double LesContacts::Pas_de_temps_ideal()const
{ double delta_optimal=ConstMath::tresgrand;
// on passe en revue tous les contacts
LaLIST <ElContact>::const_iterator il,ilfin=listContact.end();
for (il=listContact.begin();il != ilfin; il++)
{ double dtelem_optimal = (*il).Pas_de_temps_ideal();
if (dtelem_optimal != 0.)
delta_optimal = MiN(delta_optimal, dtelem_optimal);
};
// retour du temps proposé
if (delta_optimal==ConstMath::tresgrand)
// cela veut dire qu'il n'a pas été modifié, on le met à 0 pour indiquer que l'on a rien
// n'a proposer
delta_optimal = 0.;
return delta_optimal;
};
// écriture base info
// cas donne le niveau de sauvegarde
void LesContacts::Ecri_base_info_LesContacts(ofstream& sort)
{ // globalement on sauvegarde toujours tout, car les éléments de contact peuvent apparaître à tout moment
// tout d'abord on indique le type
sort << "\n LesContacts: taille " << listContact.size() << " " ;
// NB: le nombre de maillages esclave et en auto-contact, peut-être redéfinit lors d'un restart
// donc n'est pas sauvegardé
// ensuite on sauvegarde la liste des éléments de contact: en fait tout d'abord les infos
// qui permettent de construire un élément ad hoc, et ensuite les infos spécifiques internes à l'élément
for (LaLIST <ElContact>::iterator ic = listContact.begin();ic != listContact.end(); ic++)
{// les infos permettants de contruire l'élément de contact: on considère que les numéros des noeuds, maillages, éléments
2023-05-03 17:23:49 +02:00
// restent identiques, par contre on peut avoir un échange des zones de restriction de contact d'une sauvegarde à un restart
sort << "\nN_es " << (*ic).Esclave()->Num_Mail() <<" " << (*ic).Esclave()->Num_noeud(); // le noeud esclave
Front * elfront = (*ic).Elfront();
sort << " El " << elfront->NumMail() << " " << elfront->PtEI()->Num_elt_const() << " "
<< elfront->Eleme()->Type_geom_front() << " "<< elfront->Num_frontiere() ; // la frontière
// les infos spécifiques éventuelles
2023-05-03 17:23:49 +02:00
(*ic).Ecri_base_info_ElContact(sort);
};
sort << "\n tps_rech_contact: "<<tempsContact;
};
// Il s'agit ici de mettre à jour les conteneurs stockés aux noeuds et/ou aux éléments
// qui servent à récupérer les infos liés aux contact correspondant à liTQ
// actuellement les conteneurs passés en paramètre ne servent que pour
// les énumérés, et les informations résultantes sont stockées au niveau des noeuds
// constituant les éléments de contact
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
//--> important : les conteneurs sont supposés initialisés avec l'appel
void LesContacts::Mise_a_jour_Pour_Grandeur_particuliere(
List_io < TypeQuelconque >& li_restreinte_TQ
)
{
LaLIST<ElContact>::iterator ili_deb= listContact.begin();
LaLIST<ElContact>::iterator ilifin= listContact.end();
LaLIST<ElContact>::iterator ili;
// on passe en revue la liste de quelconque
{List_io<TypeQuelconque>::iterator itq,itqfin=li_restreinte_TQ.end();
for (itq=li_restreinte_TQ.begin();itq!=itqfin;itq++)
{const TypeQuelconque_enum_etendu& enuTypeQuelconque = (*itq).EnuTypeQuelconque();
if (enuTypeQuelconque.Nom_vide()) // veut dire que c'est un enum pur
switch (enuTypeQuelconque.EnumTQ())
{ case NOEUD_PROJECTILE_EN_CONTACT:
{// ----- cas des noeuds projectiles en contact
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
// on attribue une grandeur arbitraire de 100 aux noeuds pour un contact actif
// pour les éléments de contact inactif -> -0.1
// un noeud peut être plusieurs fois en contact -> les nombres sont cumulées
// on fait l'hypothèse qu'un ne sera jamais inactif plus de 99 fois, du coup
// en regardant le nombre modulo 100 on peut en déduire le nombre d'inactivité
// et en regardant le nombre de centaine on en déduit le nombre de contact
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += 100.; }
else
{*(tyTQ.ConteneurDouble()) -= 0.1; }
};
break;
}
case NOEUD_FACETTE_EN_CONTACT:
{// ----- cas des noeuds facettes en contact
// on parcours la liste des éléments de contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
// on attribue une grandeur arbitraire de 100 aux noeuds pour un contact actif
// pour les éléments de contact inactif -> -0.1
// un noeud peut être plusieurs fois en contact -> les nombres sont cumulées
// on fait l'hypothèse qu'un ne sera jamais inactif plus de 99 fois, du coup
// en regardant le nombre modulo 100 on peut en déduire le nombre d'inactivité
// et en regardant le nombre de centaine on en déduit le nombre de contact
Tableau <Noeud*>& tablN = elcont.TabNoeud();
int NBNF=tablN.Taille();
// on boucle sur les noeuds de la facette (le premier noeud = noeud esclave)
if (elcont.Actif())
{for (int i=2;i<=NBNF;i++)
{TypeQuelconque& tyqN = tablN(i)->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
*(tyTQ.ConteneurDouble()) += 100.;
}
}
else
{for (int i=2;i<=NBNF;i++)
{TypeQuelconque& tyqN = tablN(i)->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
*(tyTQ.ConteneurDouble()) -= 0.1;
}
};
};
break;
}
case PENETRATION_CONTACT:
{// ----- cas des noeuds projectiles en contact
// on parcours la liste des élément en contact
// on cumule s'il y a plusieurs contacts
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{// on définit un vecteur au niveau du noeud en contact, qui part du noeud
// projectile et va au point d'impact
const Coordonnee& Mtdt = elcont.Point_intersection();
*(tyTQ.ConteneurCoordonnee()) += Mtdt - elcont.Esclave()->Coord2();
}; // sinon on ne fait rien
};
break;
}
case GLISSEMENT_CONTACT:
{// ----- cas des noeuds projectiles en contact
// on parcours la liste des élément en contact
// on cumule s'il y a plusieurs contacts
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{// on définit un vecteur au niveau du noeud en contact, qui part du noeud
// projectile et va au point d'impact
*(tyTQ.ConteneurCoordonnee()) += elcont.Dep_tangentiel();
}; // sinon on ne fait rien
};
break;
}
case NORMALE_CONTACT:
{// ----- cas des noeuds projectiles en contact
// on parcours la liste des élément en contact
// on cumule s'il y a plusieurs contacts
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{// on définit un vecteur au niveau du noeud en contact, qui part du noeud
// projectile et va au point d'impact
*(tyTQ.ConteneurCoordonnee()) += elcont.Normale_actuelle();
}; // sinon on ne fait rien
};
break;
}
2023-05-03 17:23:49 +02:00
// case N_FRONT:
// {// ----- cas des noeuds projectiles en contact
// // on parcours la liste des élément en contact
// // on cumule s'il y a plusieurs contacts
// for (ili=ili_deb;ili!=ilifin;ili++)
// {ElContact & elcont = (*ili); // pour simplifier
// TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
// Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
// tyqN.Grandeur_pointee());
// // on récupère la normale au noeud projectile
// *(tyTQ.ConteneurCoordonnee()) = elcont.Normale_actuelle();
// };
// break;
// }
case FORCE_CONTACT:
{// ----- cas des noeuds projectiles en contact
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{// on récupère la force de contact
*(tyTQ.ConteneurCoordonnee()) += elcont.Force_contact();
}; // sinon on ne fait rien
};
break;
}
case CONTACT_PENALISATION_N:
{// ----- on attribue la pénalisation au noeud projectile
// on met la pénalisation totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.Penalisation(); };
};
break;
}
case CONTACT_PENALISATION_T:
{// ----- on attribue la pénalisation au noeud projectile
// on met la pénalisation totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.Penalisation_tangentielle(); };
};
break;
}
case CONTACT_ENERG_PENAL:
{// ----- on attribue l'énergie de pénalisation au noeud projectile
// on met l'énergie totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.EnergiePenalisation(); };
};
break;
}
case CONTACT_ENERG_GLISSE_ELAS:
{// ----- on attribue l'énergie de pénalisation au noeud projectile
// on met l'énergie totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.EnergieFrottement().EnergieElastique(); };
};
break;
}
case CONTACT_ENERG_GLISSE_PLAS:
{// ----- on attribue l'énergie de pénalisation au noeud projectile
// on met l'énergie totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.EnergieFrottement().DissipationPlastique(); };
};
break;
}
case CONTACT_ENERG_GLISSE_VISQ:
{// ----- on attribue l'énergie de pénalisation au noeud projectile
// on met l'énergie totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.EnergieFrottement().DissipationVisqueuse(); };
};
break;
}
case CONTACT_NB_DECOL:
{// ----- on attribue le nombre de décolement au noeud projectile
// on met le totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.Nb_decol(); };
};
break;
}
case CONTACT_COLLANT:
{// ----- on attribue le fait d'être collant ou pas au noeud projectile
// on met le totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.Collant(); };
};
break;
}
case NUM_ZONE_CONTACT:
{// ----- on attribue le numéro de zone de contact au noeud projectile
// on met le totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.Num_zone_contact(); };
};
break;
}
case CONTACT_NB_PENET:
{// ----- on attribue le nombre de décolement au noeud projectile
// on met le totale s'il y a plusieurs contacts
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) += elcont.Nb_pene(); };
};
break;
}
case CONTACT_CAS_SOLIDE:
{// ----- on attribue le nombre au noeud projectile
// =0 contact bi déformable, =1 le noeud est libre et la frontière est bloqué (solide)
// = 2 le noeud est bloqué (solide) la frontière est libre
// = 3 tout est solide
// ici on ne met pas le totale s'il y a plusieurs contacts !!
// c'est le dernier élément qui contient le noeud projectile, qui donne le résultat
// on parcours la liste des élément en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact & elcont = (*ili); // pour simplifier
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
tyqN.Grandeur_pointee());
if (elcont.Actif())
{*(tyTQ.ConteneurDouble()) = elcont.Cas_solide(); };
};
break;
}
default: ;// on ne fait rien
};
};
};
};
// récupération de la liste de tous les grandeurs particulières disponibles avec le contact
// cette liste est identique quelque soit le maillage: il n'y a donc pas de tableau indicé du num de maillage
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io<TypeQuelconque> LesContacts::ListeGrandeurs_particulieres(bool absolue) const
{
// def de la liste de retour
List_io <TypeQuelconque> liTQ;
// on ne ramène les infos que si le contact est actif
if (ParaGlob::param->ParaAlgoControleActifs().ContactType()!= 0)
{
// grandeurs de travail
int dim = ParaGlob::Dimension();
// ici on est en 3D et les grandeurs sont par principe en absolue, donc la variable absolue ne sert pas
Grandeur_scalaire_double grand_courant(0.);
Coordonnee inter(dim);
Grandeur_coordonnee grand_coor_courant(inter);
// def d'un type quelconque représentatif à chaque grandeur
// a priori ces grandeurs sont défini aux noeuds
//on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
// $$$ cas de la visualisation des noeuds projectiles en contact
{TypeQuelconque typQ1(NOEUD_PROJECTILE_EN_CONTACT,X1,grand_courant);
liTQ.push_back(typQ1);
};
// $$$ cas de la visualisation des noeuds des facettes en contact
{TypeQuelconque typQ1(NOEUD_FACETTE_EN_CONTACT,X1,grand_courant);
liTQ.push_back(typQ1);
};
// $$$ cas de la visualisation du glissement des noeuds projectiles actifs
{TypeQuelconque typQ1(GLISSEMENT_CONTACT,X1,grand_coor_courant);
liTQ.push_back(typQ1);
};
2023-05-03 17:23:49 +02:00
// $$$ cas de la visualisation de la normale de contact (moyenne)
{TypeQuelconque typQ1(NORMALE_CONTACT,X1,grand_coor_courant);
liTQ.push_back(typQ1);
};
2023-05-03 17:23:49 +02:00
// // $$$ cas de la visualisation de la normale aux noeuds frontières
// {TypeQuelconque typQ1(N_FRONT,X1,grand_coor_courant);
// liTQ.push_back(typQ1);
// };
// $$$ cas de la visualisation de la pénétration en contact
{TypeQuelconque typQ1(PENETRATION_CONTACT,X1,grand_coor_courant);
liTQ.push_back(typQ1);
};
// $$$ cas de la visualisation des forces de contact
{TypeQuelconque typQ1(FORCE_CONTACT,X1,grand_coor_courant);
liTQ.push_back(typQ1);
};
// $$$ nombre de pénétration
{TypeQuelconque typQ1(CONTACT_NB_PENET,X1,grand_courant);
liTQ.push_back(typQ1);
};
// $$$ nombre de décolement
{TypeQuelconque typQ1(CONTACT_NB_DECOL,X1,grand_courant);
liTQ.push_back(typQ1);
};
// $$$ cas_solide
{TypeQuelconque typQ1(CONTACT_CAS_SOLIDE,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(CONTACT_ENERG_PENAL,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(CONTACT_ENERG_GLISSE_ELAS,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(CONTACT_ENERG_GLISSE_PLAS,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(CONTACT_ENERG_GLISSE_VISQ,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(CONTACT_PENALISATION_N,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(CONTACT_PENALISATION_T,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(CONTACT_COLLANT,X1,grand_courant);
liTQ.push_back(typQ1);
};
{TypeQuelconque typQ1(NUM_ZONE_CONTACT,X1,grand_courant);
liTQ.push_back(typQ1);
};
};
// retour
return liTQ;
};
// concernant les grandeurs gérées par le contact:
// ramène une liste d'enuméré correspondant aux List_io<TypeQuelconque> passé en paramètre
// idem pour une List_io < Ddl _enum_etendu >
void LesContacts::List_reduite_aux_contact(const List_io<TypeQuelconque>& liTQ
,List_io < TypeQuelconque >& li_restreinte_TQ
)
{
// initialisation des listes de retour
li_restreinte_TQ.clear();
// on passe en revue la liste
List_io<TypeQuelconque>::const_iterator itq,itqfin=liTQ.end();
for (itq=liTQ.begin();itq!=itqfin;itq++)
{const TypeQuelconque& tipParticu = (*itq); // pour simplifier
const TypeQuelconque_enum_etendu& enuTypeQuelconque = tipParticu.EnuTypeQuelconque();
if (enuTypeQuelconque.Nom_vide()) // veut dire que c'est un enum pur
switch (enuTypeQuelconque.EnumTQ())
{ case NOEUD_PROJECTILE_EN_CONTACT: case NOEUD_FACETTE_EN_CONTACT:
case PENETRATION_CONTACT: case FORCE_CONTACT:
case CONTACT_PENALISATION_N: case CONTACT_PENALISATION_T:
case CONTACT_ENERG_PENAL: case NORMALE_CONTACT:
case GLISSEMENT_CONTACT: case CONTACT_ENERG_GLISSE_ELAS:
case CONTACT_ENERG_GLISSE_VISQ: case CONTACT_ENERG_GLISSE_PLAS:
case CONTACT_NB_DECOL: case CONTACT_NB_PENET:
case CONTACT_CAS_SOLIDE: case CONTACT_COLLANT:
2023-05-03 17:23:49 +02:00
case NUM_ZONE_CONTACT: //case N_FRONT :
{// ----- cas des noeuds projectiles en contact
li_restreinte_TQ.push_front(TypeQuelconque(tipParticu));
break;
}
default: ;// on ne fait rien
};
};
};
// initialisation des listes de grandeurs qu'ils faudra transférérer aux niveaux des noeuds des élements
// de contact, on définit si besoin, les conteneurs ad hoc au niveau des noeuds
void LesContacts::Init_Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ)
{liQ_en_sortie = liTQ; // on récupère la liste --> sans doute que cela ne sert à rien
LaLIST<ElContact>::iterator ili_deb= listContact.begin();
LaLIST<ElContact>::iterator ilifin= listContact.end();
LaLIST<ElContact>::iterator ili;
// on passe en revue la liste
List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
// on part du principe qu'il y a plus de noeuds en contact que de grandeur donc on fait une
// boucle externe sur les noeuds en contact: on parcours la liste des noeuds en contact
for (ili=ili_deb;ili!=ilifin;ili++)
{ElContact& elcont = (*ili); // pour simplifier
for (itq=liTQ.begin();itq!=itqfin;itq++)
{TypeQuelconque& tipParticu = (*itq); // pour simplifier
EnumTypeQuelconque enuTQ = tipParticu.EnuTypeQuelconque().EnumTQ();
switch (enuTQ)
{ case NOEUD_PROJECTILE_EN_CONTACT: case NOEUD_FACETTE_EN_CONTACT:
case GLISSEMENT_CONTACT: case PENETRATION_CONTACT:
case FORCE_CONTACT: case CONTACT_NB_PENET:
case CONTACT_PENALISATION_N: case CONTACT_PENALISATION_T:
case CONTACT_NB_DECOL: case CONTACT_CAS_SOLIDE:
case CONTACT_ENERG_PENAL: case CONTACT_COLLANT:
2023-05-03 17:23:49 +02:00
case NUM_ZONE_CONTACT: //case N_FRONT :
case NORMALE_CONTACT: case CONTACT_ENERG_GLISSE_ELAS:
case CONTACT_ENERG_GLISSE_VISQ: case CONTACT_ENERG_GLISSE_PLAS:
{// ----- cas des noeuds projectiles en contact
elcont.Esclave()->AjoutUnTypeQuelconque(*itq); // ajout du conteneur
break;
}
default: ; // sinon rien
};
};
};
} ;
//========================== fonction protegee =============================
// mise à jour des boites d'encombrement pour les éléments qui contiennent une frontière
void LesContacts::Mise_a_jour_boite_encombrement_element_contenant_front()
{
list <Element *>::iterator il,ilfin = liste_elemens_front.end();
for (il = liste_elemens_front.begin();il!=ilfin;il++)
(*il)->Boite_encombre_element(TEMPS_tdt);
};
// suppression du gap de contact pour les noeuds "collant avec suppression de gap"
void LesContacts::Suppression_gap_pour_noeud_collant()
{
2023-05-03 17:23:49 +02:00
int niveau_commentaire_lescontacts = Permet_affichage();
// on passe en revue les zones de contact et si nécessaire on supprime les gaps
// sinon retour
bool continuer = false; // init par défaut
// list <quatre_string_un_entier> nom_ref_zone_contact; // liste des noms de références des zones de contact
list <quatre_string_un_entier>::iterator iu,iufin = nom_ref_zone_contact.end();
for (iu = nom_ref_zone_contact.begin();iu != iufin; iu++)
if ((*iu).n == 2)
{continuer = true; break;};
if (!continuer)
return;
// sinon il faut effectivement faire une suppression de gap
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts > 2)
cout << "\n >>>> Suppression_gap_pour_noeud_collant : ";
// on va iterer sur les noeuds esclaves collants dont on veut supprimer le gap
LaLIST_io <Front>::iterator iM,iMfin; // des itérator de travail
int nb_zone = MaX(1,nom_ref_zone_contact.size());
double dist_max = Dabs(ParaGlob::param->ParaAlgoControleActifs().DistanceMaxiAuPtProjete());
int tout_projeter = true; // init
int boucle_maxi = 10; // 10 boucle maxi
int boucle = 1;
do
2023-05-03 17:23:49 +02:00
{ if (niveau_commentaire_lescontacts >2 )
cout << "\n boucle : "<<boucle << flush;
for (int intot = 1;intot<= nb_mail_Esclave;intot++) // boucle sur les maillages esclaves
for (int j=1;j<=nb_zone;j++) // boucle sur les zones de contact
{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(); // tab des noeuds esclaves à considérer
int compteur_noeuds_projecte=0; // le nombre de noeuds qui sont projetés
double le_maxi_des_distances_trouve = 0.;
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
if (tesN_col(inesc) == 2 ) // cas noeud collant avec volonté de supprimer le gap
{ Noeud* noee = tesc(inesc); // pour simplifier
//--- debug
//if (noee->Num_noeud() == 5)
// {cout << "\n arrivée au bon element ";
// }
const Coordonnee pt_esc = noee->Coord0(); // position du noeud esclave initial
list <Coordonnee > list_P; // la liste des projetés
list <LaLIST_io <Front>::iterator> li_pt_front_P; // liste sur les faces pour le debug
for (int jlf=1;jlf<=nbmailMaitre;jlf++) // boucle sur les maillages maitres
{//Tableau < Tableau < LaLIST_io <Front> > > t_listFront;
LaLIST_io <Front>& t_l_front = t_listFront(jlf)(j);
iMfin=t_l_front.end();
for (iM = t_l_front.begin() ; iM != iMfin; iM++) // boucle sur les front maitres
{// si c'est dans le volume de la frontière augmenté de la distance ad hoc on test
// plus précisément
if ((*iM).In_boite_emcombrement_front(pt_esc,dist_max))
{// on projete le noeud sur la frontière
Coordonnee P;
////--- debug
//if ((noee->Num_noeud() == 5) && ((*iM).PtEI()->Num_elt()==367))
// {cout << "\n arrivée au bon element ";
//
// }
//{double Ndis = (P-pt_esc).Norme();
// if (Ndis > 20)
// (*iM).Eleme()->Projection_normale(pt_esc,P);
//}
//-- fin debug
// //----debug
//{if ((noee->Num_noeud() == 12)
// && ((*iM).Num_frontiere() == 1) && ((*iM).PtEI()->Num_elt() == 3130))
// { cout << "\n debug : frontiere 1 de l'element 3130";}
//}
////----fin debug
// si la projection est valide on enregistre
if ((*iM).Eleme()->Projection_normale(pt_esc,P))
{ list_P.push_back(P);
li_pt_front_P.push_back(iM);
};
//--- debug
//{double Ndis = (P-pt_esc).Norme();
// if (Ndis > 20)
// (*iM).Eleme()->Projection_normale(pt_esc,P);
//}
//-- fin debug
};
};
};
// maintenant on va garder le plus proche
bool projection_ok = false; // init
if (list_P.size() != 0)
{list <Coordonnee >::iterator il,ilfin=list_P.end();
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts >5 )
{cout << "\n " << list_P.size() << " proj trouvees "
<< " Noe: "<<noee->Num_noeud()
<< " mail: " << noee->Num_Mail() << " (zone"<<j<<")";
};
Coordonnee M = pt_esc; // init
Coordonnee P(M); // la projection
double distance = dist_max;
LaLIST_io <LaLIST_io <Front>::iterator>::iterator iface = li_pt_front_P.begin();
LaLIST_io <LaLIST_io <Front>::iterator>::iterator iface_maxi ;
for (il=list_P.begin(); il!= ilfin;il++,iface++)
{ double Ndis = (M-(*il)).Norme();
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts >5 )
cout << " dist: " << Ndis ;
if (Ndis < distance)
{P = (*il); distance = Ndis;
projection_ok = true; // au moins un nouveau point
iface_maxi = iface;
};
};
// si la distance == 0., il n'y a pas à changer les coordonnées
// car le point projeté == le point initial
if (distance > ConstMath::petit)
{// on change les coordonnées du noeud
noee->Change_coord0(P);
noee->Change_coord1(P);
noee->Change_coord2(P);
compteur_noeuds_projecte++;
tout_projeter=false;
if (distance > le_maxi_des_distances_trouve)
le_maxi_des_distances_trouve = distance;
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts >3 )
cout << "\n suppression gap=("<<distance<<") du noeud "<<noee->Num_noeud()
<< " du maillage " << noee->Num_Mail() << " (zone "<<j<<")";
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts >4 )
{cout << "\n ancienne coordonnee "<< pt_esc
<< " nouvelle " << P;
// dans le cas où iface_maxi a été attribué
if (projection_ok)
(*(*iface_maxi)).Affiche();
////--- debug
//{
//const Coordonnee pt_esc = noee->Coord0();
//Coordonnee PP;
//(*(*iface_maxi)).Eleme()->Projection_normale(pt_esc,PP);
//cout << "\n $$$ nouvelle coordonnees projetee "<< PP;
//}
////-- fin debug
};
}
else if (projection_ok)
// si on n'a pas de projection avec changement de position
// mais par contre on a quand même trouvé un projeté on enregistre
{compteur_noeuds_projecte++;};
};
if ((!projection_ok) && (boucle==1)) // au premier passage
2023-05-03 17:23:49 +02:00
{ if (niveau_commentaire_lescontacts >3 )
cout << "\n pas de projection trouvee donc de suppression gap du noeud "<<noee->Num_noeud()
<< " du maillage" << noee->Num_Mail() << " (zone "<<j<<")";
} ;
}; //-- fin de la boucle sur inesc
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts >2 )
{if (compteur_noeuds_projecte)
cout << "\n zone: " << j <<", " << compteur_noeuds_projecte << " suppression(s) de gap, maxi_distance= "
<< le_maxi_des_distances_trouve << "( passage"<<boucle<<")" ;
int non_gap = tesc_taille-compteur_noeuds_projecte;
if ((non_gap)&& (boucle==1)) // au premier passage
cout << "\n zone: " << j <<", *** attention pour "<<non_gap
<< " noeud(s) pas de projection trouvee !! ";
};
}; //-- fin de la boucle sur intot
boucle++;
}
while ((!tout_projeter) && (boucle < boucle_maxi));
// Sortie(1);
};
// récupération de la zone de contact d'un élément de contact existant
// c'est un peu lourdinge, mais l'avantage c'est que cela s'adapte à une situation qui
// a par exemple changé
// si en retour le numéro de zone = 0, cela signifie que le contact ne peut plus exister
int LesContacts::Recup_ref( ElContact& al)
{ int nb_zone = MaX(1,nom_ref_zone_contact.size());
const Tableau <Noeud*>& tn = al.TabNoeud();
int num_mail_esclave = tn(1)->Num_Mail();
int num_mail_maitre = tn(2)->Num_Mail();
int num_noe = tn(1)->Num_noeud();
// on parcours la liste des frontières succeptibles d'entrer en contact
// pour repérer la zone
int num_zone = 0; // init
int nb_maitre = t_listFront.Taille();
int nb_esclave = tesctotal.Taille();
for (int i=1;i<=nb_maitre;i++)
{for (int j=1;j<=nb_zone;j++)
{LaLIST_io <Front> & list_fronta = t_listFront(i)(j); // pour simplifier
LaLIST_io <Front>::iterator il,ilfin = list_fronta.end();
for (il = list_fronta.begin();il != ilfin; il++)
{if ((*il)==(*al.Elfront()))
// les deux pointeurs pointent sur la même frontière, donc
// maintenant on regarde du coté des noeuds esclaves
{ for (int ie = 1; ie<=nb_esclave;ie++)
{const Tableau <Noeud*>& tesc= tesctotal(i)(j); // pour simplifier la notation:
int tesc_taille=tesc.Taille(); // tab des noeuds esclaves à considérer
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
{if (tesc(inesc) == al.Esclave())
// les deux pointeurs pointent sur le même noeud, c'est ok
{num_zone = j; break;};
};
if (num_zone)
break;
};
};
if (num_zone)
break;
};
if (num_zone)
break;
};
if (num_zone)
break;
};
// retour des infos
return num_zone;
};
// création d'un tableau de condition linéaire, correspondant à tous les éléments de contact en cours
// qu'ils soient actifs ou pas (a prior cette méthode est conçu pour donner des infos relativement à la largeur
// de bandes en noeuds due aux CLL)
// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL,
const Tableau <Condilineaire>& LesContacts::ConnectionCLL()
{
// on boucle sur le tableau et pour chaque element on crée une condition lineaire
int tabTaille = listContact.size();
t_connectionCLL.Change_taille(tabTaille);
// un tableau servant à la def de la CLL
Tableau <Enum_ddl > t_enu(1); t_enu(1)=X1 ;
LaLIST <ElContact>::const_iterator il,ilfin=listContact.end();
int posi=1; // init pour le tableau
for (il=listContact.begin();il != ilfin;il++,posi++)
{ const Tableau < Noeud *>& t_n = (*il).Const_TabNoeud();
// on est dans le cas ou l'on connait les infos relatives uniquements aux noeuds, aux enum ddl
t_connectionCLL(posi) = Condilineaire(t_enu, t_n);
};
// retour
return t_connectionCLL;
};
// récupère le nombre de contact actif et met à jour ce nombre
// normalement devrait toujours être correct mais ?? il y a quelque chose d'incorrecte quelque part
2023-05-03 17:23:49 +02:00
int LesContacts::Calcul_Nb_contact_actif()
{ LaLIST <ElContact>::iterator il,ilfin = listContact.end();
nb_contact_actif = 0; // init
for (il = listContact.begin();il != ilfin; il++)
if ((*il).Actif())
nb_contact_actif++;
return nb_contact_actif;
};
// création du conteneur Fct_nD_contact
void LesContacts::Creation_Fct_nD_contact()
{
{// cas de la penalisation normale
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penalisationPenetration();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_penalisationPenetration = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage de la penalisation normale "
<< " le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_penalisationPenetration=NULL;};
};
{// cas fct_nD_penetration_contact_maxi
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penetration_contact_maxi();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_penetration_contact_maxi = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage de la "
<< " penetration maxi, le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_penetration_contact_maxi=NULL;};
};
{// cas Fct_nD_penetration_borne_regularisation
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penetration_borne_regularisation();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_penetration_borne_regularisation = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage de la "
<< " borne de regularisation, le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_penetration_borne_regularisation=NULL;};
};
{// cas fct_nD_force_contact_noeud_maxi
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_force_contact_noeud_maxi();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_force_contact_noeud_maxi = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage de la "
<< " force de contact normale, le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_force_contact_noeud_maxi=NULL;};
};
{// cas fct_nD_penalisationTangentielle
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penalisationTangentielle();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_penalisationTangentielle = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage de la penalisation tangentielle "
<< " le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_penalisationTangentielle=NULL;};
};
{// cas fct_nD_tangentielle_contact_maxi
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_tangentielle_contact_maxi();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_tangentielle_contact_maxi = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage du "
<< " deplacement tangentiel maxi, le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_tangentielle_contact_maxi=NULL;};
};
{// cas fct_nD_tangentielle_borne_regularisation
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_tangentielle_borne_regularisation();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_tangentielle_borne_regularisation = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage de la "
<< " borne de regularisation tangentielle, le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_tangentielle_borne_regularisation=NULL;};
};
{// cas fct_nD_force_tangentielle_noeud_maxi
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_force_tangentielle_noeud_maxi();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_nD_force_tangentielle_noeud_maxi = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage de la "
<< " force tangentielle maxi, le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_nD_force_tangentielle_noeud_maxi=NULL;};
};
2023-05-03 17:23:49 +02:00
{// cas fct_niveau_commentaire
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_niveau_commentaire_contact();
if (nom_fct != "_")
{// on va récupérer la fonction
if (sauve_lesFonctionsnD->Existe(nom_fct))
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
// sauvegarde
fct_nD_contact.fct_niveau_commentaire = pt_fonct;
}
else
{ cout << "\n *** erreur dans la definition de la fonction nD de pilotage du "
<< " niveau de commentaire en contact, le nom : " << nom_fct
<< " ne correspond pas a une fonction nD existante !! ";
Sortie(1);
};
}
else
{fct_nD_contact.fct_niveau_commentaire=NULL;};
};
// initialisation des conteneurs statique des fonction nD
fct_nD_contact.Init_conteneur_statique();
};
/*// mise à jour du stockage inter, pour prendre en
// compte une nouvelle numérotation des noeuds
void LesContacts::Prise_en_compte_nouvelle_numerotation_noeud()
{ //on va reconstruire ta_inverse
int nb_zone = MaX(1,nom_ref_zone_contact.size());
// on garde en mémoire les anciens numéros pour faire le pontage
Tableau < Tableau < Tableau <int> > > ta_inverse_old(ta_inverse);
// on recherche les maxi des numéros de noeuds esclave, pour dimensionner ta_inverse !!
Tableau < Tableau <int> > maxi_num_noe_esclave(nb_mail_Esclave); // init à 0
for (int i=1;i<=nb_mail_Esclave;i++)
{maxi_num_noe_esclave(i).Change_taille(nb_zone);
for (int j=1;j<=nb_zone;j++)
{const Tableau <Noeud*>& tesc= tesctotal(i)(j); // pour simplifier la notation:
int tesc_taille=tesc.Taille(); // tab des noeuds esclaves à considérer
int& max_num_esclave = maxi_num_noe_esclave(i)(j); // pour simplifier
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
{ Noeud* noee = tesc(inesc); // pour simplifier
int num_noeud = noee->Num_noeud();
if (num_noeud > max_num_esclave)
max_num_esclave = num_noeud;
};
};
};
// Maintenant on peut dimensionner ta_inverse
for (int i=1;i<=nb_mail_Esclave;i++)
{ta_inverse(i).Change_taille(nb_zone);
for (int j=1;j<=nb_zone;j++)
ta_inverse(i)(j).Change_taille(maxi_num_noe_esclave(i)(j),0);
};
// ensuite on va remplir ta_inverse
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:
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
ta_inverse(intot)(j)(noee->Num_noeud()) = inesc;
};
};
};
// on va créer un tableau de changement des numéros de noeuds
Tableau < Tableau <int> > nouveau_Noe(nb_mail_Esclave);
// on cherche la taille maxi
Tableau <int> maxi_maxi_num_noe_esclave(nb_mail_Esclave); // les maxis pour chaque maillage
for (int i=1;i<=nb_mail_Esclave;i++)
{int& max_max_esclave = maxi_maxi_num_noe_esclave(i) = 0; // init
for (int j=1;j<=nb_zone;j++)
{int& max_num_esclave = maxi_num_noe_esclave(i)(j); // pour simplifier
if (max_num_esclave > max_max_esclave)
max_max_esclave = max_num_esclave;
};
};
// on balaie les anciens noeuds
for (int i=1;i<=nb_mail_Esclave;i++)
{nouveau_Noe(i).Change_taille(maxi_maxi_num_noe_esclave(i));
Tableau <int>& nouveau_Noe_i = nouveau_Noe(i);
for (int j=1;j<=nb_zone;j++)
{ Tableau <int> & ta_inverse_old_ij = ta_inverse_old(i)(j);
Tableau <int> & ta_inverse_ij = ta_inverse(i)(j);
int nbN = ta_inverse_old_ij.Taille();
for (int k=1;k<= nbN;k++) // k c'est le numéro de l'ancien noeud
{if (ta_inverse_old_ij(k) != 0)
{for (int k2=1;k2<= nbN;k2++)
{ if (ta_inverse_old_ij(k) == ta_inverse_ij(k2))
{nouveau_Noe_i(k)=k2;break;};
};
};
};
};
};
// // maintenant on met à jour le tableau tesN_encontact
// // Tableau < Tableau < LaLIST < LaLIST<ElContact>::iterator > > > tesN_encontact;
// // on sauvegarde l'ancien
// Tableau < Tableau < LaLIST < LaLIST<ElContact>::iterator > > > tesN_encontact_old(tesN_encontact);
// // et on fait la passation
// for (int i=1;i<=nb_mail_Esclave;i++)
// {Tableau <int>& nouveau_Noe_i = nouveau_Noe(i);
// int nbn = tesN_encontact(i).Taille();
// for (int j=1;j<=nbn;j++)
// { tesN_encontact(i)(nouveau_Noe_i(j)) = tesN_encontact_old(i)(j);
// };
// };
// on continue avec le tableau: liste pour chaque noeud, des éléments qui contient ce noeud
// indice(i)(j) : = la liste des éléments qui contiennent le noeud j, pour le maillage i
Tableau < const Tableau <List_io < Element* > > *> indice_old(indice);
int nb_mail = indice_old.Taille();
for (int i=1;i<=nb_mail;i++)
{if (indice_old(i) != NULL)
{ int nbn = indice_old(i)->Taille();
// const Tableau <List_io < Element* > > & indice_i = indice(i);
// for (int j=1;j<=nbn;j++)
//indice
}
}
cout << "\n LesContacts::Prise_en_compte_nouvelle_numerotation_noeud() pas terminé !!"
<< " il faut changer lesMaillages pour récupérer directement la nouvelle numérotation !!";
Sortie(1);
};
*/
// récupération via les éléments de contact des forces maxis
// et affichage éventuel
// un : le maxi en effort normal, deux: le maxi en effort tangentiel
DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche) const
{DeuxDoubles retour;
2023-05-03 17:23:49 +02:00
int niveau_commentaire_lescontacts = Permet_affichage();
LaLIST <ElContact>::const_iterator iNmax,iTmax,il,ilfin = listContact.end();
for (il = iNmax = iTmax = listContact.begin();il != ilfin; il++)
if ((*il).Actif())
{ const ElContact& icont = (*il); // pour simplifier
double fNmax = icont.F_N_MAX();
double fTmax = icont.F_T_MAX();
if (Dabs(fNmax) > Dabs(retour.un) )
2023-05-03 17:23:49 +02:00
{retour.un = fNmax;iNmax = il;
};
if (Dabs(fTmax) > Dabs(retour.deux) )
2023-05-03 17:23:49 +02:00
{retour.deux = fTmax;iTmax = il;
};
};
if ((affiche && (ParaGlob::NiveauImpression() > 2))
2023-05-03 17:23:49 +02:00
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
)
cout << "\n contact: reaction ==> F_N max " << retour.un << " F_T max " << retour.deux;
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts > 6)
{cout << "\n F_N max: "; (*iNmax).Affiche(0);
cout << "\n F_T max: "; (*iTmax).Affiche(0);
cout << "\n";
}
else if (niveau_commentaire_lescontacts > 3)
{cout << "\n F_N max: "; (*iNmax).Affiche(1);
cout << "\n F_T max: "; (*iTmax).Affiche(1);
cout << "\n";
};
return retour;
};
// récupération via les éléments de contact des gaps maxis
// un : le maxi en gap normal, deux: le maxi en gap tangentiel
DeuxDoubles LesContacts::Gap_contact_maxi(bool affiche) const
{DeuxDoubles retour;
2023-05-03 17:23:49 +02:00
LaLIST <ElContact>::const_iterator iNmax,iTmax,il,ilfin = listContact.end();
for (il = iNmax = iTmax = listContact.begin();il != ilfin; il++)
if ((*il).Actif())
{ const ElContact& icont = (*il); // pour simplifier
double fNmax = icont.Gaptdt();
double fTmax = icont.Dep_T_tdt();
if (Dabs(fNmax) > Dabs(retour.un) )
2023-05-03 17:23:49 +02:00
{retour.un = fNmax;iNmax = il;
};
if (Dabs(fTmax) > Dabs(retour.deux) )
2023-05-03 17:23:49 +02:00
{retour.deux = fTmax;iTmax = il;
};
};
2023-05-03 17:23:49 +02:00
int niveau_commentaire_lescontacts = Permet_affichage();
if ((affiche && (ParaGlob::NiveauImpression() > 2))
2023-05-03 17:23:49 +02:00
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
)
cout << ", maxi gap_N : " << retour.un << " gap_T : " << retour.deux;
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts > 6)
{cout << "\n maxi gap_N : "; (*iNmax).Affiche(0);
cout << "\n maxi gap_T : "; (*iTmax).Affiche(0);
}
else if (niveau_commentaire_lescontacts > 3)
{cout << "\n maxi gap_N : "; (*iNmax).Affiche(1);
cout << "\n maxi gap_T : "; (*iTmax).Affiche(1);
};
return retour;
};
2023-05-03 17:23:49 +02:00
// création et ajout des éléments de frontière correspondant aux angles morts
// en 2D : noeud frontière + éléments interne
// en 3D : ligne frontière + éléments interne
void LesContacts::ElementAngleMort(LesMaillages& lesMail)
{
// la liste des éléments qui contiennent des frontières, est reconstitué au démarrage avec Init_contact(..
//>>>>> list <Element *> liste_elemens_front;
// la liste pour chaque noeud, des éléments qui contient ce noeud : construite avec Init_contact
// indice(i)(j) : = la liste des éléments qui contiennent le noeud j, pour le maillage i
//>>>>> Tableau < const Tableau <List_io < Element* > > *> indice;
// la liste des éléments frontières succeptibles d'entrer en contact
// ces Front (qui contiennent que des pointeurs sauf une boite d'encombrement)
// sont différents de ceux des maillages, et sont donc stocké en interne
//>>>>> Tableau < Tableau < LaLIST_io <Front> > > t_listFront;
// t_listFront(i)(j)(k) : maillage maître (i)
// zone de contact (j)
// (K) = kième frontière (dans l'ordre de la liste)
// ** pour le tableaux t_listFront, le numéros dit de maillage, n'est pas le numéro
// ** intrinsèque de maillage (telle que ceux associés aux noeuds et éléments)
// ** mais uniquement un numéro locale d'ordre
// ** mais on a: les éléments de frontière de t_listFront(i) font partie du maillage
// i + (nb_mail_Esclave-nbmailautocontact)
int niveau_commentaire_lescontacts = Permet_affichage();
if (niveau_commentaire_lescontacts > 4)
cout << "\n ==> LesContacts::ElementAngleMort: ";
// --- à la fin du traitement on a besoin de mettre à jour les éléments mitoyens des Front
// --- on sauvegarde des infos
Tableau < Tableau < list <Front*> > > t_listFront_initial; // les pointeurs de front initiaux sans les angles morts
// t_liFront_noeud(i)(j)(k) : la liste des frontières initiales qui contiennent le noeud k de la zone j du maillage i
Tableau < Tableau < Tableau < list <Front*> > > > t_liFront_noeud;
t_liFront_noeud.Change_taille(lesMail.NbMaillage());
//**** à faire la même chose pour les elements segment .....
int tail1 = t_listFront.Taille(); // num ordre dans les maillages
t_listFront_initial.Change_taille(tail1);
for (int i =1;i<= tail1;i++)
{int i_mail = i + (nb_mail_Esclave-nbmailautocontact); // le num de maillage
int nb_noe_total = lesMail.Nombre_noeud(i_mail); // le nombre total de noeud du maillage
int tail2=t_listFront(i).Taille(); // nombre de zones
t_listFront_initial(i).Change_taille(tail2);
t_liFront_noeud(i).Change_taille(tail2);
for (int j=1;j<= tail2;j++) // on balaie les zones
{list <Front*> & t_listFront_initial_ij = t_listFront_initial(i)(j); // pour simplifier
LaLIST_io <Front> & t_listFront_ij = t_listFront(i)(j); // pour simplifier
// on dimensionne au nombre maxi de noeud pour chaque zone ...
// ça peut faire des gros tableaux mais il faut bien que l'on sache à quelle zone on s'intéresse ...
// donc pour l'instant c'est l'idée que je retiens
t_liFront_noeud(i)(j).Change_taille(nb_noe_total);
Tableau <list <Front*> >& t_liFront_noeud_ij = t_liFront_noeud(i)(j);
LaLIST_io <Front>::iterator il,ilfin=t_listFront_ij.end();
for (il = t_listFront_ij.begin();il != ilfin; il++)
{t_listFront_initial_ij.push_back(&(*il));
// on va remplir t_liFront_noeud_ij
ElFrontiere* elfro = (*il).Eleme(); // pour simplifier
const Tableau <Noeud *>& tabN = elfro->TabNoeud_const();
int nbNF = tabN.Taille();
for (int l=1;l<=nbNF;l++)
{ Noeud * noe = tabN(l);
t_liFront_noeud_ij(noe->Num_noeud()).push_back(&(*il));
};
};
};
};
// --- constitution des front d'angle mort
// l'idée est de rechercher les éléments qui sont en relation directe avec la frontière
// via une ligne ou un point, mais qui n'ont été pris en compte du fait qu'ils n'étaient pas
// reliés à une frontière de base
// on commence par les lignes ce qui conduit éventuellement à augmenter t_listFront
// ensuite on regarde les noeuds. Ainsi, si un élément nouveau est introduit via les lignes
// les noeuds de la ligne + l'élément ne vont pas s'ajouter
// 1) === cas des lignes frontières + éléments internes
// ce cas ne concerne que les espaces de travail 3D non axisymétrique
if ((ParaGlob::Dimension() == 3) && !(ParaGlob::AxiSymetrie()))
{ // on crée les frontières lignes au cas où
lesMail.CreeListFrontiere_ligne_3D();
// on récupère toutes les frontières lignes
// ramène le tableau de pointeurs de frontières ligne 3D créées par CreeListFrontiere_ligne_3D
Tableau <LaLIST <Front>*>& lifrLigne = lesMail.ListFront_ligne_3D();
if (nom_ref_zone_contact.size() == 0)
{ // cas d'un contact non restreint
// cela correspond finalement à une seule zone de contact (cf. Init_contact(..))
//on boucle sur les maillages maitres de t_listFront
for (int im=1;im<=nbmailMaitre;im++)
{ // ici on ne boucle pas sur les zones restreintes car il n'y en n'a pas
LaLIST_io <Front> & la_list_des_front = t_listFront(im)(1);
int nb_front_init = la_list_des_front.size(); // la taille initiale
LaLIST <Front>& lifrLigne_mail = *lifrLigne(im); // pour simplifier
// avant de balayer les lignes, on fait une liste des éléments qui contiennent des frontières déjà référencées
list <const Element* > li_Elem_avec_front;
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
for (il = la_list_des_front.begin(); il != ilfin; il++)
li_Elem_avec_front.push_back((*il).PtEI());
// on supprime les doublons et on ordonne, c'est pour l'opti des recherches ensuites
li_Elem_avec_front.sort(); // ordonne
li_Elem_avec_front.unique(); // supprime les doublons
// maintenant on regarde s'il faut ajouter des éléments d'angle mort
// on va boucler sur les frontières lignes 3D
LaLIST <Front>::iterator jl,jlfin=lifrLigne_mail.end();
for (jl = lifrLigne_mail.begin(); jl != jlfin; jl++)
{ Element * el = (*jl).PtEI();// récup de l'élément
// on regarde si cet élément ne fait pas partie de la liste d'élément
// qui contient déjà une frontière
if (find(li_Elem_avec_front.begin(),li_Elem_avec_front.end(),el) == li_Elem_avec_front.end())
// on n'a pas trouvé d'élément,
//on ajoute l'élément front sauf cas particulier
{// on fait quelques tests pour écarter des cas non recevable
bool continuer = true; // par défaut
// si on est en 3D et que l'élément est lui même un élément ligne, ou un
// élément de surface, il ne constitue pas un angle mort puisqu'il n'y à pas de volume mort associé
Enum_type_geom enu_type_geom_ele = Type_geom_generique(el->Id_geometrie());
if ((enu_type_geom_ele == LIGNE) && (enu_type_geom_ele == SURFACE))
{continuer = false;}
if (continuer)
// on doit indiquer qu'il s'agit d'un élément d'angle mort
// on se sert d'un élément intermédiaire
{Front inter((*jl));
inter.Change_angle_mort(1);
la_list_des_front.push_back(inter);
};
}
2023-05-03 17:23:49 +02:00
};
int nb_front_fin = la_list_des_front.size(); // la taille finale
if (niveau_commentaire_lescontacts >2 )
cout << "\n mail. maitre "<<im<<" : "<<(nb_front_fin-nb_front_init)
<< " frontieres segment pour angle mort pour contact ";
}; // fin de la boucle sur les maillages maitres
}
else
{ // cas d'une zone restreinte de contact
// on va boucler sur les zones définies pour le contact
//on boucle sur les maillages maitres de t_listFront
for (int im=1;im<=nbmailMaitre;im++)
{ LaLIST <Front>& lifrLigne_mail = *lifrLigne(im); // pour simplifier
// ici on boucle sur les zones restreintes
int nb_zone_et1 = 1+t_listFront(im).Taille();
for (int i_zone=1;i_zone < nb_zone_et1;i_zone++)
{// la liste des front de la zone
LaLIST_io <Front> & la_list_des_front = t_listFront(im)(i_zone);
int nb_front_init = la_list_des_front.size(); // la taille initiale
// avant de balayer les lignes, on fait une liste des éléments relatifs à la zone
// qui contiennent des frontières déjà référencées
list <const Element* > li_Elem_avec_front;
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
for (il = la_list_des_front.begin(); il != ilfin; il++)
li_Elem_avec_front.push_back((*il).PtEI());
// on supprime les doublons et on ordonne, c'est pour l'opti des recherches ensuites
li_Elem_avec_front.sort(); // ordonne
li_Elem_avec_front.unique(); // supprime les doublons
// maintenant on regarde s'il faut ajouter des éléments d'angle mort
// on va boucler sur les frontières lignes 3D
LaLIST <Front>::iterator jl,jlfin=lifrLigne_mail.end();
for (jl = lifrLigne_mail.begin(); jl != jlfin; jl++)
{ Element * el = (*jl).PtEI();// récup de l'élément
// on regarde si cet élément ne fait pas partie de la liste d'élément
// qui contient déjà une frontière
if (find(li_Elem_avec_front.begin(),li_Elem_avec_front.end(),el) == li_Elem_avec_front.end())
// on n'a pas trouvé d'élément,
//on ajoute l'élément front sauf cas particulier
{// on fait quelques tests pour écarter des cas non recevable
bool continuer = true; // par défaut
// si on est en 3D et que l'élément est lui même un élément ligne, ou un
// élément de surface, il ne constitue pas un angle mort puisqu'il n'y à pas de volume mort associé
Enum_type_geom enu_type_geom_ele = Type_geom_generique(el->Id_geometrie());
if ((enu_type_geom_ele == LIGNE) && (enu_type_geom_ele == SURFACE))
{continuer = false;}
if (continuer)
// on n'a pas trouvé d'élément, on ajoute l'élément front
// on doit indiquer qu'il s'agit d'un élément d'angle mort
// on se sert d'un élément intermédiaire
{Front inter((*jl));
inter.Change_angle_mort(1);
la_list_des_front.push_back(inter);
};
};
2023-05-03 17:23:49 +02:00
};
int nb_front_fin = la_list_des_front.size(); // la taille finale
if (niveau_commentaire_lescontacts >2 )
cout << "\n mail. maitre "<<im << " : zone de contact: " << i_zone
<<" : " <<(nb_front_fin-nb_front_init)
<< " frontieres segment pour angle mort pour contact ";
};// fin de la boucle sur les zones
}; // fin de la boucle sur les maillages maitres de t_listFront
}; // fin du test avec ou sans zone de contact
};
// 2) === maintenant on s'intéresse aux cas des noeuds frontières + éléments internes
Tableau <LaLIST <Front>*>& listFrontiere = lesMail.ListFrontiere();
int ntmail = listFrontiere.Taille(); // nb maxi de maillages
// 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 (cf. Init_contact(..))
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
//on boucle sur les maillages maitres de t_listFront
for (int jf=ntmail-nbmailMaitre+1;jf<=ntmail;jf++,ilistfront++)
{ // ici on ne boucle pas sur les zones restreintes car il n'y en n'a pas
LaLIST_io <Front> & la_list_des_front = t_listFront(ilistfront)(1);
int nb_front_init = la_list_des_front.size(); // la taille initiale
// pour continuer il faut: 1) qu'il y a des front, 2) que ces fronts appartiennent au maillage
if (nb_front_init > 0)
if ((*la_list_des_front.begin()).NumMail() == jf )
{
// on va créer une liste de numéro des noeuds de la zone de frontière concernée
// et en même temps
// avant de balayer les noeuds, on fait une liste des éléments relatifs à la zone
// qui contiennent des frontières déjà référencées
list <int> num_noe_front;
list <const Element* > li_Elem_avec_front;
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
for (il = la_list_des_front.begin(); il != ilfin; il++)
{ const Tableau <Noeud *>& tnoe = (*il).Eleme()->TabNoeud_const();
int nb_noe_et1 = tnoe.Taille();
for (int m =1;m<nb_noe_et1;m++)
num_noe_front.push_back(tnoe(m)->Num_noeud());
li_Elem_avec_front.push_back((*il).PtEI());
};
// on ordonne et on supprime les doublons
num_noe_front.sort(); // ordonne
num_noe_front.unique(); // suppression des doublons
li_Elem_avec_front.sort(); // ordonne
li_Elem_avec_front.unique(); // supprime les doublons
// on définit une liste temporaire des nouvelles front d'angle mort créé
// c'est utilisé pour définir les mitoyens des éléments d'angle morts
// qui sont apparus avec les angles morts (== les mitoyens angle mort des éléments angle morts !!)
list <Front *> front_angle_mort;
// maintenant on parcours les noeuds contenu dans num_noe_front
// et on regarde s'il faut ajouter des éléments point d'angle mort
list <int>::iterator ih,ih_fin=num_noe_front.end();
for (ih = num_noe_front.begin();ih != ih_fin;ih++)
{int i_noe = (*ih); // le num du noeud maître que l'on va tester
Tableau <Noeud *> ttn(1);
ttn(1)= &(lesMail.Noeud_LesMaille(jf,i_noe)); // récup du pointeur de noeud
// récup de la liste pour le noeud i_noe, des éléments qui contient ce noeud : construite avec Init_contact
const List_io < Element* >& liel = (*indice(jf))(i_noe);
// on boucle sur chaque élément qui contient le noeud
List_io < Element* >::const_iterator il,ilfin=liel.end();
for (il = liel.begin();il != ilfin;il++)
{const Element* el=(*il); // pour simplifier
// on regarde si cet élément ne fait pas partie de la liste d'élément
// qui contient déjà une frontière
bool trouver = false;
list <const Element* >::const_iterator ikl,iklfin=li_Elem_avec_front.end();
for (ikl = li_Elem_avec_front.begin();ikl != iklfin; ikl++)
{if (((*ikl)->Num_elt_const() == el->Num_elt_const()) && ((*ikl)->Num_maillage() == el->Num_maillage()))
{trouver= true; break;}
};
if (!trouver)
{// on n'a pas trouvé d'élément,
// 1. on récup le num local EF du noeud
int nb_noeu_el_et_1 = 1+el->Nombre_noeud(); // le nombre de noeud de l'élément
int num_noe_local = 0;
for (int k =1;k<nb_noeu_el_et_1;k++)
if (el->Num_noeud(k) == ttn(1)->Num_noeud())
{num_noe_local=k; break;};
// 2. on récupère la frontière noeud correspondante en forçant une création éventuelle
// on passe par l'intermédiaire de lesMail pour pouvoir modifier l'élément
// car c'est l'élément qui stocke et gère la frontière
Element& elem_non_const = lesMail.Element_LesMaille(el->Num_maillage(), el->Num_elt_const());
// on fait quelques tests pour écarter des cas non recevable
bool continuer = true; // par défaut
// a) si on est en 2D axi et que l'élément est un élément noeud ou un élément ligne, cela veut dire
// qu'il génére par rotation en 3D : une ligne ou une surface, or lignes ou surfaces n'intègrent pas
// d'élément de contact d'angle mort puisqu'il n'y à pas de volume mort associé
Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie());
if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE)))
{continuer = false;}
// b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
else if ((ParaGlob::Dimension() == 3)
&& ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE))
)
{continuer = false;}
// on continue sauf cas particulier
if (continuer)
{// 3. on crée l'élément de frontière ad hoc
ElFrontiere* const elfpoint = elem_non_const.Frontiere_points(num_noe_local,true);
// ramene le numero de la frontière passée en argument si elle existe actuellement au niveau de l'élément
// sinon ramène 0
// ramene également type_front: qui indique le type de frontière: POINT_G, LIGNE ou SURFACE
// c'est une méthode très longue, a utiliser avec précaution
Enum_type_geom type_front;
int num_front = el->Num_frontiere(*elfpoint,type_front);
// 4. on crée l'élément front ad hoc et on l'ajoute à la liste
const DdlElement & ddlElem = el->TableauDdl(); // récup des ddl
int angle_mort = 1;
la_list_des_front.push_front(Front(*elfpoint,&elem_non_const,num_front,angle_mort));
LaLIST_io <Front>::iterator iik = la_list_des_front.begin(); // récup de l'iterator
// on met à jour les frontières mitoyennes
int num_noeud = ttn(1)->Num_noeud(); // le num global du noeud
// récup de la liste des frontières initiales contenant le noeud
list <Front*> & t_liFront_noeud_ijk = t_liFront_noeud(ilistfront)(1)(num_noeud);
list <Front*>::iterator km,kmfin=t_liFront_noeud_ijk.end();
for (km=t_liFront_noeud_ijk.begin();km != kmfin;km++)
{(*km)->AjoutMitoyen(&(*iik));// ajout frontière pour la frontière initiale
(*iik).AjoutMitoyen(*km); // ajout frontière pour la nouvelle frontière d'angle mort
};
// on sauvegarde le nouvelle front dans une liste spécifique
front_angle_mort.push_front(&(*iik));
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts >4 )
{ cout << "\n ajout front point: noeud "<<el->Num_noeud(num_noe_local)
<< " mail: " << jf //<< " zone "
<< " element: "<<el->Num_elt_const() ;
};
};
2023-05-03 17:23:49 +02:00
};
};
};
int nb_front_fin = la_list_des_front.size(); // la taille finale
if (niveau_commentaire_lescontacts >2 )
cout << "\n ajout angle mort pour contact: mail. maitre "<< jf <<" : "<<(nb_front_fin-nb_front_init)
<< " frontieres point ";
#ifdef MISE_AU_POINT
// petite vérif en passant
if ((nb_front_fin-nb_front_init) != front_angle_mort.size())
{cout << "\n *** erreur dans la definition des elements point d'angle mort "
<< " on a deux listes qui les representent mais qui n'ont pas la meme taille "
<< (nb_front_fin-nb_front_init) << " et " << front_angle_mort.size()
<< "\n LesContacts::ElementAngleMort(..";
Sortie(1);
};
#endif
// on utilise front_angle_mort pour définir les mitoyens angle mort des éléments angle morts
list <Front *>::iterator ag,agfin=front_angle_mort.end();
for (ag=front_angle_mort.begin();ag != agfin; ag++)
{list <Front *>::iterator bg;
bg = ag; bg++;
// on utilise deux boucles imbriquées
for ( ; bg!= agfin ; bg++)
{const Tableau <Noeud *>& tan = (*ag)->Eleme()->TabNoeud_const();
const Tableau <Noeud *>& tbn = (*bg)->Eleme()->TabNoeud_const();
// normalement c'est des FrontPoinF, donc il n'y a qu'un seul noeud frontière
if (tan(1)->Num_noeud() == tbn(1)->Num_noeud())
// les deux éléments FrontPoinF partage le même noeud,
// on met à jour les mitoyens
{ (*ag)->AjoutMitoyen((*bg));
(*bg)->AjoutMitoyen((*ag));
};
};
};
}; // fin du test if (nb_front_init > 0) et if ((*la_list_des_front.begin()).NumMail() == jf )
}; // fin de la boucle sur les maillages maitres de t_listFront
}
else
{ // cas d'une zone restreinte de contact
// on va boucler sur les zones définies pour le contact
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
//on boucle sur les maillages maitres de t_listFront
for (int jf=ntmail-nbmailMaitre+1;jf<=ntmail;jf++,ilistfront++)
{ // ici on boucle sur les zones restreintes
int nb_zone_et1 = 1+t_listFront(ilistfront).Taille();
for (int i_zone=1;i_zone < nb_zone_et1;i_zone++)
{// la liste des front de la zone
LaLIST_io <Front> & la_list_des_front = t_listFront(ilistfront)(i_zone);
int nb_front_init = la_list_des_front.size(); // la taille initiale
// pour continuer il faut: 1) qu'il y a des front, 2) que ces fronts appartiennent au maillage
if (nb_front_init > 0)
if ((*la_list_des_front.begin()).NumMail() == jf )
{
// on va créer une liste de numéro des noeuds de la zone de frontière concernée
// et en même temps
// avant de balayer les noeuds, on fait une liste des éléments relatifs à la zone
// qui contiennent des frontières déjà référencées
list <int> num_noe_front;
list <const Element* > li_Elem_avec_front;
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
for (il = la_list_des_front.begin(); il != ilfin; il++)
{ const Tableau <Noeud *>& tnoe = (*il).Eleme()->TabNoeud_const();
int nb_noe_et1 = tnoe.Taille();
for (int m =1;m<nb_noe_et1;m++)
num_noe_front.push_back(tnoe(m)->Num_noeud());
li_Elem_avec_front.push_back((*il).PtEI());
};
// on ordonne et on supprime les doublons
num_noe_front.sort(); // ordonne
num_noe_front.unique(); // suppression des doublons
li_Elem_avec_front.sort(); // ordonne
li_Elem_avec_front.unique(); // supprime les doublons
// on définit une liste temporaire des nouvelles front d'angle mort créé
// c'est utilisé pour définir les mitoyens des éléments d'angle morts
// qui sont apparus avec les angles morts (== les mitoyens angle mort des éléments angle morts !!)
list <Front *> front_angle_mort;
// maintenant on parcours les noeuds contenu dans num_noe_front
// et on regarde s'il faut ajouter des éléments point d'angle mort
list <int>::iterator ih,ih_fin=num_noe_front.end();
for (ih = num_noe_front.begin();ih != ih_fin;ih++)
{int i_noe = (*ih); // le num du noeud maître que l'on va tester
Tableau <Noeud *> ttn(1);
ttn(1)= &(lesMail.Noeud_LesMaille(jf,i_noe)); // récup du pointeur de noeud
// récup de la liste pour le noeud i_noe, des éléments qui contient ce noeud : construite avec Init_contact
const List_io < Element* >& liel = (*indice(jf))(i_noe);
// on boucle sur chaque élément qui contient le noeud
List_io < Element* >::const_iterator il,ilfin=liel.end();
for (il = liel.begin();il != ilfin;il++)
{const Element* el=(*il); // pour simplifier
// on regarde si cet élément ne fait pas partie de la liste d'élément
// qui contient déjà une frontière
bool trouver = false;
list <const Element* >::const_iterator ikl,iklfin=li_Elem_avec_front.end();
for (ikl = li_Elem_avec_front.begin();ikl != iklfin; ikl++)
{if (((*ikl)->Num_elt_const() == el->Num_elt_const()) && ((*ikl)->Num_maillage() == el->Num_maillage()))
{trouver= true; break;}
};
if (!trouver)
{// on n'a pas trouvé d'élément,
// 1. on récup le num local EF du noeud
int nb_noeu_el_et_1 = 1+el->Nombre_noeud(); // le nombre de noeud de l'élément
int num_noe_local = 0;
for (int k =1;k<nb_noeu_el_et_1;k++)
if (el->Num_noeud(k) == ttn(1)->Num_noeud())
{num_noe_local=k; break;};
// 2. on récupère la frontière noeud correspondante en forçant une création éventuelle
// on passe par l'intermédiaire de lesMail pour pouvoir modifier l'élément
// car c'est l'élément qui stocke et gère la frontière
Element& elem_non_const = lesMail.Element_LesMaille(el->Num_maillage(), el->Num_elt_const());
// on fait quelques tests pour écarter des cas non recevable
bool continuer = true; // par défaut
// a) si on est en 2D axi et que l'élément est un élément noeud ou un élément ligne, cela veut dire
// qu'il génére par rotation en 3D : une ligne ou une surface, or lignes ou surfaces n'intègrent pas
// d'élément de contact d'angle mort puisqu'il n'y à pas de volume mort associé
Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie());
if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE)))
{continuer = false;}
// b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
else if ((ParaGlob::Dimension() == 3)
&& ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE))
)
{continuer = false;}
// on continue sauf cas particulier
if (continuer)
{// 3. on crée l'élément de frontière ad hoc
ElFrontiere* const elfpoint = elem_non_const.Frontiere_points(num_noe_local,true);
// ramene le numero de la frontière passée en argument si elle existe actuellement au niveau de l'élément
// sinon ramène 0
// ramene également type_front: qui indique le type de frontière: POINT_G, LIGNE ou SURFACE
// c'est une méthode très longue, a utiliser avec précaution
Enum_type_geom type_front;
int num_front = el->Num_frontiere(*elfpoint,type_front);
// 4. on crée l'élément front ad hoc et on l'ajoute à la liste
const DdlElement & ddlElem = el->TableauDdl(); // récup des ddl
int angle_mort = 1;
la_list_des_front.push_front(Front(*elfpoint,&elem_non_const,num_front,angle_mort));
LaLIST_io <Front>::iterator iik = la_list_des_front.begin(); // récup de l'iterator
// on met à jour les frontières mitoyennes
// // t_liFront_noeud(i)(j)(k) : la liste des frontières initiales qui contiennent le noeud k de la zone j du maillage i
// Tableau < Tableau < Tableau < list <Front*> > > > t_liFront_noeud;
int num_noeud = ttn(1)->Num_noeud(); // le num global du noeud
// récup de la liste des frontières initiales contenant le noeud
list <Front*> & t_liFront_noeud_ijk = t_liFront_noeud(ilistfront)(i_zone)(num_noeud);
list <Front*>::iterator km,kmfin=t_liFront_noeud_ijk.end();
for (km=t_liFront_noeud_ijk.begin();km != kmfin;km++)
{(*km)->AjoutMitoyen(&(*iik));// ajout frontière pour la frontière initiale
(*iik).AjoutMitoyen(*km); // ajout frontière pour la nouvelle frontière d'angle mort
};
// on sauvegarde le nouvelle front dans une liste spécifique
front_angle_mort.push_front(&(*iik));
2023-05-03 17:23:49 +02:00
if (niveau_commentaire_lescontacts >4 )
{ cout << "\n ajout front point: noeud "<<el->Num_noeud(num_noe_local)
<< " mail: " << jf << " zone "<< i_zone
<< " element: "<<el->Num_elt_const() ;
};
};
2023-05-03 17:23:49 +02:00
};
};
};
int nb_front_fin = la_list_des_front.size(); // la taille finale
if (niveau_commentaire_lescontacts >2 )
cout << "\n ajout angle mort pour contact: mail. maitre "<<jf << " : zone de contact: " << i_zone
<<" : " <<(nb_front_fin-nb_front_init)
<< " frontieres point ";
#ifdef MISE_AU_POINT
// petite vérif en passant
if ((nb_front_fin-nb_front_init) != front_angle_mort.size())
{cout << "\n *** erreur dans la definition des elements point d'angle mort "
<< " on a deux listes qui les representent mais qui n'ont pas la meme taille "
<< (nb_front_fin-nb_front_init) << " et " << front_angle_mort.size()
<< "\n LesContacts::ElementAngleMort(..";
Sortie(1);
};
#endif
// on utilise front_angle_mort pour définir les mitoyens angle mort des éléments angle morts
list <Front *>::iterator ag,agfin=front_angle_mort.end();
for (ag=front_angle_mort.begin();ag != agfin; ag++)
{list <Front *>::iterator bg;
bg = ag; bg++;
// on utilise deux boucles imbriquées
for ( ; bg!= agfin ; bg++)
{const Tableau <Noeud *>& tan = (*ag)->Eleme()->TabNoeud_const();
const Tableau <Noeud *>& tbn = (*bg)->Eleme()->TabNoeud_const();
// normalement c'est des FrontPoinF, donc il n'y a qu'un seul noeud frontière
if (tan(1)->Num_noeud() == tbn(1)->Num_noeud())
// les deux éléments FrontPoinF partage le même noeud,
// on met à jour les mitoyens
{ (*ag)->AjoutMitoyen((*bg));
(*bg)->AjoutMitoyen((*ag));
};
};
};
if (niveau_commentaire_lescontacts >7 )
{ cout << "\n liste finale des elements angle mort "
<< " mail: " << jf << " zone "<< i_zone;
for (ag=front_angle_mort.begin();ag != agfin; ag++)
(*ag)->Affiche();
};
}; // fin du test if (nb_front_init > 0) et if ((*la_list_des_front.begin()).NumMail() == jf )
};// fin de la boucle sur les zones
}; // fin de la boucle sur les maillages maitres de t_listFront
}; // fin du test avec ou sans zone de contact
};