// 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-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.


#include "AlgoriCombine.h"
#include "MatBand.h"
#include <cmath>

    //------- décomposition en 3 du calcul d'équilibre -------------
    // a priori   : InitAlgorithme  et FinCalcul ne s'appellent qu'une fois, 
    // par contre : CalEquilibre peut s'appeler plusieurs fois, le résultat sera différent si entre deux calcul
    //              certaines variables ont-été changés    


    // initialisation
void AlgoriCombine::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
               LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
               ,VariablesExporter* varExpor
               ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,
           Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts
           ,Resultats* resultats)
  { // INITIALISATION globale
    tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu
    Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info

  #ifdef UTILISATION_MPI
    // calcul de l'équilibrage initiale par le cpu 0
    if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
       {distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail,lesContacts);
        distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
        paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
                                ,distribution_CPU_algo.Tab_indique_CPU_en_cours()
                                ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours()
                                ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours());
       };
  #endif

    // on s'occupe des fonctions nD de pilotage
    // 1) cas de choix_algo
    if ((nom_choix_algo.length()) && (choix_algo == NULL))
     // cas où on doit récupérer la fonction nD
     {choix_algo = lesFonctionsnD->Trouve(nom_choix_algo);
       if (choix_algo->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
          {// on vérifie qu'en retour on a un 2 scalaires
           choix_algo->Valeur_pour_variables_globales(); // pour simplifier
           if (choix_algo->NbComposante() != 1)
              {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_choix_algo
                    << " qui permet de faire le choix de l'algo interne a utiliser "
                    << " ne retourne pas 1 scalaire  !! a priori ce n'est pas correct ";
               Sortie(1);
              };
           }
       else
         {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_choix_algo
               << " qui permet de faire le choix de l'algo interne a utiliser "
               << " utilise des variables autres que globales, ce n'est pas possible ! ";
          Sortie(1);
         };
     };
    // 2) cas de la validation et sauvegarde
    if ((nom_gestion_sauvegarde.length()) && (gestion_sauvegarde == NULL))
    // cas où on doit récupérer la fonction nD
     {gestion_sauvegarde = lesFonctionsnD->Trouve(nom_gestion_sauvegarde);
       if (gestion_sauvegarde->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
          {// on vérifie qu'en retour on a un scalaire
           gestion_sauvegarde->Valeur_pour_variables_globales(); // pour simplifier
           if (gestion_sauvegarde->NbComposante() != 1)
              {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sauvegarde
                    << " qui permet le pilotage de la sauvegarde "
                    << " ne retourne pas un scalaire unique !! a priori ce n'est pas correct ";
               Sortie(1);
              };
           }
       else
         {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sauvegarde
               << " qui permet le pilotage de la sauvegarde "
               << " utilise des variables autres que globales, ce n'est pas possible ! ";
          Sortie(1);
         };
     };
    // 3) gestion de la sortie à convergence de chaque algo
    if ((nom_gestion_sortie_a_convergence.length()) && (gestion_sortie_a_convergence == NULL))
    // cas où on doit récupérer la fonction nD
     {gestion_sortie_a_convergence = lesFonctionsnD->Trouve(nom_gestion_sortie_a_convergence);
       if (gestion_sortie_a_convergence->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
          {// on vérifie qu'en retour on a un scalaire
           gestion_sortie_a_convergence->Valeur_pour_variables_globales(); // pour simplifier
           if (gestion_sortie_a_convergence->NbComposante() != 1)
              {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sortie_a_convergence
                    << " qui permet de piloter la sortie a convergence de chaque algo "
                    << " ne retourne pas un scalaire unique !! a priori ce n'est pas correct ";
               Sortie(1);
              };
           }
       else
         {cout << "\n *** erreur parametre AlgoriCombine: la fonction nD " << nom_gestion_sortie_a_convergence
               << " qui permet de piloter la sortie a convergence de chaque algo  "
               << " utilise des variables autres que globales, ce n'est pas possible ! ";
          Sortie(1);
         };
     };
    
    // on passe en revue tous les algorithmes et on les initialise
    int nb_algo = tab_algo.Taille();
    for (int i=1;i<=nb_algo;i++)
     {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
    #ifdef UTILISATION_MPI
      // passage de l'équilibrage à ParaGlob
      paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
                              ,distribution_CPU_algo.Tab_indique_CPU_en_cours()
                              ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours()
                              ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours());
    #endif
      charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
      tab_algo(i)->InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
          ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts,resultats);
     };

   // on regarde s'il y a besoin de sauvegarde
   // explication: cela ce fait ici, car au niveau de chaque sous-algo, l'ouverture en écriture a été gelée
   // du fait que chaque sous algo n'est pas le maitre, ceci pour éviter une sucession d'ouverture écritures
   // mais il faut quand même finir par ouvrir en écriture si cela est demandé après toutes les lectures
   if (this->Active_sauvegarde())
    { // on récupère la position de restart lue par le dernier algo
      // récupération de la position lue par l'algo dans le .BI, changé lors d'un restart par exemple
      // il s'agit de la sauvegarde par l'algo de la position qu'il a lue en restart
      debut_increment =  tab_algo(nb_algo)->Debut_increment();
   
      //&& (ParaGlob::param->TypeCalcul_maitre() == this->typeCalcul) )
      // si le fichier base_info n'est pas en service on l'ouvre
      entreePrinc->Ouverture_base_info("ecriture");
      // dans le cas ou se n'est pas un restart on sauvegarde l'incrément actuel
      // c'est-à-dire le premier incrément
      // après s'être positionné au début du fichier
      if (this->Num_restart() == 0)
       { entreePrinc->Sort_BI_Positionnement_offset(entreePrinc->position_debut_fichier);
         int cas = 1;
         paraGlob->Ecriture_base_info(*(entreePrinc->Sort_BI()),cas);
         this->Ecriture_base_info
            (cas,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage
            ,charge,lesCondLim,lesContacts,resultats,OrdreVisu::INCRE_0);
        }
      else
       { // sinon on se place dans le fichier à la position du restart
         // debut_increment a été définit dans algori (classe mère)
         entreePrinc->Sort_BI_Positionnement_offset(debut_increment);
       };
    };

    tempsInitialisation.Arret_du_comptage(); // temps cpu
  };
    // mise à jour
