2021-09-23 11:21:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
// 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)
|
2021-09-23 11:21:15 +02:00
|
|
|
// 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 "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()
|
2023-05-03 17:23:49 +02:00
|
|
|
{ int ret = LoiAbstraiteGeneral::TestComplet();
|
|
|
|
if (mu_statique == -ConstMath::tresgrand)
|
2021-09-23 11:21:15 +02:00
|
|
|
{ cout << "\n mu_statique n'est pas defini dans la loi de coulomb ";
|
|
|
|
ret = 0;
|
|
|
|
};
|
2023-05-03 17:23:49 +02:00
|
|
|
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;
|
|
|
|
};
|
2021-09-23 11:21:15 +02:00
|
|
|
|
|
|
|
//----- 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 <Coordonnee>& 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;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|