799 lines
34 KiB
C++
Executable file
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;
|
|
}
|
|
};
|
|
};
|