// 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 "Fonc_scal_combinees_nD.h"
#include "MotCle.h"
#include "TypeQuelconqueParticulier.h"
#include "CharUtil.h"



    // CONSTRUCTEURS :
Fonc_scal_combinees_nD::Fonc_scal_combinees_nD(string nom) :
 Fonction_nD(nom,FONC_SCAL_COMBINEES_ND)
 ,expression_fonction(),p(),tab_fVal()
 ,tab_fVal_int(),nom_variables_int()
 ,enu_variables_globale_int(),nom_variables_globales_int()
 ,Fi(),nom_fonctioni(),ident_interne()
 ,tab_fVal_Fi(),tab_ret_Fi(),tab_ret()
 ,indice_precedant(1)
  {};
    
    // de copie
Fonc_scal_combinees_nD::Fonc_scal_combinees_nD(const Fonc_scal_combinees_nD& Co) :
  Fonction_nD(Co)
  ,expression_fonction(Co.expression_fonction),p(),tab_fVal(Co.tab_fVal)
  ,tab_fVal_int(Co.tab_fVal_int),nom_variables_int(Co.nom_variables_int)
  ,enu_variables_globale_int(Co.enu_variables_globale_int)
  ,nom_variables_globales_int(Co.nom_variables_globales_int)
  ,indice_precedant(Co.indice_precedant)
  ,Fi(Co.Fi),nom_fonctioni(Co.nom_fonctioni)
  ,ident_interne(Co.ident_interne)
  ,tab_fVal_Fi(Co.tab_fVal_Fi),tab_ret_Fi(Co.tab_ret_Fi)
  ,tab_ret(Co.tab_ret)

  { // création des fonctions locales que si elles étaient déjà locales
    int tai = Fi.Taille();
    for (int i=1;i<= tai; i++)
      if (Co.Fi(i)->NomFonction() == "_")
         {Fi(i)=Fonction_nD::New_Fonction_nD(*(Co.Fi(i)));};
    // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs
    Fonction_nD::Construction_index_conteneurs_evoluees();
    //et on définie la fonction et les variables attachées
    Fonc_scal_combinees_nD::Init_fonction_analytique();
  };

    // de copie à partir d'une instance générale
Fonc_scal_combinees_nD::Fonc_scal_combinees_nD(const Fonction_nD& Coo) :
   Fonction_nD(Coo)
  ,expression_fonction(),p(),tab_fVal()

  { if (Coo.Type_Fonction() != FONC_SCAL_COMBINEES_ND)
      { cout << "\n erreur dans le constructeur de copie pour une fonction "
             << " FONC_SCAL_COMBINEES_ND "
             << " a partir d'une instance générale ";
        cout << "\n Fonc_scal_combinees_nD::Fonc_scal_combinees_nD(const Fonction_nD& Co) ";
        Sortie(1);
      };
    // définition des données
    Fonc_scal_combinees_nD & Co = (Fonc_scal_combinees_nD&) Coo;
    tab_fVal=Co.tab_fVal;
    tab_fVal_int=Co.tab_fVal_int;
    nom_variables_int=Co.nom_variables_int;
    enu_variables_globale_int = Co.enu_variables_globale_int;
    nom_variables_globales_int = Co.nom_variables_globales_int;
    expression_fonction = Co.expression_fonction;
   
    // fonctions internes
    indice_precedant=Co.indice_precedant;
    Fi=Co.Fi;
    nom_fonctioni = Co.nom_fonctioni;
    ident_interne = Co.ident_interne;
    int tai = Fi.Taille();
    // création des fonctions locales que si elles étaient déjà locales
    for (int i=1;i<= tai; i++)
      if (Co.Fi(i)->NomFonction() == "_")
         {Fi(i)=Fonction_nD::New_Fonction_nD(*(Co.Fi(i)));};
    // les tableaux
    tab_ret = Co.tab_ret;
    tab_fVal_Fi = Co.tab_fVal_Fi;
    tab_ret_Fi = Co.tab_ret_Fi;
    // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs
    Fonction_nD::Construction_index_conteneurs_evoluees();
    // arrivée ici on définie la fonction et les variables attachées
    Fonc_scal_combinees_nD::Init_fonction_analytique();
  };

    // DESTRUCTEUR :
Fonc_scal_combinees_nD::~Fonc_scal_combinees_nD()
  { // on efface les fonctions que si c'est des fonctions locales
    int tai = Fi.Taille();
    for (int i=1;i<= tai; i++)
      if ((Fi(i) != NULL)&&(nom_fonctioni(i)=="i_interne_i")) delete Fi(i);
  };
    
    // METHODES PUBLIQUES :
    
    // --------- virtuelles ---------

// Surcharge de l'operateur = : realise l'egalite de deux fonctions
Fonction_nD& Fonc_scal_combinees_nD::operator= (const Fonction_nD& elt)
{ // la suite ne peut fonctionner que s'il s'agit d'une fonction de même type
  if (typeFonction != elt.Type_Fonction())
   {cout << "\n *** erreur d'affectation entre fonction nD "
         << nom_ref << " et " << elt.NomFonction()
         << "\n Fonc_scal_combinees_nD::operator= (..."
         << endl;
    Sortie(1);
   };
  // on commence par appeler la méthode ad hoc pour la fonction Fonction_nD
  Fonction_nD::Transfert_info(elt);
  // puis on s'occupe des variables de la fonction
  const Fonc_scal_combinees_nD & Co = ((Fonc_scal_combinees_nD &) elt);
 
  tab_fVal=Co.tab_fVal;
  tab_fVal_int=Co.tab_fVal_int;
  nom_variables_int=Co.nom_variables_int;
  enu_variables_globale_int = Co.enu_variables_globale_int;
  nom_variables_globales_int = Co.nom_variables_globales_int;
  expression_fonction = Co.expression_fonction;

  // fonctions internes
  indice_precedant=Co.indice_precedant;
  Fi=Co.Fi;
  nom_fonctioni = Co.nom_fonctioni;
  ident_interne = Co.ident_interne;
  int tai = Fi.Taille();
  // création des fonctions locales que si elles étaient déjà locales
  for (int i=1;i<= tai; i++)
    if (Co.Fi(i)->NomFonction() == "_")
       {Fi(i)=Fonction_nD::New_Fonction_nD(*(Co.Fi(i)));};
  // les tableaux
  tab_ret = Co.tab_ret;
  tab_fVal_Fi = Co.tab_fVal_Fi;
  tab_ret_Fi = Co.tab_ret_Fi;
  // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs
  Fonction_nD::Construction_index_conteneurs_evoluees();
  // arrivée ici on définie la fonction et les variables attachées
  Fonc_scal_combinees_nD::Init_fonction_analytique();

  return *this;
};


    // affichage de la fonction
void Fonc_scal_combinees_nD::Affiche(int niveau) const
  { cout << "\n fonction composee : Fonc_scal_combinees_nD : nom_ref= " << nom_ref;
    int tai = Fi.Taille();
    // on parcours toutes les fonctions
    for (int i=1;i<= tai; i++)
      { // si c'est une fonction interne on l'affiche globalement
        // si c'est une fonction globale, on n'affiche que son nom
        cout << "\n fonction de base: " << i << " ";
        if (Fi(i) == NULL)
         { cout << "\n fonction interne ("<< i << "): "<< nom_fonctioni(i) <<", pas encore definie ";}
        else if(Fi(i)->NomFonction() == "_")  {Fi(i)->Affiche(niveau);}
        else  {cout << Fi(i)->NomFonction() << " ";};
      };
    // --- les variables en interne
    if (permet_affichage > 5)
     {cout << "\n variables en interne: nom fct int + variables de la fonction sans les variables globales ";
      {int nb = nom_variables_int.Taille();
       for (int i= 1;i<=nb;i++)
        cout << nom_variables_int(i) << " ";
      };
      // les énumérés globaux internes
      {int nb = enu_variables_globale_int.Taille();
       if (nb != 0)
        {cout << "  \n variables_globales_interne_en_enumere= " ;
         cout << "taille " << nb << "  ";
         for (int i=1;i<= nb;i++)
           cout << Nom_GrandeurGlobale(enu_variables_globale_int(i)) << " ";
        };
      };
      // idem en string
      {int nb = nom_variables_globales_int.Taille();
       if (nb != 0)
        {cout << "  \n variables_globales_interne_en_string= " ;
         cout << "taille " << nb << "  ";
         for (int i=1;i<= nb;i++)
           cout << nom_variables_globales_int(i) << " ";
        };
      };
     };
    // --- les variables dans l'ensemble
    cout << "\n -- vue d'ensemble des variables: --- "
         << " \n arguments= " << 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) << " ";
   
    cout << "\n taille vecteur de retour: "<< this->NbComposante()
         << "\n f(x)= " << expression_fonction
         << " ";
    // appel de la méthode associée de la classe virtuelle
    Affiche_interne(MaX(niveau,permet_affichage));
    if (niveau > 0)
     { cout << "\n derniers parametres d'appel: ";
       int nb_var = tab_fVal_int.Taille();
       for (int j=1;j<=nb_var;j++)
          { cout << " para("<<j<<")= "<< tab_fVal_int(j);}
       cout << "\n dernieres valeurs de retour de la fonction: ";
       cout << tab_ret ;
     };
    cout << "\n ----- fin affichage fonction Fonc_scal_combinees_nD ----- ";
  };

    // vérification que tout est ok, pres à l'emploi
    // ramène true si ok, false sinon
bool Fonc_scal_combinees_nD::Complet_Fonction(bool affichage)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 fonction
   int nb_fct = Fi.Taille();
   if (nb_fct == 0)
       ret = false;
   for (int i=1;i<=nb_fct;i++)
     {if (Fi(i) == NULL)
       ret = false; break;
     };
   if (!ret && (ParaGlob::NiveauImpression() >0)&& affichage)
      { cout << "\n ***** la fonction n'est pas complete (aucune fonction de base n'existe) ";
        this->Affiche();
      };
   return ret;
  } ;

   // Lecture des donnees de la classe sur fichier
    // le nom passé en paramètre est le nom de la fonction
    // s'il est vide c-a-d = "", la methode commence par lire le nom sinon
    // ce nom remplace le nom actuel