void AlgoriCombine::MiseAJourAlgo(ParaGlob * paraGlob,LesMaillages * lesMail,
               LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
               ,VariablesExporter* varExpor
               ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,
           Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts
           ,Resultats* resultats)
  { // INITIALISATION globale 
    tempsMiseAjourAlgo.Mise_en_route_du_comptage(); // temps cpu
    Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info

    // on passe en revue tous les algorithmes et on demande leur mise à jour
    int nb_algo = tab_algo.Taille();
    for (int i=1;i<=nb_algo;i++)
      {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
     #ifdef UTILISATION_MPI
       // passage de l'équilibrage à ParaGlob
       paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
                               ,distribution_CPU_algo.Tab_indique_CPU_en_cours()
                               ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours()
                               ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours());
     #endif
       charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
       tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
          ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts,resultats);
      };

    tempsMiseAjourAlgo.Arret_du_comptage(); // temps cpu
  };

    // calcul
// si tb_combiner est non null -> un tableau de 3 fonctions
//  - la première fct dit si on doit valider ou non le calcul à convergence ok,
//  - la deuxième dit si on doit sortir de la boucle ou non à convergence ok
//  - la troisième sert d'indicateur: si == un pointeur nulle, cela signifie qu'au début du
//    sous - algo on part pour le calcul final des positions à t, sinon on part des position à tdt
//    ==> sert en I/O des sous-algo, chaque sous-algo disant au suivant s'il a valider ou pas
//    le paramètre est figé pour le premier algo
//
// si la validation est effectuée, la sauvegarde pour le post-traitement est également effectuée
//                                 en fonction de la demande de sauvegard,
// sinon pas de sauvegarde pour le post-traitement à moins que l'on a demandé un mode debug
//   qui lui fonctionne indépendamment
void AlgoriCombine::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
           ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
           ,VariablesExporter* varExpor
           ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage
           ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lescontacts
           ,Resultats* resultats,Tableau < Fonction_nD* > * )

   {
    tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
    Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info
  #ifdef UTILISATION_MPI
    int proc_en_cours = ParaGlob::Monde()->rank();
  #endif

    int nb_algo = tab_algo.Taille();
    Tableau < Fonction_nD* > * tb_combiner = new Tableau < Fonction_nD* >;
    tb_combiner->Change_taille(3,NULL); // init par défaut
    
    // --- mise à jour du numéro de chargement des algos
    // le numéro de chargement est initialement déterminé par le premier algo
    icharge = tab_algo(1)->Num_increment();
    for (int i=1;i<=nb_algo;i++)
      tab_algo(i)->Affectation_icharge(icharge);
    // concernant la troisième fonction qui gère le départ de chaque sous-algo
    // à partir de X_t ou pas, 
    (*tb_combiner)(3)=NULL;  // on part de la position X_t
        // ensuite ce sont les sous-algos qui modifient  le paramètre
        // en fonction du fait qu'il valide ou pas le calcul
        
    // on boucle sur les incréments de charge
    bool affichage = true; // affichage a priori de la fin des calculs
    while (   (!charge->Fin(icharge,affichage))
               && (charge->Fin(icharge,true)!=2) // si on a dépassé le nombre d'incrément permis on s'arrête dans tous les cas
               && (charge->Fin(icharge,false)!=3) // idem si on a dépassé le nombre d'essai d'incrément permis
                                                   // 1er appel avec true: pour affichage et second avec false car c'est déjà affiché
               && (!pa.EtatSortieEquilibreGlobal())
             )
        {
        
         // l'appel des algos s'effectuent soit successivement si aucune info particulière
         // soit en fonction du retour de la fonction choix
         if (choix_algo == NULL)
          {// cas où on passe les algos successivement dans l'ordre de leurs définitions

           for (int i=1;i<=nb_algo;i++)
             {// avant tout chose, on met à jour
//              //------ debug
//              cout << "\n ********* debug calequilibre Combiner: "
//                   << "     tab_algo(1)->pa.Deltat()= " << tab_algo(1)->pa.Deltat()
//                   << "\n     tab_algo(2)->pa.Deltat()= " << tab_algo(2)->pa.Deltat()
//                   << "\n     tab_algo(3)->pa.Deltat()= " << tab_algo(3)->pa.Deltat() << flush;
//              //--- fin debug
              ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
            #ifdef UTILISATION_MPI
              // passage de l'équilibrage à ParaGlob
              paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
                                      ,distribution_CPU_algo.Tab_indique_CPU_en_cours()
                                      ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours()
                                      ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours());
            #endif

              charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
              bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier
              if (aff_incr)
                 cout << "\n---------------------------------------------------------------------"
                      << "\n >>>> algorithme ("<< i <<"): "
                      << Nom_TypeCalcul(tab_algo(i)->TypeDeCalcul())
            #ifdef UTILISATION_MPI
                      << " (proc "<< proc_en_cours<< ") "
            #endif
                      << "  >>>> "
                      << "\n---------------------------------------------------------------------\n"
                      << flush;
              tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
                                        ,lesLoisDeComp,diversStockage,charge,lesCondLim
                                        ,lescontacts,resultats
                                        );
              // on met à jour tb_combiner
              if (gestion_sortie_a_convergence != NULL)
               {(*tb_combiner)(2)=gestion_sortie_a_convergence;}
              else // sinon par défaut
               {(*tb_combiner)(2)=cst_1; // sortie de boucle à la convergence propre à l'algo
               };
              if (gestion_sauvegarde != NULL)
               {(*tb_combiner)(1)=gestion_sauvegarde;}
              else // sinon c'est le dernier algo qui sauvegarde par défaut
               {if (i != nb_algo)
                 {(*tb_combiner)(1)=cst_0;}// pas de validation
                else // pour le dernier algo
                 {(*tb_combiner)(1)=cst_1;}; // validation
               };


//              //------ debug
//              cout << "\n ********* debug calequilibre Combiner: "
//                   << "     tab_algo(1)->pa.Deltat()= " << tab_algo(1)->pa.Deltat()
//                   << "\n     tab_algo(2)->pa.Deltat()= " << tab_algo(2)->pa.Deltat()
//                   << "\n     tab_algo(3)->pa.Deltat()= " << tab_algo(3)->pa.Deltat() << flush;
//              //--- fin debug
              // puis on calcul l'équilibre
              tab_algo(i)->CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
                 ,lesLoisDeComp,diversStockage,charge,lesCondLim,lescontacts,resultats
                 ,tb_combiner);
//              //------ debug
//              cout << "\n ********* debug calequilibre Combiner: apres tab_algo(i)->CalEquilibre "
//                   << "     tab_algo(1)->pa.Deltat()= " << tab_algo(1)->pa.Deltat()
//                   << "\n     tab_algo(2)->pa.Deltat()= " << tab_algo(2)->pa.Deltat()
//                   << "\n     tab_algo(3)->pa.Deltat()= " << tab_algo(3)->pa.Deltat() << flush;
//              //--- fin debug
              // s'il y a une fctnD de sauvegarde on garde le numéro du dernier sous-algo qui a sauvegardé
              // car c'est le seul important pour la sauvegarde
              if (gestion_sauvegarde != NULL)
               {if ((bool) gestion_sauvegarde->Valeur_pour_variables_globales()(1))
                  {nb_dernier_algo_qui_a_fait_une_sauvegarde = i;};
               }
              else // sinon c'est le dernier par défaut qui sauvegarde
               {nb_dernier_algo_qui_a_fait_une_sauvegarde = nb_algo; };
             };
           // récup du numéro de chargement
           icharge = tab_algo(nb_algo)->Num_increment(); // c'est le dernier qui sauvegarde
           
          }
         else // sinon il existe une fonction de choix, on s'en sert
          { bool sans_changement_increment = true;
            do
             {int i = choix_algo->Valeur_pour_variables_globales()(1);
              if ((i >0)&&(i <= nb_algo))
               {// on met à jour
                ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
              #ifdef UTILISATION_MPI
                // passage de l'équilibrage à ParaGlob
                paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
                                        ,distribution_CPU_algo.Tab_indique_CPU_en_cours()
                                        ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours()
                                        ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours());
              #endif

                charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
                bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier
                if (aff_incr)
                   cout << "\n---------------------------------------------------------------------"
                        << "\n >>>> algorithme ("<< i <<"): "
                        << Nom_TypeCalcul(tab_algo(i)->TypeDeCalcul())
              #ifdef UTILISATION_MPI
                        << " (proc "<< proc_en_cours<< ") "
              #endif
                        << "  >>>> "
                        << "\n---------------------------------------------------------------------\n"
                        << flush;
                tab_algo(i)->MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
                                          ,lesLoisDeComp,diversStockage,charge,lesCondLim
                                          ,lescontacts,resultats
                                          );
                // on met à jour tb_combiner
                if (gestion_sortie_a_convergence != NULL)
                 {(*tb_combiner)(2)=gestion_sortie_a_convergence;}
                else // sinon par défaut
                 {(*tb_combiner)(2)=cst_1; // sortie de boucle à la convergence propre à l'algo
                 };
                if (gestion_sauvegarde != NULL)
                 {(*tb_combiner)(1)=gestion_sauvegarde;}
                else // sinon c'est le dernier algo qui sauvegarde par défaut
                 {if (i != nb_algo)
                   {(*tb_combiner)(1)=cst_0;}// pas de validation
                  else // pour le dernier algo
                   {(*tb_combiner)(1)=cst_1;}; // validation
                 };
                // puis on calcul l'équilibre
                tab_algo(i)->CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
                   ,lesLoisDeComp,diversStockage,charge,lesCondLim,lescontacts,resultats
                   ,tb_combiner);
                // récup du numéro de chargement
                icharge = tab_algo(i)->Num_increment();
             }
            else
             {cout << "\n erreur** la fonction de choix d'algo indique l'algo num: "<< i
                   << " qui n'a pas ete defini !! on ne peut pas continuer "
                   << "\n AlgoriCombine::CalEquilibre(..."<<flush;
              Sortie(1);
             };
            // on regarde s'il était demandé une validation
            sans_changement_increment = !((bool) gestion_sauvegarde->Valeur_pour_variables_globales()(1));
            // si on a sauvegardé on va sortir de la boucle, on sauvegarde le num d'algo
            if (!sans_changement_increment)
              nb_dernier_algo_qui_a_fait_une_sauvegarde = i;
            } while (sans_changement_increment);
          };
         // --- mise à jour du numéro de chargement pour tous les algos
         for (int i=1;i<=nb_algo;i++)
           tab_algo(i)->Affectation_icharge(icharge);
        }; // fin du while


    tempsCalEquilibre.Arret_du_comptage(); // temps cpu
  };

