418 lines
21 KiB
C++
418 lines
21 KiB
C++
|
|
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-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 <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
/************************************************************************
|
|
* 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 <Noeud*>& TabNoeud() {return tabNoeud;};
|
|
const Tableau <Noeud*>& Const_TabNoeud() const {return tabNoeud;};
|
|
// ramene le tableau pour assemblage: dépend du Cas_solide()
|
|
// est cohérent avec TableauDdlCont
|
|
Tableau <Noeud*>& 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 <Coordonnee>& 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 <Coordonnee>& 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 <Noeud*> 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 <Coordonnee> 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 <Noeud*> 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 <Coordonnee> 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 <double > 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 <DdlElement> list_Ddl_global; // liste de tous les DdlElements des éléments de contact
|
|
static list <Vecteur> list_SM; // list de seconds membres locals: sert pour tous les éléments de contact
|
|
static list <Mat_pleine> 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 <Coordonnee >* 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
|