// 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; };