// dernière passe                  
void AlgoriCombine::FinCalcul(ParaGlob * paraGlob,LesMaillages * lesMail,LesReferences* lesRef
           ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
           ,VariablesExporter* varExpor
           ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,
           Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats)
 {
    // fin des calculs
    Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(COMBINER); // transfert info
//    // on passe en revue tous les algorithmes et on demande la fin des calculs
    // non, sinon on a plusieurs dernières sauvegardes !!
    // donc on ne sauvegarde la fin que via le dernier sous_algo qui a sauvegardé
//    int nb_algo = tab_algo.Taille();
//    for (int i=1;i<=nb_algo;i++)
    int i=nb_dernier_algo_qui_a_fait_une_sauvegarde;
     {ParaGlob::param->Change_ParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
    #ifdef UTILISATION_MPI
      // passage de l'équilibrage à ParaGlob
      paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
                              ,distribution_CPU_algo.Tab_indique_CPU_en_cours()
                              ,distribution_CPU_algo.Tableau_noeud_CPU_en_cours()
                              ,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours());
    #endif

      charge->ChangeParaAlgoControle(tab_algo(i)->ParaAlgoControle_de_lalgo());
      tab_algo(i)->FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor
          ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts,resultats);
     };

 };

   
       //---- gestion des commndes interactives --------------
    // écoute et prise en compte d'une commande interactive
    // ramène true tant qu'il y a des commandes en cours
