// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) .
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// For more information, please consult: .
/************************************************************************
* DATE: 23/01/97 *
* $ *
* AUTEUR: G RIO (mailto:gerardrio56@free.fr) *
* $ *
* PROJET: Herezh++ *
* $ *
************************************************************************
* BUT: Creation et gestion des contacts. *
* $ *
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * *
* VERIFICATION: *
* *
* ! date ! auteur ! but ! *
* ------------------------------------------------------------ *
* ! ! ! ! *
* $ *
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
* MODIFICATIONS: *
* ! date ! auteur ! but ! *
* ------------------------------------------------------------ *
* $ *
************************************************************************/
#ifndef LESCONTACTS_H
#define LESCONTACTS_H
#include "Front.h"
#include
#include "List_io.h"
#include "ElContact.h"
#include "Condilineaire.h"
#include "Nb_assemb.h"
#include "LesMaillages.h"
#include "LesReferences.h"
#include "Basiques.h"
#include "TypeQuelconque.h"
#include "Temps_CPU_HZpp.h"
/// @addtogroup Groupe_sur_les_contacts
/// @{
///
class LesContacts
{
public :
// CONSTRUCTEURS :
// constructeur par defaut
LesContacts ();
// constructeur de copie
LesContacts (const LesContacts& a);
// DESTRUCTEUR :
~LesContacts ();
// METHODES PUBLIQUES :
// ramène la liste des éléments de contact
LaLIST & LesElementsDeContact() {return listContact;};
// 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 Init_contact(LesMaillages& lesMail
,const LesReferences& lesRef
,LesFonctions_nD* lesFonctionsnD);
// mise à jour du tableau "indice": là on utilise les numéros de noeuds qui peuvent changer
// via une renumérotation. Le tableau indice, est un tableau utilisé pour les recherches
// mais le numéro de noeud n'est pas utilisé pour les stockages divers (on utilise un pointeur de noeud)
// du coup le tableau indice peut évoluer ex: après un remaillage avec chg de num de noeud
// il doit donc être remis à jour avant l'étude de nouveau contact
// la 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
void Mise_a_jour_indice(const Tableau < const Tableau > *> ind)
{ indice = ind;};
// indique si l'initialisation a déjà été effectuée ou pas, car celle-ci ne doit-être faite
// qu'une fois
bool Init_contact_pas_effectue() const { return (tesctotal.Taille() == 0);};
// verification qu'il n'y a pas de contact avant le premier increment de charge
void Verification();
// definition des elements de contact eventuels
// - imposition des conditions de non penetration
// dep_max : déplacement maxi des noeuds du maillage
// , sert pour def des boites d'encombrement maxi des frontières
// ramène true s'il y a effectivement création d'élément de contact
bool DefElemCont(double dep_max);
// 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
// , sert pour def des boites d'encombrement maxi des frontières
bool Nouveau(double dep_max);
// suppression définitive, si le contact à disparu, des éléments inactifs
// ramène false si aucun élément n'est finalement supprimé
bool SuppressionDefinitiveElemInactif();
// relachement des noeuds collés
// ramène true s'il y a des noeuds qui ont été relachés
bool RelachementNoeudcolle();
// definition de conditions lineaires de contact
// marquage des ddl correspondant aux directions bloquees s'il s'agit d'un contact de type 1
// casAssemb : donne le cas d'assemblage en cours
//
const Tableau & ConditionLin(const Nb_assemb& casAssemb);
// 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 & ConnectionCLL();
// effacement du marquage de ddl bloque du au conditions lineaire de contact
void EffMarque();
// 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 Maitres_avec_deplacement_imposer() const;
// 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)
// en retour, ramène un booleen qui :
// = 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 Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb,int& cumule);
// 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 Actualisation(int choix);
// 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 Liste_noeuds_position_changer(list & li_noe);
// calcul des reactions de contact et stockage des valeurs
// solution : le vecteur residu
// test d'un decollement eventuelle, pour un noeud en contact
// ramene true s'il y a decollement, sinon false
// casAssemb : donne le cas d'assemblage en cours
void CalculReaction(Vecteur& residu,bool& decol,const Nb_assemb& casAssemb
,bool affiche);
// récupération via les éléments de contact des forces maxis
// un : le maxi en effort normal, deux: le maxi en effort tangentiel
DeuxDoubles Forces_contact_maxi(bool affiche) const;
// 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 Gap_contact_maxi(bool affiche) const;
// 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, des forces de réaction et de la pénétration
// donc nécessite que le contact ait déjà été étudié et que les efforts de contact ait été calculé
double Pas_de_temps_ideal()const;
// calcul d'une estimation du pas de temps critique du aux éléments de contact
// affichage des reactions de contact sur la sortie
void Affiche(ofstream& sort) const ;
// affichage à l'écran des informations liées au contact
void Affiche() const ;
// affichage et definition interactive des commandes
void Info_commande_LesContacts(UtilLecture & entreePrinc);
// 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 Lecture_zone_contact(UtilLecture & entreePrinc,const LesReferences& lesRef);
// récupération des ddl ou des grandeurs actives de tdt vers t
void TdtversT();
// actualisation des ddl et des grandeurs actives de t vers tdt
void TversTdt();
//------- temps cpu -----
// retourne temps cumulé pour imposer les CL imposées
const Temps_CPU_HZpp& Temps_cpu_Contact() const {return tempsContact;};
//----- lecture écriture de restart -----
// cas donne le niveau de sauvegarde
void Ecri_base_info_LesContacts(ofstream& sort);
// on utilise deux pointeurs de fonctions qui permettent de récupérer le pointeur de noeud esclave
// idem au niveau de l'élément
template
void Lec_base_info_LesContacts(ifstream& ent
,T& instance // l'instance qui permet d'appeler les pointeurs de fonctions
,Noeud& (T::*RecupNoeud)(int i, int j) const
,Element& (T::*RecupElement_LesMaille) (int i, int j) const);
// méthode générale: récupération des grandeurs particulière (hors ddl )
// correspondant à liTQ
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
// ===> n'est pas utilisée dans le cas du contact, c'est la méthode spécifique
// Mise_a_jour_Pour_Grandeur_particuliere qui la remplace (qui n'est pas en const car elle
// modifie les conteneurs des noeuds et éventuellement éléments)
void Grandeur_particuliere
(bool absolue,List_io& ,Loi_comp_abstraite::SaveResul * ,list& decal) const
{};
// 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
//--> important : les conteneurs sont supposés initialisés avec l'appel
void Mise_a_jour_Pour_Grandeur_particuliere(
List_io < TypeQuelconque >& li_restreinte_TQ
);
// 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 ListeGrandeurs_particulieres(bool absolue) const;
// concernant les grandeurs gérées par le contact:
// ramène une liste d'iterator correspondant aux List_io passé en paramètre
// idem pour une List_io < Ddl _enum_etendu >
void List_reduite_aux_contact(const List_io& liTQ
,List_io < TypeQuelconque >& li_restreinte_TQ
);
// 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
// ok, mais à revoir sans doute cf. pense bete 14 oct
void Init_Grandeur_particuliere (bool absolue,List_io& li1);
//retourne le niveau d'affichage
int Permet_affichage() const
{int niveau_commentaire_lescontacts = ParaGlob::param->ParaAlgoControleActifs().Niveau_commentaire_LesContact();
if (niveau_commentaire_lescontacts == 0) {niveau_commentaire_lescontacts = ParaGlob::NiveauImpression();};
return niveau_commentaire_lescontacts;
};
// ne sert plus (à virer car problématique !! )
// mise à jour du stockage inter, pour prendre en
// compte une nouvelle numérotation des noeuds
// void Prise_en_compte_nouvelle_numerotation_noeud();
// initialisation de la liste de grandeurs qui sont effectivement gérées par le contact
// ok, mais à revoir sans doute cf. pense bete 14 oct
// List_io Init_list_grandeur_contact_a_sortir(const Tableau >& li1);
class ReactCont
{ // surcharge de l'operator de lecture
friend istream & operator >> (istream &, ReactCont &);
// surcharge de l'operator d'ecriture
friend ostream & operator << (ostream &, const ReactCont &);
public :
Noeud* noe; // noeud esclave
Coordonnee force ; // force de reaction au noeud esclave
Tableau tabNoeud; // les noeuds de la frontiere maitre
Tableau tabForce; // les reac "" ""
// constructeur par defaut
ReactCont() ;
// constructeur en fonction des datas du noeud esclave seul
ReactCont(Noeud* no,const Coordonnee& forc) ;
// constructeur en fonction des datas de tous les noeuds
ReactCont(Noeud* no,const Coordonnee& forc,Tableau tN,const Tableau & tFor);
// constructeur de copie
ReactCont(const ReactCont& a);
// affectation
ReactCont& operator = (const ReactCont& a);
// test
bool operator == (const ReactCont& a);
bool operator != (const ReactCont& a);
};
//----------------------------------------------------------------------------------------------------
private :
// VARIABLES PROTEGEES de la classe LesContacts:
LesFonctions_nD* sauve_lesFonctionsnD ; // sauvegarde à l'initialisation (méthode Init_contact)
ElContact::Fct_nD_contact fct_nD_contact; // fonctions nD de pilotage: peuvent ne pas exister
LaLIST listContact; // la liste des elements en contact
LaLIST ::iterator> listContact_nouveau_tatdt; // la liste des nouveaux contacts qui sont apparus sur l'incrément
LaLIST listContact_efface_tatdt; // la liste des contacts effacés sur l'incrément
int nb_contact_actif; // nombre de contact actif courant
// list numtesN; // .un : maillage, .deux: num zone de contact, .trois: num propre du noeud
// // la liste des numéros dans tesN des noeuds en contact
Tableau tabReacCont; // les reactions
Tableau tabCoLin; // tableau des conditions lineaires
static MotCle motCle; // liste des mots clés
// la liste des éléments qui contiennent des frontières, est reconstitué au démarrage avec Init_contact(..
list 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 > *> indice;
//--------- les tableaux de gestions pour la recherche de contact ----------------
list nom_ref_zone_contact; // liste des noms de références des zones de contact éventuelle
// cette liste peut être vide, dans ce cas cela signifie que toutes les frontières des pièces sont
// suceptible de rentrer en contact. Dans le cas où la liste n'est pas vide, seules les grandeurs
// référencées sont succeptibles de rentrer en contact
// nom1 -> nom_mail_ref_zone_contact pour les noeuds
// nom2 -> le nom de la référence de noeuds
// nom3 -> nom_mail_ref_zone_contact pour les frontières
// nom4 -> le nom de la référence de frontière
// n -> l'entier = 0 : pas d'utilisation
// = 1 : indique qu'il faut considérer un contact collant (glue)
Tableau lissage_de_la_normale; // même dimension que nom_ref_zone_contact
// lissage_de_la_normale(i) : indique si oui ou non, la normale sur la zone i doit être lissée
// 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 > > 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)
// les noeuds esclaves potentiels
Tableau < Tableau < Tableau < Noeud*> > > tesctotal;
// tesctotal(i)(j)(k) : maillage esclave (i), zone de contact (j)
// noeud esclave (k) : k= le numéro d'ordre dans tesctotal(i)(j),
// ==>> ce n'est pas le numéro du noeud dans le maillage !
// indicateur de noeuds collants
Tableau < Tableau < Tableau < int> > > tesN_collant;
// tesN_collant(i)(j)(k): maillage esclave (i), zone de contact (j)
// noeud esclave (k):k= le numéro d'ordre dans tesctotal(i)(j),
// ==>> ce n'est pas le numéro du noeud dans le maillage !
// indique pour si le noeud esclave doit être
// considéré en contact collant (=1) ou pas (=0)
// tesN_encontact: globalise tous les contacts sur un noeud (indépendamment des zones de contact)
// tesN_encontact(i)(num_noe) : nombre de contact avec le noeud
// ancien stockage: Tableau < Tableau < LaLIST < LaLIST::iterator > > > tesN_encontact;
// ancien stockage // tesN_encontact(i)(num_noe): maillage (i), noeud -> num_noe:
// indique pour le noeud esclave s'il est en contact ou non via la taille de la liste associée
// utilisation: pour chaque Noeud* = tesctotal(i)(k) -> la liste des éléments en contact
// contenant le noeud k
// on remplace par une map: l'avantage c'est que l'on utilise plus les numéros de noeuds pour
// retrouver la liste, mais on utilise à la place la valeur pointeur de noeud esclave qui
// doit être unique, du coup c'est indépendant de la numérotation des noeuds -> permet de la renumérotation
// sans changer la map
Tableau < std::map::iterator > > > tesN_encontact;
// tesN_encontact(numMail_esclave)[*pt_noeud] -> la liste des iterators d'élément en contact
// avec le noeud
//--------- fin tableaux de gestions pour la recherche de contact ----------------
int nb_mail_Esclave; // indique le nombre de maillages esclaves
int nbmailautocontact; // indique le nombre de maillages esclaves en auto contact, donc qui joue le rôle esclave et maître, ou maillages mixte: dépend de la manière dont les zones de contact ont été définit
int nbmailMaitre; // indique le nombre de maillages maitres
// = nombre total de maillage - (nb_mail_Esclave-nbmailautocontact)
// si l'on considère l'ensemble des maillages du calcul on a successivement:
// les nb_mail_Esclave-nbmailautocontact premier maillages: purement esclave
// puis les nbmailautocontact qui sont en auto contact: ils jouent le rôle d'esclaves et maîtres en même temps
// puis nbmailMaitre-nbmailautocontact : purement maître
list < Deux_String > cont_solide_defor; // liste des noms de maillages définissants les contacts
// solide-déformable: (*ie).nom1 -> le maillage solide , (*ie).nom2 -> le maillage deformable
// ---- pour le post traitement ---
List_io liQ_en_sortie; // liste de grandeurs quelconque qu'il faut sortir
// -------- une variable de travail pour la méthode LesContacts::ConnectionCLL()---
Tableau t_connectionCLL;
//------- temps cpu -----
// retourne temps cumulé pour imposer les CL imposées
Temps_CPU_HZpp tempsContact;
// METHODES PROTEGEES :
// mise à jour des boites d'encombrement pour les éléments qui contiennent une frontière
void Mise_a_jour_boite_encombrement_element_contenant_front();
// suppression du gap de contact pour les noeuds "collant avec suppression de gap"
void Suppression_gap_pour_noeud_collant();
// 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 Recup_ref( ElContact& al) ;
// récupère le nombre de contact actif et met à jour ce nombre
int Calcul_Nb_contact_actif();
// création du conteneur Fct_nD_contact
void Creation_Fct_nD_contact();
// 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 ElementAngleMort(LesMaillages& lesMail);
// test si un nouvel élément de contact possible appartient en fait déjà à la liste des contacts enregistrés
// NB: pas rusé mais il faudrait pour optimiser, ordonner la liste des éléments de contact en
// introduisant une nouvelle relation d'ordre et un nouvel operateur d'égalité ...
//il faut regarder s'il est actif aussi ???
//mais en création on pourrait regarder les intactifs, et au lieu de créer un nouveau, passer l'inactif en actif
//du coup, il faudrait peut-être ramener l'élément trouvé pour changer son activité ??
//donc ici il y a quelque chose à faire
ElContact* Element_contact_deja_present( const ElContact& al)
{LaLIST ::iterator ili,ilifin = listContact.end();
for (ili = listContact.begin();ili != ilifin;ili++)
if ((*ili).MemeOrigine(al))
return (&(*ili));
return NULL;
} ;
// idem mais avec un iterator
// permet de comparer un iterator de la liste avec les éléments de la liste
ElContact* Element_contact_deja_present( LaLIST ::iterator& il)
{LaLIST ::iterator ili,ilifin = listContact.end();
for (ili = listContact.begin();ili != ilifin;ili++)
if (((*ili).MemeOrigine(*il)) && (il != ili))
return (&(*ili));
return NULL;
} ;
};
/// @} // end of group
// pour faire de l'inline: nécessaire avec les templates
// on n'inclut que les méthodes templates
#include "LesContacts_2.cc"
#define LesContacts_2_deja_inclus
#endif