void Fonc_scal_combinees_nD::LectDonnParticulieres_Fonction_nD(const string& nom,UtilLecture * entreePrinc)
  { // entête de la fonction
    if (nom == "")  { *(entreePrinc->entree) >> nom_ref;}
    else {nom_ref=nom;};
    string nom_class_methode("Fonc_scal_combinees_nD::LectDonnParticulieres_Fonction_nD("); // variable interne pour les erreurs de lecture
   
    // 1) === on lit d'abord les fonctions utilisées comme variables inter
    entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
    // on lit les fonctions
    list < Fonction_nD* > li_Fi; // un liste intermédiaire pour faciliter la lecture
    list <string > li_nom_fonctioni;
    list <string > li_ident_interne;
    // maintenant lecture courante
    string nom_indicateur,identificateur;
    do
     { // tout d'abord lecture de la fonction de base
       string toto,nom_lu,nom_fonc;
       Fonction_nD*  F=NULL;
       *(entreePrinc->entree) >> nom_indicateur >> nom_lu; 
       // vérif
       if (nom_indicateur != "fct_base=" )
         { cout << "\n erreur en lecture du nom de la fonction  "
                << " on attendait la chaine: fct_base= et on a lue: " << nom_indicateur;
           entreePrinc->MessageBuffer("**erreur Fonc_scal_combinees_nD::LectureDonneesParticulieres**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);          
         };
       // on regarde si la fonction existe, si oui on récupère la référence
       if (Type_EnumFonction_nD_existe(nom_lu))
        // cas ou c'est un nom de type de fonction -> lecture directe
         {nom_fonc = "_"; // on signale que c'est une fonction interne
         
          // on lit l'identificateur interne
          string mot_cle("ident_interne_");
          if (!entreePrinc->Lecture_mot_cle_et_string(nom_class_methode,mot_cle,identificateur))
             { throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);
             };
//          entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne

          F = Fonction_nD::New_Fonction_nD(nom_fonc,Id_Nom_Fonction_nD (nom_lu.c_str()));
          // lecture de la fonction
          F->LectDonnParticulieres_Fonction_nD(nom_fonc,entreePrinc);
          nom_fonc="i_interne_i";
//          entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
         }
       else
        // sinon on retiend le nom pour une complétion future
        // et idem pour l'identificateur
         {nom_fonc = identificateur = nom_lu;};
        // stockage
       li_Fi.push_back(F); li_nom_fonctioni.push_back(nom_fonc);
       li_ident_interne.push_back(identificateur);
       // 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_fcts_interne_fonction_combinee_")==0)
          entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
     } while (strstr(entreePrinc->tablcar,"fin_fcts_interne_fonction_combinee_")==0);
    // on passe à la ligne suivante
    entreePrinc->NouvelleDonnee();  // lecture d'une nouvelle ligne
    // on met en tableau
    int tai = li_Fi.size();
    Fi.Change_taille(tai);
    nom_fonctioni.Change_taille(tai);
    ident_interne.Change_taille(tai);
    
    list < Fonction_nD* >::iterator ili,ilifin= li_Fi.end();
    list <string >::iterator sli= li_nom_fonctioni.begin();
    list <string >::iterator xli= li_ident_interne.begin();
    int ia=1;
    for (ili=li_Fi.begin();ili!=ilifin;ili++,sli++,ia++,xli++)
      {Fi(ia)=*ili;nom_fonctioni(ia)=*sli;
       ident_interne(ia)=*xli;
      };
   
    // 2) === on lit maintenant l'expression analytique de combinaison et les variables patentées
   
    expression_fonction = "aucune_expression"; // init pour le traitement d'erreur
    // on lit tant que l'on ne rencontre pas la ligne contenant "fin_parametres_fonction_combinee_"
    // ou un nouveau mot clé global auquel cas il y a pb !!
    MotCle motCle; // ref aux mots cle
    list < string> list_de_variables; // liste intermédiaire
    list <Enum_GrandeurGlobale >  list_enu_variables_glob;
    list < string> list_de_variables_nom_globales; // idem string glob
    string titi;
    while (strstr(entreePrinc->tablcar,"fin_parametres_fonction_combinee_")==0)
       {
        // si on a  un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur
        if ( motCle.SimotCle(entreePrinc->tablcar))
         { cout << "\n erreur de lecture des parametre de definition d'une fonction combinee : on n'a pas trouve le mot cle "
                << " fin_parametres_fonction_combinee_ et par contre la ligne courante contient un mot cle global  ";
           entreePrinc->MessageBuffer("** erreur des parametres d'une fonction expression litterale **");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
         };
         
        // lecture d'un mot clé
        *(entreePrinc->entree) >> titi;
        
        if ((entreePrinc->entree)->rdstate() == 0)
          {} // lecture normale
        #ifdef ENLINUX 
        else  if ((entreePrinc->entree)->fail())
                  // on a atteind la fin de la ligne et on appelle un nouvel enregistrement
                 {   // on lit sans tenir compte des < éventuelles
                     entreePrinc->NouvelleDonneeSansInf();
                     *(entreePrinc->entree) >>titi;
                 }
        #else
        else  if ((entreePrinc->entree)->eof())
                 // la lecture est bonne mais on a atteind la fin de la ligne
                 { if(titi != "fin_parametres_fonction_combinee_")
                     // on lit sans tenir compte des < éventuelles
                     {entreePrinc->NouvelleDonneeSansInf();
                      *(entreePrinc->entree) >> titi;
                     };
                 } 
        #endif
        else // cas d'une erreur de lecture
         { cout << "\n erreur de lecture inconnue  ";
           entreePrinc->MessageBuffer("** erreur2 des parametres d'une fonction combinee **");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
         };

        // on lit maintenant l'expression littérale
        if (titi == "fct=")
         { std::getline (*(entreePrinc->entree), expression_fonction);
         }
        // cas de la lecture d'une variable
        else if(titi == "un_argument=")
         {string truc; *(entreePrinc->entree) >> truc;
          // on regarde s'il s'agit d'une variable globale
          if (EstUneGrandeurGlobale(truc))
           { list_enu_variables_glob.push_back(Id_nom_GrandeurGlobale (truc));
           }
          // idem mais sous forme d'un string
          else if (ParaGlob::param->GrandeurGlobal(truc) != NULL)
           { list_de_variables_nom_globales.push_back(truc);}
          else // sinon ce n'est pas une grandeur globale
           {list_de_variables.push_back(truc);};
         }
        else if(titi == "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
           {string truc; *(entreePrinc->entree) >> truc;
            if (truc == "fin_list_var_")
                break;
            // on regarde s'il s'agit d'une variable globale
            if (EstUneGrandeurGlobale(truc))
             { list_enu_variables_glob.push_back(Id_nom_GrandeurGlobale (truc));}
            // idem mais sous forme d'un string
            else if (ParaGlob::param->GrandeurGlobal(truc) != NULL)
             { list_de_variables_nom_globales.push_back(truc);}
            else // sinon ce n'est pas une grandeur globale
             {list_de_variables.push_back(truc);};
            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 fonction combinee **");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);
           }
          else // sinon la lecture est ok a priori
            ;
         }
        // cas de la lecture du niveau d'impression pour les erreurs
        else if(titi == "permet_affichage_")
         {*(entreePrinc->entree) >> permet_affichage;
         }
        // cas de la lecture du type d'expression du tenseur
        else if(titi == "Tenseur_base_ad_hoc_")
          {*(entreePrinc->entree) >> absolue;
          }
        // sinon ce n'est pas un mot clé connu, on le signale
        else if(titi != "fin_parametres_fonction_combinee_")
         { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu "
                << " on a lu : " << titi << endl;
           entreePrinc->MessageBuffer("**Fonc_scal_combinees_nD::LectureDonneesParticulieres**");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);
         };
        
       }; //-- fin du while
   
    // on vérifie que l'on a bien lue une expression
    if (expression_fonction == "aucune_expression")
      {cout << "\n erreur en lecture de l'expression litterale de la fonction combinee , l'expression est absente "
            << " ou il y a une erreur de syntaxe ";
       entreePrinc->MessageBuffer("**Fonc_scal_combinees_nD::LectureDonneesParticulieres**");
       throw (UtilLecture::ErrNouvelleDonnee(-1));
       Sortie(1);
      };
   
    // on considère que l'utilisateur donne une liste d'arguments
    // qui sont dédiés uniquement à l'expression globale,
    // car les variables des fonctions internes sont définies
    // au moment de la définition (lecture) des lois internes
    // en lecture, il y a détection des variables globales
    //  celles-ci sont rangées dans le tableau enu_variables défini
    // dans Fonction_nD.h, et dans nom_variables_globales
    // ces tableaux contiendront à la fin, toutes les
    // variables globales c-a-d : celles propres et celles des fonctions membres
    // du coup: enu_variables_globale_int et nom_variables_globales_int
    // contiendront à la fin uniquement les variables globales de la fonction propre
    //
    // par contre au moment de l'appel de la fonction, toutes les variables
    // nécessaires sont stockés en entrée dans le tableau tab_fVal
    // NB: ne sont pas incluses les variables globales par ce qu'elles
    //    sont accessibles directement
    //
    // l'ordre des variables est le suivant
    // 1) les variables internes à chaque fonction membre, en suivant
    //    l'ordre d'apparition des fonctions
    // 2) les variables de la fonction globale
   
     //==== A) définition des éléments internes de l'appel interne
     //         de la fonction principale
   
     // on met en ordre de marche les variables globales patentées:
     //  tout d'abord on supprime les doublons
     list_enu_variables_glob.sort();
     list_enu_variables_glob.unique();
     list_de_variables_nom_globales.sort();
     list_de_variables_nom_globales.unique();
     //   on parcours les variables globales patentées
     int nb_enu = list_enu_variables_glob.size();
     int ienu=1;
     enu_variables_globale_int.Change_taille(nb_enu);
     // première def, avant de connaître les globaux des fonctions membres
     enu_variables_globale.Change_taille(nb_enu);
     {list <Enum_GrandeurGlobale >::iterator il,ilfin=list_enu_variables_glob.end();
      for (il=list_enu_variables_glob.begin();il!=ilfin;il++,ienu++)
         {enu_variables_globale_int(ienu) = *il;
          enu_variables_globale(ienu) = *il;
         };
     };
     // idem pour les noms de ref
     int nb_nom = list_de_variables_nom_globales.size();
     int i_nom=1;
     nom_variables_globales_int.Change_taille(nb_nom);
     // première def, avant de connaître les globaux des fonctions membres
     nom_variables_globales.Change_taille(nb_nom);
     {list <string >::iterator il,ilfin=list_de_variables_nom_globales.end();
      for (il=list_de_variables_nom_globales.begin();il!=ilfin;il++,i_nom++)
         {nom_variables_globales_int(i_nom) = *il;
          nom_variables_globales(i_nom) = *il;
         };
     };
   
     // on définie les variables internes à l'expression
     // a) les fonctions internes qui seront également utilisés
     //    comme variables intermédiaire
     int taille2 = ident_interne.Taille();
     // b) les variables déclarées comme tel
     int taille1 = list_de_variables.size(); // récup de la taille
     // c) les variables globales dont la taille est déjà connue
     //    c'est nb_enu
   
   
     // on met à jour les tailles
     nom_variables_int.Change_taille(taille1+taille2); // les noms
     tab_fVal_int.Change_taille(taille1+taille2+nb_enu+nb_nom);    // les valeurs en double
     // i) on parcours les fonctions de base
     int i= 1;
     for (int iFi = 1; iFi<= taille2;iFi++,i++)
       { // on utilise l'identificateur interne
         nom_variables_int(i)=ident_interne(iFi); // récup du nom
       };
     // ii) on parcours les variables patentées
     list < string>::iterator il,ilfin = list_de_variables.end();
     for (il = list_de_variables.begin();il != ilfin;il++,i++)
      { nom_variables_int(i)=(*il); // on récupère le nom
      };
