// 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 "Fonction_nD.h" #include /* va_list, va_start, va_copy, va_arg, va_end */ #include "Enum_ddl.h" #include "NevezTenseur.h" #include "TypeQuelconqueParticulier.h" // les différentes fonctions existantes #include "F_nD_courbe1D.h" #include "Fonc_scal_combinees_nD.h" #include "Fonction_expression_litterale_nD.h" #include "Fonction_externe_nD.h" #include "MotCle.h" // CONSTRUCTEURS : // par défaut Fonction_nD::Fonction_nD(string nom, EnumFonction_nD typ) : nom_variables(),t_inter_double() ,enu_variables_globale(),nom_ref(nom),typeFonction(typ) ,nom_variables_globales() ,tab_enu_etendu(),tab_enu_quelconque() ,equivalence_nom_enu_etendu_et_enu_quelconque(false) ,index_enu_etendu(),index_enu_quelconque() ,x_x_i(),x_glob(),xinter(NULL) ,depend_M(0),depend_Mt(0),depend_M0(0),depend_temps(0),permet_affichage(0) //------ grandeurs évoluées ------- ,type_des_variables(),val_ddl_enum(),li_enu_etendu_scalaire() ,coor_ddl_enum(),num_dans_coor(),premier_famille_Coord() ,tens_ddl_enum(),ind_tens(),premier_famille_tenseur(),absolue(false) ,li_equi_Quel_evolue(),tab_equi_Coor(),tab_equi_tens() ,posi_ddl_enum(),tailles_tab() { // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs // non car au début il n'y a rien comme variable !! // Fonction_nD::Construction_index_conteneurs_evoluees(); }; // constructeur avec plus d'info // dans le cas ou les variables sont associées à des types quelconques, par défaut on considère qu'il // s'agit de conteneur d'un scalaire simple. Dans le cas contraire il faut utiliser // Preparation_Grandeur_quelconque( pour spécifier les tailles réelles Fonction_nD::Fonction_nD(const Tableau & var, string nom, EnumFonction_nD typ ) : nom_variables(var),t_inter_double(var.Taille()) ,enu_variables_globale(),nom_ref(nom),typeFonction(typ) ,nom_variables_globales() ,tab_enu_etendu(),tab_enu_quelconque() ,equivalence_nom_enu_etendu_et_enu_quelconque(false) ,index_enu_etendu(),index_enu_quelconque() ,x_x_i(),x_glob(),xinter(NULL) ,depend_M(0),depend_Mt(0),depend_M0(0),depend_temps(0),permet_affichage(0) //------ grandeurs évoluées ------- ,type_des_variables(),val_ddl_enum(),li_enu_etendu_scalaire() ,coor_ddl_enum(),num_dans_coor(),premier_famille_Coord() ,tens_ddl_enum(),ind_tens(),premier_famille_tenseur(),absolue(false) ,li_equi_Quel_evolue(),tab_equi_Coor(),tab_equi_tens() ,posi_ddl_enum(),tailles_tab() {// comme on a le tableau de variables, on tente une équivalence éventuelle // Fonction_nD::Construction_enu_etendu_et_quelconque(); // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs Fonction_nD::Construction_index_conteneurs_evoluees(); }; // def de tous les paramètres: utile pour être appelé par les classes dérivées Fonction_nD::Fonction_nD ( string nom_ref_ // nom de ref de la fonction ,Tableau & nom_variables_non_globales // les variables non globales ,Tableau & enu_variables_globale_ // enu globaux ,Tableau & nom_variables_globales_ // idem sous forme de strings ,EnumFonction_nD typ ) // le type de fonction : nom_variables(nom_variables_non_globales),t_inter_double(nom_variables_non_globales.Taille()) ,enu_variables_globale(enu_variables_globale_),nom_ref(nom_ref_),typeFonction(typ) ,nom_variables_globales(nom_variables_globales_) ,tab_enu_etendu(),tab_enu_quelconque() ,equivalence_nom_enu_etendu_et_enu_quelconque(false) ,index_enu_etendu(),index_enu_quelconque() ,x_x_i(),x_glob(),xinter(NULL) ,depend_M(0),depend_Mt(0),depend_M0(0),depend_temps(0),permet_affichage(0) //------ grandeurs évoluées ------- ,type_des_variables(),val_ddl_enum(),li_enu_etendu_scalaire() ,coor_ddl_enum(),num_dans_coor(),premier_famille_Coord() ,tens_ddl_enum(),ind_tens(),premier_famille_tenseur(),absolue(false) ,li_equi_Quel_evolue(),tab_equi_Coor(),tab_equi_tens() ,posi_ddl_enum(),tailles_tab() {// comme on a le tableau de variables, on tente une équivalence éventuelle // Fonction_nD::Construction_enu_etendu_et_quelconque(); // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs Fonction_nD::Construction_index_conteneurs_evoluees(); }; // de copie Fonction_nD::Fonction_nD(const Fonction_nD& Co) : nom_variables(Co.nom_variables),t_inter_double(Co.t_inter_double) ,enu_variables_globale(Co.enu_variables_globale) ,nom_variables_globales(Co.nom_variables_globales) ,nom_ref(Co.nom_ref),typeFonction(Co.typeFonction) ,tab_enu_etendu(Co.tab_enu_etendu),tab_enu_quelconque(Co.tab_enu_quelconque) ,equivalence_nom_enu_etendu_et_enu_quelconque(Co.equivalence_nom_enu_etendu_et_enu_quelconque) ,index_enu_etendu(Co.index_enu_etendu),index_enu_quelconque(Co.index_enu_quelconque) ,x_x_i(Co.x_x_i),x_glob(Co.x_glob),xinter(NULL) ,depend_M(Co.depend_M),depend_Mt(Co.depend_Mt),depend_M0(Co.depend_M0) ,depend_temps(Co.depend_temps) //------ grandeurs évoluées ------- ,type_des_variables(Co.type_des_variables),val_ddl_enum(Co.val_ddl_enum) ,li_enu_etendu_scalaire() // reconstruit avec les index ,coor_ddl_enum(Co.coor_ddl_enum),num_dans_coor(Co.num_dans_coor) ,premier_famille_Coord(Co.premier_famille_Coord) ,tens_ddl_enum(Co.tens_ddl_enum),ind_tens(Co.ind_tens) ,premier_famille_tenseur(Co.premier_famille_tenseur) ,absolue(Co.absolue) ,li_equi_Quel_evolue(),tab_equi_Coor(),tab_equi_tens() // est reconstruit ensuite ,posi_ddl_enum(Co.posi_ddl_enum),tailles_tab(Co.tailles_tab) ,permet_affichage(Co.permet_affichage) {if (Co.xinter != NULL) xinter = new Tableau (*(Co.xinter)); // comme on a le tableau de variables, on tente une équivalence éventuelle // Fonction_nD::Construction_enu_etendu_et_quelconque(); // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs Fonction_nD::Construction_index_conteneurs_evoluees(); }; // DESTRUCTEUR : Fonction_nD::~Fonction_nD() {if (xinter != NULL) delete xinter; if (tens_ddl_enum.Taille() != 0) {int taille = tens_ddl_enum.Taille(); for (int i=1; i<= taille; i++) if (tens_ddl_enum(i) != NULL) delete tens_ddl_enum(i); }; }; // METHODES PUBLIQUES : // ---------- non virtuelle --------- //// complète les tableaux internes en fonction de la taille des conteneurs //// associés aux types quelconques éventuelles //// *** doit -être appelée s'il y a des grandeurs quelconque dont les conteneurs //// sont associés à plusieurs scalaires //void Fonction_nD::Preparation_Grandeur_quelconque(const Tableau & tqi) // {// on parcourt la liste des enumérés de grandeurs quelconque // int tail = tab_enu_quelconque.Taille(); // if (tqi.Taille() != tail) // { cout << "\n *** pb dans Fonction_nD::Preparation_Grandeur_quelconque( " // << " le tableau en parametre " << tqi.Taille() // << " n'a pas la meme taille que le nombre de grandeur quelconque enregistrees " // << tail // << " on ne peut pas continuer " < & Fonction_nD::Valeur_FnD(Tableau * t_enu,Tableau * t_qi ,Tableau * t_num_ordre) {// on se sert des tableaux d'adressage indirect pour remplir le tableau de passage // tab_enu_etendu(i) correspond à nom_variables(index_enu_etendu(i)) // tab_enu_quelconque(i) correspond à nom_variables(index_enu_quelconque(i)) // un tableau intermédiaire qui sert pour Valeur(Tableau ... // Tableau x_x_i; #ifdef MISE_AU_POINT // on vérifie qu'il y a bien équivalence entre les variables if (!equivalence_nom_enu_etendu_et_enu_quelconque) { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << " les variables de passage ne sont pas tous des ddl etendue ou des grandeurs " << " quelconque scalaire " << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Valeur(Tableau ..."<& tenu = *t_enu; // pour simplifier l'appel for (int i= 1; i<= tail_tab_enu_etendu;i++) {x_x_i(index_enu_etendu(i)) = tenu(i).Valeur(); }; }; int tail_tab_enu_quelc = tab_enu_quelconque.Taille(); if (t_qi != NULL) {Tableau & tqi = *t_qi; // pour simplifier l'appel for (int i= 1; i<= tail_tab_enu_quelc;i++) { x_x_i(index_enu_quelconque(i)) = tqi(i)->GrandeurNumOrdre(1); #ifdef MISE_AU_POINT int nb_scalaire_type_quelconque = tqi(i)->NbMaxiNumeroOrdre(); if (nb_scalaire_type_quelconque != 1) { cout << "\n *** pb dans le nombre de parametre de passage pour l'appel de la fonction nD " << " au niveau des parametres d'appel " << " la grandeur quelconque "<< i<< "correspondante a " << (tqi)(i)->EnuTypeQuelconque().NomPlein() << " n'est pas une grandeur scalaire " << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Valeur(Tableau ..."< 4) {cout << "\n retour fonction: "< & inter = Valeur_FnD_interne(&x_x_i); int nb_val = inter.Taille(); for (int i=1;i<=nb_val;i++) cout << " val("< 5) {cout << "\n parametres d'appel: "; int nb_var = x_x_i.Taille(); for (int j=1;j<=nb_var;j++) { cout << " para("<Affiche();Sortie(1); }; }; // ramène un pointeur sur la fonction correspondant au type de fonction passé en paramètre Fonction_nD* Fonction_nD::New_Fonction_nD(string& nom,EnumFonction_nD typeFonction) { // définition du pointeur de retour Fonction_nD* fonction; // choix en fonction du typeCourbe switch (typeFonction) { case FONCTION_EXPRESSION_LITTERALE_nD : fonction= new Fonction_expression_litterale_nD(nom); break; case FONCTION_COURBE1D : fonction= new F_nD_courbe1D(nom); break; case FONC_SCAL_COMBINEES_ND : fonction= new Fonc_scal_combinees_nD(nom); break; case FONCTION_EXTERNE_ND : fonction= new Fonction_externe_nD(nom); break; default : { cout << "\nErreur : valeur incorrecte du type de Fonction_nD : " << typeFonction << "\n"; cout << "\n New_Fonction_nD(EnumFonction_nD typeFonction) \n"; Sortie(1); } }; return fonction; }; // ramène un pointeur sur une courbe copie de celle passée en paramètre // IMPORTANT : il y a création d'une courbe (utilisation d'un new) Fonction_nD* Fonction_nD::New_Fonction_nD(const Fonction_nD& Co) { // définition du pointeur de retour Fonction_nD* fonction; // choix en fonction du typeFonction switch (Co.Type_Fonction()) { case FONCTION_EXPRESSION_LITTERALE_nD : fonction= new Fonction_expression_litterale_nD( Co); break; case FONCTION_COURBE1D : fonction= new F_nD_courbe1D(Co); break; case FONC_SCAL_COMBINEES_ND : fonction= new Fonc_scal_combinees_nD(Co); break; case FONCTION_EXTERNE_ND : fonction= new Fonction_externe_nD(Co); break; default : { cout << "\nErreur : valeur incorrecte du type de Fonction_nD : " << Co.Type_Fonction() << "\n"; cout << "\n New_Fonction_nD(const Fonction_nD& Co) \n"; Sortie(1); } }; return fonction; }; // ramène la liste des identificateurs de courbes actuellement disponibles list Fonction_nD::Liste_Fonction_disponible() { // définition de la liste de retour list list_ret; // remplissage de la liste list_ret.push_back(FONCTION_EXPRESSION_LITTERALE_nD); list_ret.push_back(FONCTION_COURBE1D); list_ret.push_back(FONC_SCAL_COMBINEES_ND); list_ret.push_back(FONCTION_EXTERNE_ND); // retour de la liste return list_ret; }; // mise à jour des variables globales: en fonction de l'apparition de nouvelles variables // globales en cours de calcul // méthode interne: qui est utilisé par les fonctions dérivées pour la méthode: // Mise_a_jour_variables_globales // retourne false si rien n'a changé bool Fonction_nD::Mise_a_jour_variables_globales_interne() {// on passe en revue les variables normales et on regarde s'il s'agit de nouvelles variables globales int taille = nom_variables.Taille(); list li_variable; // liste de travail list li_globale; // "" bool a_changer = false; // a priori rien ne change // maintenant on parcours les variables for (int i=1;i<=taille;i++) {if (ParaGlob::param->GrandeurGlobal(nom_variables(i)) != NULL) // il s'agit d'une variable globale {// on n'ajoute que si elle n'est pas déjà présente std::list ::iterator it = find (li_globale.begin(), li_globale.end(),nom_variables(i)); if (it == li_globale.end()) {li_globale.push_back(nom_variables(i)); }; // quelque soit le cas il faut valider a_changer=true; } else // sinon c'est toujours une variable li_variable.push_back(nom_variables(i)); }; // on met à jour les tableaux if (a_changer) {// on ajoute maintenant les variables globales déjà existantes int taille_globale = nom_variables_globales.Taille(); // Init_from_list for (int j=1;j<= taille_globale;j++) {// on n'ajoute que si elle n'est pas déjà présente list ::iterator it = find (li_globale.begin(), li_globale.end(),nom_variables_globales(j)); if (it == li_globale.end()) {li_globale.push_back(nom_variables_globales(j));} }; // on met à jour les tableaux nom_variables.Init_from_list(li_variable); t_inter_double.Change_taille(nom_variables.Taille()); // pour les variables globales on considère les points suivants: // leur nombre ne peut pas décroitre // l'ordre n'a pas vraiment d'importance // int taille_ajout = li_globale.size(); int taille_finale = li_globale.size(); if (taille_finale < nom_variables_globales.Taille()) {cout << "\n erreur changement de taille des variables globales " << "\n Fonction_nD::Mise_a_jour_variables_globales_interne() " << endl; Sortie(1); }; nom_variables_globales.Init_from_list(li_globale); // int taille_ini = nom_variables_globales.Taille(); // nom_variables_globales.Change_taille(taille_ini+taille_ajout); // nom_variables_globales.Change_taille(taille_finale); // list ::iterator il,ilfin=li_globale.end(); // int ip = 1; //taille_ini+1; // for (il = li_globale.begin();il != ilfin; il++,ip++) // nom_variables_globales(ip) = (*il); // nom_variables_globales.Init_from_list(li_globale); }; // on met à jour le tableau d'échange interne : x_glob int nb_tot_glob = enu_variables_globale.Taille() + nom_variables_globales.Taille(); x_glob.Change_taille(nb_tot_glob); // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs Fonction_nD::Construction_index_conteneurs_evoluees(); return a_changer; }; // Tableau nom_variables; //variables de la fonction, vu de l'extérieur // // Tableau enu_variables_globale; //tableau des énumérés // // de variables globales // // éventuellement vide s'il ne sert pas // Tableau nom_variables_globales; //tableau des énumérés // 2) retourne une liste de nom correspondant aux noms de courbes dont dépend *this list & Fonction_nD::ListDependanceCourbes(list & lico) const { // par défaut, ne dépend pas de fonctions, donc on ramène une liste vide // ce sera surchargé dans les classes qui elles éventuellement dépendent de quelque chose if (lico.size() != 0) lico.clear(); return lico; }; // 3) retourne une liste de nom correspondant aux noms de fonctions dont dépend *this list & Fonction_nD::ListDependanceFonctions(list & lico) const { // par défaut, ne dépend pas de fonctions, donc on ramène une liste vide // ce sera surchargé dans les classes qui elles éventuellement dépendent de quelque chose if (lico.size() != 0) lico.clear(); return lico; }; // ---------- METHODES PROTEGEES :------------------- // ramène true si les variables de la classe mère sont complèté bool Fonction_nD::Complet_var() const { bool ret = true; if (typeFonction == AUCUNE_FONCTION_nD) ret = false; if (nom_ref == "") ret = false; return ret; }; // définit le paramètre depend_M en fonction des nom_variables // 3 indicateurs permettant de connaître rapidement si // la fonction dépend de la position d'un point M à tdt, t et t=0 // 0 : la fonction ne dépend pas de la position d'un point M // non nul : la fonction dépend de la position d'un point M // dans ce cas, une au moins un des nom_variables // a un nom de la même famille que le ddl X1 // et depend_M = nombre de composantes demandés (ne sert pas vraiment) // si = -1 : cela signifie que la fonction dépend "que" de M void Fonction_nD::Definition_depend_M() {// on parcours les noms des variables int taille = nom_variables.Taille(); depend_M=0; // init a priori depend_Mt=0; // idem à t depend_M0 = 0; // idem à 0 Ddl_enum_etendu d_X1_t = Ddl_enum_etendu(X1,"X1_t"); Ddl_enum_etendu d_X1_t0 = Ddl_enum_etendu(X1,"X1_t0"); if (permet_affichage > 6) cout << "\n == >>> Fonction_nD::Definition_depend_M ( fct= " << nom_ref << ") "; list var_X_deja_enreg; // une liste de travail list var_independante; // une liste de travail for (int i=1; i<= taille; i++) {// on ne traite que si la variable n'a pas déjà été traité if (find(var_independante.begin(),var_independante.end(),nom_variables(i)) == var_independante.end()) {var_independante.push_back(nom_variables(i)); if (ExisteEnum_ddl(nom_variables(i))) // on regarde s'il s'agit d'un ddl patenté {if (permet_affichage > 7) cout << "\n cas d'un ddl de base: nom_variables("< 7) cout << " depend_M += 1 "; var_X_deja_enreg.push_back(nom_variables(i)); }; }; } // sinon on regarde s'il s'agit d'un ddl étendu relatif à t = 0 ou t else if (Ddl_enum_etendu::VerifExistence(nom_variables(i))) { if (permet_affichage > 7) cout << "\n cas d'un ddl etendu relatif a t=0 ou t : nom_variables("< 7) cout << " depend_Mt += 1 "; var_X_deja_enreg.push_back(nom_variables(i)); // on peut utiliser la même liste de travail } }; if ( Ddl_enum_etendu::PremierDdlEnumEtenduFamille(dd_et) == d_X1_t0) // si c'est de la famille d'X1_t0 c'est ok, on regarde s'il ne s'agit pas d'une variable // déjà consultée, car nom_variables peut contenir plusieurs fois la même variable {if (find(var_X_deja_enreg.begin(),var_X_deja_enreg.end(),nom_variables(i)) == var_X_deja_enreg.end()) {depend_M0 += 1; if (permet_affichage > 7) cout << " depend_M0 += 1 "; var_X_deja_enreg.push_back(nom_variables(i)); // on peut utiliser la même liste de travail } }; }; } }; // le nombre de variables indépendantes, car nom_variables peut contenir plusieurs fois la même variable int nb_var_inde = var_independante.size(); if (permet_affichage > 6) cout << "\n nb de variables independantes : "<< nb_var_inde << " "; // maintenant si depend_M est > à la dimension => il n'y a pas qu'une dépendance à M // if ((depend_M <= ParaGlob::Dimension()) && (depend_M > 0)) if ((depend_M <= taille) && (depend_M > 0)) {// on vérifie que l'on n'a pas utilisé plus de composantes que la dimension if (depend_M <= ParaGlob::Dimension()) {if (depend_M == nb_var_inde) depend_M = -1; // cas d'une dépendance stricte à M } else { cout << "\n **** erreur le nombre de composante de dependance a M_tdt "< 0)) {// on vérifie que l'on n'a pas utilisé plus de composantes que la dimension if (depend_Mt <= ParaGlob::Dimension()) {if (depend_Mt == nb_var_inde) depend_Mt = -1;// cas d'une dépendance stricte à Mt } else { cout << "\n **** erreur le nombre de composante de dependance a M_t"< 0)) {// on vérifie que l'on n'a pas utilisé plus de composantes que la dimension if (depend_M0 <= ParaGlob::Dimension()) {if (depend_M0 == nb_var_inde) depend_M0 = -1; // cas d'une dépendance stricte à M0 } else { cout << "\n **** erreur le nombre de composante de dependance a M_t=0 : "< 6) {cout << "\n == >>> Fonction_nD::Definition_depend_M : valeur des indicateurs finaux " << "\n pour memoire: = 0 -> la fct ne depend pas de la position " << " = -1 : la fct depend que de la position " << " > 0 : la fct depend de la position mais pas seulement " << "\n depend_M = " << depend_M << ",depend_Mt = " << depend_Mt << ", depend_M0 = " << depend_M0 << " "; }; }; // définit le paramètre depend_temps en fonction des nom_variables void Fonction_nD::Definition_depend_temps() {// on parcours les identifiants globaux int taille = enu_variables_globale.Taille(); depend_temps=false; // init a priori // le temps est une grandeurs globales for (int i=1; i<= taille; i++) if (enu_variables_globale(i) == TEMPS_COURANT) // on regarde s'il s'agit d'un ddl patenté {depend_temps = true; break; }; }; //// construction à partir des noms de variables, des tableaux tab_enu_etendu et //// tab_enu_quelconque //void Fonction_nD::Construction_enu_etendu_et_quelconque() // {// on parcours les noms des variables // int taille = nom_variables.Taille(); // // a priori on considère qu'il y a équivalence // equivalence_nom_enu_etendu_et_enu_quelconque = true; // list li_inter_enu; // une liste intermédiaire de travail // list li_index_enu; // list li_inter_tyQ; // idem // list li_index_quelc; // // // un conteneur de service: un réel par ddl // Ddl_enum_etendu ddl_de_service; // // par contre pour les grandeurs quelconques, on peut avoir plusieurs // // réels par grandeur quelconque // // // for (int i=1; i<= taille; i++) // {if (ddl_de_service.VerifExistence(nom_variables(i))) // {li_inter_enu.push_back(Ddl_enum_etendu(nom_variables(i))); // li_index_enu.push_back(i); // } // else if (Existe_typeQuelconque(nom_variables(i))) // {li_inter_tyQ.push_back(Id_nomTypeQuelconque(nom_variables(i))); // li_index_quelc.push_back(i); // } // else equivalence_nom_enu_etendu_et_enu_quelconque = false ; // }; // // maintenant on peut définir les tableaux // int tail_enu_ddl = li_inter_enu.size(); // { tab_enu_etendu.Change_taille(tail_enu_ddl); // index_enu_etendu.Change_taille(tail_enu_ddl); // int i_enu=1; // un compteur pour le tableau // list ::iterator il,ilfin=li_inter_enu.end(); // list ::iterator i_int=li_index_enu.begin(); // for (il=li_inter_enu.begin();il!=ilfin;il++,i_enu++,i_int++) // {tab_enu_etendu(i_enu)=(*il); // index_enu_etendu(i_enu)=(*i_int); // }; // }; // int tail_enuquel = li_inter_tyQ.size(); // { tab_enu_quelconque.Change_taille(tail_enuquel); // index_enu_quelconque.Change_taille(tail_enuquel); // int i_enu=1; // un compteur pour le tableau // list ::iterator il,ilfin=li_inter_tyQ.end(); // list ::iterator i_int=li_index_quelc.begin(); // for (il=li_inter_tyQ.begin();il!=ilfin;il++,i_enu++,i_int++) // {tab_enu_quelconque(i_enu)=(*il); // index_enu_quelconque(i_enu) = (*i_int); // #ifdef MISE_AU_POINT // EnumTypeQuelconque inter = (*il); // if (NombreElementFoncDim(Type_de_grandeur_associee(inter)) != 1) // { cout << "\n *** pb de dimensions d'argument non coherentes !! " // << " la grandeur quelconque "<< NomTypeQuelconque(inter) // << ", n'est pas un scalaire simple " // << "\n Fonction_nD::Construction_enu_etendu_et_quelconque(..."< li_inter_posi_ddl_enum; // liste des positions // --- cas des tenseurs list li_inter_tens_ddl_enum; // pour les tenseurs // list li_ind_tens; // pour les indices dans les tenseurs List_io li_premier_famille_tenseur; // pour savoir si c'est déjà enregistré // --- cas des coordonnées list li_coor_ddl_enum; // list li_num_dans_coor; List_io li_premier_famille_Coord; // pour savoir si c'est déjà enregistré // --- init de la liste équivalente de grandeurs quelconques évoluées li_equi_Quel_evolue.clear(); // on remet à 0 // on défini des conteneurs ad hoc int dim = ParaGlob::Dimension(); // la dimension globale // ... cas des Coordonnees Coordonnee v_rep(dim); // un vecteur de travail Grandeur_coordonnee grand5(v_rep); // def d'une grandeur courante coordonnée // ... cas des tenseurs TenseurBB* tens = NevezTenseurBB(dim); // un tenseur typique // maintenant on définit une grandeur typique de type tenseurBB Grandeur_TenseurBB gtBB(*tens); list < int > li_position; // liste de la position des variables dans les tableaux // on parcours les noms de variables list li_inter_enu; // une liste intermédiaire de travail list li_index_enu; list li_inter_tyQ; // idem list li_index_quelc; // un conteneur de service: un réel par ddl Ddl_enum_etendu ddl_de_service; list list_inter_val_ddl_enum; // inter qui donnera ensuite: val_ddl_enum // par contre pour les grandeurs quelconques, on peut avoir plusieurs // réels par grandeur quelconque int indice_enu_ddl = 0; // init int indice_t_quelconque = 0; // init for (int i=1; i<= taille; i++) // on balaie les noms de variable {// on sépare tout d'abord entre ddl_enum_etendu et type quelconque if (ddl_de_service.VerifExistence(nom_variables(i))) {ddl_de_service = Ddl_enum_etendu(nom_variables(i)); li_inter_enu.push_back(ddl_de_service); li_index_enu.push_back(i); // def de la position du ddl dans le tableau final des ddl (créé à la fin) indice_enu_ddl++;li_inter_posi_ddl_enum.push_back(indice_enu_ddl); // récup du type de grandeur auquel apartient l'énumération // l'idée est de passer en revue le type de grandeur EnumTypeGrandeur enu_type_grandeur = ddl_de_service.TypeDeGrandeur(); switch (enu_type_grandeur) {case SCALAIRE : case SCALAIRE_ENTIER : case SCALAIRE_DOUBLE : {// dans le cas d'un scalaire on a directement une équivalence à Ddl_enum_etendu // quelque soit le scalaire, on le stocke en double list_inter_val_ddl_enum.push_back(0.); // on ajoute une valeur 0. arbitraire li_enu_etendu_scalaire.push_back(ddl_de_service); type_des_variables(i)=1; break; } case TENSEUR : case TENSEUR_NON_SYM : case TENSEURBB : case TENSEURHH : case TENSEURBH : case TENSEURHB : case TENSEUR_NON_SYM_BB : case TENSEUR_NON_SYM_HH : { // on considère que c'est toujours un tenseur en absolu et par défaut c'est un tenseur BB type_des_variables(i)=3; // maintenant il faut savoir si on a déjà enregistré un tenseur qui contiend la composante if (!(Ddl_enum_etendu::Existe_dans_la_liste(li_premier_famille_tenseur,Ddl_enum_etendu::PremierDdlEnumEtenduFamille(ddl_de_service)))) // s'il n'existe pas on rajoute le premier de la famille { TenseurBB * pt_tens= NevezTenseurBB(dim); li_inter_tens_ddl_enum.push_back(pt_tens); li_premier_famille_tenseur.push_back (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(ddl_de_service)); // on s'occupe de la grandeur quelconque équivalente EnumTypeQuelconque enuQ = Ddl_enum_etendu::Equivalent_en_grandeur_quelconque(ddl_de_service); TypeQuelconque typQ6(enuQ,ddl_de_service.Enum(),gtBB); li_equi_Quel_evolue.push_back(typQ6); }; // // maintenant il faut récupérer la position = l'indice, de l'enu dans le tenseur // Deuxentiers_enu deux = IJind(ddl_de_service.Enum(),dim); // li_ind_tens.push_back(deux); break; } case COORDONNEE : case COORDONNEEB : case COORDONNEEH : {// on considère que c'est toujours un type coordonnée en absolu et par défaut c'est un Coordonnee type_des_variables(i)=2; // maintenant il faut savoir si on a déjà enregistré un Coordonnee qui contiend la composante if (!(Ddl_enum_etendu::Existe_dans_la_liste(li_premier_famille_Coord,Ddl_enum_etendu::PremierDdlEnumEtenduFamille(ddl_de_service)))) // s'il n'existe pas on rajoute le premier de la famille { Coordonnee pt_coor(dim); li_coor_ddl_enum.push_back(pt_coor); li_premier_famille_Coord.push_back(Ddl_enum_etendu::PremierDdlEnumEtenduFamille(ddl_de_service)); // on s'occupe de la grandeur quelconque équivalente EnumTypeQuelconque enuQ = Ddl_enum_etendu::Equivalent_en_grandeur_quelconque(ddl_de_service); TypeQuelconque typQ6(enuQ,ddl_de_service.Enum(),grand5); li_equi_Quel_evolue.push_back(typQ6); }; // // maintenant il faut récupérer la position = l'indice, de l'enu dans Coordonnee // int indice_coor = Indice_coor(ddl_de_service.Enum(),dim); // li_num_dans_coor.push_back(indice_coor); break; } default : // pour l'instant les autres cas, par exemple Vecteur, ne sont pas pris en compte cout << "\nErreur : la grandeur " << nom_variables(i) << " n'est pas pris en compte pour les fonctions nD !\n"; cout << "\n Fonction_nD::Construction_index_conteneurs_evoluees(.. \n"; Sortie(1); }; // fin du switch } // fin du cas où c'est un ddl_enum_etendu else if (Existe_typeQuelconque(nom_variables(i))) {li_inter_tyQ.push_back(Id_nomTypeQuelconque(nom_variables(i))); li_index_quelc.push_back(i); type_des_variables(i)=4; } else {// il y a des variables qui ne rentrent pas dans le cadre dd enu étendu et grandeur quelconque // on ne pourra pas utiliser l'appel via des grandeurs évoluées: on le sauvegarde // pour signaler des erreurs mais cela peut changer ensuite // par exemple via la transformation de variables locales en variables globales qui sont // dynamiquement créés, du coup on laisse l'algo equivalence_nom_enu_etendu_et_enu_quelconque = false ; type_des_variables(i)=0; }; }; // on poursuit même s'il n'y a pas équivalence parfaite // de manière a remplacer la méthode : Construction_enu_etendu_et_quelconque() // cependant s'il y a une équivalence parfaite // on ne pourra pas utiliser l'appel évolué // donc certains indexes ne seront pas utilisables // if (equivalence_nom_enu_etendu_et_enu_quelconque) {// maintenant on va construire les tableaux qui sont équivalent aux listes tailles_tab.Change_taille(4); tailles_tab(1)=list_inter_val_ddl_enum.size(); tailles_tab(2)=li_coor_ddl_enum.size(); tailles_tab(3)=li_inter_tens_ddl_enum.size(); tailles_tab(4)=li_inter_tyQ.size(); // .... pour les ddl étendue // le tableau global de ddl étendu tab_enu_etendu.Init_from_list(li_inter_enu); posi_ddl_enum.Init_from_list(li_inter_posi_ddl_enum); val_ddl_enum.Init_from_list(list_inter_val_ddl_enum); coor_ddl_enum.Init_from_list(li_coor_ddl_enum); premier_famille_Coord.Init_from_list(li_premier_famille_Coord); // num_dans_coor.Init_from_list(li_num_dans_coor); num_dans_coor.Change_taille(tab_enu_etendu.Taille()); tens_ddl_enum.Init_from_list(li_inter_tens_ddl_enum); premier_famille_tenseur.Init_from_list(li_premier_famille_tenseur); // ind_tens.Init_from_list(li_ind_tens); ind_tens.Change_taille(tab_enu_etendu.Taille()); index_enu_etendu.Init_from_list(li_index_enu); // .... pour les grandeurs quelconques // le tableau global de grandeurs quelconque tab_enu_quelconque.Init_from_list(li_inter_tyQ); index_enu_quelconque.Init_from_list(li_index_quelc); // il faut maintenant revoir le tableau posi_ddl_enum dans le cas // ou un tenseur et/ou un Coordonnee contient plusieurs Ddl_enum_etendu // on fait systématiquement le test // if (tab_enu_etendu.Taille() > (tailles_tab(1)+tailles_tab(2)+tailles_tab(3))) {// on utilise les premiers de famille dont l'indice est le même que les // tableau de tenseur et de Coordonnee int nb_enu = tab_enu_etendu.Taille(); for (int i=1;i<=nb_enu;i++) {// récup du type de grandeur auquel apartient l'énumération // l'idée est de passer en revue le type de grandeur Ddl_enum_etendu & ddenumetendu = tab_enu_etendu(i); // pour simplifier EnumTypeGrandeur enu_type_grandeur = ddenumetendu.TypeDeGrandeur(); //TypeGrandeur(ddenumetendu.Enum()); switch (enu_type_grandeur) {case TENSEUR : case TENSEUR_NON_SYM : case TENSEURBB : case TENSEURHH : case TENSEURBH : case TENSEURHB : case TENSEUR_NON_SYM_BB : case TENSEUR_NON_SYM_HH : { // on récupère la position dans le tableau de tenseur int position = premier_famille_tenseur.Contient (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(ddenumetendu)); posi_ddl_enum(i)=position; // maintenant il faut récupérer la position = l'indice, de l'enu dans le tenseur // erreur : 18 mars 2023 Deuxentiers_enu deux = IJind(ddl_de_service.Enum(),dim); Deuxentiers_enu deux = IJind(ddenumetendu.Enum(),dim); ind_tens(i) = deux; break; } case COORDONNEE : case COORDONNEEB : case COORDONNEEH : { // on récupère la position dans le tableau de Coordonnee int position = premier_famille_Coord.Contient (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(ddenumetendu)); posi_ddl_enum(i)=position; // maintenant il faut récupérer la position = l'indice, de l'enu dans Coordonnee int indice_coor = Indice_coor(ddenumetendu.Enum(),dim); num_dans_coor(i) = indice_coor; break; } default : break;// sinon c'est des scalaires }; // fin du switch }; }; // fin du if (tab_enu_etendu.Taille() > (tailles_tab(1)+tailles_tab(2)+tailles_tab(3))) ////------- debug //cout << "\n\n debug Fonction_nD::Construction_index_conteneurs_evoluees() : FCT= " << nom_ref // << "\n les variables: "<< nom_variables // << "\n li_equi_Quel_evolue= " << li_equi_Quel_evolue // << " num_dans_coor= "<::iterator iqc,iqc_fin=li_equi_Quel_evolue.end(); // cout << "\n posi_ddl_enum= " << posi_ddl_enum << endl; for (int i=1;i<=nb_etendu;i++) if ((type_des_variables(index_enu_etendu(i)) == 2) || (type_des_variables(index_enu_etendu(i)) == 3)) {EnumTypeQuelconque enuQ = Ddl_enum_etendu::Equivalent_en_grandeur_quelconque(tab_enu_etendu(i)); TypeQuelconque tq(enuQ); // on cherche dans la liste enregistrée List_io ::iterator result1 = std::find(li_equi_Quel_evolue.begin(),li_equi_Quel_evolue.end(), tq); if (result1 == li_equi_Quel_evolue.end()) {cout << "\n *** erreur d'adressage dans " << "Fonction_nD::Construction_index_conteneurs_evoluees()"; this->Affiche(); Sortie(1); }; if (type_des_variables(index_enu_etendu(i)) == 2) // cas de coordonnées tab_equi_Coor(posi_ddl_enum(i))=result1; else if (type_des_variables(index_enu_etendu(i)) == 3) // cas des tenseurs tab_equi_tens(posi_ddl_enum(i))=result1; }; delete tens; // car on n'en a plus besoin // on met à jour le tableau de transfert // ici par défaut chaque type quelconque est associé à un conteneur scalaire // si ce n'est pas le cas, on considère que l'utilisateur utilisera la méthode // Preparation_Grandeur_quelconque( pour mettre les bonnes dimensions x_x_i.Change_taille(tab_enu_etendu.Taille()+tab_enu_quelconque.Taille()); }; // fin du cas où il y a une équivalence parfaite }; // Passage des infos variables évoluées en tableau de réels // I/O : di Tableau & Fonction_nD::Vers_tab_double(Tableau & di ,const Tableau * val_ddl_enum ,const Tableau * coor_ddl_enum ,const Tableau * tens_ddl_enum ,const Tableau * tqi ,const Tableau * t_num_ordre) { #ifdef MISE_AU_POINT if (di.Taille() != (tab_enu_etendu.Taille() + tab_enu_quelconque.Taille())) { cout << "\n *** pb dans le transfert des grandeurs evoluees vers scalaires " << " tab_enu_etendu.Taille()= " << tab_enu_etendu.Taille() << " tab_enu_quelconque.Taille()= "<< tab_enu_quelconque.Taille() << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Vers_tab_double(..."<Taille() != tailles_tab(1)) { cout << "\n *** pb dans le transfert des grandeurs evoluees vers scalaires " << " taille val_ddl_enum = " << val_ddl_enum->Taille() << " est different du nombre prevu !" << tailles_tab(1) << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Vers_tab_double(..."<Taille() != tqi->Taille()) { cout << "\n *** pb dans le transfert des grandeurs quelconques vers scalaires " << " taille tqi = " << tqi->Taille() << " est different du nombre de numero d'ordre prevu !" << t_num_ordre->Taille() << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Vers_tab_double(..."<operator()(posi_ddl_enum(ienu)); break;} case 2: // Coordonnee {int j = posi_ddl_enum(ienu); di(num_variable) = (*coor_ddl_enum)(j)(num_dans_coor(ienu)); break;} case 3: // tenseur {int j = posi_ddl_enum(ienu); int k = ind_tens(ienu).i; int l = ind_tens(ienu).j; di(num_variable) = (*(*tens_ddl_enum)(j))(k,l); break;} default: break; }; }; // fin de la boucle sur les enum // 2) sur les grandeurs quelconques int nb_quelc = index_enu_quelconque.Taille(); for (int ieq = 1; ieq <= nb_quelc; ieq++) { int num_variable = index_enu_quelconque(ieq); int nb_ordre = 1; // init par défaut if (t_num_ordre != NULL) nb_ordre = (*t_num_ordre)(ieq); di(num_variable) = (*tqi)(ieq)->GrandeurNumOrdre(nb_ordre); }; // fin de la boucle sur les enu quelconques // retour return di; }; // idem, mais via les listes // val_ddl_enum(k) correspond à li_evolue_scalaire de rang i Tableau & Fonction_nD::Vers_tab_double(Tableau & di ,const Tableau * val_ddl_enum ,List_io * li_evolue_scalaire ,List_io * li_evoluee_non_scalaire ,const Tableau * tqi ,const Tableau * t_num_ordre) { #ifdef MISE_AU_POINT // on vérifie qu'il s'agit bien des mêmes listes if ((&li_enu_etendu_scalaire) != li_evolue_scalaire) { cout << "\n *** pb dans le transfert des grandeurs evoluees vers scalaires " << " la liste des enum etendu scalaires n'est pas celle fournie par la fonction" << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Vers_tab_double(..."<Taille() != li_enu_etendu_scalaire.size()) { cout << "\n *** pb dans le transfert des grandeurs evoluees vers scalaires " << " val_ddl_enum est de taille " << val_ddl_enum->Taille() << " alors qu'il est prevu d'avoir "<< li_enu_etendu_scalaire.size() << " grandeurs scalaires !" << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Vers_tab_double(..."<Taille() != tqi->Taille()) { cout << "\n *** pb dans le transfert des grandeurs quelconques vers scalaires " << " taille tqi = " << tqi->Taille() << " est different du nombre de numero d'ordre prevu !" << t_num_ordre->Taille() << " ce n'est pas normal !! , on arrete le calcul " << "\n Fonction_nD::Vers_tab_double(..."<::iterator i_scal = li_enu_etendu_scalaire.begin(); List_io ::iterator i_evol = li_equi_Quel_evolue.begin(); int indice_scal=1; // init : indice dans le tableau val_ddl_enum ////------- debug //cout << "\n\n debug Fonction_nD::Vers_tab_double( : FCT= " << nom_ref // << "\n les variables: "<< nom_variables // << "\n li_equi_Quel_evolue= " << li_equi_Quel_evolue // << " num_dans_coor= "<::iterator& il = tab_equi_Coor(j); Grandeur_coordonnee& coo = *((Grandeur_coordonnee*) (*il).Grandeur_pointee()); Coordonnee& coord = *(coo.ConteneurCoordonnee()); di(num_variable) = coord(num_dans_coor(ienu)); ////------- debug //cout << "\n num_variable= "< erreur // calcul des valeurs de la fonction double Fonction_nD::Val_avec_nbArgVariable(double x,...) { // un certain nombre de variables utilisée pour gérer // http://www.cplusplus.com/reference/cstdarg/va_copy/ // cf. variadic function int count = 0; double val = x; va_list vl,vl_count; va_start(vl,x); // on va remplir le tableau xinter, pour faire un appel classique int nb_var = this->NbVariable(); if (xinter == NULL) xinter = new Tableau (nb_var); if (nb_var != 0) {(*xinter)(count+1)=val; /* count number of arguments: */ va_copy(vl_count,vl); while (val != 0) {if (count < nb_var) // cas normal {val=va_arg(vl_count,double); ++count; (*xinter)(count+1)=val; } else // sinon il y a plus d'argument que prévu, on génère une erreur { cout << "\n *** erreur dans l'appel de la fonction " << nom_ref << " le nombre d'argument est superieur a "<< nb_var << " ce qui n'est pas prevu dans la definition de la fonction " << "\n Fonction_nD::Val_avec_nbArgVariable( "; if (ParaGlob::NiveauImpression() > 1) this->Affiche(); cout << endl; Sortie(1); }; }; va_end(vl_count); }; // maintenant on peut utiliser la méthode classique Tableau & ret = this->Valeur_FnD_interne(xinter); return ret(1); }; // méthode utilisée par les classes dérivées, pour transférer les infos qui sont // gérées au niveau de Fonction_nD Fonction_nD& Fonction_nD::Transfert_info(const Fonction_nD& elt) { // on reprend toutes les données gérées par Fonction_nD typeFonction = elt.typeFonction; nom_ref = elt.nom_ref; nom_variables = elt.nom_variables; t_inter_double = elt.t_inter_double; enu_variables_globale = elt.enu_variables_globale; nom_variables_globales = elt.nom_variables_globales; tab_enu_etendu = elt.tab_enu_etendu; type_des_variables = elt.type_des_variables; val_ddl_enum = elt.val_ddl_enum; li_enu_etendu_scalaire = elt.li_enu_etendu_scalaire; coor_ddl_enum = elt.coor_ddl_enum; num_dans_coor = elt.num_dans_coor; tens_ddl_enum = elt.tens_ddl_enum; premier_famille_tenseur = elt.premier_famille_tenseur; ind_tens = elt.ind_tens; posi_ddl_enum = elt.posi_ddl_enum; tailles_tab = elt.tailles_tab; tab_enu_quelconque = elt.tab_enu_quelconque; equivalence_nom_enu_etendu_et_enu_quelconque = elt.equivalence_nom_enu_etendu_et_enu_quelconque; index_enu_etendu = elt.index_enu_etendu; index_enu_quelconque = elt.index_enu_quelconque; // les listes pour les appels via les listes li_enu_etendu_scalaire = elt.li_enu_etendu_scalaire; li_equi_Quel_evolue = elt.li_equi_Quel_evolue; tab_equi_Coor = elt.tab_equi_Coor; tab_equi_tens = elt.tab_equi_tens; x_x_i = elt.x_x_i; x_glob = elt.x_glob; depend_M = elt.depend_M; depend_Mt = elt.depend_Mt; depend_M0 = elt.depend_M0; depend_temps = elt.depend_temps; }; // affichage des données internes, utilisée par les fonctions dérivées // niveau donne le degré d'affichage void Fonction_nD::Affiche_interne(int niveau) const { if (niveau > 0) { cout << "\n type_de_fonction: "<< Nom_Fonction_nD(typeFonction) << " nom_ref= " << nom_ref << "\n les_variables_lues: " << nom_variables ; if (niveau > 1) { // les énumérés globaux éventuels int taille_enu_variables_globale= enu_variables_globale.Taille(); if (taille_enu_variables_globale != 0) { cout << "\n enumeres_globaux:_taille " << enu_variables_globale.Taille(); for (int i=1;i<= taille_enu_variables_globale;i++) cout << " " << Nom_GrandeurGlobale(enu_variables_globale(i)); }; // les noms de variables globales éventuelles int taille_nom_variables_globales= nom_variables_globales.Taille(); if (taille_nom_variables_globales != 0) { cout << "\n noms_variables_globales:_taille " << nom_variables_globales.Taille(); for (int i=1;i<= taille_nom_variables_globales;i++) cout << " " << nom_variables_globales(i); }; // enu étendu équivalent aux variables non globales int taille_tab_enu_etendu= tab_enu_etendu.Taille(); if (taille_tab_enu_etendu != 0) { cout << "\n enum_etendu_locaux:_taille " << tab_enu_etendu.Taille(); for (int i=1;i<= taille_tab_enu_etendu;i++) {cout << " " << tab_enu_etendu(i).Nom_plein(); int j = posi_ddl_enum(i); switch (type_des_variables(i)) {case 1: cout << " type scalaire: valeur actuelle= " << val_ddl_enum(j) ; break; case 2: cout << " type coordonnees: valeur actuelle= " << coor_ddl_enum(j)(num_dans_coor(j)); break; case 3: cout << " type tenseur: valeur actuelle= " << (*tens_ddl_enum(j))(ind_tens(j).i,ind_tens(j).j) ; break; default: cout << "\n type non reconnue= " << type_des_variables(i) << "\n Fonction_nD::Affiche_interne( "; Sortie(1); }; }; // bilan des variables évoluées cout << "\n il y a: " << tailles_tab(1) << " scalaire(s) " << tailles_tab(2) << " coordonnee(s) " << tailles_tab(3) << " composante(s) de tenseur " << endl; }; // grandeurs quelconques équivalentes aux variables non globales int taille_tab_enu_quelconque= tab_enu_quelconque.Taille(); if (taille_tab_enu_quelconque != 0) { cout << "\n enum_quelconque:_taille " << tab_enu_quelconque.Taille() << "\n liste: "; for (int i=1;i<= taille_tab_enu_quelconque;i++) cout << NomTypeQuelconque(tab_enu_quelconque(i)) << ", "; }; }; // autres infos cout << "\n il y a " << this->NbComposante() << " valeur(s) en retour de la fonction "; if (depend_temps || depend_M || depend_Mt ||depend_M0 ) { cout << "\n "; if (depend_temps) cout << " la fonction depend du temps, "; if (depend_M || depend_Mt ||depend_M0 ) cout << " la fonction depend du point M : "; if (depend_M) cout << " courant, "; if (depend_Mt) cout << " a t, "; if (depend_M0) cout << " a 0, "; }; }; }; //------ méthodes appelée par les classes dérivées ---- // relatives aux données gérées par Fonction_nD // 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 Fonction_nD::Lect_base_info(ifstream& ent,const int cas) { if (cas == 1) { string toto; string nom; // lecture des arguments ent >> nom >> nom_variables; t_inter_double.Change_taille(nom_variables.Taille()); // les énumérés des variables globales ent >> nom; int nb_enu=0; ent >> nom >> nb_enu; enu_variables_globale.Change_taille(nb_enu); for (int i=1;i<= nb_enu;i++) { ent >> nom; enu_variables_globale(i) = Id_nom_GrandeurGlobale(nom); }; // les nom des variables globales indicées en string ent >> nom; int nb_nom=0; ent >> nom >> nb_nom; nom_variables_globales.Change_taille(nb_nom); for (int i=1;i<= nb_nom;i++) { ent >> nom; nom_variables_globales(i) = nom; }; // enu étendu équivalent aux variables non globales ent >> nom >> tab_enu_etendu; // grandeurs quelconques équivalentes aux variables non globales int taille_tab_enu_quelconque; // init ent >> nom >> taille_tab_enu_quelconque >> toto; tab_enu_quelconque.Change_taille(taille_tab_enu_quelconque); for (int i=1;i<= taille_tab_enu_quelconque;i++) {ent >> nom; tab_enu_quelconque(i) = Id_nomTypeQuelconque(nom); }; // bilan des variables évoluées (on lit pour passer les infos // dans le .BI, mais cela va être recalculé au moment de la fabrication // des index tailles_tab.Change_taille(4); ent >> nom >> tailles_tab(1) >> nom >> tailles_tab(2) >> nom >> tailles_tab(3) >> nom >> tailles_tab(4) >> nom; ent >> nom >> permet_affichage ; // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs Fonction_nD::Construction_index_conteneurs_evoluees(); }; }; // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void Fonction_nD::Ecrit_base_info(ofstream& sort,const int cas) { if (cas == 1) { // les variables sort << " \n arguments= " << nom_variables << " \n variables_globales_en_enumere= " ; int nb_enu = enu_variables_globale.Taille(); sort << "taille " << nb_enu << " "; for (int i=1;i<= nb_enu;i++) sort << Nom_GrandeurGlobale(enu_variables_globale(i)) << " "; sort << " \n variables_globales_en_string= " ; int nb_str = nom_variables_globales.Taille(); sort << "taille " << nb_str << " "; for (int i=1;i<= nb_str;i++) sort << nom_variables_globales(i) << " "; // enu étendu équivalent aux variables non globales int taille_tab_enu_etendu= tab_enu_etendu.Taille(); sort << "\n enum_etendu_locaux: " << tab_enu_etendu; // grandeurs quelconques équivalentes aux variables non globales int taille_tab_enu_quelconque= tab_enu_quelconque.Taille(); sort << "\n enum_quelconque:_taille " << tab_enu_quelconque.Taille() << "\n liste: "; for (int i=1;i<= taille_tab_enu_quelconque;i++) sort << NomTypeQuelconque(tab_enu_quelconque(i)) << " "; // bilan des variables évoluées sort << "\n bilan_var_evolue_il_y_a: " << tailles_tab(1) << " scalaire(s) " << tailles_tab(2) << " coordonnee(s) " << tailles_tab(3) << " composante(s)_de_tenseur " << tailles_tab(4) << " grandeur_quelconque " ; sort << "\n permet_affichage_ "< list_enu_variables_glob; // enum glob // on transvase le tableau dans la liste enu_variables_globale.Init_list(list_enu_variables_glob); // idem pour les noms globaux list < string> list_de_variables_nom_globales; // string glob nom_variables_globales.Init_list(list_de_variables_nom_globales); // puis les variables qui ne sont pas globales list < string> list_de_variables; // liste nom_variables.Init_list(list_de_variables); bool lecture_effective = false; // init while (( (strstr(entreePrinc->tablcar,"un_argument=")==0) && (strstr(entreePrinc->tablcar,"deb_list_var_")==0) ) || (nom_lu == "un_argument=") || (nom_lu == "deb_list_var_") ) { // 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 fonction nD : on n'a pas trouve de mot cle relatif a une variable" << " et par contre la ligne courante contient un mot cle global " << " *** a priori il y a une erreur de mise en donnees ! " ; entreePrinc->MessageBuffer("** erreur des parametres d'une fonction nD **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // lecture d'un mot clé éventuellement if (( (nom_lu != "un_argument=") && (nom_lu != "deb_list_var_") ) || lecture_effective ) *(entreePrinc->entree) >> nom_lu; // sinon cela veut dire que nom_lu a déjà été lu et repéré // relatif à une variable // ou que l'on vient de terminer une lecture de variabl 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 { // on lit sans tenir compte des < éventuelles entreePrinc->NouvelleDonneeSansInf(); *(entreePrinc->entree) >>nom_lu; } #else else if ((entreePrinc->entree)->eof()) // la lecture est bonne mais on a atteind la fin de la ligne { if (nom_lu.find("fin_parametres_fonction_") == std::string::npos) //if(nom_lu != "fin_parametres_fonction_expression_litterale_") // on lit sans tenir compte des < éventuelles {entreePrinc->NouvelleDonneeSansInf(); *(entreePrinc->entree) >> nom_lu; }; } #endif else // cas d'une erreur de lecture { cout << "\n erreur de lecture inconnue "; entreePrinc->MessageBuffer("** erreur2 des parametres d'une fonction nD **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // cas de la lecture d'une variable if(nom_lu == "un_argument=") {*(entreePrinc->entree) >> nom_lu; // on regarde s'il s'agit d'une variable globale correspondant à un énuméré global if (EstUneGrandeurGlobale(nom_lu)) { list_enu_variables_glob.push_back(Id_nom_GrandeurGlobale (nom_lu));} // idem mais sous forme d'un string else if (ParaGlob::param->GrandeurGlobal(nom_lu) != NULL) { list_de_variables_nom_globales.push_back(nom_lu);} else // sinon ce n'est pas une grandeur globale {list_de_variables.push_back(nom_lu);}; // on signale que la lecture a été effective lecture_effective = true; } else if(nom_lu == "deb_list_var_") // lecture d'une liste d'argument {// on va lire juqu'au mot clé fin_list_var_ int nb_boucle = 0; // indicateur pour éviter une boucle infinie do {*(entreePrinc->entree) >> nom_lu; if (nom_lu == "fin_list_var_") break; // on regarde s'il s'agit d'une variable globale if (EstUneGrandeurGlobale(nom_lu)) { list_enu_variables_glob.push_back(Id_nom_GrandeurGlobale (nom_lu));} // idem mais sous forme d'un string else if (ParaGlob::param->GrandeurGlobal(nom_lu) != NULL) { list_de_variables_nom_globales.push_back(nom_lu);} else // sinon ce n'est pas une grandeur globale {list_de_variables.push_back(nom_lu);}; nb_boucle++; } while (nb_boucle < 200); if (nb_boucle > 199) { cout << "\n erreur de lecture au niveau d'une liste de variable " << " deb_list_var_ nom1 nom2 ... fin_list_var_"; entreePrinc->MessageBuffer("** erreur lecture parametre d'une d'une fonction nD ** **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else // sinon c'est ok // on signale que la lecture a été effective lecture_effective = true; } ; // sinon rien, ce n'est plus une variable, on va donc sortir // du while à la suite }; // fin du while // nom_lu contient la dernière information lue qui ne correspond pas à une variable //--- maintenant on va gérer les variables lues // on supprime les doublons dans les variables globales list_enu_variables_glob.sort(); list_enu_variables_glob.unique(); list_de_variables_nom_globales.sort(); list_de_variables_nom_globales.unique(); // on remet à jour le tableau des énumérés globaux enu_variables_globale.Init_from_list(list_enu_variables_glob); // idem pour les noms de reférence globaux nom_variables_globales.Init_from_list(list_de_variables_nom_globales); // puis pour les variables qui ne sont pas globales nom_variables.Init_from_list(list_de_variables); // on met à jour les tableaux internes de passage de valeurs x_x_i.Change_taille(nom_variables.Taille()); x_glob.Change_taille(enu_variables_globale.Taille()+nom_variables_globales.Taille()); }; // affichage des variables de la fonction, dépend du niveau d'impression void Fonction_nD::Affichage_variables() const { if (permet_affichage > 5) { cout << "\n ---- Fonction_nD " << nom_ref ; cout << " \n arguments_specifiques= " << nom_variables << " \n variables_globales_en_enumere= " ; int nb_enu = enu_variables_globale.Taille(); cout << "taille " << nb_enu << " "; for (int i=1;i<= nb_enu;i++) cout << Nom_GrandeurGlobale(enu_variables_globale(i)) << " "; cout << " \n variables_globales_en_string= " ; int nb_str = nom_variables_globales.Taille(); cout << "taille " << nb_str << " "; for (int i=1;i<= nb_str;i++) cout << nom_variables_globales(i) << " "; }; }; // récupération des valeurs des variables globales et stockage dans le tableau // interne x_glob void Fonction_nD::Recup_Grandeurs_globales() { // --- on parcours les variables globales: // 1) les énumérés int index_glob=1; int tail_enu = enu_variables_globale.Taille(); if (tail_enu>0) { // en debug on vérifie que les grandeurs globales sont présentent #ifdef MISE_AU_POINT try { int taille = enu_variables_globale.Taille(); for (int i=1;i<= taille;i++) {// on récupère le pointeur correspondant à la grandeur const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i))); if (pointe == NULL) { cout << "\n *** pb dans l'appel de la fonction " << nom_ref << " !! " << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) << ", n'est pas disponible, on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..."<Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; }; } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur { ErrSortieFinale toto; throw (toto); } catch(...) { cout << "\n ** erreur dans l'appel de la fonction " << nom_ref ; cout << " verifier la presence des grandeurs globales voulues " << "\n Fonction_nD::Recup_Grandeurs_globales(..."<Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; #endif for (int i=1;i<= tail_enu;i++,index_glob++) {// on récupère le pointeur correspondant à la grandeur const void* pointe = (ParaGlob::param->GrandeurGlobal(enu_variables_globale(i))); TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()) { case TYPE_SIMPLE: { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) {case PARTICULIER_SCALAIRE_ENTIER: {Grandeur_scalaire_entier& gr = *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = *(gr.ConteneurEntier()); break; } case PARTICULIER_SCALAIRE_DOUBLE: {Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = *(gr.ConteneurDouble()); break; } case PARTICULIER_DDL_ETENDU: {Grandeur_Ddl_etendu& gr = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = (gr.GrandeurNumOrdre(1)); break; } case PARTICULIER_SCALAIRE_DOUBLE_NOMMER_INDICER: {Grandeur_Double_Nommer_indicer& gr = *((Grandeur_Double_Nommer_indicer*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = *(gr.ConteneurDouble()); break; } default: { cout << "\n *** pb dans dans l'appel de la fonction "<< nom_ref << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) << ", n'est pas prise en compte actuellement , on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..." <Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; } break; } default: { cout << "\n *** pb dans dans l'appel de la fonction "<< nom_ref << " la variable globale "<< Nom_GrandeurGlobale(enu_variables_globale(i)) << ", n'est pas prise en compte actuellement , on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..." <Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; }; if (permet_affichage > 5) {cout << "\n " << Nom_GrandeurGlobale(enu_variables_globale(i)) << " " << x_glob(index_glob); }; }; }; // 2) idem pour les globaux en nom c-a-d typées sous forme de string int tail_nom = nom_variables_globales.Taille(); if (tail_nom>0) { // en debug on vérifie que les grandeurs globales sont présentent #ifdef MISE_AU_POINT try { for (int i=1;i<= tail_nom;i++) {// on récupère le pointeur correspondant à la grandeur const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i))); if (pointe == NULL) { cout << "\n *** pb dans Fonction_expression_litterale_nD " << nom_ref << " !! " << " la variable globale "<< nom_variables_globales(i) << ", n'est pas disponible, on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..."<Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; }; } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur { ErrSortieFinale toto; throw (toto); } catch(...) { cout << "\n ** erreur dans l'appel de la fonction " << nom_ref ; cout << " verifier la presence des grandeurs globales voulues " << "\n Fonction_nD::Recup_Grandeurs_globales(..."<Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; #endif // on parcours les variables globales int taille = nom_variables_globales.Taille(); for (int i=1;i<= taille;i++,index_glob++) {// on récupère le pointeur correspondant à la grandeur const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_variables_globales(i))); TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); switch(gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()) { case TYPE_SIMPLE: { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) {case PARTICULIER_SCALAIRE_ENTIER: {Grandeur_scalaire_entier& gr = *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = *(gr.ConteneurEntier()); break; } case PARTICULIER_SCALAIRE_DOUBLE: {Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = *(gr.ConteneurDouble()); break; } case PARTICULIER_DDL_ETENDU: {Grandeur_Ddl_etendu& gr = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = (gr.GrandeurNumOrdre(1)); break; } case PARTICULIER_SCALAIRE_DOUBLE_NOMMER_INDICER: {Grandeur_Double_Nommer_indicer& gr = *((Grandeur_Double_Nommer_indicer*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = *(gr.ConteneurDouble()); break; } case PARTICULIER_VECTEUR_NOMMER: {Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = (gr.GrandeurNumOrdre(1)); #ifdef MISE_AU_POINT // on vérifie qu'une seule grandeur est stockée if (gr.NbMaxiNumeroOrdre() > 1) { cout << "\n *** pb dans dans l'appel de la fonction "<< nom_ref << " la variable globale "<< nom_variables_globales(i) << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en " << " compte pour l'intant, on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..." <Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; #endif break; } default: { cout << "\n *** pb dans dans l'appel de la fonction "<< nom_ref << " la variable globale "<< nom_variables_globales(i) << ", n'est pas prise en compte actuellement , on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..." <Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; } break; } case TABLEAU_T: // valable uniquement pour les vecteur nommer // dans ce cas on n'utilise pour l'instant que la première valeur { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()) { case PARTICULIER_VECTEUR_NOMMER: {Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier x_glob(index_glob) = (gr.GrandeurNumOrdre(1)); #ifdef MISE_AU_POINT // on vérifie qu'une seule grandeur est stockée if (gr.NbMaxiNumeroOrdre() > 1) { cout << "\n *** pb dans dans l'appel de la fonction "<< nom_ref << " la variable globale "<< nom_variables_globales(i) << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en " << " compte pour l'intant, on ne peut pas continuer " << "\n grandeur= "<Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; #endif break; } default: { cout << "\n *** pb dans dans l'appel de la fonction "<< nom_ref << " la variable globale "<< nom_variables_globales(i) << ", n'est pas prise en compte actuellement , on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..." <Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; } break; } default: { cout << "\n *** pb dans dans l'appel de la fonction "<< nom_ref << " la variable globale "<< nom_variables_globales(i) << ", n'est pas prise en compte actuellement , on ne peut pas continuer " << "\n Fonction_nD::Recup_Grandeurs_globales(..." <Affiche();ErrCalculFct_nD toto;throw (toto); Sortie(1); }; }; if (permet_affichage > 5) {cout << "\n " << nom_variables_globales(i) << " " << x_glob(index_glob); }; }; }; };