// 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 "Courbe_expression_litterale_1D.h" #include "Sortie.h" #include "ConstMath.h" #include "MathUtil.h" #include "ParaGlob.h" #include "MotCle.h" #include // std::numeric_limits // CONSTRUCTEURS : Courbe_expression_litterale_1D::Courbe_expression_litterale_1D(string nom) : Courbe1D(nom,COURBE_EXPRESSION_LITTERALE_1D) ,ax(-ConstMath::tresgrand),bx(ConstMath::tresgrand) ,expression_fonction(),p(),fVal() ,delta_xSur_x(pow(std::numeric_limits::epsilon(),(1./5.))) // ,ordre_troncature(2) {}; // de copie Courbe_expression_litterale_1D::Courbe_expression_litterale_1D(const Courbe_expression_litterale_1D& Co) : Courbe1D(Co),ax(Co.ax),bx(Co.bx) ,expression_fonction(Co.expression_fonction),p(),fVal(Co.fVal) ,delta_xSur_x(Co.delta_xSur_x) // ,ordre_troncature(Co.ordre_troncature) { // arrivée ici on définie la fonction et la variable attachée p.SetExpr(expression_fonction); p.DefineVar("x", &fVal); }; // de copie à partir d'une instance générale Courbe_expression_litterale_1D::Courbe_expression_litterale_1D(const Courbe1D& Coo) : Courbe1D(Coo) ,expression_fonction(),p(),fVal(),delta_xSur_x() { if (Coo.Type_courbe() != COURBE_EXPRESSION_LITTERALE_1D) { cout << "\n erreur dans le constructeur de copie pour une courbe Courbe_expression_litterale_1D " << " à partir d'une instance générale "; cout << "\n Courbe_expression_litterale_1D::Courbe_expression_litterale_1D(const Courbe1D& Co) "; Sortie(1); }; // définition des données Courbe_expression_litterale_1D & Co = (Courbe_expression_litterale_1D&) Coo; ax = Co.ax; bx = Co.bx; expression_fonction = Co.expression_fonction; p.SetExpr(expression_fonction); p.DefineVar("x", &fVal); }; // DESTRUCTEUR : Courbe_expression_litterale_1D::~Courbe_expression_litterale_1D() {}; // METHODES PUBLIQUES : // --------- virtuelles --------- // affichage de la courbe void Courbe_expression_litterale_1D::Affiche() const { cout << "\n Courbe_expression_litterale_1D: nom_ref= " << nom_ref << " "; cout << "\n a=" << ax << " b= " << bx << " " << " f(x)= " << expression_fonction << " delta_xSur_x= " << delta_xSur_x<<" "; }; // vérification que tout est ok, pres à l'emploi // ramène true si ok, false sinon bool Courbe_expression_litterale_1D::Complet_courbe()const { bool ret = Complet_var(); // on regarde du coté de la classe mère tout d'abord // puis les variables propres return ret; } ; // Lecture des donnees de la classe sur fichier // le nom passé en paramètre est le nom de la courbe // s'il est vide c-a-d = "", la methode commence par lire le nom sinon // ce nom remplace le nom actuel void Courbe_expression_litterale_1D::LectDonnParticulieres_courbes(const string& nom,UtilLecture * entreePrinc) { expression_fonction = "aucune_expression"; // init pour le traitement d'erreur if (nom == "") { *(entreePrinc->entree) >> nom_ref;} else {nom_ref=nom;}; entreePrinc->NouvelleDonneeSansInf(); // on lit sans tenir compte des < éventuelles // entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne // on lit tant que l'on ne rencontre pas la ligne contenant "fin_parametres_courbe_expression_litterale_" // ou un nouveau mot clé global auquel cas il y a pb !! MotCle motCle; // ref aux mots cle string titi; while (strstr(entreePrinc->tablcar,"fin_parametres_courbe_expression_litterale_")==0) { // si on a un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur if ( motCle.SimotCle(entreePrinc->tablcar)) { cout << "\n erreur de lecture des parametre de definition d'une courbe avec expression litterale : on n'a pas trouve le mot cle " << " fin_parametres_courbe_expression_litterale_ et par contre la ligne courante contient un mot cle global "; entreePrinc->MessageBuffer("** erreur des parametres d'une courbe expression litterale **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // lecture d'un mot clé *(entreePrinc->entree) >> titi; if ((entreePrinc->entree)->rdstate() == 0) {} // lecture normale #ifdef ENLINUX else if ((entreePrinc->entree)->fail()) // on a atteind la fin de la ligne et on appelle un nouvel enregistrement { entreePrinc->NouvelleDonneeSansInf(); // on lit sans tenir compte des < éventuelles *(entreePrinc->entree) >>titi; } #else else if ((entreePrinc->entree)->eof()) // la lecture est bonne mais on a atteind la fin de la ligne { if(titi != "fin_parametres_courbe_expression_litterale_") // on lit sans tenir compte des < éventuelles {entreePrinc->NouvelleDonneeSansInf(); *(entreePrinc->entree) >> titi; }; } #endif else // cas d'une erreur de lecture { cout << "\n erreur de lecture inconnue "; entreePrinc->MessageBuffer("** erreur2 des parametres d'une courbe expression litterale**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // mini x if (titi == "a=") {*(entreePrinc->entree) >> ax; } // maxi x else if (titi == "b=") {*(entreePrinc->entree) >> bx; } // delta_xSur_x else if (titi == "delta_xSur_x=") {*(entreePrinc->entree) >> delta_xSur_x; if (delta_xSur_x < ConstMath::trespetit) { cout << "\n erreur en lecture du coefficient delta_xSur_x , on attendait une valeur positive" << " superieur a : " << ConstMath::trespetit << "et on a lue : " << delta_xSur_x; entreePrinc->MessageBuffer("**Courbe_expression_litterale_1D::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; } // on lit maintenant l'expression littérale else if (titi == "f(x)=") { std::getline (*(entreePrinc->entree), expression_fonction); } // sinon ce n'est pas un mot clé connu, on le signale else if(titi != "fin_parametres_courbe_expression_litterale_") { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu " << " on a lu : " << titi << endl; entreePrinc->MessageBuffer("**Courbe_expression_litterale_1D::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; }; //-- fin du while // on vérifie que l'on a bien lue une expression if (expression_fonction == "aucune_expression") {cout << "\n erreur en lecture de l'expression litterale de la fonction f(x) , l'expression est absente " << " ou il y a une erreur de syntaxe "; entreePrinc->MessageBuffer("**Courbe_expression_litterale_1D::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // arrivée ici on définie la fonction et la variable attachée p.SetExpr(expression_fonction); p.DefineVar("x", &fVal); }; // def info fichier de commande void Courbe_expression_litterale_1D::Info_commande_Courbes1D(UtilLecture & entreePrinc) { ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier sort << "\n#............................................" << "\n# exemple de definition d'une courbe Courbe_expression_litterale_1D ( f(x) = une expression de x |" << "\n# les parametres (tous optionnels) de la courbe sont (ordre a respecter) : " << "\n# . une limite inferieur pour x, ex: a= -1 , par defaut= -l'infini " << "\n# . une limite superieur pour x, ex: b= 4 , par defaut= +l'infini " << "\n# . un delta_x/x qui est utilise pour le calcul des derivees: " << "\n# ex: delta_xSur_x= 0.01 " << "\n# par defaut c'est : (std::numeric_limits::epsilon() ^ (1/5)) " << "\n# et a chaque calcul de derivee on utilise un delta x qui vaut: " << "\n# max (|x * (std::numeric_limits::epsilon() ^ (1/5))|,(std::numeric_limits::epsilon() ^ (1/5))| " << "\n# avec std::numeric_limits::epsilon() ^ (1/5)= " << pow(std::numeric_limits::epsilon(),(1./5.)) // << ConstMath::petit // << "\n# . l'ordre de troncature de la derivee numerique: par defaut 2 (DFC classique)" // << "\n# on peut egalement indiquer 4 -> ce qui conduit a utiliser 5 evaluations " << "\n# exemple complet " << "\n courbe_monte COURBE_EXPRESSION_LITTERALE_1D # nom de la courbe puis le type de la courbe " << "\n # def des coeff de la courbe= mini et maxi de x " << "\n # pour x < a => f=f(a), pour x>b => f=f(b)" << "\n # a et b sont facultatif, par defaut = -l'infini et + l'infini " << "\n a= 0. b= 1. f(x)= (x^2+3.)/cos(x)+log((1.+x)/(1.+x^3))*23.-8. " << "\n fin_parametres_courbe_expression_litterale_ " << endl; }; // ramène la valeur double Courbe_expression_litterale_1D::Valeur(double x) { double ret=0.; try {if (x < ax) {fVal = ax; ret = p.Eval(); } else if (x > bx) {fVal = bx; ret = p.Eval(); } else {fVal = x; ret = p.Eval(); }; } catch(mu::Parser::exception_type &e) { cout << "\n ** erreur dans l'appel de la fonction "<< expression_fonction << " x= "< bx) {fVal = bx; ret.valeur = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = bx-delta_x; double f_xMoinsDelta_x = p.Eval(); ret.derivee = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; } else {fVal = x; ret.valeur = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = x-delta_x; double f_xMoinsDelta_x = p.Eval(); ret.derivee = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; }; } catch(mu::Parser::exception_type &e) { cout << "\n ** erreur dans l'appel de la fonction et derivee "<< expression_fonction << " x= "< bx) {fVal = bx+delta_x; double f_xPlusDelta_x = p.Eval(); fVal = bx-delta_x; double f_xMoinsDelta_x = p.Eval(); ret = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; } else {fVal = x+delta_x; double f_xPlusDelta_x = p.Eval(); fVal = x-delta_x; double f_xMoinsDelta_x = p.Eval(); ret = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; }; } catch(mu::Parser::exception_type &e) { cout << "\n ** erreur dans l'appel de derivee de la fonction "<< expression_fonction << " x= "< bx) {fVal = bx; ret.valeur = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = bx-delta_x; double f_xMoinsDelta_x = p.Eval(); ret.derivee = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; ret.der_sec = (f_xPlusDelta_x - 2.* ret.valeur + f_xMoinsDelta_x)*unSurdelta_x*unSurdelta_x; } else {fVal = x; ret.valeur = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = x-delta_x; double f_xMoinsDelta_x = p.Eval(); ret.derivee = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; ret.der_sec = (f_xPlusDelta_x - 2.* ret.valeur + f_xMoinsDelta_x)*unSurdelta_x*unSurdelta_x; }; } catch(mu::Parser::exception_type &e) { cout << "\n ** erreur dans l'appel de la fonction et derivee et derivee seconde "<< expression_fonction << " x= "< bx) {fVal = bx; double f_x = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = bx-delta_x; double f_xMoinsDelta_x = p.Eval(); ret = (f_xPlusDelta_x - 2.* f_x + f_xMoinsDelta_x)*unSurdelta_x*unSurdelta_x; } else {fVal = x; double f_x = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = x-delta_x; double f_xMoinsDelta_x = p.Eval(); ret = (f_xPlusDelta_x - 2.* f_x + f_xMoinsDelta_x)*unSurdelta_x*unSurdelta_x; }; } catch(mu::Parser::exception_type &e) { cout << "\n ** erreur dans l'appel de la derivee seconde de la fonction "<< expression_fonction << " x= "< bx) {fVal = bx; ret.valeur = p.Eval(); ret.dedans = false; } else {fVal = x; ret.valeur = p.Eval(); ret.dedans = true; }; } catch(mu::Parser::exception_type &e) { cout << "\n ** erreur dans l'appel de la fonction "<< expression_fonction << " x= "< bx) {fVal = bx; ret.valeur = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = bx-delta_x; double f_xMoinsDelta_x = p.Eval(); ret.derivee = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; ret.dedans = false; } else {fVal = x; ret.valeur = p.Eval(); fVal += delta_x; double f_xPlusDelta_x = p.Eval(); fVal = x-delta_x; double f_xMoinsDelta_x = p.Eval(); ret.derivee = 0.5*(f_xPlusDelta_x-f_xMoinsDelta_x)*unSurdelta_x; ret.dedans = true; }; } catch(mu::Parser::exception_type &e) { cout << "\n ** erreur dans l'appel de la fonction et derivee "<< expression_fonction << " x= "<> nom; if (nom != "Courbe_expression_litterale_1D") { cout << "\n erreur dans la vérification du type de courbe lue "; cout << "\n Courbe_expression_litterale_1D::Lecture_base_info(... "; Sortie(1); } // lecture des infos ent >> nom >> ax >> nom >> bx >> nom >> expression_fonction >> nom >> delta_xSur_x; p.SetExpr(expression_fonction); p.DefineVar("x", &fVal); } }; // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void Courbe_expression_litterale_1D::Ecriture_base_info(ofstream& sort,const int cas) { // on n'a que des grandeurs constantes if (cas == 1) { sort << " Courbe_expression_litterale_1D "; sort << " a= " << ax << " b= " << bx << " f(x)= " << expression_fonction << " delta_xSur_x= " << delta_xSur_x<<" "; } }; // sortie du schemaXML: en fonction de enu void Courbe_expression_litterale_1D::SchemaXML_Courbes1D(ofstream& ,const Enum_IO_XML enu) { switch (enu) { case XML_TYPE_GLOBAUX : { break; } case XML_IO_POINT_INFO : { break; } case XML_IO_POINT_BI : { break; } case XML_IO_ELEMENT_FINI : { break; } }; };