//     // iii) on parcours les variables globales
//     for (int inunu = 1; inunu <= nb_enu; inunu++,i++)
//       { // on utilise l'identificateur interne
//         nom_variables_int(i)=Nom_GrandeurGlobale(enu_variables_globale(inunu)); // récup du nom
//       };
//     // idem pour les noms de variables globales indicées en string
//     for (int inom = 1; inom <= nb_nom; inom++,i++)
//        nom_variables_int(i)=nom_variables_globales(inom);
//
     // arrivée ici on définie la fonction
     Init_fonction_analytique();
   
     //==== B) définition des éléments externes à l'appel externe
     //        de la fonction globales
   
     // si toute les fonctions internes sont définies en internes
     // on peut mettre à jour les tableaux: tab_fVal et nom_variables
     // ainsi que tab_fVal_Fi
     // sinon il faut attendre l'appel de "Lien_entre_fonc_courbe"
     bool tous_interne = true;
     int tail = Fi.Taille();
     tab_fVal_Fi.Change_taille(tail);
     tab_ret_Fi.Change_taille(tail);
     for (int i = 1;i<=tail;i++)
       if (Fi(i) == NULL) {tous_interne = false; break;}
     if (!tous_interne)
       // il y a des fct externes, on met à 0 les tableaux au cas où
       {tab_fVal.Change_taille(0);nom_variables.Change_taille(0);}
     else // sinon on renseigne
       {int nb_var = 0; // init
        for (int i = 1;i<=tail;i++)
          nb_var += Fi(i)->Nom_variables().Taille();
        // puis les variables patentées
        nb_var += tab_fVal_int.Taille() - tail - nb_enu - nb_nom;
        // on dimensionne
        nom_variables.Change_taille(nb_var);
        tab_fVal.Change_taille(nb_var);
        int inom_variable = 1;
        // tout d'abord on s'occupe des variables des fonctions internes
        for (int i = 1;i<=tail;i++)
          {//nb_var += Fi(i)->NbVariable();
           const Tableau <string >& nom_var = Fi(i)->Nom_variables();
           int tail = nom_var.Taille();
           for (int i=1;i<= tail;i++,inom_variable++)
             {nom_variables(inom_variable)=nom_var(i);
             };
           // les tableaux de passage
           tab_fVal_Fi(i).Change_taille(tail);
           // les tableaux de retour de chaque fonction
           tab_ret_Fi(i).Change_taille(Fi(i)->NbComposante());
          };
        // puis on s'occupe des variables patentées
        // on parcours les variables patentées lues en entrées
        list < string>::iterator il,ilfin = list_de_variables.end();
        for (il = list_de_variables.begin();il != ilfin;il++,inom_variable++)
           nom_variables(inom_variable)=(*il); // on enregistre le nom
       };
     // arrivée ici si le niveau d'affichage le permet on affiche ce que l'on a lue
     if (permet_affichage > 8)
      {cout << "\n == >>> Fonc_scal_combinees_nD::LectDonnParticulieres_Fonction_nD: avant la construction des index ...";
       this->Affiche();
      };
       
//     //--- debug
//     {cout << "\n debug 1 Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne() ";
//      cout << "\n lecture fonction: " << nom_ref;
//      cout << "\n taille = "<<nom_variables_globales.Taille();
//      for (int j=1;j<= nom_variables_globales.Taille();j++)
//       cout << " variable ("<<j<<")= "<< nom_variables_globales(j) << flush;
////     Sortie(1);
//     };
//     //--- fin debug
     // on définit le paramètre depend_M de la classe maître en fonction des nom_variables
     Fonction_nD::Definition_depend_M();
     // idem pour le temps
     Fonction_nD::Definition_depend_temps();
     // idem pour la cohérence avec les enu
//     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();
     // affichage éventuel ce que l'on a lue
     if (permet_affichage > 8)
      {cout << "\n == >>> Fonc_scal_combinees_nD::LectDonnParticulieres_Fonction_nD: apres la construction des index ...";
       this->Affiche();
      };
//     //--- debug
//     {cout << "\n debug 2 Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne() ";
//      cout << "\n lecture fonction: " << nom_ref;
//      cout << "\n taille = "<<nom_variables_globales.Taille();
//      for (int j=1;j<= nom_variables_globales.Taille();j++)
//       cout << " variable ("<<j<<")= "<< nom_variables_globales(j) << flush;
////       Sortie(1);
//     };
//     //--- fin debug

  };
 
// mise à jour des variables globales: en fonction de l'apparition de nouvelles variables
// globales en cours de calcul
void Fonc_scal_combinees_nD::Mise_a_jour_variables_globales()
 { // --- on s'occupe des variables internes
   // on passe en revue les variables patentées et on regarde s'il s'agit de nouvelles variables globales
   int taille = nom_variables_int.Taille();
   list <string> li_variable; // liste de travail
   list <string> li_globale;  //   ""
   bool a_changer_int = false; // a priori rien ne change
   // maintenant on parcours les variables
   for (int i=1;i<=taille;i++)
    {if (ParaGlob::param->GrandeurGlobal(nom_variables_int(i)) != NULL)
      // il s'agit d'une variable globale
      {li_globale.push_back(nom_variables_int(i));
       a_changer_int=true;
      }
     else // sinon c'est toujours une variable
      li_variable.push_back(nom_variables_int(i));
    };
   // on met à jour les tableaux
   if (a_changer_int)
      {// -- pour les variables
       // on met à jour le tableau
       nom_variables_int.Init_from_list(li_variable);
       
       // -- pour les nom globaux
       // on ajoute les variables globales déjà existantes
       int taille_globale = nom_variables_globales_int.Taille();  // Init_from_list
       for (int j=1;j<= taille_globale;j++)
          li_globale.push_back(nom_variables_globales_int(j));
       // on ne garde qu'une version de chaque variable globale
       li_globale.sort();li_globale.unique();
       // on met à jour le tableau
       nom_variables_globales_int.Init_from_list(li_globale);
      };

   //  --- on renseigne les variables patentées de la fonction mère: Fonction_nD
   Fonc_scal_combinees_nD::Mise_a_jour_variables_nD();
   // appel de la fonction interne pour modifier les noms de variables
   bool a_changer = Fonction_nD::Mise_a_jour_variables_globales_interne();
   if (a_changer_int || a_changer)
      // maintenant il faut redéfinir l'ordre d'appel de la fonction
    { // si quelque chose à changé, l'ordre des variables dans l'appel de la fonction
      // interne a changé. Le choix qui est fait est de reconstruire la fonction interne
      // on ré-initialise la fonction analytique
      Init_fonction_analytique();
    };
 };

// 1) renseigne si la fonction dépend d'autre fonction ou non
bool Fonc_scal_combinees_nD::DependAutreFoncCourbes() const
 { bool ret=false;
   int tai = Fi.Taille();
   for (int i=1;i<=tai;i++)
    {if(Fi(i) == NULL) {ret=true;}
     else if (nom_fonctioni(i)!="i_interne_i") {ret=true;};
    };
   return ret;
  };
  
// 2) retourne une liste de nom correspondant aux noms de fonctions dont dépend *this
list <string>& Fonc_scal_combinees_nD::ListDependanceFonctions(list <string>& lico) const
 { // tout d'abord on vide la liste passée en paramètres
   if (lico.size() != 0)
      lico.clear();
   // 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_fonctioni(i));}
      else if (nom_fonctioni(i)!="i_interne_i")
       //ici la fonction est déjà définie mais cela n'empèche pas de donner la dépendance
       { lico.push_back(nom_fonctioni(i));};
     }
   return lico;
 };
   
// 3) établit la connection entre la demande de *this et les fonctions passées en paramètres
void Fonc_scal_combinees_nD::Lien_entre_fonc_courbe
        (list <Fonction_nD *>&  liptfonc,list <Courbe1D *>&  )
 { int tai = Fi.Taille();
   Tableau <Fonction_nD *> tab_Fi(tai); // def à null par défaut
   for (int i=1;i<=tai;i++)
     if(Fi(i) == NULL)  
     	{list <Fonction_nD *>::iterator ili,ilifin=liptfonc.end();
         for (ili=liptfonc.begin();ili!=ilifin;ili++)
           if ((*ili)->NomFonction() == nom_fonctioni(i))
             {tab_Fi(i)=(*ili);break;};
     	}
     else // sinon la fonction existe déjà, on met le pointeur à Null
      {
       #ifdef MISE_AU_POINT
        list <Fonction_nD *>::iterator ili,ilifin=liptfonc.end();
        for (ili=liptfonc.begin();ili!=ilifin;ili++)
           if (   ((*ili)->NomFonction() == nom_fonctioni(i))
               && (tab_Fi(i) != (*ili))
              )
             {cout << "\n *** erreur : la liaison entre la fonction externe "
                   << nom_ref << " d'expression: " << nom_fonctioni(i)
                   << " change de valeur "
                   << "\n Fonc_scal_combinees_nD::Lien_entre_fonc_courbe(... ";
              Sortie(1);
             };
       #endif
       tab_Fi(i)=NULL;
      };
       
   // et on définit les fonctions membres
   this->DefFonctionsMembres(tab_Fi);
  
   // l'ordre des variables peut avoir changé, on redéfinit les variables
   // pour la fonction analytique
   Init_fonction_analytique();
   
   // affichage éventuel ce que l'on a lue
   if (permet_affichage > 6)
    {cout << "\n == >>> Fonc_scal_combinees_nD::Lien_entre_fonc_courbe ";
     this->Affiche();
    };


   // on définit le paramètre depend_M de la classe maître en fonction des nom_variables
   Fonction_nD::Definition_depend_M();
   // idem pour le temps
   Fonction_nD::Definition_depend_temps();
   // Contruction des index pour les grandeurs évoluées, ainsi que les conteneurs
   Fonction_nD::Construction_index_conteneurs_evoluees();
  };
    
