// 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-2021 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: Element de contact. *
* $ *
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * *
* VERIFICATION: *
* *
* ! date ! auteur ! but ! *
* ------------------------------------------------------------ *
* ! ! ! ! *
* $ *
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
* MODIFICATIONS: *
* ! date ! auteur ! but ! *
* ------------------------------------------------------------ *
* $ *
************************************************************************/
#ifndef ELCONTACT_H
#define ELCONTACT_H
#include "Front.h"
#include "Noeud.h"
#include "Condilineaire.h"
#include "LesFonctions_nD.h"
/** @defgroup Groupe_sur_les_contacts
*
* BUT: groupe relatif aux contacts
*
*
* \author Gérard Rio
* \version 1.0
* \date 23/01/97
* \brief groupe relatif aux contacts
*
*/
/// @addtogroup Groupe_sur_les_contacts
/// @{
///
class ElContact
{
public :
// une classe structure de transfert pour simplifier le passage de paramètres
class Fct_nD_contact
{ public:
Fct_nD_contact();
Fct_nD_contact(const Fct_nD_contact& a);
~Fct_nD_contact();
Fct_nD_contact& operator= (const Fct_nD_contact& a);
// utilisation de fct nD
Fonction_nD * fct_nD_penalisationPenetration; // fct nD dans le cas d'une valeur pilotée
Fonction_nD * fct_nD_penetration_contact_maxi; // fct nD dans le cas d'une valeur pilotée
Fonction_nD * fct_nD_penetration_borne_regularisation; // fct nD dans le cas d'une valeur pilotée
Fonction_nD * fct_nD_force_contact_noeud_maxi; // fct nD dans le cas d'une valeur pilotée
Fonction_nD * fct_nD_penalisationTangentielle;
Fonction_nD * fct_nD_tangentielle_contact_maxi; // fct nD dans le cas d'une valeur pilotée
Fonction_nD * fct_nD_tangentielle_borne_regularisation; // fct nD dans le cas d'une valeur pilotée
Fonction_nD * fct_nD_force_tangentielle_noeud_maxi; // fct nD dans le cas d'une valeur pilotée
};
// CONSTRUCTEURS :
// par defaut
ElContact();
// la version avec fonction de pilotage nD
ElContact(Fct_nD_contact & fct_contact);
// fonction d'un pointeur d'element frontiere et d'un pointeur de noeud
// du fait éventuel qu'il peut-être collant ou pas
ElContact ( const Front * elfront, const Noeud * noeud, Fct_nD_contact & fct_contact_, int collant = 0);
// de copie
ElContact ( const ElContact & a);
// DESTRUCTEUR :
~ElContact ();
// METHODES PUBLIQUES :
// init d'une fonction nD pour le pilotage du type de contact 4
static void Init_fct_pilotage_contact4(Fonction_nD * fct_pilo_contact4)
{fct_pilotage_contact4 = fct_pilo_contact4;};
// méthode statique de modification éventuelle du type de contact utilisé localement
// par exemple pour le type 4 en fonction des itérations
static int Recup_et_mise_a_jour_type_contact() ;
// affichage à l'écran des informations liées au contact
void Affiche() const ;
// calcul d'un contact eventuel entre le noeud esclave et la frontiere
// ramene true s'il y a contact
// si init = false, on recherche le contact a partir du precedent point sauvegarde
// sinon on commence a l'aide d'element de reference,
// et on calcule et sauvegarde les coordonnées
// initiale locales theta^i du point de contact
// si le contact existe et si l'algo le demande (cf. ParaAlgoControle) :
// le noeud pourrait-être ramené sur la surface mais:
// on ne fait pas de projection, sinon on ne peut pas tester plusieurs contacts pour
// choisir le meilleur, puisque les choses changent entre avant et après le test de contact
// donc ici la position du noeud esclave n'est pas modifiée
bool Contact( bool init = true);
// juste après l'utilisation de la méthode Contact(), ramène le point en contact
const Coordonnee& Point_intersection() const { return Mtdt; };
// un stockage utilisé par les méthodes appelantes
int& Num_zone_contact() {return num_zone_contact;};
// calcul de la trajectoire a prendre en compte pour le contact
// ---- a) cas ou à t il n'y avait pas de contact, ou que l'on n'a pas fait de projection sur la surface (cas du contact cinématique)
// 4 cas : 1) le noeud bouge, dans ce cas la trajectoire est determinee
// par la variation de la position du noeud
// 2) le noeud est immobile, mais la frontiere bouge, la trajectoire est determine
// par une parallele a la variation moyenne de la frontiere (variation de G)
// 4) est une variante du 2), cas où l'on a une rotation autour de G, dans ce cas on prend comme trajectoire
// le maxi des déplacements de noeud
// 3) rien ne bouge, on utilise la normale au point de reference de l'element de frontiere
// pour calculer la trajectoire .
// dans le cas 3 la variable test = 0 , sinon elle vaut 1 pour le cas 1 et 2 pour le cas 2 , 4 pour le cas 4
// ---- b) cas ou à t on était déjà en contact avec projection sur la surface
// la trajectoire est alors systématiquement la direction de la dernière normale,
// retour : test=5
Coordonnee Trajectoire(int & test);
// calcul de l'Intersection de la trajectoire du noeud definit par le vecteur V
// avec l'element frontiere
// ramene les coordonnees du noeud projete
// dans le cas où il n'y a pas d'intersection, on ramène un point de dimension nulle
Coordonnee Intersection( const Coordonnee& V,bool init);
// construction de la condition lineaire de contact
// nb_assemb : indique le numéro d'assemblage correspondant
Condilineaire ConditionLi(int nb_assemb);
// ramene le tableau de tous les noeuds, le premier est celui esclave
Tableau & TabNoeud() {return tabNoeud;};
const Tableau & Const_TabNoeud() const {return tabNoeud;};
// ramene le tableau pour assemblage: dépend du Cas_solide()
// est cohérent avec TableauDdlCont
Tableau & TabNoeud_pour_assemblage() {return tabNoeud_pour_assemblage;};
// retourne les tableaux de ddl associés aux noeuds, gere par l'element
// qui sont actifs au moment de la demande
// Tableau de DdlElement pour l'assemblage uniquement
const DdlElement & TableauDdlCont() const {return *ddlElement_assemblage;};
// ramene le noeud esclave
inline Noeud* Esclave() { return noeud;};
// ramene la force de contact pour consultation
const Coordonnee& Force_contact() const {return force_contact;};
// ramène les maxis concernant le noeud esclave
double F_N_MAX() const {return F_N_max;};
double F_T_MAX() const {return F_T_max;};
// ramène la pénalisation actuelle éventuelle
const double& Penalisation() const {return penalisation;};
const double& Penalisation_tangentielle() const {return penalisation_tangentielle;};
// ramène le déplacement tangentiel actuel
const Coordonnee& Dep_tangentiel() const {return dep_tangentiel;};
// ramène la normale actuelle
const Coordonnee& Normale_actuelle() const {return N;};
// idem pour les réactions sur les noeuds de la facette
const Tableau & TabForce_cont() const {return tabForce_cont;};
// actualisation de la projection du noeud esclave en fonction de la position de l'element
// maitre frontiere. Lorsque le noeud change d'element fontiere, on change l'element
// frontiere de l'element de contact en consequence
// dans le cas ou on ne trouve pas d'intersection, cas d'un noeud qui sort d'une zone de
// contact, on retourne false, sinon retourne true
// en fonction de la méthode de contact, le noeud est ramené éventuellement sur la frontière
bool Actualisation();
// ramene un pointeur sur l'element frontiere
inline Front * Elfront() const { return elfront;};
// permet de changer le deplacement maxi de tous les noeuds, qui sert
// pour éviter de considérer des contact trop éloignés
static void Change_dep_max(const double & deplac_max)
{dep_max = deplac_max * ParaGlob::param->ParaAlgoControleActifs().FacPourRayonAccostage();};
// test et met à jour le compteur de décollage du noeud
// si le noeud decolle ou non en fonction de la force de reaction
// ramene 1: s'il decolle
// 0: s'il ne décolle pas
bool Decol();
// change force: permet de changer la valeur de la force
// utile quand la force est calculée en dehors de l'élément de contact
void Change_force(const Coordonnee& force);
// idem pour les forces réparties sur la facette
void Change_TabForce_cont(const Tableau & tab) {tabForce_cont=tab;};
// gestion de l'activité
int Actif() const {return actif;}; // ramène l'activité du contact
void Met_Inactif() { actif = 0;nb_decol_tdt=0;}; // met en inactif
void Met_actif() { actif++;nb_decol_tdt=0;}; // met en actif une fois de plus
// ramène le nombre actuel de décolement
int Nb_decol() const {return nb_decol_tdt;};
// ramène le nombre de pénétration actuel
int Nb_pene() const {return nb_pene_tdt;};
// --- calcul des puissances virtuelles développées par les efforts de contact ----------
// et eventuellement calcul de la raideur associé
// -> explicite à tdt
virtual Vecteur* SM_charge_contact();
// -> implicite,
virtual Element::ResRaid SM_K_charge_contact();
// récupération des énergies intégrées sur l'éléments, résultants d'un précédent calcul
// explicite, ou implicite:
// 1- il s'agit ici de l'énergie développée par le frottement glissant ou pas
const EnergieMeca& EnergieFrottement() const {return energie_frottement;};
// 2- énergie de pénalisation (élastique a priori)
const double& EnergiePenalisation() const {return energie_penalisation;};
// cas d'une méthode avec pénalisation: calcul éventuel d'un pas de temps idéal,
// permettant de limiter la pénétration
// 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 Pas_de_temps_ideal()const;
// ramène l'info sur le fait que le contact est avec un solide ou pas
// retour = 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 bloqué (solide)
int Cas_solide() const {return cas_solide;};
// permet de modifier le contact entre collant ou non suivant "change"
void Change_contact_collant(bool change);
// récup de l'information concernant le contact collant ou pas
int Collant() const {return cas_collant;};
// récup des gaps calculés
const double & Gaptdt() const {return gap_tdt;};
const double & Dep_T_tdt() const {return dep_T_tdt;}
// mise à jour du niveau de commentaire
static void Mise_a_jour_niveau_commentaire(int niveau)
{niveau_commentaire = niveau;};
// 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();
//----- lecture écriture de restart -----
void Lec_base_info_ElContact(ifstream& ent);
void Ecri_base_info_ElContact(ofstream& sort);
protected :
// VARIABLES PROTEGEES :
int actif; // un indicateur, disant si le contact est actif ou pas
// conteneur plutôt utilisé par les classes appelantes
// =1 -> premier contact, > 1 contact qui suit un contact
Front* elfront; // un element frontiere
Noeud * noeud; // un pointeur de noeud
int num_zone_contact; // un stockage uniquement utilisé par les méthodes appelantes
// pour éviter de le construire à chaque demande on définit un tableau de tous les noeuds
Tableau tabNoeud; // tableau de tous les noeud, le premier est noeud
// le tableau des positions successives du noeud esclave, ceci pour effectuer une moyenne glissante
Tableau tab_posi_esclave;
// le nombre courant de positions de noeuds esclaves actuellement stockées
int nb_posi_esclave_stocker_t,nb_posi_esclave_stocker_tdt;
// indice dans tab_posi_esclave, du prochain stockage
int indice_stockage_glissant_t,indice_stockage_glissant_tdt;
Coordonnee Mtdt,Mt; // sauvegarde du point d'intercection s'il est recevable
Coordonnee M_noeud_tdt_avant_projection; // dans le cas d'une projection du noeud sur la surface maître
// sauvegarde des coordonnées du noeuds esclave: utilisation avec le type de contact 4
// les fonctions d'interpolation au premier point en contact: sert pour le contact collant
Vecteur phi_theta_0 ;
EnergieMeca energie_frottement; // énergie développée par le frottement glissant ou pas
double energie_penalisation; // énergie due à la pénalisation (élastique a priori)
// cas_solide permet de simplifier le contact dans le cas ou le maître ou l'esclave est solide
// sert pour diminuer la taille de la raideur uniquement
int cas_solide; // =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
int cas_collant; // prise en compte éventuelle d'un contact collant, si 0: contact normal
// = 1 : contact collant
Vecteur * residu; // residu local
Mat_pleine * raideur; // raideur locale
DdlElement * ddlElement_assemblage; // le ddlElement qui correspond
Tableau tabNoeud_pour_assemblage; // tableau des noeuds qui servent pour l'assemblage
Coordonnee force_contact,force_contact_t; // force de contact sur le noeud principal
double F_N_max,F_T_max,F_N_max_t,F_T_max_t; // les maxis constatés
Tableau tabForce_cont,tabForce_cont_t; // le tableau des forces sur les noeuds de la facette
Coordonnee N; // la dernière normale calculée
Coordonnee dep_tangentiel; // le dernier déplacement tangentiel calculé
int nb_decol_t,nb_decol_tdt; // nombre de fois où le noeud décolle de manière consécutive
double gap_t,gap_tdt; // les pénétrations d'un pas à l'autre
double dep_T_t, dep_T_tdt; // les valeurs absolue des déplacements tangentiels d'un pas à l'autre
double nb_pene_t,nb_pene_tdt; // le nombre de penetration positives
// cas TypeCalculPenalisationPenetration() = 4 ou -4
// -> cas d'un facteur multiplicatif évolutif, on fait une moyenne glissante de 2
// on mémorise donc les facteurs multiplicatifs successifs
double mult_pene_t,mult_pene_tdt;
// cas TypeCalculPenalisationTangentielle() = 4 ou -4
// -> cas d'un facteur multiplicatif évolutif, on fait une moyenne glissante de 2
// on mémorise donc les facteurs multiplicatifs successifs
double mult_tang_t,mult_tang_tdt;
double penalisation,penalisation_tangentielle; // on sauvegarde la pénalisation
// l'intérêt est de pouvoir la visualiser
double penalisation_t,penalisation_tangentielle_t; // les grandeurs à t
// utilisation de fct nD
Fct_nD_contact fct_nD_contact;
// pour le contact 4, pour le calcul de la pénalisation avec une moyenne glissante
Tableau val_penal; // tableau de stockage intermédiaire
int pt_dans_val_penal; // indice du prochain elem du tableau a remplir
// stocke le dernier type de trajectoire du noeud par rapport à la facette
// c-a-d la valeur de la variable test dans la fonction Trajectoire(int & test)
int type_trajectoire_t,type_trajectoire_tdt;
// concernant les enum de ddl associées aux éléments de contact, on définit un tableau global
// qui est utilisé par tous les éléments
static list list_Ddl_global; // liste de tous les DdlElements des éléments de contact
static list list_SM; // list de seconds membres locals: sert pour tous les éléments de contact
static list list_raideur; // list de raideurs locales: " " " "
// stockage du maximum de distance tolérée entre noeud à tdt et le projeté, sert pour éliminer les contacts aberrants
static double dep_max;
static int niveau_commentaire;
// stockage d'une fonction nD pour le pilotage du type de contact 4
static Fonction_nD * fct_pilotage_contact4;
// METHODES PROTEGEES :
// calcul la normal en fonction de differente conditions
Coordonnee Calcul_Normale (int dim, Plan & pl, Droite & dr,int indic);
void Libere();
// construction du tableau de tous les noeuds, le premier est celui esclave
// et mise à jour de ddlElement et de list_Ddl_global éventuellement
void Construction_TabNoeud();
// récupération d'informations des classes internes pour le calcul du résidu
// N: le vecteur normal
// M_impact: le point d'impact sur la surface (ou ligne)
// phii : les fonctions d'interpolation au point d'impact
// si avec_var est vrai: il y a retour du tableau de variation de la normale
Tableau * RecupInfo(Coordonnee& N,Coordonnee& M_impact,Vecteur& phii,bool avec_var );
// mise à jour de cas_solide et donc de ddlElement en fonction de l'activité des ddl
// mise à jour du tableau de noeud pour l'assemblage tabNoeud_pour_assemblage
void Mise_a_jour_ddlelement_cas_solide_assemblage();
// récup d'une place pour le résidu local et mise à jour de list_SM éventuellement
void RecupPlaceResidu(int nbddl);
// récup d'une place pour la raideur locale et mise à jour de list_raideur éventuellement
void RecupPlaceRaideur(int nbddl);
// calcul du facteur de pénalisation en pénétration, en fonction de la géométrie
// du module de compressibilité et des différents possibles
// éventuellement, calcul de la dérivée: d_beta_gapdu, du facteur par rapport au gap
// la sensibilité dépend du type de calcul du facteur de pénalisation
double CalFactPenal(const double& gap,double & d_beta_gap,int contact_type);
// calcul du facteur de pénalisation tangentielle, en fonction de la géométrie
// du module de compressibilité et des différents cas possibles
// éventuellement, calcul de la dérivée: d_beta_gapdu, du facteur par rapport au gap
// la sensibilité dépend du type de calcul du facteur de pénalisation
double CalFactPenalTangentiel(const double& gap,double & d_beta_gap);
// limitation éventuelle au niveau de la pénétration maxi
//void Limitation_penetration_maxi(
// calcul éventuel de la moyenne glissante des positions successive du noeud esclave
void ChangeEnMoyGlissante(Coordonnee& Noe_atdt);
// calcul de la moyenne glissante de la pénalisation
void Moyenne_glissante_penalisation(double& penalisation, double& essai_penalisation);
// calcul d'une fonction nD relative à des données de contact
double Valeur_fct_nD(Fonction_nD * fct_nD) const;
};
/// @} // end of group
#endif