Herezh_dev/herezh_pp/Util/Courbes/F_union_1D.cc

799 lines
34 KiB
C++
Executable file

// 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.
//
// 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 <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "F_union_1D.h"
#include "Sortie.h"
#include "ConstMath.h"
#include "MathUtil.h"
#include "CharUtil.h"
// CONSTRUCTEURS :
F_union_1D::F_union_1D(string nom) :
Courbe1D(nom,F_UNION_1D),Fi(),Xi(),nom_courbei(),indice_precedant(1)
{};
// de copie
F_union_1D::F_union_1D(const F_union_1D& Co) :
Courbe1D(Co),indice_precedant(Co.indice_precedant)
,Fi(Co.Fi),Xi(Co.Xi),nom_courbei(Co.nom_courbei)
{ // création des courbes locales que si elles étaient déjà locales
int tai = Fi.Taille();
for (int i=1;i<= tai; i++)
if (Co.Fi(i)->NomCourbe() == "_")
{Fi(i)=Courbe1D::New_Courbe1D(*(Co.Fi(i)));};
};
// de copie à partir d'une instance générale
F_union_1D::F_union_1D(const Courbe1D& Coo) :
Courbe1D(Coo)
{ if (Coo.Type_courbe() != F_UNION_1D)
{ cout << "\n erreur dans le constructeur de copie pour une courbe F_UNION_1D "
<< " a partir d'une instance générale ";
cout << "\n F_union_1D::F_union_1D(const Courbe1D& Co) ";
Sortie(1);
};
// définition des données
F_union_1D & Co = (F_union_1D&) Coo;
indice_precedant=Co.indice_precedant;
Fi=Co.Fi;
Xi=Co.Xi;
nom_courbei = Co.nom_courbei;
int tai = Fi.Taille();
// création des courbes locales que si elles étaient déjà locales
for (int i=1;i<= tai; i++)
if (Co.Fi(i)->NomCourbe() == "_")
{Fi(i)=Courbe1D::New_Courbe1D(*(Co.Fi(i)));};
};
// DESTRUCTEUR :
F_union_1D::~F_union_1D()
{ // on efface les courbes que si c'est des courbes locales
int tai = Fi.Taille();
for (int i=1;i<= tai; i++)
if ((Fi(i) != NULL)&&(nom_courbei(i)=="i_interne_i")) delete Fi(i);
};
// METHODES PUBLIQUES :
// --------- virtuelles ---------
// affichage de la courbe
void F_union_1D::Affiche() const
{ cout << "\n courbe composee : F_union_1D : nom_ref= " << nom_ref;
int tai = Fi.Taille();
// on parcours toutes les courbes
for (int i=1;i<= tai; i++)
{ cout << "\n intervalle: [" << Xi(i) <<","<<Xi(i+1)<<"] ";
// si c'est une courbe interne on l'affiche globalement
// si c'est une courbe globale, on n'affiche que son nom
cout << ", fonction de base: " << i << " ";
if (Fi(i)->NomCourbe() == "_") {Fi(i)->Affiche();}
else {cout << Fi(i)->NomCourbe() << " ";};
};
cout << "\n permet_affichage: " << permet_affichage;
cout << "\n ----- fin fonction F_union_1D ----- ";
};
// vérification que tout est ok, pres à l'emploi
// ramène true si ok, false sinon
bool F_union_1D::Complet_courbe()const
{ bool ret = Complet_var(); // on regarde du coté de la classe mère tout d'abord
// puis les variables propres, il faut au moins une courbe
if (Fi.Taille() == 0)
ret = false;
if (!ret && (ParaGlob::NiveauImpression() >0))
{ cout << "\n ***** la courbe n'est pas complete (aucune courbe de base n'existe) ";
this->Affiche();
};
return ret;
} ;
// dans le cas où les courbes membres sont des courbes externes
// fonction pour les définir
// les courbes sont défini en interne que si les courbes argument sont elles même
// des courbes locales. c'est-à-dire si FFi(i)->NomCourbe() ="_" alors on recrée une courbe
// interne avec new pour Fi(i), sinon Fi(i)=FFi(i) et pas de création;
// dans le cas où FFi(i) est NULL on passe, pas de traitement pour ce pointeur
void F_union_1D::DefCourbesMembres(Tableau <Courbe1D* >& FFi)
{ // l'objectif est
// 1) d'adapter le nombre de courbe à celui de FFi
// 2) de ne changer que celle qui sont non nul dans FFi
int tai = Fi.Taille(); // taille existante
int taii = FFi.Taille(); // taille du nouveau tableau
// on commence par effacer les courbes existantes supérieur à taii
if (taii < tai)
for (int i=taii;i<= tai; i++)
if ((Fi(i) != NULL)&&(nom_courbei(i)=="i_interne_i"))
{ delete Fi(i);Fi(i)=NULL;};
// on change de taille
Fi.Change_taille(taii);
tai = taii;
for (int i=1;i<= tai; i++)
{ // création d'une courbe locale que si elle était déjà locales
if (FFi(i) != NULL)
{if (FFi(i)->NomCourbe() == "_") // cas où FFi(i) est une courbe non globale
{ if (Fi(i)==NULL)
// cas où la courbe locale n'est pas défini mais on veut une courbe interne
{ Fi(i)=Courbe1D::New_Courbe1D(*(FFi(i)));nom_courbei(i)="i_interne_i";}
else if (Fi(i)->NomCourbe() == "_")
// cas où la courbe F1 est local et on veut la remplacer par une nouvelle locale
{ delete Fi(i);
Fi(i)=Courbe1D::New_Courbe1D(*(FFi(i)));nom_courbei(i)="i_interne_i";
}
else
// cas où la courbe Fi(i est global et on veut la remplacer par une locale
{ Fi(i)=Courbe1D::New_Courbe1D(*(FFi(i)));nom_courbei(i)="i_interne_i";};
}
else // cas ou FFi(i) est une courbe globale
{ if (Fi(i)==NULL)
// cas où la courbe locale n'est pas défini
{ Fi(i)=FFi(i);nom_courbei(i)="e_externe_e";}
else if (Fi(i)->NomCourbe() == "_")
// cas où la courbe Fi(i) est local et on veut la remplacer par une globale
{ delete Fi(i);
Fi(i)=FFi(i);nom_courbei(i)="e_externe_e";
}
else
// cas où la courbe Fi(i) est global et on veut la remplacer par une globale
{ Fi(i)=FFi(i);nom_courbei(i)="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_union_1D::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 les courbes et les intervalles à suivre jusqu'au mot de fin de courbe
list < Courbe1D* > li_Fi; // un liste intermédiaire pour faciliter la lecture
list <double > li_Xi;
list <string > li_nom_courbei;
// on commence par lire éventuellement la borne inférieure du domaine de définition
string toto;
double xmin=-ConstMath::tresgrand; // par défaut
if(strstr(entreePrinc->tablcar,"Xmin=")!=0)
{ *(entreePrinc->entree) >> toto >> xmin;
if (toto != "Xmin=")
{ cout << "\n erreur en lecture de la borne inferieure "
<< " on attendait la chaine: Xmin= et on a lue: " << toto;
entreePrinc->MessageBuffer("**erreur F_union_1D::LectureDonneesParticulieres**");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
};
li_Xi.push_back(xmin); // enregistrement
// maintenant lecture courante
string nom_indicateur;
do
{ // tout d'abord lecture de la courbe
string toto,nom_lu,nom_courbe;
Courbe1D* F=NULL;
*(entreePrinc->entree) >> nom_indicateur >> nom_lu;
// vérif
if (nom_indicateur != "courbe=" )
{ cout << "\n erreur en lecture du nom de courbe "
<< " on attendait la chaine: courbe= et on a lue: " << nom_indicateur;
entreePrinc->MessageBuffer("**erreur F_union_1D::LectureDonneesParticulieres**");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
// 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_courbe = "_"; // on signale que c'est une courbe interne
F = Courbe1D::New_Courbe1D(nom_courbe,Id_Nom_Courbe1D (nom_lu.c_str()));
// lecture de la courbe
F->LectDonnParticulieres_courbes (nom_courbe,entreePrinc);
nom_courbe="i_interne_i";
entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne
}
else
// sinon on retiend le nom pour une complétion future
{nom_courbe = nom_lu;};
// stockage
li_Fi.push_back(F); li_nom_courbei.push_back(nom_courbe);
// lecture maintenant de la fin de l'intervalle
double xmax=ConstMath::tresgrand; // par défaut
bool fin_lecture=false;
if (strstr(entreePrinc->tablcar,"Xmax=")!=0)
{*(entreePrinc->entree) >> nom_indicateur >> xmax;
// vérif
if (nom_indicateur != "Xmax=" )
{ cout << "\n erreur en lecture de la borne maxi de l'intervalle "
<< " on attendait la chaine: Xmax= et on a lue: " << nom_indicateur;
entreePrinc->MessageBuffer("**erreur F_union_1D::LectureDonneesParticulieres**");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
}
}
else // sinon ça doit-être la dernière lecture
{fin_lecture = true;};
li_Xi.push_back(xmax); // enregistrement
// on passe une ligne si on n'est pas déjà à la fin et on vérifie que ce n'est pas finie
if (strstr(entreePrinc->tablcar,"fin_courbe_union")==0)
entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne
// on regarde s'il n'y a pas un niveau d'affichage particulier
if (strstr(entreePrinc->tablcar,"permet_affichage_")!=0)
{ int val_defaut = 0;int min=10;int max=0; // min > max -> pas pris en compte
string nom_class_methode("F_union_1D::LectureDonneesParticulieres");
string mot_cle("permet_affichage_");
if (entreePrinc->Lecture_un_parametre_int(val_defaut,nom_class_methode
,min,max,mot_cle,permet_affichage))
entreePrinc->NouvelleDonnee(); // lecture d'une nouvelle ligne
};
if (fin_lecture && (strstr(entreePrinc->tablcar,"fin_courbe_union")==0))
{ cout << "\n erreur en lecture de la borne maxi de l'intervalle "
<< " le mot cle Xmax= est obligatoire sauf pour la derniere fonction ";
entreePrinc->MessageBuffer("**erreur F_union_1D::LectureDonneesParticulieres**");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
} while (strstr(entreePrinc->tablcar,"fin_courbe_union")==0);
// on met en tableau
int tai = li_Fi.size();
Fi.Change_taille(tai);
Xi.Change_taille(tai+1);
nom_courbei.Change_taille(tai);
list < Courbe1D* >::iterator ili,ilifin= li_Fi.end();
list <double >::iterator xli= li_Xi.begin();
Xi(1)=*xli;xli++; //la borne inférieure
list <string >::iterator sli= li_nom_courbei.begin();
int ia=1;
for (ili=li_Fi.begin();ili!=ilifin;ili++,xli++,sli++,ia++)
{Fi(ia)=*ili;Xi(ia+1)=*xli;nom_courbei(ia)=*sli;}
};
// 1) renseigne si la courbe dépend d'autre courbe ou non
bool F_union_1D::DependAutreCourbes() const
{ bool ret=false;
int tai = Fi.Taille();
for (int i=1;i<=tai;i++)
if(Fi(i) == NULL) {ret=true;}
else if (nom_courbei(i)!="i_interne_i") {ret=true;};
return ret;
};
// 2) retourne une liste de nom correspondant aux noms de courbes dont dépend *this
list <string>& F_union_1D::ListDependanceCourbes(list <string>& 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
int tai = Fi.Taille();
for (int i=1;i<=tai;i++)
if(Fi(i) == NULL) lico.push_back(nom_courbei(i));
return lico;
};
// 3) établit la connection entre la demande de *this et les courbes passées en paramètres
void F_union_1D::Lien_entre_courbe (list <Courbe1D *>& liptco)
{ int tai = Fi.Taille();
Tableau <Courbe1D *> tab_Fi(tai); // def à null par défaut
for (int i=1;i<=tai;i++)
if(Fi(i) == NULL)
{list <Courbe1D *>::iterator ili,ilifin=liptco.end();
for (ili=liptco.begin();ili!=ilifin;ili++)
if ((*ili)->NomCourbe() == nom_courbei(i))
{tab_Fi(i)=(*ili);break;};
}
else // sinon la courbe existe déjà, on met le pointeur à Null
tab_Fi(i)=NULL;
// et on définit les courbes
this->DefCourbesMembres(tab_Fi);
};
// def info fichier de commande
void F_union_1D::Info_commande_Courbes1D(UtilLecture & entreePrinc)
{
ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
sort << "\n#............................................"
<< "\n# il s'agit d'une fonction qui agglomere plusieurs fonctions deja existantes"
<< "\n# chaque fonction est defini sur un intervalle disjoint des autres "
<< "\n# Les intervalles doivent se suivre "
<< "\n# Xmin= precise la borne inferieur de definition de la fonction"
<< "\n# c'est un parametre facultatif, s'il manque, la borne inf est - l'infini"
<< "\n# ensuite il y a une liste de courbes: "
<< "\n# suivi chacune de la fin de l'intervalle correspondant"
<< "\n# ici cf1 est pour x appartenant a [-10,0[, cf2 est pour x appartenant a [0,10["
<< "\n# cf3 est pour x appartenant a [10,20["
<< "\n courbe_exemple F_UNION_1D "
<< "\n# Xmin= -10 courbe= cf1 Xmax= 0"
<< "\n# courbe= cf2 Xmax= 10"
<< "\n# courbe= cf3 Xmax= 20"
<< "\n# fin_courbe_union"
<< "\n# "
<< "\n# pour la dernier courbe il est possible de ne pas faire figurer Xmax=, dans"
<< "\n# ce cas, cela signifie que la borne finale est l'infini"
<< "\n# enfin, si la valeur de x est en dehors de l'intervalle, on applique la premiere"
<< "\n (x<Xmin) ou la derniere fonction (x>Xmax) "
<< endl;
};
// ramène la valeur
double F_union_1D::Valeur(double x)
{ // on commence par chercher l'intervalle qui contient x
//tout d'abord on regarde s'il est en dehors des bornes
// si oui on lui donne
if (x < Xi(1))
{indice_precedant=1;
return Fi(1)->Valeur(x);
};
int tai = Fi.Taille();
int taiPlusUn = tai + 1;
if (x > Xi(taiPlusUn))
{indice_precedant=1; // comme c'est le dernier intervalle on met à 1 car
// de toute manière cela ne sert à rien de continuer
return Fi(tai)->Valeur(x);
};
// maintenant on cherche le couple de xi qui encadre le x
int indice=0;bool trouve=false;
// on commence tout d'abord à chercher à partir du précédent indice
// s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
if (x >= Xi(indice_precedant))
{for (int indic=indice_precedant;indic < taiPlusUn;indic++)
if (x < Xi(indic+1)) {trouve=true;indice=indic; break;};
}
else // sinon il est inférieur
{for (int indic = 1; indic <indice_precedant;indic++)
if (x < Xi(indic+1)) {trouve=true;indice = indic; break;};
};
//
//
// // sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
// // on repart à partir de 0 !! ***** a optimiser par dichotomie *****
// if (!trouve)
// { // cas où on n'a pas trouver après l'indice
// for (int indic = 1; indic <indice_precedant;indic++)
// if (x <= Xi(indic+1)) {trouve=true;indice = indic; break;};
// };
// gestion d'erreur
if (!trouve)
{ cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe F_union_1D "
<< "\n x demandee: " << x
<< "\n double F_union_1D::Valeur(double x) ";
cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref;
Sortie(1);
};
// calcul du y
indice_precedant = indice;
return Fi(indice)->Valeur(x);
};
// ramène la valeur et la dérivée en paramètre
Courbe1D::ValDer F_union_1D::Valeur_Et_derivee(double x)
{ // on commence par chercher l'intervalle qui contient x
//tout d'abord on regarde s'il est en dehors des bornes
// si oui on lui donne
if (x < Xi(1))
{indice_precedant=1;
return Fi(1)->Valeur_Et_derivee(x);
};
int tai = Fi.Taille();
if (x > Xi(tai+1))
{indice_precedant=1; // comme c'est le dernier intervalle on met à 1 car
// de toute manière cela ne sert à rien de continuer
return Fi(tai)->Valeur_Et_derivee(x);
};
// maintenant on cherche le couple de xi qui encadre le x
int indice=0;bool trouve=false;
// on commence tout d'abord à chercher à partir du précédent indice
// s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
if (x >= Xi(indice_precedant))
for (int indic=indice_precedant;indic<=tai;indic++)
if (x < Xi(indic+1)) {trouve=true;indice=indic; break;};
// sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
// on repart à partir de 0 !! ***** a optimiser par dichotomie *****
if (!trouve)
{ // cas où on n'a pas trouver après l'indice
for (int indic = 1; indic <indice_precedant;indic++)
if (x <= Xi(indic+1)) {trouve=true;indice = indic; break;};
};
// gestion d'erreur
if (!trouve)
{ cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe F_union_1D "
<< "\n x demandee: " << x
<< "\n Courbe1D::ValDer F_union_1D::Valeur_Et_derivee(double x) ";
cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref;
Sortie(1);
};
// calcul du retour
indice_precedant = indice;
return Fi(indice)->Valeur_Et_derivee(x);
};
// ramène la dérivée
double F_union_1D::Derivee(double x)
{ // on commence par chercher l'intervalle qui contient x
//tout d'abord on regarde s'il est en dehors des bornes
// si oui on lui donne
if (x < Xi(1))
{indice_precedant=1;
return Fi(1)->Derivee(x);
};
int tai = Fi.Taille();
if (x > Xi(tai+1))
{indice_precedant=1; // comme c'est le dernier intervalle on met à 1 car
// de toute manière cela ne sert à rien de continuer
return Fi(tai)->Derivee(x);
};
// maintenant on cherche le couple de xi qui encadre le x
int indice=0;bool trouve=false;
// on commence tout d'abord à chercher à partir du précédent indice
// s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
if (x >= Xi(indice_precedant))
for (int indic=indice_precedant;indic<=tai;indic++)
if (x < Xi(indic+1)) {trouve=true;indice=indic; break;};
// sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
// on repart à partir de 0 !! ***** a optimiser par dichotomie *****
if (!trouve)
{ // cas où on n'a pas trouver après l'indice
for (int indic = 1; indic <indice_precedant;indic++)
if (x <= Xi(indic+1)) {trouve=true;indice = indic; break;};
};
// gestion d'erreur
if (!trouve)
{ cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe F_union_1D "
<< "\n x demandee: " << x
<< "\n double F_union_1D::Derivee(double x) ";
cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref;
Sortie(1);
};
// calcul du retour
indice_precedant = indice;
return Fi(indice)->Derivee(x);
};
// ramène la valeur et les dérivées première et seconde en paramètre
Courbe1D::ValDer2 F_union_1D::Valeur_Et_der12(double x)
{ // on commence par chercher l'intervalle qui contient x
//tout d'abord on regarde s'il est en dehors des bornes
// si oui on lui donne
if (x < Xi(1))
{indice_precedant=1;
return Fi(1)->Valeur_Et_der12(x);
};
int tai = Fi.Taille();
if (x > Xi(tai+1))
{indice_precedant=1; // comme c'est le dernier intervalle on met à 1 car
// de toute manière cela ne sert à rien de continuer
return Fi(tai)->Valeur_Et_der12(x);
};
// maintenant on cherche le couple de xi qui encadre le x
int indice=0;bool trouve=false;
// on commence tout d'abord à chercher à partir du précédent indice
// s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
if (x >= Xi(indice_precedant))
for (int indic=indice_precedant;indic<=tai;indic++)
if (x < Xi(indic+1)) {trouve=true;indice=indic; break;};
// sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
// on repart à partir de 0 !! ***** a optimiser par dichotomie *****
if (!trouve)
{ // cas où on n'a pas trouver après l'indice
for (int indic = 1; indic <indice_precedant;indic++)
if (x <= Xi(indic+1)) {trouve=true;indice = indic; break;};
};
// gestion d'erreur
if (!trouve)
{ cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe F_union_1D "
<< "\n x demandee: " << x
<< "\n Courbe1D::ValDer F_union_1D::Valeur_Et_derivee(double x) ";
cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref;
Sortie(1);
};
// calcul du retour
indice_precedant = indice;
return Fi(indice)->Valeur_Et_der12(x);
};
// ramène la dérivée seconde
double F_union_1D::Der_sec(double x)
{ // on commence par chercher l'intervalle qui contient x
//tout d'abord on regarde s'il est en dehors des bornes
// si oui on lui donne
if (x < Xi(1))
{indice_precedant=1;
return Fi(1)->Der_sec(x);
};
int tai = Fi.Taille();
if (x > Xi(tai+1))
{indice_precedant=1; // comme c'est le dernier intervalle on met à 1 car
// de toute manière cela ne sert à rien de continuer
return Fi(tai)->Der_sec(x);
};
// maintenant on cherche le couple de xi qui encadre le x
int indice=0;bool trouve=false;
// on commence tout d'abord à chercher à partir du précédent indice
// s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
if (x >= Xi(indice_precedant))
for (int indic=indice_precedant;indic<=tai;indic++)
if (x < Xi(indic+1)) {trouve=true;indice=indic; break;};
// sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
// on repart à partir de 0 !! ***** a optimiser par dichotomie *****
if (!trouve)
{ // cas où on n'a pas trouver après l'indice
for (int indic = 1; indic <indice_precedant;indic++)
if (x <= Xi(indic+1)) {trouve=true;indice = indic; break;};
};
// gestion d'erreur
if (!trouve)
{ cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe F_union_1D "
<< "\n x demandee: " << x
<< "\n double F_union_1D::Derivee(double x) ";
cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref;
Sortie(1);
};
// calcul du retour
indice_precedant = indice;
return Fi(indice)->Der_sec(x);
};
// 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
Courbe1D::Valbool F_union_1D::Valeur_stricte(double x)
{ // on commence par chercher l'intervalle qui contient x
//tout d'abord on regarde s'il est en dehors des bornes
// si oui on lui donne
if (x < Xi(1))
{indice_precedant=1;
Valbool ret = Fi(1)->Valeur_stricte(x);
ret.dedans = false;
return ret;
};
int tai = Fi.Taille();
if (x > Xi(tai+1))
{indice_precedant=1; // comme c'est le dernier intervalle on met à 1 car
// de toute manière cela ne sert à rien de continuer
Valbool ret = Fi(tai)->Valeur_stricte(x);
ret.dedans = false;
return ret;
};
// maintenant on cherche le couple de xi qui encadre le x
int indice=0;bool trouve=false;
// on commence tout d'abord à chercher à partir du précédent indice
// s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
if (x >= Xi(indice_precedant))
for (int indic=indice_precedant;indic<=tai;indic++)
if (x < Xi(indic+1)) {trouve=true;indice=indic; break;};
// sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
// on repart à partir de 0 !! ***** a optimiser par dichotomie *****
if (!trouve)
{ // cas où on n'a pas trouver après l'indice
for (int indic = 1; indic <indice_precedant;indic++)
if (x <= Xi(indic+1)) {trouve=true;indice = indic; break;};
};
// gestion d'erreur
if (!trouve)
{ cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe F_union_1D "
<< "\n x demandee: " << x
<< "\n double F_union_1D::Derivee(double x) ";
cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref;
Sortie(1);
};
// calcul du retour
indice_precedant = indice;
Valbool ret = Fi(indice)->Valeur_stricte(x);
ret.dedans = true;
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
Courbe1D::ValDerbool F_union_1D::Valeur_Et_derivee_stricte(double x)
{ // on commence par chercher l'intervalle qui contient x
//tout d'abord on regarde s'il est en dehors des bornes
// si oui on lui donne
if (x < Xi(1))
{indice_precedant=1;
ValDerbool ret = Fi(1)->Valeur_Et_derivee_stricte(x);
ret.dedans = false;
return ret;
};
int tai = Fi.Taille();
if (x > Xi(tai+1))
{indice_precedant=1; // comme c'est le dernier intervalle on met à 1 car
// de toute manière cela ne sert à rien de continuer
ValDerbool ret = Fi(tai)->Valeur_Et_derivee_stricte(x);
ret.dedans = false;
return ret;
};
// maintenant on cherche le couple de xi qui encadre le x
int indice=0;bool trouve=false;
// on commence tout d'abord à chercher à partir du précédent indice
// s'il est supérieur au xi de l'indice existant, l'algo qui suit est ok
if (x >= Xi(indice_precedant))
for (int indic=indice_precedant;indic<=tai;indic++)
if (x < Xi(indic+1)) {trouve=true;indice=indic; break;};
// sinon cela veut dire qu'il se trouve dans les xi plus bas que l'indice
// on repart à partir de 0 !! ***** a optimiser par dichotomie *****
if (!trouve)
{ // cas où on n'a pas trouver après l'indice
for (int indic = 1; indic <indice_precedant;indic++)
if (x <= Xi(indic+1)) {trouve=true;indice = indic; break;};
};
// gestion d'erreur
if (!trouve)
{ cout << "\n erreur : on ne trouve pas la valeur demandee a l'aide de la courbe F_union_1D "
<< "\n x demandee: " << x
<< "\n F_union_1D::Valeur_Et_derivee_stricte(double x) ";
cout << "\n" << Nom_Courbe1D(this->Type_courbe()) << " : nom_ref= " << nom_ref;
Sortie(1);
};
// calcul du retour
indice_precedant = indice;
ValDerbool ret = Fi(indice)->Valeur_Et_derivee_stricte(x);
ret.dedans = true;
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_union_1D::Lecture_base_info(ifstream& ent,const int cas)
{ // on n'a que des grandeurs constantes
if (cas == 1)
{ string nom;
ent >> nom; // "\n <F_UNION_1D> "
// string nom1=nom.substr(nom.find(<)+1,nom.find(>)-1);
// lecture et vérification de l'entête
string type_courbe_a_lire('<'+Nom_Courbe1D(this->Type_courbe())+'>');
if (nom != type_courbe_a_lire) //"F_union_1D")
{ cout << "\n erreur dans la verification du type de courbe lue ";
cout << "\n courbe en lecture: " << type_courbe_a_lire;
cout << "\n F_union_1D::Lecture_base_info(... ";
Sortie(1);
}
// lecture du nombre de courbe
int tai=0;
ent >> nom >> tai;
Fi.Change_taille(tai);
Xi.Change_taille(tai+1);
nom_courbei.Change_taille(tai);
// lecture de la borne inf
ent >> nom >> Xi(1);
// lecture des courbes et des bornes
string nom1,nom2,nom3;
for (int i=1;i<=tai;i++)
{ // lecture de la courbe
ent >> nom1 >> nom2 >> nom3;
if (nom1 != "courbe=")
{ cout << "\n erreur dans la verification du type, on attendait le mot cle courbe= "
<< " et on a lu " << nom1 << " ";
cout << "\n F1_rond_F2::Lecture_base_info(... ";
Sortie(1);
}
else
{ if (nom2 == "COURBE_INTERNE")
{// cas d'une courbe en interne
// 1) on commence par effacer la courbe existante si nécessaire
if (Fi(i) != NULL) {if (Fi(i)->NomCourbe() == "_") delete Fi(i);};
// 2) on crée la courbe adoc
nom2="_";
Fi(i) = Courbe1D::New_Courbe1D(nom2,Id_Nom_Courbe1D (nom3.c_str()));
// 3) on lit les données particulières
Fi(i)->Lecture_base_info(ent,cas);
nom_courbei(i)="i_interne_i";
}
else
{// cas d'une courbe externe on lit le nom
nom_courbei(i) = nom2;
};
};
// lecture de la borne max pour la fonction i
ent >> nom1 >> Xi(i+1);
};
// lecture du niveau d'affichage
ent >> nom >> permet_affichage;
// on lit le tag de fin de définition
ent >> nom; // <F_UNION_1D>
}
};
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void F_union_1D::Ecriture_base_info(ofstream& sort,const int cas)
{ // on n'a que des grandeurs constantes
if (cas == 1)
{ sort << "\n <F_UNION_1D> ";
int tai = Fi.Taille();
sort << " nbcourbe= " << tai << " "; // le nombre de courbes
// la borne mini
sort << " Xmin= " << Xi(1)<< " ";
// on balaie les courbes
for (int i=1;i<=tai;i++)
{if (Fi(i)->NomCourbe() == "_")
{// cas d'une courbe interne
sort << "\n courbe= COURBE_INTERNE " << Fi(i)->Type_courbe();
Fi(i)->Ecriture_base_info(sort,cas);
}
else
// cas d'une courbe externe
{sort << "\n courbe= " << Fi(i)->NomCourbe() << " " << Fi(i)->Type_courbe();};
// la borne max pour la fonction i
sort << " Xmax= " << Xi(i+1) << " ";
};
sort << "\n permet_affichage: " << permet_affichage;
sort << "\n </F_UNION_1D> ";
}
};
// sortie du schemaXML: en fonction de enu
void F_union_1D::SchemaXML_Courbes1D(ofstream& ,const Enum_IO_XML enu)
{
switch (enu)
{ case XML_TYPE_GLOBAUX :
{/*sort << "\n <!-- *************************** F_UNION_1D *************************** -->"
<< "\n <!-- def d'un type contenant une valeur et un boolean -->"
<< "\n <xs:complexType name=\"valeurPlusBooleen\">"
<< "\n <xs:simpleContent>"
<< "\n <xs:extension base=\"xs:double\">"
<< "\n <xs:attribute name=\"present\" type=\"xs:boolean\" />"
<< "\n </xs:extension>"
<< "\n </xs:simpleContent> "
<< "\n </xs:complexType>"
<< "\n <!-- maintenant le type de la courbe -->"
<< "\n<xs:complexType name=\"F_UNION_1D\" >"
<< "\n <xs:annotation>"
<< "\n <xs:documentation> courbe F_UNION_1D constituee de N points </xs:documentation>"
<< "\n </xs:annotation>"
<< "\n <xs:sequence>"
<< "\n <xs:element name=\"derivee_initiale_\" type=\"valeurPlusBooleen\" />"
<< "\n <xs:element name=\"derivee_finale_\" type=\"valeurPlusBooleen\" />"
<< "\n <xs:element name=\"les_points\" type=\"COORDONNEE_2\" minOccurs='0' maxOccurs=\"unbounded\" />"
<< "\n </xs:sequence>"
<< "\n</xs:complexType>";*/
break;
}
case XML_IO_POINT_INFO :
{
break;
}
case XML_IO_POINT_BI :
{
break;
}
case XML_IO_ELEMENT_FINI :
{
break;
}
};
};