// def info fichier de commande
void Fonc_scal_combinees_nD::Info_commande_Fonctions_nD(UtilLecture & entreePrinc)
  {
     ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
	    cout << "\n cas de la fonction combinee Fonc_scal_combinees_nD : "
          << " \ndefinition standart (rep o) ou documentation exhaustive (rep n'importe quoi) ? ";
	    string rep = "_"; rep = lect_return_defaut(false,"o");
     sort << "\n# .......  fonction scalaire combinee ........";
     // cas particulier
     if ((rep == "o") || (rep == "O" ) || (rep == "0") )
       { sort
          << "\n#   exemple 3: def de choix_selon_energie_cinetique  :    "
          << "\n#     -> choix entre deux fonctions suivant la valeur de l'energie cinetique "
          << "\n#       "
          << "\n#      choix_selon_energie_cinetique  FONC_SCAL_COMBINEES_ND   "
          << "\n#         fct_base= F1 # fct 1 "
          << "\n#         fct_base= F2 # fct 2 "
          << "\n#       fin_fcts_interne_fonction_combinee_ "
          << "\n#           un_argument= ENERGIE_CINETIQUE    "
          << "\n#       fct=  (ENERGIE_CINETIQUE < 2) ? F1 : F2 "
          << "\n#      fin_parametres_fonction_combinee_ "
          << "\n#       "
          << "\n#  NB: ici les fonctions F1 et F2 doivent exister par ailleurs "
          << "\n#      les parametre  sont ceux de F1 + ceux de F2 + ENERGIE_CINETIQUE "
          << "\n#       qui est une grandeur globale"
          << "\n#      si ENERGIE_CINETIQUE < 2 alors F1 sinon F2 "
          << "\n#       ";
       }
     else // cas d'une description exhaustive
      { sort << "\n#............................................"
          << "\n#   Il s'agit d'une fonction qui peut combiner plusieurs fonctions de base"
          << "\n#   sous forme d'une expression analytique quelconque "
          << "\n#   "
          << "\n#   1) --- Tout d'abord on definit les fonctions de base "
          << "\n#   deux possibilites pour chaque fonction de base:  "
          << "\n#    a) soit la fonction existe deja, i.e. a deja ete definit par ailleurs"
          << "\n#    b) soit on veut definir une fonction interne a la fonction combinee"
          << "\n#   NB: dans le cas a) la fonction existante peut etre utilisee plusieurs fois"
          << "\n#       par exemple pour la definition de plusieurs fonctions combinees"
          << "\n#       dans le cas b) la fonction definie en interne n'est pas accessible en"
          << "\n#       en dehors de la fonction combinee qui est en cours de definition "
          << "\n#   -> syntaxe cas a) : "
          << "\n#   fct_base= nom_fonction_existante "
          << "\n#     ou  "
          << "\n#         fct_base= : le mot cle "
          << "\n#         nom_fonction_existante : le nom de la fonction"
          << "\n#   -> syntaxe cas b) : "
          << "\n#   fct_base= nom_type_fonction ident_interne_ nom_identificateur "
          << "\n#     ou  "
          << "\n#         fct_base= : le mot cle "
          << "\n#         nom_type_fonction : une chaine de caracteres donnant le type "
          << "\n#                             de la fonction que l'on veut definir "
          << "\n#         ident_interne_ : mot clé indique que c'est une fonction interne "
          << "\n#         nom_identificateur : le nom interne qu'on souhaite pour la fontion "
          << "\n#   "
          << "\n#   la liste des fonctions de base doit se terminer par le mot cle   "
          << "\n#    (sur une ligne seule ): "
          << "\n#      fin_fcts_interne_fonction_combinee_ "
          << "\n#   "
          << "\n#   2) --- on definit la liste de variables de la fonction globale  "
          << "\n#      cette liste inclu par defaut tout d'abord : "
          << "\n#     i) les variables internes de chaque fonction de base, dans l'ordre "
          << "\n#        ou les fonctions sont declarees. On n'a donc pas a les redeclarer. "
          << "\n#     ii) de nouvelles variables avec les 2 syntaxes suivantes "
          << "\n#       a) soit une variable par ligne selon la syntaxe: "
          << "\n#          un_argument= nom_argument"
          << "\n#          ou  "
          << "\n#            un_argument= : le mot cle "
          << "\n#            nom_argument : le nom de la variable "
          << "\n#       b) soit une liste de variables (sur une ligne) selon la syntaxe "
          << "\n#            deb_list_var_   nom1 nom2 ... fin_list_var_ "
          << "\n#         ou  "
          << "\n#         deb_list_var_ et fin_list_var_ : balises encadrant la liste"
          << "\n#         nom1 nom2 ... : le nom de chaque variable "
          << "\n#   "
          << "\n#     NB: les variables peuvent etre des grandeurs locales ou globales"
          << "\n#   "
          << "\n#   3) --- on definit l'expression de la fonction globale   "
          << "\n#       l'expression s'ecrit une une ligne (qui peut-etre fractionnee "
          << "\n#        via le caractere \ cf. doc). Elle doit commencer par le mot "
          << "\n#       cle fct= suivi d'une expression analytique quelconque (cf. doc "
          << "\n#       fonction analytique) "
          << "\n#       l'expression peut contenir : "
          << "\n#         les noms de variables, le nom des fonctions ou de leur "
          << "\n#       identificateur. "
          << "\n#       "
          << "\n#   La liste des variables (partie 2) et la definition de l'expression  "
          << "\n#   generale doit se terminer par le mot cle   (sur une ligne seule ): "
          << "\n#      fin_parametres_fonction_combinee_ "
          << "\n#   "
          << "\n#   exemple 1: def de la fonction addition_simple :    "
          << "\n#              somme de deux fonctions de base "
          << "\n#       "
          << "\n#      addition_simple  FONC_SCAL_COMBINEES_ND   "
          << "\n#         fct_base= montee # fct 1 "
          << "\n#         fct_base= relax # fct 2 "
          << "\n#       fin_fcts_interne_fonction_combinee_ "
          << "\n#       fct= montee + relax "
          << "\n#      fin_parametres_fonction_combinee_ "
          << "\n#       "
          << "\n#  NB: ici les fonctions montee et relax doivent exister par ailleurs "
          << "\n#      les parametre de addition_simple sont ceux de montee + ceux de "
          << "\n#       relax "
          << "\n#       "
          << "\n#   exemple 2: def de la fonction addition_pondere :    "
          << "\n#              somme ponderee de deux fonctions de base definies en interne"
          << "\n#       "
          << "\n#      addition_pondere  FONC_SCAL_COMBINEES_ND   "
          << "\n#         fct_base= FONCTION_EXPRESSION_LITTERALE_nD  ident_interne_ F1 "
          << "\n#           un_argument= x    "
          << "\n#           fct=  sin(x) "
          << "\n#          fin_parametres_fonction_expression_litterale_  "
          << "\n#         fct_base= FONCTION_EXPRESSION_LITTERALE_nD  ident_interne_ F2 "
          << "\n#           un_argument= y    "
          << "\n#           fct=  cos(y) "
          << "\n#          fin_parametres_fonction_expression_litterale_  "
          << "\n#       fin_fcts_interne_fonction_combinee_ "
          << "\n#       deb_list_var_   e ENERGIE_CINETIQUE fin_list_var_ "
          << "\n#       fct= (1.-e^2)*(ENERGIE_CINETIQUE-1.)*F1 + e^2*F2 "
          << "\n#      fin_parametres_fonction_combinee_ "
          << "\n#       "
          << "\n#  NB: . ici les fonctions de base F1(x) et F2(y) sont definies en interne "
          << "\n#      . les parametre de addition_pondere sont dans l'ordre: "
          << "\n#       x, y, e, ENERGIE_CINETIQUE  "
          << "\n#      . le parametre ENERGIE_CINETIQUE est une grandeur globale "
          << "\n#       "
          << "\n#   exemple 3: def de choix_selon_energie_cinetique  :    "
          << "\n#     -> choix entre deux fonctions suivant la valeur de l'energie cinetique "
          << "\n#       "
          << "\n#      choix_selon_energie_cinetique  FONC_SCAL_COMBINEES_ND   "
          << "\n#         fct_base= F1 # fct 1 "
          << "\n#         fct_base= F2 # fct 2 "
          << "\n#       fin_fcts_interne_fonction_combinee_ "
          << "\n#           un_argument= ENERGIE_CINETIQUE    "
          << "\n#       fct=  (ENERGIE_CINETIQUE < 2) ? F1 : F2 "
          << "\n#      fin_parametres_fonction_combinee_ "
          << "\n#       "
          << "\n#  NB: ici les fonctions F1 et F2 doivent exister par ailleurs "
          << "\n#      les parametre  sont ceux de F1 + ceux de F2 + ENERGIE_CINETIQUE"
          << "\n#      si ENERGIE_CINETIQUE < 2 alors F1 sinon F2 "
          << "\n#       "
          << "\n#       "
          << "\n#       "
          << "\n#  type d'expression des tenseurs:      "
          << "\n#  Tenseur_base_ad_hoc_ suivi de  "
          << "\n#     0 si dans la  base ad hoc   "
          << "\n#     1 si  dans une base globale     "
          << "\n#   NB: les deux sont en orthonorme    "
          << "\n#       par defaut, c'est dans une base ad hoc"
          << "\n#   ex:  Tenseur_base_ad_hoc_ 0   "
          << "\n#       "
          << "\n#       "
          << "\n#  niveau d'impression: dans certain cas il peut-etre utile d'afficher    "
          << "\n#   les resultats intermediaires des calculs et egalement des erreurs intermediaires    "
          << "\n#   pour mettre en route ce fonctionnement il faut indiquer sur une ligne seule le mot cle     "
          << "\n#   permet_affichage_ suivi d'un chiffre donnant le niveau d'impression (entre 0 et 10)    "
          << "\n# ex: permet_affichage_ 5  "
          << "\n#   Remarques: 1) ceci ne fonction qu'avec la version non fast    "
          << "\n#      cependant, la lecture reste correcte avec le mot cle permet_affichage_ "
           << "\n#     mais la presence du mot cle n'entraine aucune action en fast  "
         << "\n#   2) le mot cle doit etre indique avant le dernier mot cle :     "
          << "\n#      fin_parametres_fonction_combinee_ "
          << "\n#       "
          << endl;
      };
   };        

