// This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-2021 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . #include "IsoHyper3DFavier3.h" #include "ComLoi_comp_abstraite.h" # include using namespace std; //introduces namespace std #include #include #include "Sortie.h" #include "ConstMath.h" #include "CharUtil.h" //================== initialisation des variables static ====================== // indicateur utilisé par Verif_Potentiel_et_var int IsoHyper3DFavier3::indic_Verif_PoGrenoble_et_var = 0; double IsoHyper3DFavier3::limite_co2=700.; // limite à partir de laquelle on considère que cosh(co2) = infini // ici cosh(700.) = 5.0712e+303 !! //================== fin d'initialisation des variables static ================ IsoHyper3DFavier3::IsoHyper3DFavier3 () : // Constructeur par defaut Hyper3D(ISOHYPER3DFAVIER3,CAT_MECANIQUE,false),K(ConstMath::trespetit),Qor(ConstMath::trespetit) ,mur(ConstMath::trespetit),mu_inf(ConstMath::trespetit) ,nQor(ConstMath::trespetit),gammaQor(ConstMath::trespetit) ,n_mu_inf(ConstMath::trespetit),gamma_mu_inf(ConstMath::trespetit) {}; // Constructeur de copie IsoHyper3DFavier3::IsoHyper3DFavier3 (const IsoHyper3DFavier3& loi) : Hyper3D (loi),K(loi.K),Qor(loi.Qor),mur(loi.mur),mu_inf(loi.mu_inf) ,nQor(loi.nQor),gammaQor(loi.gammaQor) ,n_mu_inf(loi.n_mu_inf),gamma_mu_inf(loi.gamma_mu_inf) {}; // Lecture des donnees de la classe sur fichier void IsoHyper3DFavier3::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D& ,LesFonctions_nD& lesFonctionsnD) { // lecture des quatres coefficients de la loi *(entreePrinc->entree) >> K >> Qor >> mur >> mu_inf ; // on regarde ensuite s'il y a la phase if (strstr(entreePrinc->tablcar,"avec_phase")!=NULL) { // lecture des 4 paramètres de phase entreePrinc->NouvelleDonnee(); // passage d'une ligne *(entreePrinc->entree) >> nQor >> gammaQor >> n_mu_inf >> gamma_mu_inf ; avec_phase=true; }; // cas avec régularisation (variable stockée dans Hyper3D.h) string nom1; if (strstr(entreePrinc->tablcar,"avec_regularisation_")!=NULL) { *(entreePrinc->entree) >> nom1 ; if (nom1 != "avec_regularisation_") { cout << "\n erreur en lecture du drapeau de regularisation, on attendait le mot cles " << " avec_regularisation_ on a lue: " << nom1 ; entreePrinc->MessageBuffer("**9--IsoHyper3DOrgeas1::LectureDonneesParticulieres(.....**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; *(entreePrinc->entree) >> fact_regularisation; avec_regularisation=true; }; // lecture de l'indication du post traitement string nom_class_methode = "IsoHyper3DFavier3";string le_mot_cle = "sortie_post_"; entreePrinc->Lecture_un_parametre_int(0,nom_class_methode,0,1,le_mot_cle,sortie_post); // appel au niveau de la classe mère Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire (*entreePrinc,lesFonctionsnD); }; // affichage de la loi void IsoHyper3DFavier3::Affiche() const { cout << " \n loi de comportement 3D hyperelastique isotrope favier3 : " << Nom_comp(id_comp) << " paramètres : \n"; cout << " K= " << K << " ; Qor = " << Qor << " ; mur = " << mur << " ; mu_inf = " << mu_inf ; if (avec_phase) { cout << "\n cas de la loi avec phase, parametre de la phase: " << " nQor= " << nQor << " gammaQor= " << gammaQor << " n_mu_inf= " << n_mu_inf << " gamma_mu_inf= " << gamma_mu_inf; } cout << endl; // appel de la classe mère Loi_comp_abstraite::Affiche_don_classe_abstraite(); }; // affichage et definition interactive des commandes particulières à chaques lois void IsoHyper3DFavier3::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# ....... loi de comportement 3D hyperelastique isotrope favier3 ........"; if ((rep != "o") && (rep != "O" ) && (rep != "0") ) { sort << "\n# **** exemple de cas AVEC la phase :" << "\n#------------------------------------------------------------------------------------" << "\n# K | Qor | mur | mu_inf | avec_phase(falculatif) |" << "\n#------------------------------------------------------------------------------------" << "\n 160000 150 17000 220 avec_phase" << "\n#-------------------------------------------------" << "\n# n_Q | gamma_Q | n_mu | gamma_mu |" << "\n#-------------------------------------------------" << "\n 0.25 0.4 0.25 0.4 " << "\n# **** exemple de cas SANS la phase :" << "\n#------------------------------------------------------------------------------------" << "\n# il est possible d'indiquer un facteur de regularisation qui permet d'eviter " << "\n# de potentiels problemes de NaN, de type division par 0 par exemple " << "\n# 1/a est remplace par 1/(a+fact_regularisation), par defaut fact_regularisation = 1.e-12 " << "\n# pour indiquer un facteur de regulation non nul on indique en dernier parametre " << "\n# le mot cle avec_regularisation_ suivi du facteur voulu " << "\n# ex: " << "\n# avec_regularisation_ 1.e-12 " << "\n# ce mot cle doit se situer avant le mot cle sortie_post_ " << "\n#------------------------------------------------------------------------------------" << "\n# il est possible de recuperer differentes grandeurs de travail par exemple " << "\n# l'intensite du potentiel, comme ces grandeurs sont calculees au moment de la resolution " << "\n# et ne sont pas stockees, il faut indiquer le mot cle sortie_post_ suivi de 1 (par defaut = 0) " << "\n# ensuite au moment de la constitution du .CVisu on aura acces aux grandeurs de travail " << "\n# ex: " << "\n# sortie_post_ 1 " << "\n# ce mot cle est le dernier des parametres specifiques de la loi il doit se situe " << "\n# a la fin de la derniere ligne de donnees " << "\n#" << "\n#------------------------------------------------------------------------------------"; }; sort << "\n#------------------------------------------------------------------------------------" << "\n# K | Qor | mur | mu_inf | avec_phase(falculatif) |" << "\n#------------------------------------------------------------------------------------" << "\n 160000 150 17000 220 " << endl; // appel de la classe Hyper3D Hyper3D::Info_commande_LoisDeComp_hyper3D(entreePrinc); // appel de la classe mère Loi_comp_abstraite::Info_commande_don_LoisDeComp(entreePrinc); }; // test si la loi est complete int IsoHyper3DFavier3::TestComplet() { int ret = LoiAbstraiteGeneral::TestComplet(); if ((K == ConstMath::trespetit) || (Qor == ConstMath::trespetit) || (mur == ConstMath::trespetit) || (mu_inf == ConstMath::trespetit)) { cout << " \n Les paramètres ne sont pas défini pour la loi " << Nom_comp(id_comp) << '\n'; Affiche(); ret = 0; } if (avec_phase) if ((nQor == ConstMath::trespetit) || (gammaQor == ConstMath::trespetit) || (n_mu_inf == ConstMath::trespetit) || (gamma_mu_inf == ConstMath::trespetit)) { cout << " \n Les paramètres de la phase ne sont pas défini pour la loi " << Nom_comp(id_comp) << '\n'; Affiche(); 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 IsoHyper3DFavier3::Lecture_base_info_loi(ifstream& ent,const int cas,LesReferences& lesRef ,LesCourbes1D& lesCourbe1D,LesFonctions_nD& lesFonctionsnD) { string toto; if (cas == 1) { ent >> toto >> K >> toto >> Qor >> toto >> mur >> toto >> mu_inf >> avec_phase; if (avec_phase) { ent >> toto >> nQor >> toto >> gammaQor >> toto >> n_mu_inf >> toto >> gamma_mu_inf; }; // gestion du post-traitement ent >> toto >> sortie_post ; }; // appel class mère Loi_comp_abstraite::Lecture_don_base_info(ent,cas,lesRef,lesCourbe1D,lesFonctionsnD); }; // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void IsoHyper3DFavier3::Ecriture_base_info_loi(ofstream& sort,const int cas) { if (cas == 1) { sort << " module_dilatation " << K << " seuil " << Qor << " pente_origine " << mur << " pente_infini " << mu_inf << " avec_phase " << avec_phase; if (avec_phase) { sort << "\n nQor= " << nQor << " gammaQor= " << gammaQor << " n_mu_inf= " << n_mu_inf << " gamma_mu_inf= " << gamma_mu_inf; }; // gestion du post-traitement sort << " sortie_post= "<< sortie_post << " "; }; // appel de la classe mère Loi_comp_abstraite::Ecriture_don_base_info(sort,cas); }; // =========== METHODES Protégées dérivant de virtuelles : ============== // METHODES internes spécifiques à l'hyperélasticité isotrope découlant de // méthodes virtuelles de Hyper3D // calcul du potentiel tout seul sans la phase car Qeps est nul // ou très proche de 0 double IsoHyper3DFavier3::PoGrenoble (const double & Qeps,const Invariant & inv) { // des variables intermédiaires double a = Qor/2./mur; double co1 = Qor*a; double co2 = Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées double E = K/6. * (logV)*(logV) + co1*log_A + mu_inf * Qeps * Qeps; // retour return E; }; // calcul du potentiel tout seul avec la phase donc dans le cas où Qeps est non nul double IsoHyper3DFavier3::PoGrenoble (const Invariant0QepsCosphi & inv_spec,const Invariant & inv) { // dans le cas de l'existence de la phase, on modifie Qr et muinf double bmuinf,bQr,muinfF,Qr; if (avec_phase) {bmuinf = (1.+gamma_mu_inf*inv_spec.cos3phi); bQr = (1.+gammaQor*inv_spec.cos3phi); muinfF = mu_inf/ pow(bmuinf,n_mu_inf); Qr = Qor/pow(bQr,nQor); } else {bmuinf = 1.; bQr = 1.; muinfF = mu_inf; Qr = Qor; } // des variables intermédiaires double a = Qr/2./mur; double co1 = Qr*a; double co2 = inv_spec.Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées double E = K/6. * (logV)*(logV) + co1*log_A + muinfF * inv_spec.Qeps * inv_spec.Qeps; // retour return E; }; // calcul du potentiel tout seul sans la phase car Qeps est nul // ou très proche de 0, et de sa variation suivant V uniquement Hyper3D::PoGrenoble_V IsoHyper3DFavier3::PoGrenoble_et_V (const double & Qeps,const Invariant & inv) { PoGrenoble_V ret; // des variables intermédiaires double a = Qor/2./mur; double co1 = Qor*a; double co2 = Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées ret.E = K/6. * (logV)*(logV) + co1*log_A + mu_inf * Qeps * Qeps; ret.EV = K/3.*logV/inv.V; ret.Ks = K / 3. *(logV/2. + 1.); // retour return ret; }; // calcul du potentiel et de sa variation suivant V uniquement Hyper3D::PoGrenoble_V IsoHyper3DFavier3::PoGrenoble_et_V (const Invariant0QepsCosphi & inv_spec,const Invariant & inv) { Hyper3D::PoGrenoble_V ret; // dans le cas de l'existence de la phase, on modifie Qr et muinf double bmuinf,bQr,muinfF,Qr; if (avec_phase) {bmuinf = (1.+gamma_mu_inf*inv_spec.cos3phi); bQr = (1.+gammaQor*inv_spec.cos3phi); muinfF = mu_inf/ pow(bmuinf,n_mu_inf); Qr = Qor/pow(bQr,nQor); } else {bmuinf = 1.; bQr = 1.; muinfF = mu_inf; Qr = Qor; } // des variables intermédiaires double a = Qr/2./mur; double co1 = Qr*a; double co2 = inv_spec.Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées ret.E = K/6. * (logV)*(logV) + co1*log_A + muinfF * inv_spec.Qeps * inv_spec.Qeps; ret.EV = K/3.*logV/inv.V; ret.Ks = K / 3. *(logV/2. + 1.); // retour return ret; }; // calcul du potentiel tout seul sans la phase car Qeps est nul // ou très proche de 0, et de ses variations première et seconde suivant V uniquement Hyper3D::PoGrenoble_VV IsoHyper3DFavier3::PoGrenoble_et_VV (const double & Qeps,const Invariant & inv) { PoGrenoble_VV ret; // des variables intermédiaires double a = Qor/2./mur; double co1 = Qor*a; double co2 = Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées premières ret.E = K/6. * (logV)*(logV) + co1*log_A + mu_inf * Qeps * Qeps; ret.EV = K/3.*logV/inv.V; // dérivées secondes ret.EVV = K/3. * (1.-logV) / (inv.V * inv.V); ret.Ks = K / 3. *(logV/2. + 1.); // retour return ret; }; // calcul du potentiel et de sa variation première et seconde suivant V uniquement Hyper3D::PoGrenoble_VV IsoHyper3DFavier3::PoGrenoble_et_VV (const Invariant0QepsCosphi & inv_spec,const Invariant & inv) { Hyper3D::PoGrenoble_VV ret; // dans le cas de l'existence de la phase, on modifie Qr et muinf double bmuinf,bQr,muinfF,Qr; if (avec_phase) {bmuinf = (1.+gamma_mu_inf*inv_spec.cos3phi); bQr = (1.+gammaQor*inv_spec.cos3phi); muinfF = mu_inf/ pow(bmuinf,n_mu_inf); Qr = Qor/pow(bQr,nQor); } else {bmuinf = 1.; bQr = 1.; muinfF = mu_inf; Qr = Qor; } // des variables intermédiaires double a = Qr/2./mur; double co1 = Qr*a; double co2 = inv_spec.Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées premières ret.E = K/6. * (logV)*(logV) + co1*log_A + muinfF * inv_spec.Qeps * inv_spec.Qeps; ret.EV = K/3.*logV/inv.V; // dérivées secondes ret.EVV = K/3. * (1.-logV) / (inv.V * inv.V); ret.Ks = K / 3. *(logV/2. + 1.); // retour return ret; }; // calcul du potentiel et de ses dérivées non compris la phase Hyper3D::PoGrenobleSansPhaseSansVar IsoHyper3DFavier3::PoGrenoble (const InvariantQeps & inv_spec,const Invariant & inv) { PoGrenobleSansPhaseSansVar ret; // des variables intermédiaires double a = Qor/2./mur; double co1 = Qor*a; double co2 = inv_spec.Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées ret.E = K/6. * (logV)*(logV) + co1*log_A + mu_inf * inv_spec.Qeps * inv_spec.Qeps; ret.EV = K/3.*logV/inv.V; // // dans le cas où l'on est très près de l'origine (voir nul) // // il faut un traitement particulier // if (co2 > ConstMath::unpeupetit) // cas normal ret.EQ = Qor * tanh(co2) + 2.* mu_inf * inv_spec.Qeps; /* else // cas ou Qeps est très proche de zéro, on utilise un développement // limité ret.EQ = (Qor/a + mu_inf)* inv_spec.Qeps - 1./3. * Qor/(a*a*a) * inv_spec.Qeps * inv_spec.Qeps * inv_spec.Qeps; */ ret.Ks = K / 3. *(logV/2. + 1.); // retour return ret; }; // calcul du potentiel et de ses dérivées avec la phase Hyper3D::PoGrenobleAvecPhaseSansVar IsoHyper3DFavier3::PoGrenoblePhase (const InvariantQepsCosphi& inv_spec,const Invariant & inv) { PoGrenobleAvecPhaseSansVar ret; // dans le cas de l'existence de la phase, on modifie Qr et muinf double bmuinf,bQr,muinfF,Qr; if (avec_phase) {bmuinf = (1.+gamma_mu_inf*inv_spec.cos3phi); bQr = (1.+gammaQor*inv_spec.cos3phi); muinfF = mu_inf/ pow(bmuinf,n_mu_inf); Qr = Qor/pow(bQr,nQor); } else {bmuinf = 1.; bQr = 1.; muinfF = mu_inf; Qr = Qor; } // des variables intermédiaires double a = Qr/2./mur; double co1 = Qr*a; double co2 = inv_spec.Qeps/a ; double A = cosh(co2); double log_A=0.; if ((Dabs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); } else { log_A = log(A);}; double logV = log(inv.V); // le potentiel et ses dérivées ret.E = K/6. * (logV)*(logV) + co1*log_A + muinfF * inv_spec.Qeps * inv_spec.Qeps; ret.EV = K/3.*logV/inv.V; // // dans le cas où l'on est très près de l'origine (voir nul) // // il faut un traitement particulier // if (co2 > ConstMath::unpeupetit) // cas normal ret.EQ = Qr * tanh(co2) + 2.* muinfF * inv_spec.Qeps; /* else // cas ou Qeps est très proche de zéro, on utilise un développement // limité ret.EQ = (Qor/a + mu_inf)* inv_spec.Qeps - 1./3. * Qor/(a*a*a) * inv_spec.Qeps * inv_spec.Qeps * inv_spec.Qeps; */ // cas de la variation faisant intervenir la phase double dEdmuinf= inv_spec.Qeps * inv_spec.Qeps; double dmuinf_dcos3phi = (- n_mu_inf * gamma_mu_inf * muinfF/bmuinf); double dQdcos3phi = (- nQor * gammaQor * Qr / bQr); ret.Ecos3phi = dEdmuinf * dmuinf_dcos3phi + ret.EQ * dQdcos3phi; ret.Ks = K / 3. *(logV/2. + 1.); // retour return ret; }; // calcul du potentiel sans phase et dérivées avec ses variations par rapport aux invariants Hyper3D::PoGrenobleSansPhaseAvecVar IsoHyper3DFavier3::PoGrenoble_et_var (const Invariant2Qeps& inv_spec,const Invariant & inv) { PoGrenobleSansPhaseAvecVar ret; // des variables intermédiaires double a = Qor/2./mur; double co1 = Qor*a; double co2 = inv_spec.Qeps/a ; double A = cosh(co2); double log_A=0.; double tanhco2 = 1.; // init par défaut if ((Abs(co2) > limite_co2) || (!isfinite(A))) // en fait A est "toujours" très grand, donc c'est normal, et il vaut mieux regarder s'il est // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); tanhco2 = 1.; // et dans ce cas on est à la limite : th(A) =(environ)= exp(co2)/exp(co2) = 1 } else { log_A = log(A); tanhco2 = tanh(co2); }; double logV = log(inv.V); // le potentiel et ses dérivées premières ret.E = K/6. * (logV)*(logV) + co1*log_A + mu_inf * inv_spec.Qeps * inv_spec.Qeps; ret.EV = K/3.*logV/inv.V; // dérivées secondes ret.EVV = K/3. * (1.-logV) / (inv.V * inv.V); ret.EQV = 0.; // dans le cas où l'on est très près de l'origine (voir nul) // il faut un traitement particulier // if (co2 > ConstMath::unpeupetit) // cas normal { ret.EQ = Qor * tanhco2 + 2.* mu_inf * inv_spec.Qeps; // dérivée seconde ret.EQQ = 2.*mur*(1. - tanhco2 * tanhco2) + 2.* mu_inf; } /* else // cas ou Qeps est très proche de zéro, on utilise un développement // limité { ret.EQ = (Qor/a + mu_inf)* inv_spec.Qeps - 1./3. * Qor/(a*a*a) * inv_spec.Qeps * inv_spec.Qeps * inv_spec.Qeps; // dérivée seconde ret.EQQ = (Qor/a + mu_inf) - Qor/(a*a*a) * inv_spec.Qeps * inv_spec.Qeps * inv_spec.Qeps; }*/ // vérif des dérivées du potentiels par rapport aux invariants, ceci par différences finies // --- Verif_PoGrenoble_et_var(inv_spec.Qeps,inv,ret ); //--- débug: autre vérification à décommenter si on veut vérifier un nan événtuel !! -------------------- // if ((Dabs(ret.E) > ConstMath::tresgrand) || (Dabs(ret.EV) > ConstMath::tresgrand) // || (Dabs(ret.EVV) > ConstMath::tresgrand) || (Dabs(ret.EQV) > ConstMath::tresgrand) // || (Dabs(ret.EQQ) > ConstMath::tresgrand) || (Dabs(ret.EQ) > ConstMath::tresgrand) ) // { cout << "\n attention *** on a detecter un comportement bizarre sur le potentiel de la loi Favier3D " // << " potentiel= " << ret.E << " var/V= " << ret.EV << " var/Q= " << ret.EQ // << " var/VV= " << ret.EVV << " var/QQ= " << ret.EQQ << " var/QV= " << ret.EQV << endl; // }; //---- fin débug ----------------------------------------------------------------------------------------- ret.Ks = K / 3. *(logV/2. + 1.); // retour return ret; }; // calcul du potentiel avec phase et dérivées avec ses variations par rapport aux invariants Hyper3D::PoGrenobleAvecPhaseAvecVar IsoHyper3DFavier3::PoGrenoblePhase_et_var (const Invariant2QepsCosphi& inv_spec,const Invariant & inv) { Hyper3D::PoGrenobleAvecPhaseAvecVar ret; // dans le cas de l'existence de la phase, on modifie Qr et muinf double bmuinf,bQr,muinfF,Qr; if (avec_phase) {bmuinf = (1.+gamma_mu_inf*inv_spec.cos3phi); bQr = (1.+gammaQor*inv_spec.cos3phi); muinfF = mu_inf/ pow(bmuinf,n_mu_inf); Qr = Qor/pow(bQr,nQor); } else {bmuinf = 1.; bQr = 1.; muinfF = mu_inf; Qr = Qor; } //debug //cout << "\n debug: IsoHyper3DFavier3::PoGrenoblePhase_et_var " // << " Qr="<ConstMath::pasmalgrand)||(!isfinite(A))) // if (Dabs(A)>ConstMath::tresgrand) {// si co2 est grand (par exemple > 800 uniquement !!) ou très petit, comme cosh(co2) = (exp(co2) + exp(-co2))/2, on a exp(co2) = inf // ou exp(-co2) = inf // mais en fait on n'utilise que le log(A) donc on peut faire une approximation // soit co2 est grand // on fait l'approximation que expo(-co2) est pratiquement nulle d'où cosh(co2) =(environ)= exp(co2)/2 // d'où log(A) =(environ)= co2-log(2) log_A = MaX(0.,Dabs(co2)-log(2.)); tanhco2 = 1.; // et dans ce cas on est à la limite : th(A) =(environ)= exp(co2)/exp(co2) = 1 } else { log_A = log(A); tanhco2 = tanh(co2); }; //debug //cout << "\n debug: 3DFavier3::Po..ePhase_et_var " // << " A="<< A << " co2="<< co2<< " log_A="< 50.*delta) erreur = true;} else erreur = true;} if (diffpourcent(potret.EQ,E_Qeps,MaX(Dabs(E_Qeps),Dabs(potret.EQ)),0.05)) {if (MiN(Dabs(E_Qeps),Dabs(potret.EQ)) == 0.) {if ( MaX(Dabs(E_Qeps),Dabs(potret.EQ)) > 50.*delta) erreur = true;} else erreur = true;} if (diffpourcent(potret.EQQ,E_Qeps2,MaX(Dabs(E_Qeps2),Dabs(potret.EQQ)),0.05)) {if (MiN(Dabs(E_Qeps2),Dabs(potret.EQQ)) == 0.) {if ( MaX(Dabs(E_Qeps2),Dabs(potret.EQQ)) > 50.*delta) erreur = true;} else erreur = true;} if (diffpourcent(potret.EVV,E_V2,MaX(Dabs(E_V2),Dabs(potret.EVV)),0.05)) {if (MiN(Dabs(E_V2),Dabs(potret.EVV)) == 0.) {if ( MaX(Dabs(E_V2),Dabs(potret.EVV)) > 50.*delta) erreur = true;} else erreur = true;} if (diffpourcent(potret.EQV,E_VQeps,MaX(Dabs(E_VQeps),Dabs(potret.EQV)),0.05)) {if (MiN(Dabs(E_VQeps),Dabs(potret.EQV)) == 0.) {if (Dabs(potret.EQV) == 0.) // si la valeur de la dérivée numérique est nulle cela signifie peut-être // que l'on est à un extréma, la seule chose que le l'on peut faire est de // vérifier que l'on tend numériquement vers cette extréma ici un minima { Invariant inv_et_ddVddQeps = inv_n0; inv_et_ddVddQeps.V += delta/10.; double Qeps_et_ddVddQeps = Qeps+delta/10.; double E_et_ddVddQeps = PoGrenoble(Qeps_et_ddVddQeps,inv_et_ddVddQeps); double Qeps_et_ddQeps = Qeps+delta/10.; double E_et_ddQeps = PoGrenoble(Qeps_et_ddQeps,inv_n0); double E_V_a_ddQeps = (E_et_ddVddQeps - E_et_ddQeps )/(delta*10.); if (10.* Dabs(E_V_a_ddQeps) > Dabs(E_V_a_dQeps)) erreur = true; } else if ( MaX(Dabs(E_VQeps),Dabs(potret.EQV)) > 150.*delta) erreur = true; } else erreur = true; } if (erreur) { cout << "\n erreur dans le calcul analytique des derivees du potentiel"; cout << "\n IsoHyper3DFavier3::Verif_PoGrenoble_et_var(.." << " , numero d'increment = " << indic_Verif_PoGrenoble_et_var; Sortie(1); } }; // vérif des dérivées du potentiels par rapport aux invariants, ceci par différences finies void IsoHyper3DFavier3::Verif_PoGrenoble_et_var (const double & Qeps,const Invariant & inv,const double& cos3phi ,const PoGrenobleAvecPhaseAvecVar& potret ) { // dans le cas du premier passage on indique qu'il y a vérification if (indic_Verif_PoGrenoble_et_var == 0) { cout << "\n ****vérification des dérivées du potentiels par rapport aux invariants****"; cout << "\n IsoHyper3DFavier3::Verif_PoGrenoble_et_var \n"; } indic_Verif_PoGrenoble_et_var++; // potret contiend le potentiel et ses variations première et seconde // on va calculer ces mêmes variations par différences finies et comparer les deux résultats // calcul des invariants sous la nouvelle forme double toto = potret.E; // pour que le débugger affiche potret Invariant inv_n0(inv.Ieps,inv.V,inv.bIIb,inv.bIIIb); // recopie des invariants sans les varddl Invariant0QepsCosphi invcos3phi(Qeps,cos3phi); double E_n = PoGrenoble(invcos3phi,inv_n0); // la valeur du potentiel de référence // ici on est sans phase donc deux invariants indépendant V et Qeps, // pour calculer les variations on définit des points distants d'un incrément puis de deux incréments // pour les dérivées premières et secondes double delta = 10.*ConstMath::unpeupetit; double Qeps_et_dQeps = Qeps+delta; Invariant0QepsCosphi invcos3phi1(Qeps_et_dQeps,cos3phi); double E_et_dQeps = PoGrenoble(invcos3phi1,inv_n0); double Qeps_moins_dQeps = Qeps - delta; Invariant0QepsCosphi invcos3phi2(Qeps_moins_dQeps,cos3phi); double E_moins_dQeps = PoGrenoble(invcos3phi2,inv_n0); Invariant inv_et_dV = inv_n0;inv_et_dV.V += delta; double E_et_dV = PoGrenoble(invcos3phi,inv_et_dV); Invariant inv_moins_dV = inv_n0;inv_moins_dV.V -= delta; double E_moins_dV = PoGrenoble(invcos3phi,inv_moins_dV); Invariant inv_et_dVdQeps = inv_n0; inv_et_dVdQeps.V += delta; double Qeps_et_dVdQeps = Qeps+delta; Invariant0QepsCosphi invcos3phi3(Qeps_et_dVdQeps,cos3phi); double E_et_dVdQeps = PoGrenoble(invcos3phi3,inv_et_dVdQeps); // cas des variations avec cos3phi double cos3phi_et_dcos3phi = cos3phi+delta; Invariant0QepsCosphi invcos3phi_et_dcos3phi(Qeps,cos3phi_et_dcos3phi); double E_et_dcos3phi = PoGrenoble(invcos3phi_et_dcos3phi,inv_n0); double cos3phi_moins_dcos3phi = cos3phi-delta; Invariant0QepsCosphi invcos3phi_moins_dcos3phi(Qeps,cos3phi_moins_dcos3phi); double E_moins_dcos3phi = PoGrenoble(invcos3phi_moins_dcos3phi,inv_n0); Invariant0QepsCosphi invcos3phi_et_dcos3phi_a_dQeps(Qeps_et_dQeps,cos3phi_et_dcos3phi); double E_et_dcos3phi_a_dQeps = PoGrenoble(invcos3phi_et_dcos3phi_a_dQeps,inv_n0); double E_et_dcos3phi_a_dV = PoGrenoble(invcos3phi_et_dcos3phi,inv_et_dV); // calcul des dérivées premières double E_V = (E_et_dV - E_n)/delta; double E_Qeps = (E_et_dQeps - E_n)/delta; double E_cos3phi = (E_et_dcos3phi -E_n)/delta; // calcul des dérivées secondes double E_V2 = (E_et_dV - 2.*E_n + E_moins_dV ) /(delta * delta); double E_Qeps2 = (E_et_dQeps - 2.*E_n + E_moins_dQeps)/(delta * delta); double E_V_a_dQeps = (E_et_dVdQeps - E_et_dQeps )/delta; double E_VQeps = ( E_V_a_dQeps - E_V)/delta; double E_cos3phi_2 = (E_et_dcos3phi - 2.*E_n + E_moins_dcos3phi ) /(delta * delta); double E_dQeps_a_dcos3phi = (E_et_dcos3phi_a_dQeps - E_et_dcos3phi )/delta; double E_dcos3phi_dQeps = (E_dQeps_a_dcos3phi - E_Qeps )/delta; double E_dV_a_dcos3phi = (E_et_dcos3phi_a_dV - E_et_dcos3phi )/delta; double E_dcos3phi_dV = (E_dV_a_dcos3phi - E_V )/delta; // dans les dérivées secondes par rapport à cos3phi on a des erreurs, sans doute à cause des petites valeurs ?? // comparaison avec les valeurs de dérivées analytiques int erreur = 0; if (diffpourcent(potret.EV,E_V,MaX(Dabs(E_V),Dabs(potret.EV)),0.05)) {if (MiN(Dabs(E_V),Dabs(potret.EV)) == 0.) {if ( MaX(Dabs(E_V),Dabs(potret.EV)) > 50.*delta) erreur = 1;} else erreur = 2; } if (diffpourcent(potret.EQ,E_Qeps,MaX(Dabs(E_Qeps),Dabs(potret.EQ)),0.05)) {if (MiN(Dabs(E_Qeps),Dabs(potret.EQ)) == 0.) {if ( MaX(Dabs(E_Qeps),Dabs(potret.EQ)) > 50.*delta) erreur = 3;} else erreur = 4;} if (diffpourcent(potret.Ecos3phi,E_cos3phi,MaX(Dabs(E_cos3phi),Dabs(potret.Ecos3phi)),0.05)) {if (MiN(Dabs(E_cos3phi),Dabs(potret.Ecos3phi)) == 0.) {if ( MaX(Dabs(E_cos3phi),Dabs(potret.Ecos3phi)) > 50.*delta) erreur = 31;} else erreur = 41;} if (diffpourcent(potret.EQQ,E_Qeps2,MaX(Dabs(E_Qeps2),Dabs(potret.EQQ)),0.05)) {if (MiN(Dabs(E_Qeps2),Dabs(potret.EQQ)) == 0.) {if ( MaX(Dabs(E_Qeps2),Dabs(potret.EQQ)) > 50.*delta) erreur = 5;} else erreur = 6;} if (diffpourcent(potret.EVV,E_V2,MaX(Dabs(E_V2),Dabs(potret.EVV)),0.05)) {if (MiN(Dabs(E_V2),Dabs(potret.EVV)) == 0.) {if ( MaX(Dabs(E_V2),Dabs(potret.EVV)) > 50.*delta) erreur = 7;} else erreur = 8;} if (diffpourcent(potret.Ecos3phi2,E_cos3phi_2,MaX(Dabs(E_cos3phi_2),Dabs(potret.Ecos3phi2)),0.05)) {if (MiN(Dabs(E_cos3phi_2),Dabs(potret.Ecos3phi2)) == 0.) {if ( MaX(Dabs(E_cos3phi_2),Dabs(potret.Ecos3phi2)) > 50.*delta) erreur = 71;} else erreur = 81;} if (diffpourcent(potret.EQV,E_VQeps,MaX(Dabs(E_VQeps),Dabs(potret.EQV)),0.05)) {if (MiN(Dabs(E_VQeps),Dabs(potret.EQV)) == 0.) {if (Dabs(potret.EQV) == 0.) // si la valeur de la dérivée numérique est nulle cela signifie peut-être // que l'on est à un extréma, la seule chose que le l'on peut faire est de // vérifier que l'on tend numériquement vers cette extréma ici un minima { Invariant inv_et_ddVddQeps = inv_n0; inv_et_ddVddQeps.V += delta/10.; double Qeps_et_ddVddQeps = Qeps+delta/10.; double E_et_ddVddQeps = PoGrenoble(Qeps_et_ddVddQeps,inv_et_ddVddQeps); double Qeps_et_ddQeps = Qeps+delta/10.; double E_et_ddQeps = PoGrenoble(Qeps_et_ddQeps,inv_n0); double E_V_a_ddQeps = (E_et_ddVddQeps - E_et_ddQeps )/(delta*10.); if (10.* Dabs(E_V_a_ddQeps) > Dabs(E_V_a_dQeps)) erreur = 9; } else if ( MaX(Dabs(E_VQeps),Dabs(potret.EQV)) > 150.*delta) erreur = 10; } else erreur = 11; } if (diffpourcent(potret.EVcos3phi,E_dcos3phi_dV,MaX(Dabs(E_dcos3phi_dV),Dabs(potret.EVcos3phi)),0.05)) {if (MiN(Dabs(E_dcos3phi_dV),Dabs(potret.EVcos3phi)) == 0.) {if (Dabs(potret.EVcos3phi) == 0.) // si la valeur de la dérivée numérique est nulle cela signifie peut-être // que l'on est à un extréma, la seule chose que le l'on peut faire est de // vérifier que l'on tend numériquement vers cette extréma ici un minima { /*Invariant inv_et_ddVddQeps = inv_n0; inv_et_ddVddQeps.V += delta/10.; double Qeps_et_ddVddQeps = Qeps+delta/10.; double E_et_ddVddQeps = PoGrenoble(Qeps_et_ddVddQeps,inv_et_ddVddQeps); double Qeps_et_ddQeps = Qeps+delta/10.; double E_et_ddQeps = PoGrenoble(Qeps_et_ddQeps,inv_n0); double E_V_a_ddQeps = (E_et_ddVddQeps - E_et_ddQeps )/(delta*10.); if (10.* Dabs(E_V_a_ddQeps) > Dabs(E_V_a_dQeps))*/ erreur = 91; } else if ( MaX(Dabs(E_dcos3phi_dV),Dabs(potret.EVcos3phi)) > 150.*delta) erreur = 101; } else erreur = 111; } if (diffpourcent(potret.EQcos3phi,E_dcos3phi_dQeps,MaX(Dabs(E_dcos3phi_dQeps),Dabs(potret.EQcos3phi)),0.05)) {if (MiN(Dabs(E_dcos3phi_dQeps),Dabs(potret.EQcos3phi)) == 0.) {if (Dabs(potret.EQcos3phi) == 0.) // si la valeur de la dérivée numérique est nulle cela signifie peut-être // que l'on est à un extréma, la seule chose que le l'on peut faire est de // vérifier que l'on tend numériquement vers cette extréma ici un minima { /*Invariant inv_et_ddVddQeps = inv_n0; inv_et_ddVddQeps.V += delta/10.; double Qeps_et_ddVddQeps = Qeps+delta/10.; double E_et_ddVddQeps = PoGrenoble(Qeps_et_ddVddQeps,inv_et_ddVddQeps); double Qeps_et_ddQeps = Qeps+delta/10.; double E_et_ddQeps = PoGrenoble(Qeps_et_ddQeps,inv_n0); double E_V_a_ddQeps = (E_et_ddVddQeps - E_et_ddQeps )/(delta*10.); if (10.* Dabs(E_V_a_ddQeps) > Dabs(E_V_a_dQeps))*/ erreur = 92; } else if ( MaX(Dabs(E_dcos3phi_dQeps),Dabs(potret.EQcos3phi)) > 150.*delta) erreur = 102; } else erreur = 112; } if (erreur > 0) { cout << "\n erreur dans le calcul analytique des derivees du potentiel"; cout << "\n IsoHyper3DFavier3::Verif_PoGrenoble_et_var(.." << " , numero d'increment = " << indic_Verif_PoGrenoble_et_var << " , numero d'erreur : " << erreur ; // Sortie(1); } };