// 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 "F_cycle_add.h" #include "Sortie.h" #include "ConstMath.h" #include "MathUtil.h" #include "CharUtil.h" // CONSTRUCTEURS : F_cycle_add::F_cycle_add(string nom) : Courbe1D(nom,F_CYCLE_ADD),F1(NULL) ,ampli(1.),longcycl(ConstMath::tresgrand),decalx(0.),decaly(0.) {}; // constructeur fonction d'une courbe existante et d'un nom F_cycle_add::F_cycle_add(Courbe1D* FF1, string nom): Courbe1D(nom,F_CYCLE_ADD),F1(FF1) ,nom_courbe1("") ,ampli(1.),longcycl(ConstMath::tresgrand),decalx(0.),decaly(0.) { // création d'une courbe locale que si elle était déjà locale if (FF1->NomCourbe() == "_") {F1=Courbe1D::New_Courbe1D(*(FF1));}; }; // de copie F_cycle_add::F_cycle_add(const F_cycle_add& Co) : Courbe1D(Co) ,F1(Co.F1) // a priori on pointe sur la même courbe interne ,nom_courbe1(Co.nom_courbe1) ,ampli(Co.ampli),longcycl(Co.longcycl),decalx(Co.decalx),decaly(Co.decaly) { // création d'une courbe locale que si elle était déjà locale if (Co.F1->NomCourbe() == "_") {F1=Courbe1D::New_Courbe1D(*(Co.F1));}; }; // de copie à partir d'une instance générale F_cycle_add::F_cycle_add(const Courbe1D& Coo) : Courbe1D(Coo) { if (Coo.Type_courbe() != F_CYCLE_ADD) { cout << "\n erreur dans le constructeur de copie pour une courbe F_CYCLE_ADD " << " à partir d'une instance générale "; cout << "\n F_cycle_add::F_cycle_add(const Courbe1D& Co) "; Sortie(1); }; // définition des données F_cycle_add & Co = (F_cycle_add&) Coo; nom_courbe1 = Co.nom_courbe1; ampli=Co.ampli; longcycl=Co.longcycl; decalx=Co.decalx; decaly=Co.decaly; // création d'une courbe locale que si elle était déjà locale if (Co.F1->NomCourbe() == "_") {F1=Courbe1D::New_Courbe1D(*(Co.F1));} else F1=Co.F1; // sinon cas d'une courbe globale }; // DESTRUCTEUR : F_cycle_add::~F_cycle_add() { // on efface la courbe que si c'est une courbe locale if ((F1 != NULL)&&(nom_courbe1=="i_interne_i")) delete F1; }; // METHODES PUBLIQUES : // --------- virtuelles --------- // affichage de la courbe void F_cycle_add::Affiche() const { cout << "\n courbe composee : F_cycle_add : nom_ref= " << nom_ref; // si c'est une courbe interne on l'affiche globalement // si c'est une courbe globale, on n'affiche que son nom cout << "\n fonction de base: "; if (F1->NomCourbe() == "_") {F1->Affiche();} else {cout << F1->NomCourbe() << " ";}; cout << "\n facteur d'amplification= " << ampli << " longueur_cycle= " << longcycl << " decalagex= " << decalx << " decalagey= " << decaly << " " ; cout << "\n ----- fin fonction F_cycle_add ----- "; }; // vérification que tout est ok, pres à l'emploi // ramène true si ok, false sinon bool F_cycle_add::Complet_courbe()const { bool ret = Complet_var(); // on regarde du coté de la classe mère tout d'abord // puis les variables propres if (F1 == NULL) ret = false; if (!ret && (ParaGlob::NiveauImpression() >0)) { cout << "\n ***** la courbe n'est pas complete "; this->Affiche(); }; return ret; } ; // dans le cas où la courbe membre est une courbe externe // fonction pour la définir // la courbe est défini en interne que si la courbe argument est elle même // une courbe locale. c'est-à-dire si FF1->NomCourbe() ="_" alors on recrée une courbe // interne avec new pour F1, sinon F=FF1 et pas de création; // dans le cas où FF1 ou FF1 est NULL on passe, pas de traitement pour ce pointeur void F_cycle_add::DefCourbesMembres(Courbe1D* FF1) { // création d'une courbe locale que si elle était déjà locales if (FF1 != NULL) {if (FF1->NomCourbe() == "_") // cas où FF1 est une courbe non globale { if (F1==NULL) { // cas où la courbe locale n'est pas défini mais on veut une courbe interne F1=Courbe1D::New_Courbe1D(*(FF1));nom_courbe1="i_interne_i"; } else if (F1->NomCourbe() == "_") // cas où la courbe F1 est local et on veut la remplacer par une nouvelle locale { delete F1; F1=Courbe1D::New_Courbe1D(*(FF1));nom_courbe1="i_interne_i"; } else // cas où la courbe F1 est global et on veut la remplacer par une locale { F1=Courbe1D::New_Courbe1D(*(FF1));nom_courbe1="i_interne_i"; }; } else // cas ou FF1 est une courbe globale { if (F1==NULL) { // cas où la courbe locale n'est pas définir F1=FF1;nom_courbe1="e_externe_e"; } else if (F1->NomCourbe() == "_") // cas où la courbe F1 est local et on veut la remplacer par une globale { delete F1; F1=FF1;nom_courbe1="e_externe_e"; } else // cas où la courbe F1 est global et on veut la remplacer par une globale { F1=FF1;nom_courbe1="e_externe_e"; }; }; }; }; // 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 F_cycle_add::LectDonnParticulieres_courbes(const string& nom,UtilLecture * entreePrinc) { // entête de la courbe if (nom == "") { *(entreePrinc->entree) >> nom_ref;} else {nom_ref=nom;}; // lecture de la courbe interne entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne // on lit l'entête if(strstr(entreePrinc->tablcar,"courbe1=")==0) { cout << "\n erreur en lecture de l'entete " << " on attendait la chaine: courbe1= "; entreePrinc->MessageBuffer("**erreur1 F_cycle_add::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; string toto,nom_lu; *(entreePrinc->entree) >> toto >> nom_lu; // on regarde si la courbe1 existe, si oui on récupère la référence if (Type_EnumCourbe1D_existe(nom_lu)) // cas ou c'est un nom de type de courbe -> lecture directe { nom_courbe1 = "_"; // on signale que c'est une courbe interne F1 = Courbe1D::New_Courbe1D(nom_courbe1,Id_Nom_Courbe1D (nom_lu.c_str())); // lecture de la courbe F1->LectDonnParticulieres_courbes (nom_courbe1,entreePrinc); nom_courbe1="i_interne_i"; } else // sinon on retiend le nom pour une complétion future {nom_courbe1 = nom_lu;}; // lecture de l'amplification et de la longueur du cycle entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne *(entreePrinc->entree) >> nom_lu >> longcycl; if (nom_lu != "longueur_cycle_=") { cout << "\n erreur en lecture de la longueur du cycle " << " on attendait la chaine: longueur_cycle_= et on a lue " << nom_lu; entreePrinc->MessageBuffer("**erreur1 F_cycle_add::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; if (longcycl <= ConstMath::petit) { cout << "\n ****** attention ****** la longueur de cycle lue vaut: " << longcycl << " c'est une grandeur tres petite, ce qui peut entrainer des erreurs de calcul !! "; }; if(strstr(entreePrinc->tablcar,"amplification_=")!=0) // cas ou on veut définir un facteur d'amplification { *(entreePrinc->entree) >> nom_lu >> ampli; if (nom_lu != "amplification_=") { cout << "\n erreur en lecture du facteur d'amplification " << " on attendait la chaine: amplification_= et on a lue " << nom_lu; entreePrinc->MessageBuffer("**erreur1 F_cycle_add::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; }; if(strstr(entreePrinc->tablcar,"decalageX_=")!=0) // cas ou on veut définir un décalage initiale { *(entreePrinc->entree) >> nom_lu >> decalx; if (nom_lu != "decalageX_=") { cout << "\n erreur en lecture du decalage initiale en x " << " on attendait la chaine: decalageX_= et on a lue " << nom_lu; entreePrinc->MessageBuffer("**erreur1 F_cycle_add::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; }; if(strstr(entreePrinc->tablcar,"decalageY_=")!=0) // cas ou on veut définir un décalage initiale { *(entreePrinc->entree) >> nom_lu >> decaly; if (nom_lu != "decalageY_=") { cout << "\n erreur en lecture du decalage en y initiale " << " on attendait la chaine: decalageY_= et on a lue " << nom_lu; entreePrinc->MessageBuffer("**erreur1 F_cycle_add::LectureDonneesParticulieres**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; }; }; // 1) renseigne si la courbe dépend d'autre courbe ou non bool F_cycle_add::DependAutreCourbes() const { bool ret=false; if(F1 == NULL) {ret=true;} else if (nom_courbe1!="i_interne_i") {ret=true;}; return ret; }; // 2) retourne une liste de nom correspondant aux noms de courbes dont dépend *this list & F_cycle_add::ListDependanceCourbes(list & lico) const { // tout d'abord on vide la liste passée en paramètres if (lico.size() != 0) lico.erase(lico.begin(),lico.end()); // on remplit en fonction de l'état if(F1 == NULL) lico.push_back(nom_courbe1); return lico; }; // 3) établit la connection entre la demande de *this et les courbes passées en paramètres void F_cycle_add::Lien_entre_courbe (list & liptco) { Courbe1D* FF1=NULL; list ::iterator ili,ilifin=liptco.end(); if (F1==NULL) { // on cherche la courbe correspondante for (ili=liptco.begin();ili!=ilifin;ili++) if ((*ili)->NomCourbe() == nom_courbe1) {FF1=(*ili);break;}; }; // et on définit les courbes this->DefCourbesMembres(FF1); }; // def info fichier de commande void F_cycle_add::Info_commande_Courbes1D(UtilLecture & entreePrinc) { ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier sort << "\n#............................................" << "\n# il s'agit d'une fonction qui est cyclique, a chaque debut de cycle" << "\n# elle prend la valeur de la fin du cycle precedent + , la valeur d'une " << "\n# fonction de base multipliee par un facteur d'amplitude fois n, " << "\n# n etant le nombre de cycle qui vaut 1 par defaut" << "\n# ainsi on doit indiquer la longueur du cycle, le facteur d'amplitude est " << "\n# facultatif (=1 par defaut). On indique au debut de la declaration, la fonction de base " << "\n# Remarque: le premier cycle commence a x=0. " << "\n# *** exemple 1 de definition d'une courbe composee F_CYCLE_ADD ****" << "\n# 1) ici on indique le nom de la courbe interne qui doit donc etre" << "\n# definis par ailleurs " << "\n courbe_exemple1 F_CYCLE_ADD # nom de la courbe " << "\n courbe1= fonction_temperature # def de la courbe interne" << "\n longueur_cycle_= 10 amplification_= 2 " << "\n " << "\n# Il est egalement possible d'introduire un decalage en x et y. Le decalage en x " << "\n# est soustrait a la valeur courante de x, tandis que le decalage en y est ajoute " << "\n# a la valeur finale de la fonction. Exemple de syntaxe " << "\n longueur_cycle_= 10 amplification_= 2 decalageX_= 10. decalageY_= 3. " << "\n " << "\n# *** exemple 2 de definition d'une courbe composee F_CYCLE_ADD ****" << "\n# ici on indique explicitement la courbe interne " << "\n# definis par ailleurs " << "\n courbe_exemple2 F_CYCLE_ADD # nom de la courbe " << "\n# def d'une fonction echelon (interne) avec une attenuation des angles " << "\n courbe1= COURBEPOLYLINEAIRE_1_D " << "\n Debut_des_coordonnees_des_points " << "\n Coordonnee dim= 2 0. 0. " << "\n Coordonnee dim= 2 0.2 0.05 " << "\n Coordonnee dim= 2 0.4 0.2 " << "\n Coordonnee dim= 2 0.6 0.8 " << "\n Coordonnee dim= 2 0.8 0.95 " << "\n Coordonnee dim= 2 1. 1. " << "\n Coordonnee dim= 2 10. 1. " << "\n Fin_des_coordonnees_des_points " << "\n# def des parametres internes du cycle " << "\n longueur_cycle_= 5. " << "\n " << endl; }; // ramène la valeur double F_cycle_add::Valeur(double x) { int n=(x-decalx)/longcycl; double resul = decaly + ampli * ((n*n+n)/2. * F1->Valeur(longcycl) + (n+1) * F1->Valeur(x-n*longcycl-decalx)); // cout << "\n cyclique : valeur = " << resul; return resul; }; // ramène la valeur et la dérivée en paramètre Courbe1D::ValDer F_cycle_add::Valeur_Et_derivee(double x) { int n=(x-decalx)/longcycl; ValDer ret1 = F1->Valeur_Et_derivee(x-n*longcycl-decalx); ValDer ret; // le retour ret.valeur = decaly + ampli * ((n*n+n)/2. * F1->Valeur(longcycl) + (n+1) * ret1.valeur); ret.derivee = ampli * (n+1) * ret1.derivee; return ret; }; // ramène la dérivée double F_cycle_add::Derivee(double x) { int n=(x-decalx)/longcycl; double derivee = F1->Derivee(x-n*longcycl-decalx); return (ampli * (n+1) * derivee); }; // ramène la valeur et les dérivées première et seconde en paramètre Courbe1D::ValDer2 F_cycle_add::Valeur_Et_der12(double x) { int n=(x-decalx)/longcycl; ValDer2 ret1 = F1->Valeur_Et_der12(x-n*longcycl-decalx); ValDer2 ret; // le retour ret.valeur = decaly + ampli * ((n*n+n)/2. * F1->Valeur(longcycl) + (n+1) * ret1.valeur); ret.derivee = ampli * (n+1) * ret1.derivee; ret.der_sec = ampli * (n+1) * ret1.der_sec; return ret; }; // ramène la dérivée seconde double F_cycle_add::Der_sec(double x) { int n=(x-decalx)/longcycl; double derivee_seconde = F1->Der_sec(x-n*longcycl-decalx); return (ampli * (n+1) * derivee_seconde); }; // ramène la valeur si dans le domaine strictement de définition // si c'est inférieur au x mini, ramène la valeur minimale possible de y // si supérieur au x maxi , ramène le valeur maximale possible de y // en fait ici il s'agit des bornes éventuelles pour la fonction F1 // car la fonction cycle n'a pas de borne Courbe1D::Valbool F_cycle_add::Valeur_stricte(double x) { int n=(x-decalx)/longcycl; Valbool ret1 = F1->Valeur_stricte(x-n*longcycl-decalx); Valbool ret2 = F1->Valeur_stricte(longcycl); Valbool ret; // le retour ret.valeur = decaly + ampli * ((n*n+n)/2. * ret2.valeur + (n+1) * ret1.valeur); ret.dedans = ret1.dedans && ret2.dedans ; return ret; }; // ramène la valeur et la dérivée si dans le domaine strictement de définition // si c'est inférieur au x mini, ramène la valeur minimale possible de y et Y' correspondant // si supérieur au x maxi , ramène le valeur maximale possible de y et Y' correspondant // en fait ici il s'agit des bornes éventuelles pour la fonction F1 // car la fonction cycle n'a pas de borne Courbe1D::ValDerbool F_cycle_add::Valeur_Et_derivee_stricte(double x) { int n=(x-decalx)/longcycl; ValDerbool ret1 = F1->Valeur_Et_derivee_stricte(x-n*longcycl-decalx); Valbool ret2 = F1->Valeur_stricte(longcycl); ValDerbool ret; // le retour ret.valeur = decaly + ampli * ((n*n+n)/2. * ret2.valeur + (n+1) * ret1.valeur); ret.derivee = ampli * (n+1) * ret1.derivee; ret.dedans = ret1.dedans && ret2.dedans ; 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 F_cycle_add::Lecture_base_info(ifstream& ent,const int cas) { // on n'a que des grandeurs constantes if (cas == 1) { string nom; // lecture et vérification de l'entête ent >> nom; if (nom != "F_CYCLE_ADD") { cout << "\n erreur dans la verification du type de courbe lue "; cout << "\n F_cycle_add::Lecture_base_info(... "; Sortie(1); } // lecture des infos string nom1,nom2,nom3; // pour la courbe1 ent >> nom1 >> nom2 >> nom3; if (nom1 != "courbe1=") { cout << "\n erreur dans la verification du type, on attendait le mot cle courbe1= " << " et on a lu " << nom1 << " "; cout << "\n F_cycle_add::Lecture_base_info(... "; Sortie(1); } else { if (nom2 == "COURBE_INTERNE1") {// cas d'une courbe en interne // 1) on commence par effacer la courbe existante si nécessaire if (F1 != NULL) {if (F1->NomCourbe() == "_") delete F1;}; // 2) on crée la courbe adoc nom2="_"; F1 = Courbe1D::New_Courbe1D(nom2,Id_Nom_Courbe1D (nom3.c_str())); // 3) on lit les données particulières F1->Lecture_base_info(ent,cas); nom_courbe1="i_interne_i"; } else {// cas d'une courbe externe on lit le nom nom_courbe1 = nom2; }; }; // amplification et longueur du cycle ent >> nom1 >> ampli >> nom2 >> longcycl ; if (nom1 != "amplification_=") { cout << "\n erreur dans la lecture du facteur d'amplification on attendait amplification_= " << " et on a lu " << nom1 << " "; cout << "\n F_cycle_add::Lecture_base_info(... "; Sortie(1); }; if (nom2 != "longueur_cycle_=") { cout << "\n erreur dans la lecture de la longueur du cycle on attendait longueur_cycle_= " << " et on a lu " << nom2 << " "; cout << "\n F_cycle_add::Lecture_base_info(... "; Sortie(1); }; ent >> nom1 >> decalx >> nom2 >> decaly ; if (nom1 != "decalageX_=") { cout << "\n erreur dans la lecture de la longueur du cycle on attendait decalageX_= " << " et on a lu " << nom1 << " "; cout << "\n F_cycle_add::Lecture_base_info(... "; Sortie(1); }; if (nom2 != "decalageY_=") { cout << "\n erreur dans la lecture de la longueur du cycle on attendait decalageY_= " << " et on a lu " << nom2 << " "; cout << "\n F_cycle_add::Lecture_base_info(... "; Sortie(1); }; }; }; // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void F_cycle_add::Ecriture_base_info(ofstream& sort,const int cas) { // on n'a que des grandeurs constantes if (cas == 1) { sort << " F_CYCLE_ADD "; if (F1->NomCourbe() == "_") {// cas d'une courbe interne sort << "\n courbe1= COURBE_INTERNE1 " << F1->Type_courbe(); F1->Ecriture_base_info(sort,cas); } else // cas d'une courbe externe {sort << "\n courbe1= " << F1->NomCourbe() << " " << F1->Type_courbe();;}; // amplification et longueur du cycle et décalage sort << "\n amplification_= " << ampli << " longueur_cycle_= " << longcycl << " decalageX_= " << decalx << " decalageY_= " << decaly << " " ; }; }; // sortie du schemaXML: en fonction de enu //void F_cycle_add::SchemaXML_Courbes1D(ofstream& sort,const Enum_IO_XML enu) void F_cycle_add::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; } }; };