// 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: .
#include "CompFrotCoulomb.h"
#include "Util.h"
#include "CharUtil.h"
// CONSTRUCTEURS :
CompFrotCoulomb::CompFrotCoulomb () : // Constructeur par defaut
CompFrotAbstraite(LOI_COULOMB,CAT_FROTTEMENT,4) // 4 pour dire que c'est valable quelque
// soit la dimension
,mu_statique(-ConstMath::tresgrand),mu_cine(NULL),x_c(NULL),regularisation(0)
,epsil(-ConstMath::tresgrand),fonc_regul(NULL)
{ };
// Constructeur de copie
CompFrotCoulomb::CompFrotCoulomb (const CompFrotCoulomb & a ) :
CompFrotAbstraite(a)
,mu_statique(a.mu_statique),mu_cine(NULL),x_c(NULL),regularisation(a.regularisation)
,epsil(a.epsil),fonc_regul(NULL)
{ if (a.mu_cine != NULL) {mu_cine = new double; *mu_cine = *(a.mu_cine);};
if (a.x_c != NULL) {x_c = new double; *x_c = *(a.x_c);};
// on regarde s'il s'agit de courbes locales ou de courbes globales
if (fonc_regul != NULL)
if (fonc_regul->NomCourbe() == "_")
{// comme il s'agit d'une courbe locale on la redéfinie (sinon pb lors du destructeur de loi)
string non_courbe("_");
fonc_regul = Courbe1D::New_Courbe1D(*a.fonc_regul);
};
};
// DESTRUCTEUR VIRTUEL :
CompFrotCoulomb::~CompFrotCoulomb ()
{ if (mu_cine != NULL) delete mu_cine;
if (x_c != NULL) delete x_c;
if (fonc_regul != NULL)
if (fonc_regul->NomCourbe() == "_") delete fonc_regul;
};
// =============== methodes ======================
// Lecture des donnees de la classe sur fichier
void CompFrotCoulomb::LectureDonneesParticulieres
(UtilLecture * entreePrinc,LesCourbes1D& lesCourbes1D,LesFonctions_nD& lesFonctionsnD)
{ string toto,nom;
*(entreePrinc->entree) >> nom; // init de la lecture
do
{ if(nom == "mu_statique=")
{ // -- lecture du coefficient mu_statique
*(entreePrinc->entree) >> mu_statique;
}
else if(nom == "fin_loi_frottement_coulomb_")
{ // -- fin de la lecture
break;
}
else if(nom == "regularisation=")
{ // -- lecture du coefficient regularisation
*(entreePrinc->entree) >> regularisation;
if (regularisation == 0)
{ // on passe les infos concernants qui ici ne servent pas car pas de régularisation
if(strstr(entreePrinc->tablcar,"epsil=")!=0) // passage de "epsil=" et de la valeur
*(entreePrinc->entree) >> nom >> nom;
if(strstr(entreePrinc->tablcar,"fonction_regul_")!=0) // passage de "fonction_regul_"
*(entreePrinc->entree) >> nom >> nom; // et du nom de courbe
}
else if ((regularisation > 0) && (regularisation < 4))
{ if(strstr(entreePrinc->tablcar,"epsil=")!=0)
{*(entreePrinc->entree) >> nom >> epsil;}
else
{ *(entreePrinc->entree) >> nom;
cout << "\n erreur en lecture du coefficient de pilotage de la regularisation, on attendait "
<< " la chaine epsil= et on a lu: " << nom << endl ;
entreePrinc->MessageBuffer("erreur 1 ");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
}
else if (regularisation == 4)
{ if(strstr(entreePrinc->tablcar,"fonction_regul_")!=0)
{*(entreePrinc->entree) >> nom >> nom;
// on regarde si la courbe existe, si oui on récupère la référence
if (lesCourbes1D.Existe(nom))
{ fonc_regul = lesCourbes1D.Trouve(nom);}
else
{ // sinon il faut la lire maintenant
string non_courbe("_");
fonc_regul = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
// lecture de la courbe
fonc_regul->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
};
}
else
{ *(entreePrinc->entree) >> nom;
cout << "\n erreur en lecture du coefficient de pilotage de la regularisation, on attendait "
<< " la chaine epsil= et on a lu: " << nom << endl ;
entreePrinc->MessageBuffer("erreur 1 ");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
}
else
{ cout << "\n erreur en lecture de la regularisation, cas: " << regularisation
<< " non prevu ";
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
} //-- fin de la lecture de la régularisation
else if (nom != "fin_loi_frottement_coulomb_")
{ cout << "\n erreur en lecture le mot cle lu " << nom << " est errone ou mal place " << endl ;
entreePrinc->MessageBuffer("erreur 1 ");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
// -- lecture avec contrôle d'un nouveau mot clé ---
*(entreePrinc->entree) >> nom;
if (!((entreePrinc->entree)->rdstate() == 0)) // cas pb
// pour mémoire ici on a
// enum io_state
// { badbit = 1<<0, // -> 1 dans rdstate()
// eofbit = 1<<1, // -> 2
// failbit = 1<<2, // -> 4
// goodbit = 0 // -> O
// };
{
#ifdef ENLINUX
if ((entreePrinc->entree)->fail())
// on a atteind la fin de la ligne et on appelle un nouvel enregistrement
{ entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
*(entreePrinc->entree) >> nom; // et on remplace le nom qui était erroné
}
#else
if ((entreePrinc->entree)->eof())
// on a atteind la fin de la ligne
{ // si ce n'est pas la fin de la lecture on appelle un nouvel enregistrement
if (nom != "fin_loi_frottement_coulomb_")
entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
*(entreePrinc->entree) >> nom; // il semble que finalement la lecture n'était pas bonne
}
#endif
else // cas d'une erreur de lecture
{ cout << "\n erreur de lecture inconnue ";
entreePrinc->MessageBuffer("** lecture des données particulières CompFrotCoulomb **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
};
// -- din lecture avec contrôle d'un nouveau mot clé ---
}while (nom != "fin_loi_frottement_coulomb_") ;
// prepa du flot de lecture pour la suite
entreePrinc->NouvelleDonnee();
};
// affichage de la loi
void CompFrotCoulomb::Affiche() const
{ cout << " \n loi de comportement de frottement de coulomb ";
cout << "\n mu_statique= " << mu_statique << " ";
if (mu_cine != NULL) { cout << " mu_cine= " << *mu_cine << " ";};
if (x_c != NULL) { cout << " x_c= " << *x_c << " ";};
if (regularisation != 0)
{ cout << "\n regularisation= " << regularisation ;
if (regularisation != 4)
{cout << " epsil= " << epsil << " ";}
else
{ cout << " fonction= " << fonc_regul->NomCourbe() <<" ";};
};
};
// affichage et definition interactive des commandes particulières à chaques lois
void CompFrotCoulomb::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
{ ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
cout << "\n definition standart (rep o) ou exemples exhaustifs (rep n'importe quoi) ? ";
string rep = "_";
// procédure de lecture avec prise en charge d'un retour chariot
rep = lect_return_defaut(true,"o");
sort << "\n# ----------------------------------------------------------------------------------"
<< "\n# |...... loi de comportement de frottement de coulomb ....... |"
<< "\n# ----------------------------------------------------------------------------------"
<< "\n\n# exemple de definition de loi"
<< "\n mu_statique= 0.3 "
<< "\n fin_loi_frottement_coulomb_ \n" ;
if ((rep != "o") && (rep != "O" ) && (rep != "0") )
{ sort << "\n#------------------------------------------------------------------------------------"
<< "\n# mu_statique= le coefficient de frottement statique "
<< "\n#------------------------------------------------------------------------------------"
<< "\n# il est possible de definir une regularisation de la courbe de frottement "
<< "\n# exemple: "
<< "\n# mu_statique= 0.3 "
<< "\n# regularisation= 3 epsil= 1. \n"
<< "\n# fin_loi_frottement_coulomb_ \n"
<< "\n#------------------------------------------------------------------------------------"
<< "\n# regularisation= donne le type de regularisation que l'on desire: en fonction de la vitesse"
<< "\n# = 1: régularisation par morceau de droite fonction de la vitesse "
<< "\n# = 2: régularisation quadratique; = 3: régularisation en tangente hyperbolique "
<< "\n# = 4: régularisation par une fonction donnée par l'utilisateur f(norme(vitesse))"
<< "\n# epsil= est le parametre de reglage de la regularisation "
<< "\n# exemple d'une regularisation de type 4: "
<< "\n# mu_statique= 0.3 "
<< "\n# regularisation= 4 fonction_regul_ courbe4 \n"
<< "\n# fin_loi_frottement_coulomb_ \n"
<< "\n#------------------------------------------------------------------------------------"
<< "\n# comme pour toutes les autres courbes dans les lois de comportement il est possible "
<< "\n# de declarer directement la courbe au lieu de donner une reference "
<< "\n# a la fin de la description de la courbe, on doit revenir a la ligne \n"
<< "\n#------------------------------------------------------------------------------------"
<< "\n# on peut egalement introduire la notion de coefficient de frottement cinematique "
<< "\n# exemple: "
<< "\n# mu_statique= 0.3 mu_cine= 0.2 x_c= 2. "
<< "\n# regularisation= 4 fonction_regul_ courbe4 \n"
<< "\n# fin_loi_frottement_coulomb_ \n"
<< "\n#------------------------------------------------------------------------------------"
<< "\n# mu_cine= est le coefficient de frottement cinematique "
<< "\n# x_c= regle le passage du frottement statique au frottement cinematique "
<< "\n# selon mu = mu_statique + (mu_statique-mu_cine)* exp(-x_c*V), V etant la vitesse tangente "
<< "\n#------------------------------------------------------------------------------------";
};
sort << endl;
// appel de la classe mère
CompFrotAbstraite::Info_commande_don_LoisDeComp(entreePrinc);
};
// test si la loi est complete
int CompFrotCoulomb::TestComplet()
{ int ret = LoiAbstraiteGeneral::TestComplet();
if (mu_statique == -ConstMath::tresgrand)
{ cout << "\n mu_statique n'est pas defini dans la loi de coulomb ";
ret = 0;
};
if (regularisation != 0)
{if (epsil == -ConstMath::tresgrand)
{ cout << "\n le parametre de reglage de la regularisation n'est pas defini dans la loi de coulomb ";
ret = 0;
}
else if (Dabs(epsil) < ConstMath::pasmalpetit)
{ cout << "\n le parametre de reglage de la regularisation = " << epsil << " dans la loi de coulomb "
<< "est trop petit ! pour fonctionner correctement ";
ret = 0;
}
else if (epsil < 0.)
{ cout << "\n le parametre de reglage de la regularisation = " << epsil << " dans la loi de coulomb "
<< "est negatif, ce qui n'est pas possible ";
ret = 0;
};
};
return ret;
};
//----- lecture écriture de restart -----
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void CompFrotCoulomb::Lecture_base_info_loi(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
,LesFonctions_nD& lesFonctionsnD)
{ string nom;
if (cas == 1)
{ ent >> nom;
if (nom != "LOI_COULOMB")
{ cout << "\n erreur en lecture de la loi : LOI_COULOMB, on attendait le mot cle : LOI_COULOMB "
<< "\n CompFrotCoulomb::Lecture_base_info_loi(...";
Sortie(1);
}
// ensuite normalement il n'y a pas de pb de lecture puisque c'est écrit automatiquement (sauf en debug)
ent >> nom >> mu_statique; // mu_statique
// -- mu_cine --
bool test; ent >> nom >> test;
if (!test)
// on efface le mu_cine s'il existe
{ if (mu_cine != NULL) {delete mu_cine;mu_cine = NULL;};}
else
{ // on crée éventuellement puis on lit
if (mu_cine == NULL) mu_cine = new double ;
ent >> (*mu_cine);
};
// -- x_c --
ent >> nom >> test;
if (!test)
// on efface le x_c s'il existe
{ if (x_c != NULL) {delete x_c;x_c = NULL;};}
else
{ // on crée éventuellement puis on lit
if (x_c == NULL) x_c = new double ;
ent >> (*x_c);
};
// -- regularisation --
ent >> nom >> regularisation >> nom >> test;
if (!test)
{ if (fonc_regul != NULL)
{if (fonc_regul->NomCourbe() == "_") delete fonc_regul; fonc_regul = NULL;};
}
else
{ ent >> nom; fonc_regul = lesCourbes1D.Lecture_pour_base_info(ent,cas,fonc_regul); };
// -- epsil --
ent >> nom >> test;
if (test)
{ ent >> epsil;};
}
CompFrotAbstraite::Lecture_don_base_info(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
};
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void CompFrotCoulomb::Ecriture_base_info_loi(ofstream& sort,const int cas)
{ if (cas == 1)
{ sort << " LOI_COULOMB " ;
sort << "\n mu_statique= " << mu_statique << " mu_cine= ";
if (mu_cine == NULL) {sort << " 0 " ;} else { sort << " 1 " << *mu_cine << " ";};
sort << " x_c= " ;
if (x_c == 0) {sort << " 0 " ;} else { sort << " 1 " << *x_c << " ";};
sort << "\n regularisation= " << regularisation << " fonction= ";
if (fonc_regul == NULL)
{ sort << false << " " ;}
else
{ sort << true << " ";
LesCourbes1D::Ecriture_pour_base_info(sort,cas,fonc_regul);
};
sort << "\n epsil= ";
if (epsil == -ConstMath::tresgrand)
{ sort << false << " ";}
else
{ sort << true << " " << epsil << " ";};
};
// appel de la classe mère
CompFrotAbstraite::Ecriture_don_base_info(sort,cas);
};
// ------------ METHODES VIRTUELLES PURES protegees -----------
// calcul des efforts de frottement à un instant t+deltat
// les indices t se rapporte au pas précédent, sans indice au temps actuel
// vit_T : vitesse, force_normale: force normale (à la cible) agissant sur le noeud projectile
// force_tangente: force tangente (à la cible) agissant sur le noeud projectile
// normale: la normale de contact normée
// energie_frottement: l'énergie échangée: élas=la totalité, viqueux et plas= uniquement le pas de temps
// delta_t : le pas de temps
// F_frot: force de frottement calculé,
// retour glisse: indique si oui ou non le noeud glisse
bool CompFrotCoulomb::Calcul_Frottement(const Coordonnee& vit_T, const Coordonnee&
,const Coordonnee& force_normale,const Coordonnee& force_tangente
,EnergieMeca& energie_frottement,const double delta_t
,Coordonnee& F_frot)
{ // on regarde si l'on doit tenir compte du frottement cinématique
double mu_frot = mu_statique; // init du frottement que l'on utilisera effectivement
double n_vit_T = vit_T.Norme();
bool glisse = false; // par défaut
if (mu_cine != NULL)
{// le frottement dépend de la norme de la vitesse
mu_frot += (mu_statique - *mu_cine) * exp(-(*x_c)*n_vit_T);
};
// on regarde si le frottement est régularisé ou pas
double n_f_tangente = force_tangente.Norme();
double n_f_normale = force_normale.Norme();
switch (regularisation)
{ case 0: // -- pas de régularisation ---
{// on regarde si le noeud glisse ou pas
if (n_f_tangente < Dabs(mu_frot)*n_f_normale)
{// la force est correcte, il n'y a pas de glissement
glisse = false;
F_frot = force_tangente;
}
else
{// on est en dehors du cône de frottement, il faut donc modifier
// la force tangentielle
glisse = true;
if (n_vit_T < ConstMath::pasmalpetit) // le déplacement est quasi_nulle
// on est obligé de considérer des cas particuliers car on ne peut pas
// utiliser la direction du déplacement, on va donc voir du coté
// de la force tangentielle initiale
{ if (n_f_tangente < ConstMath::pasmalpetit) // force également quasi-nulle
// on la laisse comme elle est mais en signalant le glissement
{ F_frot = force_tangente;}
else // sinon on utilise la direction de la force
{ F_frot = force_tangente *(mu_frot*n_f_normale/n_f_tangente);};
}
else // cas normale, la vitesse est non nulle on l'utilise
{ F_frot = vit_T * (-mu_frot*n_f_normale/n_vit_T);};
// mise à jour des énergies qui ici est uniquement plastique
// si le déplacement est nulle -> énergie nulle
energie_frottement.ChangeDissipationPlastique((F_frot * vit_T)*delta_t);
};
break;
}//-- fin du cas sans régularisation
case 1: case 2: case 3: case 4: // -- régularisation avec une fonction de la vitesse ---
{double fonct_phi = 0.;
switch (regularisation)
{case 1 :{ if (n_vit_T < -epsil) {fonct_phi = -1.;}
else if (n_vit_T < epsil) {fonct_phi = n_vit_T /(2.*epsil);}
else {fonct_phi = 1.;}
break;
}
case 2 :{fonct_phi = n_vit_T/sqrt(n_vit_T*n_vit_T + epsil*epsil); break;}
case 3 :{fonct_phi = tanh (n_vit_T/epsil); break;}
case 4 :{fonct_phi = fonc_regul->Valeur(n_vit_T); break;}
};
glisse = true; // systématiquement
// on recherche une direction de mouvement
if (n_vit_T < ConstMath::pasmalpetit) // le déplacement est quasi_nulle
// on est obligé de considérer des cas particuliers car on ne peut pas
// utiliser la direction du déplacement, on va donc voir du coté
// de la force tangentielle initiale
{ if (n_f_tangente < ConstMath::pasmalpetit) // force également quasi-nulle
// on la laisse comme elle est mais en signalant le glissement
{ F_frot = force_tangente;}
else // sinon on utilise la direction de la force
{ F_frot = force_tangente * (mu_frot*n_f_normale*fonct_phi/n_f_tangente);};
}
else // cas normale: la vitesse est non nulle on l'utilise
{ F_frot = vit_T * (-mu_frot*n_f_normale*fonct_phi/n_vit_T);};
// mise à jour des énergies qui ici est uniquement plastique
// si le déplacement est nulle -> énergie nulle
energie_frottement.ChangeDissipationPlastique((F_frot * vit_T)*delta_t);
break;
}//-- fin du cas régularisation avec une fonction de la vitesse ---
}; //--- fin du switch sur regularisation
// retour
return glisse;
};
// calcul des efforts de frottement à un instant t+deltat
// et ses variations par rapport aux ddl de vitesse
// vit_T : vitesse, force_normale: force normale (à la cible) agissant sur le noeud projectile
// force_tangente: force tangente (à la cible) agissant sur le noeud projectile
// energie_frottement: l'énergie échangée: élas=la totalité, viqueux et plas= uniquement le pas de temps
// delta_t : le pas de temps
// F_frot: force de frottement calculé,
// d_F_frot_vit: variation de la force de frottement par rapport aux coordonnées de vitesse
// retour glisse: indique si oui ou non le noeud glisse
bool CompFrotCoulomb::Calcul_DFrottement_tdt
(const Coordonnee& vit_T, const Coordonnee&
,const Coordonnee& force_normale,const Coordonnee& force_tangente
,EnergieMeca& energie_frottement,const double delta_t
,Coordonnee& F_frot,Tableau & d_F_frot_vit)
{ // on regarde si l'on doit tenir compte du frottement cinématique
double mu_frot = mu_statique; // init du frottement que l'on utilisera effectivement
double n_vit_T = vit_T.Norme();
bool glisse = false; // par défaut
int dima = vit_T.Dimension();
energie_frottement.Inita(0.); // init
Coordonnee d_mu_frot(dima);
if (mu_cine != NULL)
{// le frottement dépend de la norme de la vitesse
double coef = (mu_statique - *mu_cine) * exp(-(*x_c)*n_vit_T);
mu_frot += coef;
d_mu_frot = vit_T * ((-(*x_c)/n_vit_T)*coef);
};
// init du tableau de variation
d_F_frot_vit.Change_taille(dima); // changement de taille éventuel
for (int i=1;i<=dima;i++) d_F_frot_vit(i).Zero();
// on regarde si le frottement est régularisé ou pas
double n_f_tangente = force_tangente.Norme();
double n_f_normale = force_normale.Norme();
switch (regularisation)
{ case 0: // -- pas de régularisation ---
{// on regarde si le noeud glisse ou pas
if (n_f_tangente < Dabs(mu_frot)*n_f_normale)
{// la force est correcte, il n'y a pas de glissement
glisse = false;
F_frot = force_tangente;
// et la dépendance à la vitesse n'est pas due à la loi de contact
}
else
{// on est en dehors du cône de frottement, il faut donc modifier
// la force tangentielle
glisse = true;
if (n_vit_T < ConstMath::pasmalpetit) // le déplacement est quasi_nulle
// on est obligé de considérer des cas particuliers car on ne peut pas
// utiliser la direction du déplacement, on va donc voir du coté
// de la force tangentielle initiale, on laisse à zero la dépendance à la vitesse
{ if (n_f_tangente < ConstMath::pasmalpetit) // force également quasi-nulle
// on la laisse comme elle est mais en signalant le glissement
{ F_frot = force_tangente;}
else // sinon on utilise la direction de la force
{ F_frot = force_tangente * (mu_frot*n_f_normale/n_f_tangente);};
}
else // cas normale, la vitesse est non nulle on l'utilise
{ F_frot = vit_T * (-mu_frot*n_f_normale/n_vit_T);
for (int i=1; i<= dima; i++)
{ Coordonnee d_V(dima); d_V(dima)=1.; // var de V par rapport à V -> identité
d_F_frot_vit(i)= (Util::VarUnVect_coor(vit_T,d_V,n_vit_T) * mu_frot
+ vit_T/n_vit_T * d_mu_frot(i)) * (-n_f_normale);
};
};
// mise à jour des énergies qui ici est uniquement plastique
// si le déplacement est nulle -> énergie nulle
energie_frottement.ChangeDissipationPlastique((F_frot * vit_T)*delta_t);
};
break;
}//-- fin du cas sans régularisation
case 1: case 2: case 3: case 4: // -- régularisation avec une fonction de la vitesse ---
{double fonct_phi = 0.; double d_fonct_phi;
switch (regularisation)
{case 1 :{ if (n_vit_T < -epsil) {fonct_phi = -1.;d_fonct_phi=0.;}
else if (n_vit_T < epsil) {fonct_phi = n_vit_T /(2.*epsil);d_fonct_phi=1./(2.*epsil);}
else {fonct_phi = 1.;d_fonct_phi=0.;}
break;
}
case 2 :{ double w1=sqrt(n_vit_T*n_vit_T + epsil*epsil);
fonct_phi = n_vit_T/w1; d_fonct_phi = 1./w1 * (1.- n_vit_T*n_vit_T / (w1*w1));
break;
}
case 3 :{fonct_phi = tanh (n_vit_T/epsil);
d_fonct_phi = (1.-fonct_phi*fonct_phi);
break;
}
case 4 :{Courbe1D::ValDer valder=fonc_regul->Valeur_Et_derivee(n_vit_T);
fonct_phi = valder.valeur; d_fonct_phi = valder.derivee;
break;
}
};
glisse = true; // systématiquement
// on recherche une direction de mouvement
if (n_vit_T < ConstMath::pasmalpetit) // le déplacement est quasi_nulle
// on est obligé de considérer des cas particuliers car on ne peut pas
// utiliser la direction du déplacement, on va donc voir du coté
// de la force tangentielle initiale, on laisse à zero la dépendance à la vitesse
{ if (n_f_tangente < ConstMath::pasmalpetit) // force également quasi-nulle
// on la laisse comme elle est mais en signalant le glissement
{ F_frot = force_tangente;}
else // sinon on utilise la direction de la force
{ F_frot = force_tangente * (mu_frot*n_f_normale*fonct_phi/n_f_tangente);};
}
else // cas normale: la vitesse est non nulle on l'utilise
{ F_frot = vit_T * (-mu_frot*n_f_normale*fonct_phi/n_vit_T);
for (int i=1; i<= dima; i++)
{ Coordonnee d_V(dima); d_V(dima)=1.; // var de V par rapport à V -> identité
d_F_frot_vit(i)= (Util::VarUnVect_coor(vit_T,d_V,n_vit_T) * (mu_frot * fonct_phi)
+ vit_T/n_vit_T * (d_mu_frot(i) * fonct_phi)
+ vit_T/n_vit_T * (mu_frot * d_fonct_phi * vit_T(i)/n_vit_T)
) * (-n_f_normale);
};
};
// mise à jour des énergies qui ici est plastique et un peu élastique
// si le déplacement est nulle -> énergie nulle
energie_frottement.ChangeDissipationPlastique((F_frot * vit_T)*delta_t);
double n_frot = F_frot.Norme();
// énergie élastique = 1/2 k x^2 = 1/2 F x
energie_frottement.ChangeEnergieElastique(0.5 * n_frot * n_vit_T * delta_t);
break;
}//-- fin du cas régularisation avec une fonction de la vitesse ---
}; //--- fin du switch sur regularisation
// retour
return glisse;
};