// calcul  des valeurs de la fonction, retour d'un tableau de scalaires
Tableau <double> & Fonc_scal_combinees_nD::Valeur_FnD_interne(Tableau <double >* xi)
 {
  try
  {// -- il s'agit ici d'un appel générique, qui est valable pour
   //     toute fonction combinée, pas forcément scalaire
   int tail = Fi.Taille();
   int i_in_xi=1; // indice pour se déplacer dans xi
//   int i_in_tab_coor=1;// indice pour se déplacer dans tab_coor
   int i_fval_int=1; // indice pour se déplacer dans fval_int
   int taille_xi=0; // init par défaut
//   int taille_tab_coor = 0; // init par défaut
//   int taille_totale_coor = 0; // idem
   if (xi != NULL)
     taille_xi=xi->Taille();
//   if (tab_coor != NULL)
//     taille_tab_coor = tab_coor->Taille();
//   // on considère que la dimension des coordonnées est c'est de la dimension totale
//   const int& dim = ParaGlob::Dimension();
//   taille_totale_coor = taille_tab_coor * dim;
//   int k_coor=1; // une variable pour se déplacer dans coor
  
   for (int i=1; i<= tail; i++,i_fval_int++)
    {Fonction_nD* fo = Fi(i); // récup de la fonction
     // on commence par remplir le tableau de passage de paramètres
     // il s'agit des variables patentées de la fonction
     int nb_var = fo->NbVariable_locale();
     Tableau <double>& fVal_Fi = tab_fVal_Fi(i);
     Tableau <double>& ret_Fi = tab_ret_Fi(i);
     for (int j=1;j<=nb_var;j++)
      {
       // on se déplace d'abord dans xi
       if (i_in_xi <= taille_xi)
        {fVal_Fi(j) = xi->operator()(i_in_xi);i_in_xi++;}
       else
        { cout << "\n *** pb de nombre d'argument non coherentes !! "
               << " on n'a pas assez d'arguments pour l'appel de la fonction inter: ";
          fo->Affiche(5);
          cout << "\n revoir la mise en donnees "
               << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."<<endl;
          // on génère une interruption ce qui permettra de dépiler les appels
          this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
        };
      };
     // récup des valeurs calculées
     ret_Fi = fo->Valeur_FnD_interne(&fVal_Fi);
     // -- partie spécifique à la fonction scalaire
     tab_fVal_int(i_fval_int) = ret_Fi(1); // retour scalaire a priori
     #ifdef MISE_AU_POINT
//     if (permet_affichage > 0)
      {double absret_Fi= Dabs( tab_fVal_int(i_fval_int));
       if ((!isfinite(absret_Fi)) || (isnan(absret_Fi)) )
        { cout << "\n probleme dans le retour d'une fonction interne nb: "<<i_fval_int
               << " on obtient: " << tab_fVal_int(i_fval_int);
          cout << "\n parametres d'appel: ";
          for (int j=1;j<=nb_var;j++)
           { cout << " para("<<j<<")= "<< fVal_Fi(j);}
          cout <<"\n fonction: ";
          fo->Affiche(5);
          cout << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(...";
          cout << endl;
//     ret_Fi = fo->Valeur_FnD_interne(&fVal_Fi);
          cout <<"\n >>> arbre d'appel : fonction this : ";
          // on génère une interruption ce qui permettra de dépiler les appels
          this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
        };
      };
     #endif
    };
  
   // on finit de remplir le tableau de passage pour la fonction maître

   // nb_var_int = les variables internes patentées, c-a-d hors variables globales
   int nb_var_int = nom_variables_int.Taille() - tail;

// a voir, mais je crois que la suite n'est pas une vrai vérif!
//   // petite vérif
//   #ifdef MISE_AU_POINT
//   if (tab_fVal_int.Taille() != (nb_var_int+tail_enu))
//  	  { cout << "\n *** pb de nombre d'argument non coherentes !! "
//            << " taille_xi+taille_totale_coor-nb_var_Fi= "<<nb_var_int
//            << ", est different de tab_fVal_int.Taille()-nb_var_glob "
//            << (tab_fVal_int.Taille()-tail_enu)
//  	         << "\n Fonc_scal_combinees_nD::Val_FnD_Evoluee(..."<<endl;
//  	    Sortie(1);
//  	  };
//   #endif
//  
  
   for (int ii = 1;ii<= nb_var_int;ii++,i_fval_int++)
    {
     // on se déplace d'abord dans xi
     if (i_in_xi <= taille_xi)
      {tab_fVal_int(i_fval_int) = xi->operator()(i_in_xi);i_in_xi++;}
//     // si xi est épuisé on regarde le tableau de coordonnée
//     else if (i_in_tab_coor <= taille_tab_coor)
//      {Coordonnee& A=tab_coor->operator()(i_in_tab_coor);
//       tab_fVal_int(i_fval_int) = A(k_coor);
//       // on gère les bornes
//       k_coor++;
//       if (k_coor>dim)
//        {i_in_tab_coor++;k_coor=1;};
//      }
     else
      { cout << "\n *** pb de nombre d'argument non coherentes !! "
             << " on n'a pas assez d'arguments pour l'appel de la fonction globale: ";
        cout << "\n revoir la mise en donnees "
             << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."<<endl;
        // on génère une interruption ce qui permettra de dépiler les appels
        this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
      };
    };

  
   // maintenant les variables globales éventuelles
   // on ne peut pas utiliser la fonction générique:
   // Fonction_nD::Recup_Grandeurs_globales();
   // car ici on fait la distinction entre toto_int et toto
   // toto pour enu_variable_globale et nom_variables_globales
   // à voir par la suite si on ne peut pas spécialiser ... mais ce n'est pas forcément
   //  un pb d'avoir une méthode spécifique


   int tail_enu = enu_variables_globale_int.Taille(); // les variables globales
   for (int i=1;i<= tail_enu;i++,i_fval_int++)
     {// on récupère le pointeur correspondant à la grandeur
      const void* pointe =  (ParaGlob::param->GrandeurGlobal(enu_variables_globale_int(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
                  tab_fVal_int(i_fval_int) = *(gr.ConteneurEntier());
                  break;
                 }
               case PARTICULIER_SCALAIRE_DOUBLE:
                 {Grandeur_scalaire_double& gr
                       = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
                  tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                  break;
                 }
                case PARTICULIER_SCALAIRE_DOUBLE_NOMMER_INDICER:
                  {Grandeur_Double_Nommer_indicer& gr
                        = *((Grandeur_Double_Nommer_indicer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                   tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                   break;
                  }
                case PARTICULIER_DDL_ETENDU:
                  {Grandeur_Ddl_etendu& gr
                     = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
                   tab_fVal_int(i_fval_int)  = (gr.GrandeurNumOrdre(1));
                   break;
                   }
                 default:
                 { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                        << " la variable globale_int  "<< Nom_GrandeurGlobale(enu_variables_globale_int(i))
                        << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                        << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."
                        <<endl;
                   // on génère une interruption ce qui permettra de dépiler les appels
                   this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
                  };
              }
           
            break;
           }
         default:
           { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                  << " la variable globale_int  "<< Nom_GrandeurGlobale(enu_variables_globale_int(i))
                  << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                  << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."
                  <<endl;
             // on génère une interruption ce qui permettra de dépiler les appels
             this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
           };
       };
     };
   // idem pour les variables globales indiçées par des strings
   int tail_nom = nom_variables_globales_int.Taille(); // idem avec des noms
   for (int i=1;i<= tail_nom;i++,i_fval_int++)
    {// on récupère le pointeur correspondant à la grandeur
     const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_variables_globales_int(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
                 tab_fVal_int(i_fval_int) = *(gr.ConteneurEntier());
                 break;
                }
              case PARTICULIER_SCALAIRE_DOUBLE:
                {Grandeur_scalaire_double& gr
                      = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
                 tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                 break;
                }
              case PARTICULIER_SCALAIRE_DOUBLE_NOMMER_INDICER:
                {Grandeur_Double_Nommer_indicer& gr
                      = *((Grandeur_Double_Nommer_indicer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                 tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                 break;
                }
              case PARTICULIER_DDL_ETENDU:
                {Grandeur_Ddl_etendu& gr
                      = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
                 tab_fVal_int(i_fval_int) = (gr.GrandeurNumOrdre(1));
                 break;
                }
              case PARTICULIER_VECTEUR_NOMMER:
                {Grandeur_Vecteur_Nommer& gr
                      = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                 tab_fVal_int(i_fval_int) = (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 "<< expression_fonction
                           << " la variable globale  "<< nom_variables_globales_int(i)
                                << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
                                << " compte pour l'intant, on ne peut pas continuer  "
                                << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."
                                <<endl;
                      // on génère une interruption ce qui permettra de dépiler les appels
                      this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
                    };
                 #endif
                 break;
                }
              default:
               { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                      << " la variable globale  "<< nom_variables_globales_int(i)
                      << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                      << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."
                      <<endl;
                 // on génère une interruption ce qui permettra de dépiler les appels
                 this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
               };
             }
         
            break;
          }
        case  TABLEAU_T:
          { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
             {case PARTICULIER_VECTEUR_NOMMER:
                {Grandeur_Vecteur_Nommer& gr
                      = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                 tab_fVal_int(i_fval_int) = (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 "<< expression_fonction
                           << " la variable globale  "<< nom_variables_globales_int(i)
                           << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
                           << " compte pour l'intant, on ne peut pas continuer  "
                           << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."
                           <<endl;
                      // on génère une interruption ce qui permettra de dépiler les appels
                      this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
                    };
                 #endif
                 break;
                }
              default:
               { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                      << " la variable globale  "<< nom_variables_globales_int(i)
                      << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                      << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."
                      <<endl;
                 // on génère une interruption ce qui permettra de dépiler les appels
                 this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
               };
             }
         
            break;
          }
        default:
          { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                 << " la variable globale  "<< nom_variables_globales_int(i)
                 << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                 << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(..."
                 <<endl;
            // on génère une interruption ce qui permettra de dépiler les appels
            this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
          };
      };
    };

      // appel de la fonction maître
      int nNum;
      double * v = p.Eval(nNum);
      for (int i=0; i<nNum; ++i)
        tab_ret(i+1) = v[i];
      #ifdef MISE_AU_POINT
//      if (permet_affichage > 0)
        {double absret_Fi= 0.;
         for (int i=0; i<nNum; ++i)
           absret_Fi += Dabs(tab_ret(i+1));
         if ((!isfinite(absret_Fi)) || (isnan(absret_Fi)) )
           { cout << "\n probleme dans le calcul de la fonction  "
                  << " on obtient en norme euclidienne: " << absret_Fi
                  << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(...";
             cout << "\n parametres d'appel: ";
             int nb_var = tab_fVal_int.Taille();
             for (int j=1;j<=nb_var;j++)
              { cout << " para("<<j<<")= "<< tab_fVal_int(j);}
             cout <<"\n >>> arbre d'appel : fonction this : ";
             this->Affiche(5);
             cout << endl;
//     p.Eval(nNum);
             // on génère une interruption ce qui permettra de dépiler les appels
             this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
           };
      };
     #endif
     }
    catch(mu::Parser::exception_type &e)
     { cout << "\n ** Fonc_scal_combinees_nD: erreur dans l'appel de la fonction "<< expression_fonction
            << " \n xi= "<< *xi;
       cout << "\n Message:  " << e.GetMsg() << "\n";
       cout << "Formula:  " << e.GetExpr() << "\n";
       cout << "Token:    " << e.GetToken() << "\n";
       cout << "Position: " << e.GetPos() << "\n";
       cout << "Errc:     " << e.GetCode() << "\n" << endl ;
       // on génère une interruption ce qui permettra de dépiler les appels
       this->Affiche(5);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 << " d'expression: " << expression_fonction
            << " \n xi= "<< *xi << "\n";
       this->Affiche(5);
       cout << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(...";
       // on génère une interruption ce qui permettra de dépiler les appels
       this->Affiche(5);ErrCalculFct_nD toto;throw (toto);
       Sortie(1);
     };

   // retour
  return tab_ret;
 };

// calcul des valeurs de la fonction, dans le cas où les variables
// sont toutes des grandeurs globales: pour l'instant que pour des variables scalaires
Tableau <double> & Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne()
  {
  // on récupère les grandeurs globales
  // on ne peut pas utiliser la fonction générique:
  // Fonction_nD::Recup_Grandeurs_globales();
  // car ici on fait la distinction entre toto_int et toto
  // toto pour enu_variable_globale et nom_variables_globales
  // à voir par la suite si on ne peut pas spécialiser ... mais ce n'est pas forcément
  //  un pb d'avoir une méthode spécifique
  
   // en debug on vérifie que les grandeurs globales sont présentent
    #ifdef MISE_AU_POINT
    try
     { // on vérifie tout d'abord que toutes les variables sont globales
       if (nom_variables.Taille() != 0)
        { cout << "\n ** erreur dans l'appel de la fonction "<< nom_ref;
          cout << " toutes les variables ne sont pas globales !!  "
               << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."<<endl;
          // on génère une interruption ce qui permettra de dépiler les appels
          this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
        };
       // maintenant on vérifie la présence des variables globales
       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 Fonc_scal_combinees_nD " << nom_ref << " !! "
                    << " la variable globale  "<< nom_variables(i)
                    << ", n'est pas disponible, on ne peut pas continuer  "
                    << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."<<endl;
               // on génère une interruption ce qui permettra de dépiler les appels
               this->Affiche(5);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 << " d'expression: " << expression_fonction;
       cout << " verifier la presence des grandeurs globales voulues "
            << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."<<endl;
       // on génère une interruption ce qui permettra de dépiler les appels
       this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
     };
    #endif

    // en debug on vérifie que les grandeurs globales sont présentent
    #ifdef MISE_AU_POINT
    try
     { int tail_nom = nom_variables_globales.Taille();
       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 Fonc_scal_combinees_nD " << nom_ref << " !! "
                    << " la variable globale  "<< nom_variables_globales(i)
                    << ", n'est pas disponible, on ne peut pas continuer  "
                    << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."<<endl;
////--- debug
//{cout << "\n debug Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne() ";
//cout << "\n taille = "<<nom_variables_globales.Taille();
//for (int j=1;j<= nom_variables_globales.Taille();j++)
//  cout << " variable ("<<j<<")= "<< nom_variables_globales(j) << flush;
//Sortie(1);
//};
////--- fin debug



               // on génère une interruption ce qui permettra de dépiler les appels
               this->Affiche(5);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 << " d'expression: " << expression_fonction;
       cout << " verifier la presence des grandeurs globales voulues "
            << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."<<endl;
       // on génère une interruption ce qui permettra de dépiler les appels
       this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
     };
    #endif

    // arrivée ici toutes les grandeurs existent
    try
     { // on va balayer les différentes fonctions internes
       // -- il s'agit ici d'un appel générique, qui est valable pour
       //     toute fonction combinée, pas forcément scalaire
       int tail = Fi.Taille();
       int i_fval_int=1; // indice pour se déplacer dans fval_int
       for (int i=1; i<= tail; i++,i_fval_int++)
        {Fonction_nD* fo = Fi(i); // récup de la fonction
         Tableau <double>& ret_Fi = tab_ret_Fi(i);
         // récup des valeurs calculées
         ret_Fi = fo->Valeur_pour_variables_globales_interne();
         // -- partie spécifique à la fonction scalaire
         tab_fVal_int(i_fval_int) = ret_Fi(1); // retour scalaire a priori
         #ifdef MISE_AU_POINT
         {double absret_Fi= Dabs( tab_fVal_int(i_fval_int));
          if ((!isfinite(absret_Fi)) || (isnan(absret_Fi)) )
           { cout << "\n probleme dans le retour d'une fonction interne nb: "<<i_fval_int
                  << " on obtient: " << tab_fVal_int(i_fval_int)
                  << " dans le cas d'un appel pour des variables globales uniquement ";
             cout <<"\n fonction: ";
             fo->Affiche(5);
             cout << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..";
             cout << endl;
             cout <<"\n >>> arbre d'appel : fonction this : ";
             // on génère une interruption ce qui permettra de dépiler les appels
             this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
           };
          };
         #endif
        };
  


       int tail_enu = enu_variables_globale_int.Taille(); // les variables globale_int
       // les variables globales int éventuelles
       for (int i=1;i<= tail_enu;i++,i_fval_int++)
         {// on récupère le pointeur correspondant à la grandeur
          const void* pointe =  (ParaGlob::param->GrandeurGlobal(enu_variables_globale_int(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
                      tab_fVal_int(i_fval_int) = *(gr.ConteneurEntier());
                      break;
                     }
                   case PARTICULIER_SCALAIRE_DOUBLE:
                     {Grandeur_scalaire_double& gr
                           = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                      break;
                     }
                   case PARTICULIER_SCALAIRE_DOUBLE_NOMMER_INDICER:
                     {Grandeur_Double_Nommer_indicer& gr
                           = *((Grandeur_Double_Nommer_indicer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                      break;
                     }
                   case PARTICULIER_DDL_ETENDU:
                     {Grandeur_Ddl_etendu& gr
                           = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = (gr.GrandeurNumOrdre(1));
                      break;
                     }

                   default:
                     { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                            << " la variable globale_int  "<< Nom_GrandeurGlobale(enu_variables_globale_int(i))
                            << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                            << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."
                            <<endl;
                       // on génère une interruption ce qui permettra de dépiler les appels
                       this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
                     };
                  }
               
                break;
               }
             default:
               { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                      << " la variable globale_int  "<< Nom_GrandeurGlobale(enu_variables_globale_int(i))
                      << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                      << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."
                      <<endl;
                 // on génère une interruption ce qui permettra de dépiler les appels
                 this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
               };
           };
         };
       // idem mais typées sous forme de string
       int tail_nom = nom_variables_globales_int.Taille();
       for (int i=1;i<= tail_nom;i++,i_fval_int++)
        {// on récupère le pointeur correspondant à la grandeur
         const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_variables_globales_int(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
                      tab_fVal_int(i_fval_int) = *(gr.ConteneurEntier());
                      break;
                     }
                   case PARTICULIER_SCALAIRE_DOUBLE:
                     {Grandeur_scalaire_double& gr
                           = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                      break;
                     }
                   case PARTICULIER_SCALAIRE_DOUBLE_NOMMER_INDICER:
                     {Grandeur_Double_Nommer_indicer& gr
                           = *((Grandeur_Double_Nommer_indicer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = *(gr.ConteneurDouble());
                      break;
                     }
                   case PARTICULIER_DDL_ETENDU:
                     {Grandeur_Ddl_etendu& gr
                           = *((Grandeur_Ddl_etendu*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = (gr.GrandeurNumOrdre(1));
                      break;
                     }
                   case PARTICULIER_VECTEUR_NOMMER:
                     {Grandeur_Vecteur_Nommer& gr
                           = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = (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 "<< expression_fonction
                                << " la variable globale  "<< nom_variables_globales_int(i)
                                << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
                                << " compte pour l'intant, on ne peut pas continuer  "
                                << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."
                                <<endl;
                           // on génère une interruption ce qui permettra de dépiler les appels
                           this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
                         };
                      #endif
                      break;
                     }
                   default:
                     { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                            << " la variable globale  "<< nom_variables_globales_int(i)
                            << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                            << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."
                            <<endl;
                       // on génère une interruption ce qui permettra de dépiler les appels
                       this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
                     };
                  }
               
                break;
               }
            case  TABLEAU_T:
               { switch(gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere())
                  {case PARTICULIER_VECTEUR_NOMMER:
                     {Grandeur_Vecteur_Nommer& gr
                           = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier
                      tab_fVal_int(i_fval_int) = (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 "<< expression_fonction
                                << " la variable globale  "<< nom_variables_globales_int(i)
                                << ", correspond a un vecteur a plusieur composantes, ce n'est pas pris en "
                                << " compte pour l'intant, on ne peut pas continuer  "
                                << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."
                                <<endl;
                           // on génère une interruption ce qui permettra de dépiler les appels
                           this->Affiche(5);ErrCalculFct_nD toto;throw (toto);
                           Sortie(1);
                         };
                      #endif
                      break;
                     }
                   default:
                     { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                            << " la variable globale  "<< nom_variables_globales_int(i)
                            << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                            << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."
                            <<endl;
                       // on génère une interruption ce qui permettra de dépiler les appels
                       this->Affiche(5);ErrCalculFct_nD toto;throw (toto);
                       Sortie(1);
                     };
                  }
               
                break;
               }
            default:
               { cout << "\n *** pb dans dans l'appel de la fonction "<< expression_fonction
                      << " la variable globale  "<< nom_variables_globales_int(i)
                      << ", n'est pas prise en compte actuellement , on ne peut pas continuer  "
                      << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(..."
                      <<endl;
                 // on génère une interruption ce qui permettra de dépiler les appels
                 this->Affiche(5);ErrCalculFct_nD toto;throw (toto);
                 Sortie(1);
               };
          };
        };

       if (permet_affichage > 5)
        {cout << "\n parametres d'appel: ";
         int nb_var = tab_fVal_int.Taille();
         for (int j=1;j<=nb_var;j++)
          { cout << " para("<<j<<")= "<< tab_fVal_int(j);}
        };
       // appel de la fonction maître
       int nNum;
       double * v = p.Eval(nNum);
       for (int i=0; i<nNum; ++i)
         tab_ret(i+1) = v[i];
       #ifdef MISE_AU_POINT
//      if (permet_affichage > 0)
        {double absret_Fi= 0.;
         for (int i=0; i<nNum; ++i)
           absret_Fi += Dabs(tab_ret(i+1));
         if ((!isfinite(absret_Fi)) || (isnan(absret_Fi)) )
           { cout << "\n probleme dans le calcul de la fonction  "
                  << " on obtient en norme euclidienne: " << absret_Fi
                  << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(...";
             cout << "\n parametres d'appel: ";
             int nb_var = tab_fVal_int.Taille();
             for (int j=1;j<=nb_var;j++)
              { cout << " para("<<j<<")= "<< tab_fVal_int(j);}
             cout <<"\n >>> arbre d'appel : fonction this : ";
             this->Affiche(5);
             cout << endl;
//     p.Eval(nNum);
             // on génère une interruption ce qui permettra de dépiler les appels
             this->Affiche(5);ErrCalculFct_nD toto;throw (toto);Sortie(1);
           };
      };
     #endif
      }
    catch(mu::Parser::exception_type &e)
     { cout << "\n ** erreur Fonc_scal_combinees_nD "
            << nom_ref << " d'expression: " << expression_fonction
            << "\n Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne(...";
       cout << "\n Message:  " << e.GetMsg() << "\n";
       cout << "Formula:  " << e.GetExpr() << "\n";
       cout << "Token:    " << e.GetToken() << "\n";
       cout << "Position: " << e.GetPos() << "\n";
       cout << "Errc:     " << e.GetCode() << "\n" << endl ;
       // on génère une interruption ce qui permettra de dépiler les appels
       this->Affiche(5);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 << " d'expression: " << expression_fonction;
       cout << "\n Fonc_scal_combinees_nD::Valeur_FnD_interne(...";
       // on génère une interruption ce qui permettra de dépiler les appels
       this->Affiche(5);ErrCalculFct_nD toto;throw (toto);
       Sortie(1);
     };
    return tab_ret;
  };
  
// 2) retourne une liste de nom correspondant aux noms de courbes dont dépend *this
list <string>& Fonc_scal_combinees_nD::ListDependanceCourbes(list <string>& lico) const
 { // tout d'abord on vide la liste passée en paramètres
   if (lico.size() != 0)
      lico.clear();
   return lico;
  };


	//----- 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 Fonc_scal_combinees_nD::Lecture_base_info(ifstream& ent,const int cas)
  { // on n'a que des grandeurs constantes
    if (cas == 1)
      { string nom;
        ent >> nom;  // "\n <Fonc_scal_combinees_nD> "
 //       string nom1=nom.substr(nom.find(<)+1,nom.find(>)-1);
        // lecture et vérification de l'entête
        string type_fonction_a_lire('<'+Nom_Fonction_nD(this->Type_Fonction())+'>');
        if (nom != type_fonction_a_lire) //"Fonc_scal_combinees_nD")
         { cout << "\n erreur dans la verification du type de fonction lue ";
           cout << "\n fonction en lecture: " << type_fonction_a_lire;
           cout << "\n Fonc_scal_combinees_nD::Lecture_base_info(... ";
           Sortie(1); 
         };
        // lecture du nom de référence
        ent >> nom >> nom_ref;
        // lecture du nombre de fonction
        int tai=0;
        ent >> nom >> tai;
        Fi.Change_taille(tai);
        nom_fonctioni.Change_taille(tai);
        // lecture des fonctions
        string nom1,nom2,nom3;
        for (int i=1;i<=tai;i++) 
        	{  // lecture de la fonction de base
        	   ent >> nom1 >> nom2 >> nom3;
               if (nom1 != "fonction=")
                { cout << "\n erreur dans la verification du type, on attendait le mot cle fonction= "
                       << " et on a lu " << nom1 << " ";
                  cout << "\n Fonc_scal_combinees_nD::Lecture_base_info(... ";
                  Sortie(1); 
                }
               else
                { if (nom2 == "FONCTION_INTERNE")
                   {// cas d'une fonction en interne
                    // 1) on commence par effacer la fonction existante si nécessaire
                    if (Fi(i) != NULL) {if (Fi(i)->NomFonction() == "_") delete Fi(i);};
                    // 2) on crée la fonction adoc
                    nom2="_";
                    Fi(i) = Fonction_nD::New_Fonction_nD(nom2,Id_Nom_Fonction_nD (nom3.c_str()));
                    // 3) on lit les données particulières
                    Fi(i)->Lecture_base_info(ent,cas);
                    nom_fonctioni(i)="i_interne_i";
                   }
                  else
                   {// cas d'une fonction externe on lit le nom
                    nom_fonctioni(i) = nom2;
                   };
                };    
        	};
        // lecture des variables
       
        // les arguments gérés par la classe mère
        Fonction_nD::Lect_base_info(ent,cas);

        // maintenant l'expression
        ent >> nom >> expression_fonction ;
       // on lit les variables internes de travail, que l'on pourrait sans doute
       // reconstruire mais c'est aussi simple de les sauvegarder et en lecture
        // de repartir d'une forme complète
        ent >> nom >>  nom_variables_int;
        // on met à jour la taille du tableau de passage de variables
        tab_fVal_int.Change_taille(nom_variables_int.Taille());
        // on lit le tag de fin de définition
        ent >> nom; //  "\n </Fonc_scal_combinees_nD> "
       
        // maintenant on initialise la fonction analytique
        Init_fonction_analytique();

        // on définit le paramètre depend_M de la classe maître en fonction des nom_variables
        Fonction_nD::Definition_depend_M();
        // idem pour le temps
        Fonction_nD::Definition_depend_temps();
        // idem pour la cohérence avec les enu
//        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();

      }
   };

    // cas donne le niveau de sauvegarde
    // = 1 : on sauvegarde tout
    // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Fonc_scal_combinees_nD::Ecriture_base_info(ofstream& sort,const int cas)
  {
    if (cas == 1)
     { sort << "\n <FONC_SCAL_COMBINEES_ND> "
            << "  nom_ref= " << nom_ref;
       int tai = Fi.Taille();
       sort << " nbfonction= " << tai << " "; // le nombre de fonctions
       // on parcours toutes les fonctions
       for (int i=1;i<= tai; i++)
         { // si c'est une fonction interne on l'affiche globalement
           // si c'est une fonction globale, on n'affiche que son nom
           sort << "\n fonction_de_base: " << i << " ";
           if (Fi(i)->NomFonction() == "_")
             {// cas d'une fonction interne
              sort << "\n fonction= FONCTION_INTERNE " << Fi(i)->Type_Fonction();
              Fi(i)->Ecriture_base_info(sort,cas);
             }
           else
            // cas d'une fonction externe
           {sort << "\n fonction= " <<  Fi(i)->NomFonction() << " " << Fi(i)->Type_Fonction();};
         };
       // les variables
       // les arguments gérés par la classe mère
       Fonction_nD::Ecrit_base_info(sort,cas);
       // retour des valeurs
       sort << "\n taille vecteur de retour: "<< this->NbComposante()
            << "\n f(x)= " << expression_fonction
            << " ";
       // on sort les variables internes de travail, que l'on pourrait sans doute
       // reconstruire mais c'est aussi simple de les sauvegarder et en lecture
       // de repartir d'une forme complète
       sort << "\n nom_variables_int= " << nom_variables_int;
       sort << "\n </FONC_SCAL_COMBINEES_ND> \n";
     };
  
   };
     
    // sortie du schemaXML: en fonction de enu 
void Fonc_scal_combinees_nD::SchemaXML_Fonctions_nD(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 fonction  -->"
  	         << "\n<xs:complexType name=\"F_UNION_1D\" >"
  	         << "\n    <xs:annotation>"
  	         << "\n      <xs:documentation> fonction 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;
		}
	};		
  };

  

// dans le cas où les fonctions membres sont des  fonctions externes
// fonction pour les définir
// les fonctions sont défini en interne que si les fonctions argument sont elles même
// des fonctions locales. c'est-à-dire si FFi(i)->NomFonction() ="_" alors on recrée une fonction
// 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 Fonc_scal_combinees_nD::DefFonctionsMembres(Tableau <Fonction_nD* >& FFi)
{  // l'objectif est 
   // 1) d'adapter le nombre de fonction à 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 fonctions existantes supérieur à taii
   if (taii < tai)
     for (int i=taii;i<= tai; i++)
         if ((Fi(i) != NULL)&&(nom_fonctioni(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 fonction locale que si elle était déjà locales
      if (FFi(i) != NULL)
       {if (FFi(i)->NomFonction() == "_") // cas où FFi(i) est une fonction non globale
           { if (Fi(i)==NULL)
               // cas où la fonction locale n'est pas défini mais on veut une fonction interne
               { Fi(i)=Fonction_nD::New_Fonction_nD(*(FFi(i)));nom_fonctioni(i)="i_interne_i";}
             else if (Fi(i)->NomFonction() == "_")
               // cas où la fonction F1 est local et on veut la remplacer par une nouvelle locale
               { delete Fi(i);
                 Fi(i)=Fonction_nD::New_Fonction_nD(*(FFi(i)));nom_fonctioni(i)="i_interne_i";
                }
             else
              // cas où la fonction Fi(i est global et on veut la remplacer par une locale
               { Fi(i)=Fonction_nD::New_Fonction_nD(*(FFi(i)));nom_fonctioni(i)="i_interne_i";};
           }
        else // cas ou FFi(i) est une fonction globale
           { if (Fi(i)==NULL)
                // cas où la fonction locale n'est pas défini
                { Fi(i)=FFi(i);nom_fonctioni(i)="e_externe_e";}
             else if (Fi(i)->NomFonction() == "_")
          // cas où la fonction Fi(i) est local et on veut la remplacer par une globale
                { delete Fi(i);
                  Fi(i)=FFi(i);nom_fonctioni(i)="e_externe_e";
                 }
             else
          // cas où la fonction Fi(i) est global et on veut la remplacer par une globale
                { Fi(i)=FFi(i);nom_fonctioni(i)="e_externe_e";};
           };
        // on met à jour les variables de la fonction
        Fi(i)->Mise_a_jour_variables_globales();
       };

    };
   //  --- on renseigne les variables de la fonction mère: Fonction_nD
   Fonc_scal_combinees_nD::Mise_a_jour_variables_nD();
};

// mise à jour des variables de la classe mère en fonction des fonctions membres
void Fonc_scal_combinees_nD::Mise_a_jour_variables_nD()
{  // l'opération suivante n'est possible que si les Fi sont non nulles
   int tail = Fi.Taille(); // les fonctions
   if (tail != 0)
    { if (Fi(1) != NULL)
       {//  --- on renseigne les variables de la fonction mère: Fonction_nD
        int nb_var = 0; // init
        // l'ordre de lequel la mise à jour est faite est important
        // il faut être sûr que les fonctions membres soient elles-mêmes
        // mise à jour (ce qui est peut-être le cas)
        // dans le doute (au risque de multiplier les mises à jour mais tant pi)
        // on force une mise à jour préventive
        for (int i = 1;i<=tail;i++)
          if (Fi(i) != NULL)
             Fi(i)->Mise_a_jour_variables_globales();
     
        for (int i = 1;i<=tail;i++)
          nb_var += Fi(i)->Nom_variables().Taille();
        // puis les variables patentées
        nb_var += nom_variables_int.Taille() - tail;
        // on dimensionne
        nom_variables.Change_taille(nb_var);
        tab_fVal.Change_taille(nb_var);
        int inom_variable = 1;
        for (int i = 1;i<=tail;i++)
          {//nb_var += Fi(i)->NbVariable();
           const Tableau <string >& nom_var = Fi(i)->Nom_variables();
           int tail = nom_var.Taille();
           for (int i=1;i<= tail;i++,inom_variable++)
             {nom_variables(inom_variable)=nom_var(i);
             };
           // les tableaux de passage
           tab_fVal_Fi(i).Change_taille(tail);
           // les tableaux de retour de chaque fonction
           tab_ret_Fi(i).Change_taille(Fi(i)->NbComposante());
          };
        // puis on s'occupe des variables patentées
        int ideb = ident_interne.Taille();
        int nb_var_patente = nom_variables_int.Taille() - tail;
        for (int i=1; i<= nb_var_patente;i++,inom_variable++)
          nom_variables(inom_variable)=nom_variables_int(ideb+i);
     
        // -- maintenant on s'occupe des grandeurs globales
        // pour les variables globales on ne garder qu'un
        // exemplaire de chacun
        list <Enum_GrandeurGlobale > li_enu_glob;
        list <string > li_nom_glob;
        for (int i = 1;i<=tail;i++)
          {// pour les énumérés
           const Tableau <Enum_GrandeurGlobale >& tab_enu = Fi(i)->Enu_variables_globales();
           int nb_enu = tab_enu.Taille();
           for (int ienu = 1; ienu <= nb_enu; ienu++)
             li_enu_glob.push_back(tab_enu(ienu));
           // pour les noms
           const Tableau <string >& tab_nom = Fi(i)->Nom_variables_globales();
           int nb_nom = tab_nom.Taille();
           for (int inom = 1; inom <= nb_nom; inom++)
             {li_nom_glob.push_back(tab_nom(inom));
//cout << "\n debug Fi("<<i<<"), tab_nom("<<inom<<")= "<< tab_nom(inom);
             }
          };
        // ensuite on ajoute les grandeurs globales internes
        int nb_enu = enu_variables_globale_int.Taille();
        for (int ienu = 1; ienu <= nb_enu; ienu++)
          li_enu_glob.push_back(enu_variables_globale_int(ienu));
        int nb_nom = nom_variables_globales_int.Taille();
        for (int inom = 1; inom <= nb_nom; inom++)
             li_nom_glob.push_back(nom_variables_globales_int(inom));
////--debug
//{int nb_nom_glob = li_nom_glob.size();
// list <string >::iterator il,ilfin=li_nom_glob.end();
// int i= 1;
// cout << "\n debug li_nom_glob 1: avant ordonner et supprimer doublon";
// for(il = li_nom_glob.begin(); il != ilfin; il++)
//  cout << "\n debug (*il)= " << (*il) ;
//};
//// -- fin debug
        // maintenant on va supprimer les doublons
        li_enu_glob.sort(); li_enu_glob.unique();
        li_nom_glob.sort(); li_nom_glob.unique();
////--debug
//{int nb_nom_glob = li_nom_glob.size();
// list <string >::iterator il,ilfin=li_nom_glob.end();
// int i= 1;
// cout << "\n debug li_nom_glob 2: liste finale";
// for(il = li_nom_glob.begin(); il != ilfin; il++)
//  cout << "\n debug (*il)= " << (*il) ;
//};
//// -- fin debug
        // maintenant on définit les tableaux
        {int nb_enu_glob = li_enu_glob.size();
         enu_variables_globale.Change_taille(nb_enu_glob);
         list <Enum_GrandeurGlobale >::iterator il,ilfin=li_enu_glob.end();
         int i= 1;
         for(il = li_enu_glob.begin(); il != ilfin; il++)
          enu_variables_globale(i) = (*il);
        };
        // et pour les noms
        {int nb_nom_glob = li_nom_glob.size();
         nom_variables_globales.Change_taille(nb_nom_glob);
         list <string >::iterator il,ilfin=li_nom_glob.end();
         int i= 1;
         for(il = li_nom_glob.begin(); il != ilfin; il++,i++)
          nom_variables_globales(i) = (*il);
        };
////--- debug
//{cout << "\n debug 3 Fonc_scal_combinees_nD::Valeur_pour_variables_globales_interne() ";
// cout << "\n lecture fonction: " << nom_ref;
// cout << "\n taille = "<<nom_variables_globales.Taille();
// for (int j=1;j<= nom_variables_globales.Taille();j++)
//  cout << " variable ("<<j<<")= "<< nom_variables_globales(j) << flush;
////    Sortie(1);
//};
////--- fin debug

     };
   };
};

 
// initialisation de la fonction analytique
void Fonc_scal_combinees_nD::Init_fonction_analytique()
 {
   try
    {
     // on supprime les variables existantes éventuelles
     p.ClearVar();
     // le nombre de variables pour l'appel de la fonction, ne change pas
     // donc la dimension de tab_fVal_int demeure identique
    
     // on parcours l'ensemble des variables internes
     int nb_var_int = nom_variables_int.Taille();
     int index_var = 1;
     for (int i = 1;i<= nb_var_int;i++,index_var++)
      { p.DefineVar(nom_variables_int(i), &tab_fVal_int(index_var)); // on définit la variable
      };
     // cas des variables globales locales
     int nb_enu = enu_variables_globale_int.Taille();
     for (int inunu = 1; inunu <= nb_enu; inunu++,index_var++)
       { // on utilise l'identificateur interne
         string nom_variables_global=Nom_GrandeurGlobale(enu_variables_globale_int(inunu)); // récup du nom
         p.DefineVar(nom_variables_global, &tab_fVal_int(index_var)); // on définit la variable
       };
     // idem pour les noms de variables globales locales
     int nb_nom = nom_variables_globales_int.Taille();
     for (int inom = 1; inom <= nb_nom; inom++,index_var++)
        p.DefineVar(nom_variables_globales_int(inom), &tab_fVal_int(index_var)); // on définit la variable
    
     // arrivée ici on définie la fonction
     p.SetExpr(expression_fonction);
     // dimensionne correctement le vecteur de retour
     // pour cela il faut faire au moins un appel
  
     int nNum;
     double * v = p.Eval(nNum);
     tab_ret.Change_taille(nNum);
    }
   catch(mu::Parser::exception_type &e)
    { cout << "\n ** erreur dans l'appel l'initialisation de la fonction "
           << nom_ref << " d'expression: " << expression_fonction
           << " \n xi= "<<tab_fVal_int;
      cout << "\n Message:  " << e.GetMsg() << "\n";
      cout << "Formula:  " << e.GetExpr() << "\n";
      cout << "Token:    " << e.GetToken() << "\n";
      cout << "Position: " << e.GetPos() << "\n";
      cout << "Errc:     " << e.GetCode() << "\n" << endl ;
      Sortie(1);
    };
 };