bool AlgoriCombine::ActionInteractiveAlgo()
	{ cout << "\n commande? ";
	  return false;
	};
	
    // sortie du schemaXML: en fonction de enu
void AlgoriCombine::SchemaXML_Algori(ofstream& sort,const Enum_IO_XML enu) const
  {
	switch (enu)
	{ case XML_TYPE_GLOBAUX :
  	   {
		 break;
		}
		case XML_IO_POINT_INFO :
		{
		 break;
		}
		case XML_IO_POINT_BI :
		{
		 break;
		}
		case XML_IO_ELEMENT_FINI :
		{
		 break;
		}
		case XML_ACTION_INTERACTIVE :
  	   {sort << "\n <!--  ********** algorithme implicite non dynamique ********************  -->"
  	         << "\n<xs:complexType name=\"INIT\" >"
  	         << "\n    <xs:annotation>"
  	         << "\n      <xs:documentation> initialisation de l'algo "
  	         << "\n      </xs:documentation>"
  	         << "\n    </xs:annotation>"
  	         << "\n</xs:complexType>";
  	    sort << "\n<xs:complexType name=\"EXECUTION\" >"
  	         << "\n    <xs:annotation>"
  	         << "\n      <xs:documentation> execution de l'ensemble de l'algo, sans l'initialisation et la derniere passe "
  	         << "\n      </xs:documentation>"
  	         << "\n    </xs:annotation>"
  	         << "\n</xs:complexType>";
  	    sort << "\n<xs:complexType name=\"FIN_ALGO_EXPLI\" >"
  	         << "\n    <xs:annotation>"
  	         << "\n      <xs:documentation>  fin de l'algo "
  	         << "\n      </xs:documentation>"
  	         << "\n    </xs:annotation>"
  	         << "\n</xs:complexType>";
		 break;
		}
		case XML_STRUCTURE_DONNEE :
		{
		 break;
		}
	};		
  };
	
