// 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 "AlgoBonelli.h"

// CONSTRUCTEURS :
AlgoBonelli::AlgoBonelli () : // par defaut
   Algori()

 { // message d'erreur
   cout << "\n constructeur par defaut de AlgoBonelli, ne doit pas etre utilise !!";
   Sortie(1);};     
     
// constructeur en fonction du type de calcul et du sous type
// il y a ici lecture des parametres attaches au type
AlgoBonelli::AlgoBonelli (const bool avec_typeDeCal
            ,const list <EnumSousTypeCalcul>& soustype
            ,const list <bool>& avec_soustypeDeCal
            ,UtilLecture& entreePrinc) :
         Algori(DYNA_EXP_BONELLI,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
         ,delta_t(0.),unsurdeltat(0.),deltatSurDeux(0.),deltat2(0.)
         ,delta_t_total(0.),unsurdeltat_total(0.),deltatSurDeux_total(0.),deltat2_total(0.)
         ,q_0(),p_0(),q_1(),p_1(),q_2(),p_2() // les vecteurs ddl globaux
         ,a_a(0.),b_b(0.322),k_max(2),omega_b(2.171),rho_b(0.6)
         ,pt_seg_temps(NULL),nb_pt_int_t(3)
         ,pPoint_i(),P_i_1(),P_i_2(),P_q1_k(),P_q2_k(),r_1_k(),r_2_k()
         ,vec_travail1(),vec_travail2(),dernier_phi()

         ,maxPuissExt(0.),maxPuissInt(0.),maxReaction(0.),inReaction(0),inSol(0.),maxDeltaDdl(0.)
         ,cas_combi_ddl(0),icas(),erreurSecondMembre(false),prepa_avec_remont(false)
         ,brestart(false),type_incre(OrdreVisu::PREMIER_INCRE)
         ,lesMail_(NULL),lesRef_(NULL),lesCourbes1D_(NULL),lesFonctionsnD_(NULL),charge_(NULL)
         ,lesCondLim_(NULL),lesContacts_(NULL),Ass1(NULL),Ass2(NULL),Ass3(NULL)
         ,vglobin(),vglobex(),vglobaal(),vcontact()
         ,vitesse_tplus()
         ,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
         ,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_masse_sauve(NULL),mat_C_pt(NULL)

  { a_a =1./3. - b_b ; // init par défaut de a_a
    // pt_seg_temps est défini dans lecture_Parametres
    // lecture des paramètres attachés au type de calcul 
    switch (entreePrinc.Lec_ent_info())
      { case 0 :
          {lecture_Parametres(entreePrinc); break;}
        case -11 : // cas de la création d'un fichier de commande
         { Info_commande_parametres(entreePrinc); break;}
        case -12 : // cas de la création d'un schéma XML, on ne fait rien à ce niveau
         {  break;}
        default:
          Sortie(1); 
      };
   };
      
// constructeur de copie
AlgoBonelli::AlgoBonelli (const AlgoBonelli& algo):
  Algori(algo)
  ,delta_t(0.),unsurdeltat(0.),deltatSurDeux(0.),deltat2(0.)
  ,delta_t_total(0.),unsurdeltat_total(0.),deltatSurDeux_total(0.),deltat2_total(0.)
  ,q_0(algo.q_0),p_0(algo.p_0),q_1(algo.q_1),p_1(algo.p_1),q_2(algo.q_2),p_2(algo.p_2)
  ,a_a(algo.a_a),b_b(algo.b_b),k_max(algo.k_max),omega_b(algo.omega_b)
  ,pt_seg_temps(NULL),nb_pt_int_t(algo.nb_pt_int_t)
  ,pPoint_i(algo.pPoint_i),P_i_1(algo.P_i_1),P_i_2(algo.P_i_2)
  ,P_q1_k(algo.P_q1_k),P_q2_k(algo.P_q2_k),r_1_k(algo.r_1_k),r_2_k(algo.r_2_k)
  ,vec_travail1(algo.vec_travail1),vec_travail2(algo.vec_travail2),dernier_phi(algo.dernier_phi)
  
  ,maxPuissExt(0.),maxPuissInt(0.),maxReaction(0.),inReaction(0),inSol(0.),maxDeltaDdl(0.)
  ,cas_combi_ddl(0),icas(0),erreurSecondMembre(false)  
  ,prepa_avec_remont(false)
  ,brestart(false),type_incre(OrdreVisu::PREMIER_INCRE)
  ,lesMail_(NULL),lesRef_(NULL),lesCourbes1D_(NULL),lesFonctionsnD_(NULL),charge_(NULL)
  ,lesCondLim_(NULL),lesContacts_(NULL),Ass1(algo.Ass1),Ass2(algo.Ass2),Ass3(algo.Ass3)
  ,vglobin(),vglobex(),vglobaal(),vcontact()
  ,vitesse_tplus()
  ,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
  ,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_masse_sauve(NULL),mat_C_pt(NULL)

    {pt_seg_temps = new GeomSeg(*(algo.pt_seg_temps)); 
     //vglobal = &vglobin;
     };
   
// destructeur
AlgoBonelli::~AlgoBonelli ()
  { if (pt_seg_temps != NULL) delete pt_seg_temps;
    delete mat_masse; delete mat_masse_sauve;delete mat_C_pt;
   }; 

// execution de l'algorithme dans le cas dynamique explicite, sans contact
void AlgoBonelli::Execution(ParaGlob * paraGlob,LesMaillages * lesMail
               ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
               ,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock
               ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats)
  { Tableau < Fonction_nD* > * tb_combiner = NULL; // ici ne sert pas
  #ifdef UTILISATION_MPI
    int proc_en_cours = ParaGlob::Monde()->rank();
  #endif
    // on définit le type de  calcul a effectuer :
    if ( soustypeDeCalcul->size()==0 )
      // cas où il n'y a pas de sous type, on fait le calcul d'équilibre classique
      // signifie que le type principal est forcément valide
       { 
           // initialisation du calcul 
           InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
                    // on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
           // bref que l'on n'a pas fini, sinon on passe
           if (! (charge->Fin(icharge,true) ) )
            { // calcul de l'équilibre
              CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats
                              ,tb_combiner);
              // fin du calcul, pour l'instant on ne considère pas les autres sous-types
              FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
            };
       }
    else
     {if ( avec_typeDeCalcul )
      // cas où le type principal est valide et qu'il y a des sous_types
      { // on regarde si le sous-type "commandeInteractive" existe, si oui on le met en place
     // détermine si le sous type de calcul existe et s'il est actif
        if (paraGlob->SousTypeCalcul(commandeInteractive))
          {// -- cas avec commandes interactives
           // initialisation du calcul 
           InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
           // calcul de l'équilibre tant qu'il y a des commandes
           while (ActionInteractiveAlgo())
           	{ // on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
              // bref que l'on n'a pas fini, sinon on passe
              if (! (charge->Fin(icharge,true) ) )
               { CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats
                              ,tb_combiner);
               };
           	};
           // fin du calcul, pour l'instant on ne considère pas les autres sous-types              
           FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
          }
        else // cas sans commandes interactives
          {
           // 1- on fait le calcul d'équilibre
           // initialisation du calcul 
           InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
                    // on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
           // bref que l'on n'a pas fini, sinon on passe
           if (! (charge->Fin(icharge,true) ) )
            { // calcul de l'équilibre
              CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                                 ,divStock,charge,lesCondLim,lesContacts,resultats
                                 ,tb_combiner);
              // fin du calcul, pour l'instant on ne considère pas les autres sous-types              
              FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                                 ,divStock,charge,lesCondLim,lesContacts,resultats );
            };
           // ensuite on teste en fonction des calculs complémentaires
           // dépendant des sous_types. Pour l'instant ici uniquement la remontée
           list <EnumSousTypeCalcul>::const_iterator ili,ili_fin = soustypeDeCalcul->end();
           list <bool>::const_iterator ila;
           for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin();
                  ili!=ili_fin;ili++,ila++)
             if (*ila) // cas où le sous type est valide  
               {if (Remonte_in(*ili)) // on test la présence du calcul de remonté
                 { // certaines initialisations sont nécessaires car c'est le premier calcul
                   Algori::InitRemontSigma(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
                   Algori::InitErreur(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
                   Algori::RemontSigma(lesMail);
                   Algori::RemontErreur(lesMail);
                  }
                else if ( (*ili) == sauveMaillagesEnCours )
                { // en MPI seul le proc 0 fait une sortie sur fichier (I/O classique, normalement le fichier n'est pas gros)
                #ifdef UTILISATION_MPI
                  // seule le process 0 fait la résolution globale
                  if (proc_en_cours == 0)
                   {
                #endif
                    cout << "\n================================================================="
                         << "\n|   ecriture des maillages en cours         en .her et .lis     |"
                         << "\n================================================================="
                         << endl;
           
                    // -----  sort les informations sur fichiers
                    // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
                    // à partir du nom de chaque maillage au format  ".her" et ".lis"
                    lesMail->Affiche_maillage_dans_her_lis(TEMPS_tdt,*lesRef);
                #ifdef UTILISATION_MPI
                  };
                #endif
                };
              };
             };// fin du cas sans commandes interactives
         }        
      else
        // cas ou le type principal n'est pas valide
        // on ne fait que le calcul complémentaire           
        { list <EnumSousTypeCalcul>::const_iterator ili,ili_fin = soustypeDeCalcul->end();
          list <bool>::const_iterator ila;
          for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin();
             ili!=ili_fin;ili++,ila++)
             if (*ila) // cas où le sous type est valide  
               {if (Remonte_in(*ili)) // on test la présence du calcul de remonté
                 { // certaines initialisations sont nécessaires car c'est le premier calcul
                   Algori::InitRemontSigma(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
                   Algori::InitErreur(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
                   Algori::RemontSigma(lesMail);
                   Algori::RemontErreur(lesMail);
                  }
                else if ( (*ili) == sauveMaillagesEnCours )
                { // en MPI seul le proc 0 fait une sortie sur fichier (I/O classique, normalement le fichier n'est pas gros)
                #ifdef UTILISATION_MPI
                  // seule le process 0 fait la résolution globale
                  if (proc_en_cours == 0)
                   {
                #endif
                    cout << "\n================================================================="
                         << "\n|   ecriture des maillages en cours         en .her et .lis     |"
                         << "\n================================================================="
                         << endl;
           
                    // -----  sort les informations sur fichiers
                    // Affichage des donnees des maillages dans des fichiers dont le nom est construit
                    // à partir du nom de chaque maillage au format  ".her" et ".lis"
                    lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
                #ifdef UTILISATION_MPI
                  };
                #endif
                };
              };
         }       
      }
   };

    // écriture des paramètres dans la base info
    // = 1 : on écrit tout
    // = 2 : on écrot uniquement les données variables (supposées comme telles)
void AlgoBonelli::Ecrit_Base_info_Parametre(ostream& sort,const int& cas)
{ switch (cas)
  {case 1 : // ------- on sauvegarde tout  -------------------------
    { 
      // ecriture des parametres de l'algorithme 
      sort << "\n k_max= " << k_max << " a_a= " << a_a << " b_b= " << b_b 
           << " rho_b= " << rho_b << " omega_b= " << omega_b << " nb_pt_int_t= " << nb_pt_int_t << " ";
   	  break;
	 }
    case  2 : // ----------- on sauvegarde en minimaliste --------------------
    { // ici rien
       break;
     }
    default :
	 {// cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
	   cout << "AlgoBonelli::Ecrit_Base_info_Parametre(ostream&  ,const int& )"
			<< " cas= " << cas << endl;
	   Sortie(1);
	   }
   };
//  sort << "\n fin_parametres_algo_specifiques_ ";
};
  
    // lecture des paramètres dans la base info
    // = 1 : on récupère tout
    // = 2 : on récupère uniquement les données variables (supposées comme telles)
    // choix = true  : fonctionememt normal
    // choix = false : la méthode ne doit pas lire mais initialiser les données à leurs valeurs par défaut
    //                 car la lecture est impossible
void AlgoBonelli::Lecture_Base_info_Parametre(istream& ent,const int& cas,bool choix)
{string toto;
 if (choix)
 {switch (cas)
  {case 1 : // ------- on récupère tout  -------------------------
    { 
      // lecture des parametres de l'algorithme
      ent >> toto >> k_max >> toto >> a_a >> toto >> b_b 
          >> toto >> rho_b >> toto >> omega_b >> toto >> nb_pt_int_t;
      if (pt_seg_temps != NULL) delete pt_seg_temps;
      pt_seg_temps = new GeomSeg(nb_pt_int_t);  
   	  break;
	 }
    case  2 :  // ----------- on récupère en minimaliste --------------------
    {  break; // ici rien
     }
    default :
	 { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
	   cout << "AlgoBonelli::Lecture_Base_info_Parametre(istream&  ,const int& )"
			<< " cas= " << cas << endl;
	   Sortie(1);
	   }
   };
  };
 // ici on n'initialise pas les paramètre de réglage de l'algo, car ceux sont à initialiser en lecture 
 // uniquement ce qui permet de les modifiers par un restart par exemple 
 };  

    // gestion et vérification du pas de temps et modif en conséquence si nécessaire
    // cas = 0: premier passage à blanc, delta t = 0
    // cas = 1: initialisation du pas de temps et vérif / au pas de temps critique
    //          ceci pour le temps t=0
    // cas = 2: initialisation du pas de temps et vérif / au pas de temps critique
    //          ceci pour le temps t. et on divise par nbstep
    //          ceci pour garantir que l'on fait le calcul avec 1 step
void AlgoBonelli::Gestion_pas_de_temps(LesMaillages * lesMail,int cas,int )
 {  bool modif_deltat = false; // booleen pour la prise en compte éventuelle de la modif du temps éventuelle
    switch (cas)
    { case 0 :
      { // cas d'un passage à blanc, rien ne bouge et delta t est mis à 0
        delta_t = 0.;
        unsurdeltat = ConstMath::unpeugrand;deltatSurDeux = 0.;
        break;
      }
      case 1 :
      { // --<DG>--  récup du pas de temps, proposé par l'utilisateur
        delta_t = pa.Deltat(); double delta_t_old = delta_t;
//        double delta_tSauve = delta_t; // sauvegarde de la situation actuelle
        // --<DG>--  on calcul le pas de temps minimal pour cela on utilise
        //               les caractéristiques dynamiques d'une biellette de longueur
        //               valant le minimum d'un coté d'arrête
        double l_sur_c = lesMail->Longueur_arrete_mini_sur_c(TEMPS_0);
        double delta_t_essai = l_sur_c ;
        // on prend en compte la particularité de l'algorithme / au pas de temps critique classique
        delta_t_essai *= omega_b * 0.5; // On utilise le omega de bifurcation et non celui critique, c'est plus sur
                                        // de toute façon , omega_b est très proche d'omega critique (cf. courbes d'évolution)
        // mise à jour éventuel du pas de temps et du pas de temps maxi et mini s'ils sont définit à partir du temps critique
        pa.Modif_Deltat_DeltatMaxi(delta_t_essai,l_sur_c); // mais pas de test vis-a-vis des bornes      
        delta_t = pa.Deltat(); // mise à jour éventuelle du pas de temps
        // maintenant on vérifie le pas de temps choisit
        if (pa.Limit_temps_stable() && ( delta_t > delta_t_essai))
        { cout << "\n ** ATTENTION ** , l'increment de temps propose : " << delta_t 
               << ", ne satisfait pas la condition de Courant (C-F-L), "
               << "\n on le regle donc pour que cette condition soit satisfaite: nouvel increment: "
               << delta_t_essai;
          delta_t = delta_t_essai;     
          // modification de l'increment de temps dans les paramètres
          switch (pa.Modif_Deltat(delta_t))
          	{case -1: { cout << "\n initialisation du pas de temps avec la condition de Courant impossible, le nouveau pas" 
                      << "\n de temps calcule est plus petit que le pas de temps mini limite: " << pa.Deltatmini();
                      Sortie(1); break;
                      }
          	 case 0: { break;} // cas normal
          	 case 1: { pa.Modif_Detat_dans_borne(delta_t); 
          	           cout << "\n >>>> rectification du pas de temps "<<delta_t_old<<" dans les bornes : nouvel increment:" << delta_t;
          	           break;
          	          } // cas ou on dépasse la borne maxi
          	};
          modif_deltat=true;	
         }
       break;  
      }
      case 2:
      // on regarde si le pas de temps n'est pas devenu supérieur au pas critique
      { double l_sur_c = lesMail->Longueur_arrete_mini_sur_c(TEMPS_t);
        double delta_t_essai = l_sur_c  ;double ancien_pas=delta_t;
        // on prend en compte la particularité de l'algorithme / au pas de temps critique classique
        delta_t_essai *= omega_b * 0.5; // On utilise le omega de bifurcation et non celui critique, c'est plus sur
                                        // de toute façon , omega_b est très proche d'omega critique (cf. courbes d'évolution)
        // on intervient que si le nouveau pas de temps critique est inférieur au pas de temps en cours
        if ( delta_t_essai < delta_t)      
          {// mise à jour éventuel du pas de temps et du pas de temps maxi s'ils sont définit à partir du temps critique
           bool modif = pa.Modif_Deltat_DeltatMaxi(delta_t_essai,l_sur_c); // mais pas de test vis-a-vis des bornes
           // s'il y a eu modif du pas de temps on met à jour le pas courant
           if (modif) { 
             delta_t = pa.Deltat(); modif_deltat=true;}
           // maintenant on vérifie néanmoins le pas de temps choisit au cas où 
           // en particulier cette vérification n'est en fait pas utile si l'utilisateur 
           // à utilisé un facteur du pas critique < 1
           if (pa.Limit_temps_stable() && ( delta_t > delta_t_essai)) 
              { if (pa.Coefficient_pas_critique_deltat() <= 1.)
                     { delta_t = pa.Coefficient_pas_critique_deltat() * delta_t_essai;}
                else { delta_t = delta_t_essai;};
                // modification de l'increment de temps dans les paramètres
                switch (pa.Modif_Deltat(delta_t))
          	     {case -1: { cout << "\n **** modification du pas de temps  impossible,"
          	                      << " le nouveau pas de temps calcule est plus petit que le pas de temps mini limite: "
          	                      << pa.Deltatmini();
                             Sortie(1); break;
                            }
          	      case 0: { break;} // cas normal
          	      case 1: { pa.Modif_Detat_dans_borne(delta_t); break;} // cas ou on dépasse la borne maxi
          	     };
                modif_deltat=true; 
              }
           if (modif_deltat)
                cout << "\n --->>>> modif increment de temps de " << ancien_pas << "  a " << delta_t;                 
          }
        break; 
        } //-- fin du cas == 2      
	  default :
		{cout << "\nErreur : valeur incorrecte du cas = " << cas << "\n";
		 cout << "AlgoBonelli::Gestion_pas_de_temps(... \n";
		 Sortie(1);
		}
    }; // fin du switch
    // --<DFC>--  mise à jour éventuelle des variables simplificatrices pour le temps     
     if ((cas==1) || ( modif_deltat)) 
      { unsurdeltat = 1./delta_t;deltatSurDeux = delta_t/2.;
        deltat2 = delta_t * delta_t;
        delta_t_total = delta_t; deltatSurDeux_total = deltatSurDeux;
        deltat2_total = deltat2; unsurdeltat_total = unsurdeltat;		
        if (ParaGlob::NiveauImpression() >= 6)
           cout << "\n omega_b/2= " << omega_b*0.5 << " a_a= " << a_a << " b_b = " << b_b << " rho_b= " << rho_b << "\n";                                
       } 
   };
    
    // modification transitoire du pas de temps et modif en conséquence si nécessaire
    // utilisée pour les différentes intégrales temporelles
    // delta_t : nouveau pas de temps transitoire imposé
void AlgoBonelli::Modif_transi_pas_de_temps(double  del_t)
	{ // modification de l'increment de temps suivant l'entrée
	  delta_t = del_t;
      switch (pa.Modif_Deltat(delta_t))
        {case -1: { cout << "\n ** AlgoBonelli: initialisation du pas de temps non acceptee, le nouveau pas" 
                      << "\n de temps calcule est plus petit que le pas de temps mini limite: " << pa.Deltatmini();
                    Sortie(1); break;
                   }
         case 0: { break;} // cas normal
         case 1: { cout << "\n ** AlgoBonelli: initialisation du pas de temps non acceptee, le nouveau pas" 
                      << "\n de temps calcule est plus grand que le pas de temps maxi limite: " << pa.Deltatmaxi();
                   Sortie(1); break;
                  }
        };
    // ---  mise à jour des variables simplificatrices pour le temps 
    unsurdeltat = 1./delta_t;deltatSurDeux = delta_t/2.;
    deltat2 = delta_t * delta_t;		
	};



// lecture des paramètres du calcul
void AlgoBonelli::lecture_Parametres(UtilLecture& entreePrinc)
 { MotCle motCle; // ref aux mots cle
   Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_EXP_BONELLI); // transfert info
   deja_lue_entete_parametre = 1; // a priori pas de lecture d'entête
   // on se positionne sur le prochain mot clé
   do 
     { entreePrinc.NouvelleDonnee();
       }
   while ( !motCle.SimotCle(entreePrinc.tablcar)) ;
   // si le mot clé est "PARA_TYPE_DE_CALCUL" cela signifie 
   // qu'il y a un paramètre à lire
   bool lecture_effective = false;
   if (strstr(entreePrinc.tablcar,"PARA_TYPE_DE_CALCUL")!=NULL)
    { //cas de la définition de paramètres 
      // on signale à Algori qu'il y a eu déjà une lecture de paramètre
      deja_lue_entete_parametre=2; 
      // lecture du premier paramètres de l'algorithme
      entreePrinc.NouvelleDonnee(); // ligne suivante
      if (strstr(entreePrinc.tablcar,"k_max_")!=NULL)
       { // on lit le nombre d'iteration de correction
         string st1;
         *(entreePrinc.entree) >> st1 >> k_max;
         if (st1 != "k_max_")
           { cout << "\n erreur en lecture du nombre d'iteration de correction "
                  << "\n on attendait le mot : k_max_ , au lieu de " << st1
                  << "\n AlgoBonelli::lecture_Parametres( ... ";
             Sortie(1);
           };
         // on vérifie la valeur lue
         if ((k_max < 1) && (k_max > 3))  
           { cout << "\n erreur en lecture du nombre d'iteration de correction "
                  << "\n on attendait une valeur comprise entre 1 et 3 au lieu de: " << k_max
                  << "\n AlgoBonelli::lecture_Parametres( ... ";
             Sortie(1);
           };
         lecture_effective = true;
       }
      else // sinon on met une valeur par défaut 
      {  k_max=2;
       };
      // lecture du rayon spectral de la matrice d'amplification, a la bifurcation
      if (strstr(entreePrinc.tablcar,"rho_b_")!=NULL)
       { // on lit le rayon spectral
         string st1;
         *(entreePrinc.entree) >> st1 >> rho_b;
         if (st1 != "rho_b_")
           { cout << "\n erreur en lecture du rayon spectral "
                  << "\n on attendait le mot : rho_b_ , au lieu de " << st1
                  << "\n AlgoBonelli::lecture_Parametres( ... ";
             Sortie(1);
           };
         lecture_effective = true;
       }
      else // sinon on met une valeur par défaut 
      {  rho_b = 0.6; // si k_max =3, ce sera modifié par la suite
       };

      // lecture directe du coefficient b --> pour test, a la bifurcation
      if (strstr(entreePrinc.tablcar,"b_b_")!=NULL)
       { // on lit le coefficient b
         string st1;
         *(entreePrinc.entree) >> st1 >> b_b;
         if (st1 != "b_b_")
           { cout << "\n erreur en lecture du facteur b_bl "
                  << "\n on attendait le mot : b_b_ , au lieu de " << st1
                  << "\n AlgoBonelli::lecture_Parametres( ... ";
             Sortie(1);
           };
         lecture_effective = true;
       }
      else // sinon on met une valeur par défaut 
      {  b_b=0.; // pour signaler que b_b n'a pas été lue
       };

      // lecture du nombre de points d'integration pour la quadrature temporelle
      if (strstr(entreePrinc.tablcar,"nb_pt_int_t_")!=NULL)
       { // on lit le nombre de point
         string st1;
         *(entreePrinc.entree) >> st1 >> nb_pt_int_t;
         if (st1 != "nb_pt_int_t_")
           { cout << "\n erreur en lecture du nombre de point d'integration "
                  << "\n on attendait le mot : nb_pt_int_t_ , au lieu de " << st1
                  << "\n AlgoBonelli::lecture_Parametres( ... ";
             Sortie(1);
           };
         lecture_effective = true;
       }
      else // sinon on met une valeur par défaut 
      {  nb_pt_int_t = 3; 
       };

      // on détermine les paramètres utils pour le calcul
      pt_seg_temps = new GeomSeg(nb_pt_int_t);
      switch (k_max)
      	{case 1:
      	  { if ((rho_b < 0.34) || (rho_b > 1.)) // vérif de la valeur demandée
            { cout << "\n erreur: le rayon spectral demande n'est pas possible "
                   << "\n il doit etre compris entre 0.34 et 1. alors que l'on a lu " << rho_b
                   << "\n AlgoBonelli::lecture_Parametres( ... ";
              Sortie(1);
             };
            if (b_b == 0.) 
             {// calcul de b_b et omega_b 
              b_b = ((0.0909 * rho_b - 0.3824) * rho_b + 0.8043) * rho_b - 0.0622 ;
              omega_b = ((0.0107 * rho_b -0.064) * rho_b + 0.3722) * rho_b + 1.8827 ;
             }
            else // cas où b_b est directement lue
             {omega_b = 1. ; // fixé arbitrairement car on ne le connait pas
             };
      	  	a_a =1./3. - b_b ;
      	  	break;	
      	  }
         case 2:
      	  { if ((rho_b < 0.) || (rho_b > 1.)) // vérif de la valeur demandée
            { cout << "\n erreur: le rayon spectral demande n'est pas possible "
                   << "\n il doit etre compris entre 0. et 1. alors que l'on a lu " << rho_b
                   << "\n AlgoBonelli::lecture_Parametres( ... ";
              Sortie(1);
             };
            if (b_b == 0.) 
             {// calcul de b_b et omega_b 
              b_b = ((-0.5624 * rho_b + 1.0679) * rho_b - 1.0313) * rho_b + 0.6776 ;
              omega_b = ((0.2778 * rho_b -1.057) * rho_b + 1.1186) * rho_b + 1.8199 ;
             }
            else // cas où b_b est directement lue
             {omega_b = 2. ; // fixé arbitrairement car on ne le connait pas
             };
      	  	a_a =1./3. - b_b ;
      	  	break;	
      	  }
         case 3:
      	  { if (rho_b != 0.4) // vérif de la valeur demandée
            { cout << "\n erreur: le rayon spectral demande n'est pas possible "
                   << "\n il doit etre egal a 0.4 (valeur par defaut) alors que l'on a lu " << rho_b
                   << "\n AlgoBonelli::lecture_Parametres( ... ";
              Sortie(1);
             };
            if (b_b == 0.) 
             {// calcul de b_b et omega_b 
              rho_b = 0.4;
              b_b = 0.332;
              omega_b = 2.753;
             }
            else // cas où b_b est directement lue
             {omega_b = 2. ; // fixé arbitrairement car on ne le connait pas
             };
      	  	a_a =1./3. - b_b ;
      	  	break;	
      	  }
      	};
    }
   else // sinon on met les valeurs par défaut c'est-à-dire E-2C (deux itérations de correction) 
    { b_b=0.322;k_max=2; omega_b=2.171;
      a_a =1./3. - b_b ; rho_b = 0.6;
      nb_pt_int_t = 3;
      pt_seg_temps = new GeomSeg(nb_pt_int_t);
    };
    
   // on prépare la prochaine lecture si la lecture a été effective et que l'on n'est pas
   // sur un mot clé
   if ((lecture_effective) && ( !motCle.SimotCle(entreePrinc.tablcar)))
      entreePrinc.NouvelleDonnee(); // ligne suivante
   // puis appel de la méthode de la classe mère 
   Algori::lecture_Parametres(entreePrinc);  
 };
 
// création d'un fichier de commande: cas des paramètres spécifiques
void AlgoBonelli::Info_commande_parametres(UtilLecture& entreePrinc)
 {  // écriture dans le fichier de commande
    ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
    sort << "\n#-----------------------------------------------------------------------------"
         << "\n|  parametres (falcultatifs ) associes au calcul de dynamique explicite DG   |"
         << "\n|  definition des parametres de controle pour Bonelli (Galerkin Discontinu)  |"
         << "\n#-----------------------------------------------------------------------------"
         << "\n"
         << "\n    PARA_TYPE_DE_CALCUL"
         << "\n  #  ..................................................................................."
         << "\n  # / k_max : 2  nombre de boucle de correction  (1, 2 ou 3), l'optimun est a priori 2 /"
         << "\n  # / rho_b : 0.6 le rayon spectral de la matrice d'amplification, a la bifurcation    /"
         << "\n  # /         pour k_max=1 (E-1C) -> rho_b peut appartenir a  [0.34,1.]                /"
         << "\n  # /         pour k_max=2 (E-2C) -> rho_b peut appartenir a  [0.0,1.]                 /"
         << "\n  # /         pour k_max=3 (E-3C) -> rho_b = 0.4 (de maniere arbitraire)               /"
         << "\n  # / nb_pt_int_t : 3 le nombre de points d'integration pour la quadrature temporelle  /"
         << "\n  # /         forces internes et externes                                            /"
         << "\n  # /  ** parametres facultatifs : (mettre les parametres sur une meme ligne et        /"
         << "\n  # /                               dans l'ordre (meme si certain manque)        ***   /"
         << "\n  #....................................................................................." 
         << "\n   k_max_  2  rho_b_  0.4 nb_pt_int_t_ 3  "
         << "\n  # / a titre de test il est egalement possible d'indiquer directement la valeur de b  /"
         << "\n  # / au lieu de celle de rho_b, selon la syntaxe b_b_ et une valeur par ex: b_b_ 0.5  /"
         << "\n  # / dans ce cas le pas  critique est celui de la dfc                                 /";
    sort << "\n" << endl;         
	   // appel de la classe mère
	   Algori::Info_com_parametres(entreePrinc);
 };

    //------- 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 AlgoBonelli::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(DYNA_EXP_BONELLI); // 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

    // avant toute chose, au cas où l'algo interviendrait après un autre algo
    // on inactive tous les ddl existants
    lesMail->Inactive_ddl();
    // on regarde s'il s'agit d'un pb purement non méca, dans ce cas il faut cependant initialiser les positions
    // à t et tdt pour le calcul de la métrique associée
    { const list <EnumElemTypeProblem >& type_pb = lesMail->Types_de_problemes();
      bool purement_non_meca = true;
      list <EnumElemTypeProblem >::const_iterator il,ilfin=type_pb.end();
      for (il=type_pb.begin();il != ilfin; il++)
        {switch (*il)
          { case MECA_SOLIDE_DEFORMABLE: case MECA_SOLIDE_INDEFORMABLE: case MECA_FLUIDE:
                 purement_non_meca=false; break;
            default: break; // sinon on ne fait rien
          };
        };
      if (purement_non_meca) // si pas de méca, on initialise les coordonnées à t et tdt avec celles de 0
        {lesMail->Init_Xi_t_et_tdt_de_0();}
      else // sinon a minima on active X1
       { lesMail->Active_un_type_ddl_particulier(X1);
       };
    };

    //   -- 1) on met à jour les pointeurs internes de classes
    lesMail_ =lesMail;   
    lesRef_ =lesRef;
    lesCourbes1D_ = lesCourbes1D;
    lesFonctionsnD_ = lesFonctionsnD;
    charge_ = charge;
    lesCondLim_ = lesCondLim;
    lesContacts_ = lesContacts;
  
    // cas du chargement, on verifie egalement la bonne adequation des references
    charge->Initialise(lesMail,lesRef,pa,*lesCourbes1D,*lesFonctionsnD);
    // on indique que l'on ne souhaite pas le temps fin stricte
    // (sinon erreur non gérée après un changement de delta t), que l'on suppose négligeable
    // après plusieurs incréments
    charge->Change_temps_fin_non_stricte(1);
    // dans le cas où l'on calcul des contraintes et/ou déformation et/ou un estimateur d'erreur
    // à chaque incrément, initialisation
    tenuXVG.Change_taille(3);tenuXVG(1)=X1;tenuXVG(2)=V1;tenuXVG(3)=GAMMA1;
    prepa_avec_remont = Algori::InitRemont(lesMail,lesRef,diversStockage,charge,lesCondLim,lesContacts,resultats);      
    if ( prepa_avec_remont)// remise enservice des ddl du pab 
          {lesMail->Inactive_ddl(); lesMail->Active_un_type_ddl_particulier(X1);};      
    // 01 --<DFC>--  récup du pas de temps, proposé par l'utilisateur, initialisation et vérif / pas critique
    this->Gestion_pas_de_temps(lesMail,1,1); // 1 signifie qu'il y a initialisation
    // 00 --<DFC>-- on crée les ddl d'accélération et de vitesse non actif mais libres
    //             car les forces intérieures et extérieures sont les entitées duales
    //             des déplacements, qui sont donc les seules grandeurs actives à ce stade
    lesMail->Plus_Les_ddl_Vitesse( HSLIBRE);
    lesMail->Plus_Les_ddl_Acceleration( HSLIBRE);
    // on défini globalement que l'on a une combinaison des ddl X V GAMMA en même temps   
    cas_combi_ddl=1;          
    // mise en place éventuelle du bulk viscosity
    lesMail->Init_bulk_viscosity(pa.BulkViscosity(),pa.CoefsBulk());
    // mise a zero de tous les ddl et creation des tableaux a t+dt
    // les ddl de position ne sont pas mis a zero ! ils sont initialise
    // a la position courante
    lesMail->ZeroDdl(true);
    // on vérifie que les noeuds sont bien attachés à un élément sinon on met un warning si niveau > 2
    if (ParaGlob::NiveauImpression() > 2)
      lesMail->AffichageNoeudNonReferencer();
    // init des ddl avec les conditions initials 
    // les conditions limites initiales de vitesse et d'accélération sont prise en compte
    // de manière identiques à des ddl quelconques, ce ne sont pas des ddl fixé !!
    lesCondLim->Initial(lesMail,lesRef,lesCourbes1D,lesFonctionsnD,true,cas_combi_ddl);
    // mise à jour des différents pointeur d'assemblage et activation des ddl
    //  a) pour les déplacements qui sont à ce stade les seuls grandeurs actives 
    //       on définit un nouveau cas d'assemblage pour les Xi
    //       à travers la définition d'une instance de la classe assemblage
    Ass1 = new Assemblage(lesMail->InitNouveauCasAssemblage(1));
    lesMail->MiseAJourPointeurAssemblage(Ass1->Nb_cas_assemb());// mise a jour des pointeurs d'assemblage  
    int nbddl_X = lesMail->NbTotalDdlActifs(X1); // nb total de ddl de déplacement
                 // qui est le même pour les accélérations et les vitesses     
    //  b) maintenant le cas des vitesses qui doivent donc être activées
    //       on définit un nouveau cas d'assemblage pour les Vi
    Ass2= new Assemblage(lesMail->InitNouveauCasAssemblage(1));
    lesMail->Inactive_un_type_ddl_particulier(X1);  //       on inactive les Xi
    lesMail->Active_un_type_ddl_particulier(V1);    //       on active les Vi
    lesMail->MiseAJourPointeurAssemblage(Ass2->Nb_cas_assemb());        // mise a jour des pointeurs d'assemblage  
    //  c) idem pour les accélérations
    //       on définit le numéro de second membre en cours 
    //       on définit un nouveau cas d'assemblage pour les pour GAMMAi
    Ass3= new Assemblage(lesMail->InitNouveauCasAssemblage(1));
    lesMail->Inactive_un_type_ddl_particulier(V1);  //       on inactive les Vi
    lesMail->Active_un_type_ddl_particulier(GAMMA1);    //       on active les GAMMAi
    lesMail->MiseAJourPointeurAssemblage(Ass3->Nb_cas_assemb());        // mise a jour des pointeurs d'assemblage 
    //  d) activation de tous les ddl, maintenant ils peuvent être les 3 actifs
    lesMail->Active_un_type_ddl_particulier(X1);
    lesMail->Active_un_type_ddl_particulier(V1);
    // en fait ces trois pointeurs d'assemblage ne sont utils  que pour la mise en place des conditions
    // limites
    // mise à jour du nombre de cas d'assemblage pour les conditions limites
    // c-a-d le nombre maxi possible (intégrant les autres pb qui sont résolu en // éventuellement)
    lesCondLim->InitNombreCasAssemblage(lesMail->Nb_total_en_cours_de_cas_Assemblage());
    // définition d'un tableau globalisant les numéros d'assemblage de X V gamma
    t_assemb.Change_taille(3);
    t_assemb(1)=Ass1->Nb_cas_assemb();t_assemb(2)=Ass2->Nb_cas_assemb();t_assemb(3)=Ass3->Nb_cas_assemb();
    // récupération des tableaux d'indices généraux des ddl bloqués, y compris les ddls associés
    icas = 1; // pour indiquer au module Tableau_indice que l'on travaille avec l'association X V GAMMA
    lesCondLim->Tableau_indice (lesMail,t_assemb
                                                   ,lesRef,charge->Temps_courant(),icas); 
    // on définit quatre tableaux qui serviront à stocker transitoirement les X V GAMMA correspondant au ddl imposés
    int ttsi = li_gene_asso.size();
    X_Bl.Change_taille(ttsi),V_Bl.Change_taille(ttsi),G_Bl.Change_taille(ttsi);
    // def vecteurs globaux
    vglobin.Change_taille(nbddl_X); // puissance interne
    vglobex.Change_taille(nbddl_X); // puissance externe
    vglobaal.Change_taille(nbddl_X,0.); // puissance totale
    // même si le contact n'est pas encore actif, il faut prévoir qu'il le deviendra peut-être !
    if (lesMail->NbEsclave() != 0)
       vcontact.Change_taille(nbddl_X); // puissance de contact
    //  04 --<DG>--  6 vecteur pour une manipulation globale des positions vitesses et accélérations
    // vecteur qui globalise toutes les positions de l'ensemble des noeuds
    X_t.Change_taille(nbddl_X);X_tdt.Change_taille(nbddl_X); delta_X.Change_taille(nbddl_X);
    var_delta_X.Change_taille(nbddl_X);
    // vecteur qui globalise toutes les vitesses de l'ensemble des noeuds
    vitesse_t.Change_taille(nbddl_X);vitesse_tplus.Change_taille(nbddl_X);
    vitesse_tdt.Change_taille(nbddl_X);
    // vecteur qui globalise toutes les accélérations
    acceleration_t.Change_taille(nbddl_X);acceleration_tdt.Change_taille(nbddl_X) ; 

    // calcul des énergies
    if (pa.Amort_visco_artificielle()) // dans le cas d'un amortissement artificiel
       forces_vis_num.Change_taille(nbddl_X,0.);
    E_cin_tdt = 0.; E_int_t = 0.; E_int_tdt = 0.; // init des différentes énergies
    E_ext_t = 0.; E_ext_tdt = 0.; bilan_E = 0.;   //       "       et du bilan
    F_int_t.Change_taille(nbddl_X); F_ext_t.Change_taille(nbddl_X); // forces généralisées int et ext au pas précédent
    F_int_tdt.Change_taille(nbddl_X); F_ext_tdt.Change_taille(nbddl_X); // forces généralisées int et ext au pas actuel
    residu_final.Change_taille(nbddl_X); // pour la sauvegarde du résidu pour le post-traitement

    //  initialisation du compteur d'increments de charge
    icharge = 0;
   
    // definition des elements de frontiere, ces elements sont utilises pour le contact
    lesMail->CreeElemFront();
    //  calcul éventuel des normales aux noeuds -> init des normales pour t=0
    lesMail->InitNormaleAuxNoeuds(); //utilisé pour la stabilisation des membranes par ex
    // --- init du contact ---
    // doit-être avant la lecture d'un restart, car il y a une initialisation de conteneurs qui est faites
    // qui ensuite est utilisée en restart
    // par exemple il faut initialiser les frontières et la répartition esclave et maître
    // pour préparer la lecture de restart éventuel
    if (lesMail->NbEsclave() != 0)
     { // definition des elements de frontiere, ces elements sont utilises pour le contact
//       int cal_front =
       lesMail->CreeElemFront();
       lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_t);
       // initialisation des zones de contacts éventuelles
       lesContacts->Init_contact(*lesMail,*lesRef,lesFonctionsnD);
       // verification qu'il n'y a pas de contact avant le premier increment de charge
       lesContacts->Verification();
       // definition des elements de contact eventuels
       lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul
     };

    //--cas de restart et/ou de sauvegarde------------
    // tout d'abord récup du restart si nécessaire
      // dans le cas ou un incrément différent de 0 est demandé -> seconde lecture à l'incrément
    brestart=false;   // booleen qui indique si l'on est en restart ou pas
    if (this->Num_restart() != 0)
        { int cas = 2;
          // ouverture de base info
          entreePrinc->Ouverture_base_info("lecture"); 
          this->Lecture_base_info(cas ,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage
                         ,charge,lesCondLim,lesContacts,resultats,(this->Num_restart()));
          icharge = this->Num_restart();//+1;
          //  récup du pas de temps, proposé par l'utilisateur, initialisation et vérif / pas critique
          this->Gestion_pas_de_temps(lesMail,2,1); // 2 signifie cas courant
          brestart = true;
          // on oblige les ddls Vi GAMMAi a avoir le même statut que celui des Xi
          // comme les conditions limites cinématiques peuvent être différentes en restart
          // par rapport à celles sauvegardées, on commence par libérer toutes les CL imposées éventuelles
          lesMail->Libere_Ddl_representatifs_des_physiques(LIBRE);
          lesMail->ChangeStatut(cas_combi_ddl,LIBRE);
          // dans le cas d'un calcul axisymétrique on bloque le ddl 3
          if (ParaGlob::AxiSymetrie())
             lesMail->Inactive_un_ddl_particulier(X3);
          // on valide l'activité des conditions limites et condition linéaires, pour le temps initial
          // en conformité avec les conditions lues (qui peuvent éventuellement changé / aux calcul qui a donné le .BI)
          lesCondLim->Validation_blocage (lesRef,charge->Temps_courant());
				      li_gene_asso = lesCondLim->Tableau_indice (lesMail,t_assemb,lesRef,charge->Temps_courant(),icas);
				      int ttsi = li_gene_asso.size();
				      X_Bl.Change_taille(ttsi);V_Bl.Change_taille(ttsi);G_Bl.Change_taille(ttsi);
          // mise à jour pour le contact s'il y du contact présumé
          if (pa.ContactType())
             lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_t);
         }
    // vérif de cohérence pour le contact
    if ((pa.ContactType()) && (lesMail->NbEsclave() == 0)) // là pb
      {cout << "\n *** erreur: il n'y a pas de maillage disponible pour le contact "
            << " la definition d'un type contact possible est donc incoherente "
            << " revoir la mise en donnees !! "<< flush;
       Sortie(1);
      };
    // on regarde s'il y a besoin de sauvegarde
    if (this->Active_sauvegarde() && (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);
         }                         
      }                           
    //--fin cas de restart et/ou de sauvegarde--------

    // ajout d'un conteneur pour les coordonnées à l'itération 0
    {Coordonnee coor(ParaGlob::Dimension()); // un type coordonnee typique
     Grandeur_coordonnee gt(coor); // une grandeur typique de type Grandeur_coordonnee
     // def d'un type quelconque représentatif  à chaque noeud
     TypeQuelconque typQ_gene_int(XI_ITER_0,X1,gt);
     lesMail->AjoutConteneurAuNoeud(typQ_gene_int);
    };

    // choix de la matrice de masse, qui est en fait celle qui correspond au ddl Xi
    // ici le numéro d'assemblage est celui de X car on projette bien sur des vitesses virtuelles c-a-d ddl X*.
    mat_masse = Choix_matrice_masse(nbddl_X,mat_masse,lesMail,lesRef
                                     ,Ass1->Nb_cas_assemb(),lesContacts,lesCondLim);
    mat_masse_sauve = Choix_matrice_masse(nbddl_X,mat_masse_sauve,lesMail,lesRef
                                           ,Ass1->Nb_cas_assemb(),lesContacts,lesCondLim);
    // choix de la résolution
    if (mat_masse->Type_matrice() == DIAGONALE)
      // dans le cas d'une matrice diagonale on force la résolution directe quelque soit l'entrée
      mat_masse->Change_Choix_resolution(DIRECT_DIAGONAL,pa.Type_preconditionnement());
    else
      mat_masse->Change_Choix_resolution(pa.Type_resolution(),pa.Type_preconditionnement());

    // on signale que l'on utilise un comportement matériel normal
    lesLoisDeComp->Loi_simplifie(false);
    // on calcul la matrice de masse qui est supposée identique dans le temps
    // c'est-à-dire que l'on considère que la masse volumique est constante
    Cal_matrice_masse(lesMail,*Ass1,*mat_masse,diversStockage,lesRef,X1,lesFonctionsnD);
    // on sauvegarde la matrice masse
    (*mat_masse_sauve) = (*mat_masse);
    // dans le cas où l'on utilise de l'amortissement numérique 
//    if (pa.Amort_visco_artificielle()) 
//      { bool initial = true; // def de la matrice (place et valeurs)
//        mat_C_pt = Cal_mat_visqueux_num_expli(*mat_masse,mat_C_pt,delta_X,initial,vitesse_tdt);
//        forces_vis_num.Change_taille(nbddl_X);
//       };         
    // mise en place des conditions limites
    // ---- initialisation des sauvegardes sur matrice et second membre
    //      ce qui ne correspond à rien ici normalement
    lesCondLim->InitSauve(Ass3->Nb_cas_assemb());
    // 
    lesCondLim->ImposeConLimtdt(lesMail,lesRef,*mat_masse,vglobaal,Ass3->Nb_cas_assemb()
	                              ,cas_combi_ddl,vglob_stat);
    // puis on prépare (si besoin est en fonction du type de matrice) la résolution
    mat_masse->Preparation_resol();
    type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul
    // --- cas des vecteurs  --- 
    // les différents vecteurs de ddl intermédiaires discontinues sont initialisés à 0
    q_0.Change_taille(nbddl_X);p_0.Change_taille(nbddl_X);
    q_1.Change_taille(nbddl_X);p_1.Change_taille(nbddl_X);
    q_2.Change_taille(nbddl_X);p_2.Change_taille(nbddl_X);
    // on initialise q_0 à la valeur de X_t
    lesMail_->Vect_loc_vers_glob(TEMPS_t,X1,q_0,X1,Ass3->Nb_cas_assemb());
    lesMail_->Vect_loc_vers_glob(TEMPS_t,V1,vitesse_t,V1,Ass3->Nb_cas_assemb());
    // on initialise de même la quantité de mouvement
////  mat_masse->Prod_mat_vec ( vitesse_t, p_0); 
    mat_masse_sauve->Prod_mat_vec ( vitesse_t, p_0); 
    // on dimensionne les vecteurs de travail, et les vecteurs intermédiaires
    pPoint_i.Change_taille(nbddl_X);
    P_i_1.Change_taille(nbddl_X);P_i_2.Change_taille(nbddl_X);
    P_q1_k.Change_taille(nbddl_X);P_q2_k.Change_taille(nbddl_X);
    r_1_k.Change_taille(nbddl_X);r_2_k.Change_taille(nbddl_X);
    vec_travail1.Change_taille(nbddl_X); vec_travail2.Change_taille(nbddl_X); 
    dernier_phi.Change_taille(2); // 2 noeuds temporels
    if (amortissement_cinetique)		
        Algori::InitialiseAmortissementCinetique(); // initialisation des compteurs pour l'amortissement au cas ou
    tempsInitialisation.Arret_du_comptage(); // temps cpu
  
  };

    // mise à jour
void AlgoBonelli::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(DYNA_EXP_BONELLI); // transfert info
  
    // activation des ddl
    lesMail->Inactive_ddl(); // on commence par inactiver tous les ddl
    lesMail->Active_un_type_ddl_particulier(X1); // puis on active les ddl qu'ils faut ici
    lesMail->Active_un_type_ddl_particulier(V1);    //       on active les Vi
    lesMail->Active_un_type_ddl_particulier(GAMMA1);    //       on active les GAMMAi

     // mise à jour au cas où
     Algori::MiseAJourAlgoMere(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                ,diversStockage,charge,lesCondLim,lescontacts,resultats);
    tempsMiseAjourAlgo.Arret_du_comptage(); // temps cpu
  
  };

// Résolution du problème mécanique en explicite dynamique 
    // calcul
// si tb_combiner est non null -> un tableau de 2 fonctions
//  - la première fct dit si on doit valider ou non le calcul à convergence ok,
//  - la seconde dit si on doit sortir de la boucle ou non à convergence ok
//
// 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 AlgoBonelli::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* > * tb_combiner)
  {
    tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
    Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_EXP_BONELLI); // transfert info
    // init var glob: du num d'itération. De manière arbitraire, en dynamique explicite
    Transfert_ParaGlob_COMPTEUR_ITERATION_ALGO_GLOBAL(1); // on a toujours une seule itération
    OrdreVisu::EnumTypeIncre type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul
    
    // préparation pour les aspects validation du calcul et sortie contrôlée des incréments
    int validation_calcul = 1; // init : par défaut la validation est effective si le calcul converge
    int sortie_boucle_controler_par_fctnD = 0; // init : par défaut la sortie n'est pas contrôler
    
    //  boucle sur les increments de charge qui sont également les incréments de temps
    // tant que la fin du chargement n'est pas atteinte 
    // dans le cas du premier chargement on calcul de toute manière, ce qui permet
    // de calculer meme si l'utilisateur indique un increment de charge supérieur
    // au temps final
    const double untiers = 1./3.;
    cout << "\n a_a=" << a_a << " b_b= " << b_b;
    // ---  récupération  des ddl  position, vitesse et accélération initial
    lesMail_->Vect_loc_vers_glob(TEMPS_t,X1,X_t,X1,Ass3->Nb_cas_assemb());
    lesMail_->Vect_loc_vers_glob(TEMPS_t,V1,vitesse_t,V1,Ass3->Nb_cas_assemb());
    lesMail_->Vect_loc_vers_glob(TEMPS_t,GAMMA1,acceleration_t,GAMMA1,Ass3->Nb_cas_assemb());

    icharge++; // on incrémente le chargement -> donne le num d'incr du prochain incr chargé
    double max_delta_X=0.; //  le maxi du delta X
    double max_var_delta_X=0.; // idem d'une itération à l'autre
    int nb_step=1; // a priori
    bool arret=false; // booleen pour arrêter indépendamment de la charge
    while (((!charge->Fin(icharge))||(icharge == 1))
           && (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é
           && !arret)
    { // renseigne les variables définies par l'utilisateur via les valeurs déjà calculées par Herezh
      Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(lesMail,varExpor,Ass1->Nb_cas_assemb(),*lesRef);
      varExpor->RenseigneVarUtilisateur(*lesMail,*lesRef);
      lesMail->CalStatistique(); // calcul éventuel de statistiques

      // mise à jour du calcul éventuel des normales aux noeuds -> mise à jour des normales à t
      // mais ici, on calcule les normales à tdt, et on transfert à t
      // comme on est au début de l'incrément, la géométrie à tdt est identique à celle à t
      // sauf "au premier incrément", si l'algo est un sous algo d'un algo combiné
      // et que l'on suit un précédent algo sur un même pas de temps
      // qui a aboutit à une géométrie à tdt différente de celle de t
      // du coup cela permet d'utiliser la nouvelle géométrie pour ce premier incrément
      lesMail->MiseAjourNormaleAuxNoeuds_de_tdt_vers_T();
      // passage aux noeuds  des vecteurs globaux:  F_INT, F_EXT
      Algori::Passage_aux_noeuds_F_int_t_et_F_ext_t(lesMail);

      //  gestion du pas de temps, vérif du delta_t / pas critique
      this->Gestion_pas_de_temps(lesMail,2,nb_step); // 2 signifie cas courant 
      // init des temps début et fin, permet ainsi de les sauvegarder, car le temps va évoluer pendant l'intégration
      double tdeb = pa.Variables_de_temps().TempsCourant();
      double tfi = tdeb + pa.Deltat();      
               
      // affichage de l'increment de charge
      if ( pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde))
        {cout << "\n======================================================================"
              << "\nINCREMENT DE CHARGE : " << icharge 
              << "  intensite " << charge->IntensiteCharge() 
              << "  t= " << charge->Temps_courant()
              << " dt= " << ParaGlob::Variables_de_temps().IncreTempsCourant()
              << "\n======================================================================";
          };    
      lesLoisDeComp->MiseAJour_umat_nbincr(icharge); // init pour les lois Umat éventuelles
      
      // ---<DG1>--  calcul des dérivées temporelles des quantités de mouvement au temps ti^{-}
      //  on considère que X_tdt au niveau des noeuds est celui de ti^{-}, dernière valeur calculée
      //  mise en place du chargement impose, c-a-d calcul de la puissance externe
      vglobin.Zero();
      vglobex.Zero();
      if (pa.ContactType())
         vcontact.Zero();
      vglobaal.Zero(); // puissance totale
		    lesMail->Force_Ddl_aux_noeuds_a_une_valeur(R_X1,0.0,TEMPS_tdt,true); // mise à 0 des ddl de réactions, qui sont uniquement des sorties
      lesMail->Force_Ddl_etendu_aux_noeuds_a_zero(Ddl_enum_etendu::Tab_FN_FT()); // idem pour les composantes normales et tangentielles
      // mise en place du chargement impose, c-a-d calcul de la puissance externe
      // si pb on sort de la boucle
      if (!(charge->ChargeSecondMembre_Ex_mecaSolid
             (*Ass1,lesMail,lesRef,vglobex,pa,lesCourbes1D,lesFonctionsnD)))
        { Change_PhaseDeConvergence(-10);break;};
      // appel du calcul  de la puissance interne et des énergies
      // dans le cas d'un calcul inexploitable arrêt de la boucle
      if (!SecondMembreEnerg(lesMail,*Ass1,vglobin)) break;

      // calcul des maxi des puissances internes
      maxPuissInt = vglobin.Max_val_abs();
      F_int_tdt = vglobin; // sauvegarde des forces généralisées intérieures
     
      if (pa.ContactType())
           vglobex += vcontact;
      maxPuissExt = vglobex.Max_val_abs();
      F_ext_tdt = vglobex; // sauvegarde des forces généralisées extérieures
      // second membre total
      vglobaal += vglobex ;vglobaal += vglobin ;

      // pPoint_i = puissance externe - puissance interne
      pPoint_i= (vglobaal);

      // ----- calcul de la prédiction avec les CL de déplacement au point d'intégration temporelle
      // mise en place des conditions limites et mise à jour de la matrice de masse si nécessaire
      const Vecteur phii1_avec_rien; // phii qui ne sert pas dans la phase de prédiction
      charge_->Avance(); // avancement de la charge et donc du temps courant
      AvanceDDL_avec_CL(phii1_avec_rien,PREDICTION_bonelli);
      bool retour_exacte=true; // pour ne pas comptabiliser les appels intermédiaires à Avance()
      charge_->Precedant(retour_exacte); // retour au temps initial
      
      // ----- Phase de correction 
      int k_k = 0;
 //     cout << "\n kk=0 ";
      do 
       {// ----- calcul des vecteurs P_i_1, P_i_2, P_q1_k, P_q2_k
        P_i_1.Zero(); P_i_2.Zero(); P_q1_k.Zero(); P_q2_k.Zero();
        //  on utilise une quadrature  de gauss 
        for (int i_pt_integ = 1;i_pt_integ <= nb_pt_int_t; i_pt_integ++ )
        	{ // calcul du temps correspondant au pt d'integ
            Vecteur const & phii= pt_seg_temps->ElemGeomC0::Phi((int)i_pt_integ);
            dernier_phi = phii; // sauvegarde, pour CalEnergieAffichageBonelli()
            double phii_1 = phii(1); double phii_2 = phii(2);
        	   double temps = tdeb * phii_1 + tfi * phii_2; // temps courant d'intégration
            // on valide le pas de temps effectivement fait
            Modif_transi_pas_de_temps(temps-tdeb);                         
            charge_->Avance(); // avancement de la charge et donc du temps courant
            
            // --- quadrature

            // mise en place des conditions limites sur les ddl stockés aux noeuds: positions et vitesses
            // mise à jour des conditions limites sur la matrice de masse si nécessaire
            AvanceDDL_avec_CL(phii,INTEGRATION_bonelli);
            
            // -- cas P_i_1 et  P_i_2 : formule un peu différente de l'article
            //  mise en place du chargement impose, c-a-d calcul de la puissance externe
            vglobex.Zero();
            // mise en place du chargement impose, c-a-d calcul de la puissance externe
            // si pb on sort de la boucle
            if (!(charge->ChargeSecondMembre_Ex_mecaSolid
             (*Ass1,lesMail,lesRef,vglobex,pa,lesCourbes1D,lesFonctionsnD)))
               { Change_PhaseDeConvergence(-10);break;};
            F_ext_tdt = vglobex;
            if (pa.ContactType())
                vcontact.Zero();
                
            if (pa.ContactType())
                 vglobex += vcontact;
            maxPuissExt = MaX(maxPuissExt,F_ext_tdt.Max_val_abs());
            // integ 
            double poids = pt_seg_temps->ElemGeomC0::Wi((int)i_pt_integ);
            P_i_1 += (phii_1 * deltatSurDeux_total * poids) * F_ext_tdt ;
            P_i_2 += (phii_2 * deltatSurDeux_total * poids) * F_ext_tdt ;
            // -- cas P_q1_k et P_q2_k
            // appel du calcul  de la puissance interne et des énergies au niveau des éléments
            // dans le cas d'un calcul inexploitable on enregistre l'erreur
            vglobin.Zero();
            if (!SecondMembreEnerg(lesMail_,*Ass1,vglobin))
                     {arret=true; erreurSecondMembre = true;
                      cout << "\n erreur dans le calcul du second membre ! ";
                      break;
                      };
            F_int_tdt = vglobin; // sauvegarde des forces généralisées intérieures
            // second membre total
            (vglobaal) = vglobex ; // dans mon cas j'ajoute alors que dans la théorie de bonelli on retranche
                                    // il y a bien donc une différence de signe entre bonelli et moi pour F_int et F_ext
            vglobaal += vglobin ;
          
            maxPuissInt = MaX(maxPuissInt,F_int_tdt.Max_val_abs());
            // integ
            P_q1_k += (phii_1 * deltatSurDeux_total * poids) * F_int_tdt; 
            P_q2_k += (phii_2 * deltatSurDeux_total * poids) * F_int_tdt; 
            // on revient aux conditions initiales de début d'incrément concernant le temps
            charge_->Precedant(retour_exacte);            
        	};
        if (arret) break; // cas d'une erreur dans le calcul du second membre
        
        // vec_travail2 = unsurdeltat_total * (matrice_mas * q_0);
////    mat_masse->Prod_mat_vec ( q_0, vec_travail2); vec_travail2 *= unsurdeltat_total; 
        mat_masse_sauve->Prod_mat_vec ( q_0, vec_travail2); vec_travail2 *= unsurdeltat_total; 
      
        // --- calcul des vecteurs résidus
        // formules différentes de l'article
        // r_1_k = unsurdeltat_total * M * q_2 + P_q1_k - P_i_1 - p_0 - unsurdeltat_total * M * q_0;
        // r_2_k = unsurdeltat_total * M * q_1 - 1/3 * P_q2_k - 1/3 * P_i_1  + 1/3 * unsurdeltat_total * M * q_0;
 //        r_1_k = unsurdeltat_total * mat_masse->Prod_mat_vec(q_2,vec_travail1) + P_q1_k - P_i_1 - p_0 - vec_travail2;
 //        r_2_k = unsurdeltat_total * mat_masse->Prod_mat_vec(q_1,vec_travail1) - untiers * (P_q2_k - P_i_2) - vec_travail2 ;
 
////        r_1_k = unsurdeltat_total * mat_masse->Prod_mat_vec(q_2,vec_travail1) - P_q1_k - P_i_1 - p_0 - vec_travail2;
////        r_2_k = unsurdeltat_total * mat_masse->Prod_mat_vec(q_1,vec_travail1) + untiers * (P_q2_k + P_i_2) - vec_travail2 ;
        r_1_k = unsurdeltat_total * mat_masse_sauve->Prod_mat_vec(q_2,vec_travail1) - P_q1_k - P_i_1 - p_0 - vec_travail2;
        r_2_k = unsurdeltat_total * mat_masse_sauve->Prod_mat_vec(q_1,vec_travail1) + untiers * (P_q2_k + P_i_2) - vec_travail2 ;


 //       cout << "\n (fint -fex)1 " << (P_q1_k - P_i_1 - p_0 - vec_travail2).Norme() 
 //            << " (fint -fex)2 " << (- untiers * (P_q2_k - P_i_2) - vec_travail2).Norme(); 
        // --- calcul des nouvelles positions
        AvanceDDL_avec_CL(phii1_avec_rien,CORRECTION_bonelli);
        // --- incrémente la boucle
        k_k ++;
       } while (k_k < k_max);
//       } while (k_k < 5);
      if (arret && erreurSecondMembre) break; // cas d'une erreur dans le calcul du second membre

      // --- calcul des réactions au dernier point d'intégration temporelle, c-a-d à l'aide
      //     des derniers efforts internes et externes calculés (et mémorisés)
      // initialisation des sauvegardes sur second membre (uniquement pour les gammai)
      // car ce sont les ddl de l'équation d'équilibre instantanée
      lesCondLim->InitSauve(Ass3->Nb_cas_assemb());

		    // on récupère les réactions avant changement de repère et calcul des torseurs de réaction
      lesCondLim->ReacAvantCHrepere(vglobaal,lesMail,lesRef,Ass3->Nb_cas_assemb(),cas_combi_ddl);

		// sauvegarde des reactions pour les  ddl bloques (simplement)
// ***dans le cas statique il semble (cf. commentaire dans l'algo) que ce soit inutile donc a voir
// ***donc pour l'instant du a un bug je commente
//      // sauvegarde des reactions aux ddl bloque (vglobin = vglobal : somme des forces généralisées)
//      lesCondLim->ReacApresCHrepere(vglobin,lesMail,lesRef,Ass3->Nb_cas_assemb(),cas_combi_ddl);

      // mise en place des conditions limites sur les Gammai -> calcul et sauvegarde des réactions
      lesCondLim->ImposeConLimtdt(lesMail,lesRef,(vglobaal),Ass3->Nb_cas_assemb()
		                            ,cas_combi_ddl,vglob_stat);
      // calcul du maxi des reactions 
      maxReaction = lesCondLim->MaxEffort(inReaction,Ass3->Nb_cas_assemb());
      // sortie d'info sur l'increment concernant les réactions 
      if ( pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde))
          InfoIncrementReac(lesMail,inReaction,maxReaction,Ass3->Nb_cas_assemb());
      
      // --- calcul et affichage éventuel du maxi de variation de ddl
      // contrairement aux autres algos dynamique, on affiche la variation maxi de x 
      Algori::Cal_Transfert_delta_et_var_X(max_delta_X,max_var_delta_X);
      maxDeltaDdl = delta_X.Max_val_abs(inSol);
      // sortie d'info sur l'increment concernant les variations de ddl 
      if ( pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde) &&(ParaGlob::NiveauImpression() > 1))
         InfoIncrementDdl(lesMail,inSol,maxDeltaDdl,Ass3->Nb_cas_assemb());
      
      // --- validation du pas de temps effectivement effectué
      Modif_transi_pas_de_temps(tfi-tdeb);                         
      charge_->Avance(); // avancement de la charge et donc du temps courant
      // --- calcul des ddl finaux 
      //     et mise en place de: X_td, vitesse_tdt et acceleration_tdt au niveau des noeuds
      AvanceDDL_avec_CL(phii1_avec_rien,FIN_DELTA_T_bonelli);
      
      // --- calcul de la vitesse à tplus ainsi que de la quantité de mouvement final à tdt^{-}  
      vitesse_tplus = unsurdeltat_total * (3. * q_1 + q_2 - 4. * q_0); // sert dans CalEnergieAffichageBonelli()
////      mat_masse->Prod_mat_vec(vitesse_tdt,p_2); //vitesse_tdt = M^{-1} * p_2
      mat_masse_sauve->Prod_mat_vec(vitesse_tdt,p_2); //vitesse_tdt = M^{-1} * p_2

      // --- préparation des grandeurs pour le pas de temps suivant
      p_0=p_2; q_0 = q_2;
                       
      // calcul des énergies et affichage des balances
      CalEnergieAffichageBonelli(1.,icharge);             
      if (icharge==1)// dans le cas du premier incrément on considère que la balance vaut l'énergie 
            // cinétique initiale, car vu que l'on ne met pas de CL à t=0, E_cin_0 est difficile à calculer
          {E_cin_0 = E_cin_tdt - bilan_E + E_int_tdt - E_ext_tdt; };
          
      // calcul éventuelle de l'amortissement cinétique
//      int relax_vit_acce = AmortissementCinetique(delta_X,1.,X_tdt,*mat_masse_sauve,icharge,vitesse_tdt);
      // s'il y a amortissement cinétique il faut re-updater les vitesses
//      if (Abs(relax_vit_acce) == 1) {lesMail->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1);};
//      if (relax_vit_acce == -1)  
//         {arret=true;	};  // arrêt du calcul car deltaddl satisfait le critère de relaxation cinétique

         
      // mise à jour des indicateurs contrôlés par le tableau: *tb_combiner
      if (tb_combiner != NULL) // cas d'un contrôle via des fonctions nD
       {if ((*tb_combiner)(1) != NULL)
           validation_calcul = (*tb_combiner)(1)->Valeur_pour_variables_globales()(1);
        if ((*tb_combiner)(2) != NULL)
           sortie_boucle_controler_par_fctnD = (*tb_combiner)(2)->Valeur_pour_variables_globales()(1);
       };

      // si on est sans validation, on ne fait rien, sinon on valide l'incrément
      // avec sauvegarde éventuelle
      if (validation_calcul)
        {// actualisation des ddl et des grandeurs actives de t+dt vers t
         lesMail->TdtversT();
         X_t = X_tdt; vitesse_t=vitesse_tdt; acceleration_t=acceleration_tdt;
         // cas du calcul des énergies, passage des grandeurs de tdt à t
         Algori::TdtversT();
         // on valide l'activité des conditions limites et condition linéaires
         lesCondLim->Validation_blocage (lesRef,charge->Temps_courant());

         // sauvegarde de l'incrément si nécessaire
         tempsCalEquilibre.Arret_du_comptage(); // pour enregistrer
         Ecriture_base_info(2,lesMail,lesRef,lesCourbes1D,lesFonctionsnD
                ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts
                ,resultats,type_incre,icharge);
         // enregistrement du num d'incrément et du temps correspondant
         list_incre_temps_calculer.push_front(Entier_et_Double(icharge,pa.Variables_de_temps().TempsCourant()));
         // visualisation éventuelle au fil du calcul
         VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD
                             ,lesLoisDeComp,diversStockage,charge
                             ,lesCondLim,lesContacts,resultats,type_incre,icharge);
         tempsCalEquilibre.Mise_en_route_du_comptage(); // on remet en route le compteur
        }; // -- fin du test: if (validation_calcul)

      //s'il y a remonté des sigma et/ou def aux noeuds et/ou calcul d'erreur
      bool change =false;  // calcul que s'il y a eu initialisation
      if(prepa_avec_remont) {change = Algori::CalculRemont(lesMail,type_incre,icharge);};
      if (change) // dans le cas d'une remonté il faut réactiver les bon ddls
          {lesMail->Inactive_ddl(); lesMail->Active_un_type_ddl_particulier(tenuXVG);};
      brestart = false; // dans le cas où l'on était en restart, on passe l'indicateur en cas courant
      // test de fin de calcul effectue dans charge via : charge->Fin()
      if (validation_calcul)
        {icharge++;
         Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
        };
      // --cas particulier où la sortie de la boucle est pilotée
      // ici, cas d'un calcul explicite au sens classique, il n'y a pas de notion de convergence
      // celle-ci est toujours considérée comme effective
      if (sortie_boucle_controler_par_fctnD)
        break;
     }
    // on remet à jour le nombre d'incréments qui ont été effectués:
    if (validation_calcul)
      {icharge--;
       Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
      }
    else // si on ne valide pas le calcul, on reinitialise la charge
     // c-a-d l'avancement en temps, incrément et facteur multiplicatif
     // de manière à avoir les mêmes conditions de départ pour le prochain calcul
      { charge->Precedant(true);}  ;
    tempsCalEquilibre.Arret_du_comptage(); // temps cpu
  };
	
    // dernière passe                  
void AlgoBonelli::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)
  { // passage finale dans le cas d'une visualisation  au fil du calcul  
    Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_EXP_BONELLI); // transfert info
    type_incre = OrdreVisu::DERNIER_INCRE;
    VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge
                          ,lesCondLim,lesContacts,resultats,type_incre,icharge);
    // sauvegarde de l'état finale de l'incrément si nécessaire
    Ecriture_base_info(2,lesMail,lesRef,lesCourbes1D,lesFonctionsnD
             ,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts
             ,resultats,type_incre,icharge);
    // enregistrement du num d'incrément et du temps correspondant                 
    list_incre_temps_calculer.push_front(Entier_et_Double(icharge,pa.Variables_de_temps().TempsCourant()));                 
  };

    
    // calcul des ddl avec prise en comptes des conditions limites suivant une technique 
    // s'appuyant sur une différence finie décentrée à droite
    // utilise les vecteurs globaux : q_2, q_1, q_0
    // --> mise à jour des ddl au niveau globaux sur les X, V, gamma puis au niveau des noeuds
    // --> ou mise à jour des composantes adoc des vecteurs globaux q_2, q_1, q_0, selon "phasage"
    // phii : interpolation en fonction du temps, ne sert que pour phasage = INTEGRATION_bonelli
    // phasage =
    //  PREDICTION_bonelli: phase de prédiction, on n'utilise "pas" l'interpolation en temps (phii)
    //                      --> calcul de q_1 et q_2 avec les conditions limites
    //  INTEGRATION_bonelli: phase d'intégration, "on utilise l'interpolation en temps" 
    //                      --> calcul de X_tdt et vitesse_tdt
    //  CORRECTION_bonelli: phase de correction, on n'utilise "pas" l'interpolation en temps (phii)
    //                      --> calcul de q_1 et q_2 avec les conditions limites
    //  FIN_DELTA_T_bonelli: phase final, on n'utilise "pas" l'interpolation en temps (phii)
    //                      --> calcul de X_tdt et vitesse_tdt pour le temps final
void AlgoBonelli::AvanceDDL_avec_CL(const Vecteur  & phii,enuTypePhase phasage)
	{
      // --- imposition des ddls bloqués
      // initialisation des coordonnees et des ddl a tdt en fonctions des 
      // ddl imposes et de l'increment du chargement
      // on regarde s'il y a changement de statut de certains ddl ==> modif de tableau d'indiçage
      bool change_statut = false;  // init des changements de statut         
      lesCondLim_->MiseAJour_tdt
           (pa.Multiplicateur(),lesMail_,charge_->Increment_de_Temps(),lesRef_,charge_->Temps_courant()
           ,lesCourbes1D_,lesFonctionsnD_,charge_->MultCharge(),change_statut,cas_combi_ddl);
      // dans le cas ou il y a changement de statut il faut remettre à jour 
      // les conditions limites sur la matrice masse
      if (change_statut)
        {li_gene_asso = lesCondLim_->Tableau_indice (lesMail_,t_assemb
                                             ,lesRef_,charge_->Temps_courant(),icas);
         int ttsi = li_gene_asso.size();
         X_Bl.Change_taille(ttsi);V_Bl.Change_taille(ttsi);G_Bl.Change_taille(ttsi);
         // récupération de la matrice masse sans conditions limites
         (*mat_masse) = (*mat_masse_sauve);
         // normalement sur la matrice visqueuse il n'y a rien n'a faire 
  //       if (pa.Amort_visco_artificielle()) // initialisation de la matrice visqueuse
  //        { bool initial = false;
  //          Cal_mat_visqueux_num_expli(matrice_mas,mat_C_pt,delta_X,initial,vitesse_tdt);
  //         }         
         // mise en place des conditions limites
         // ---- initialisation des sauvegardes sur matrice et second membre
         //      ce qui ne correspond à rien ici normalement
         lesCondLim_->InitSauve(Ass3->Nb_cas_assemb());
         lesCondLim_->ImposeConLimtdt(lesMail_,lesRef_,*mat_masse,vglobaal
                                      ,Ass3->Nb_cas_assemb(),cas_combi_ddl,vglob_stat);
         // puis on prépare (si besoin est en fonction du type de matrice) la résolution
          mat_masse->Preparation_resol();
        }  
      // ---  récupération (initialisation) des ddl  position, vitesse et accélération 
      // récupération au niveau global des ddl locaux avec conditions limite à tdt  
      // pour le vecteur accélération, seules les ddl avec CL sont différents de la précédente
      // récupération
      lesMail_->Vect_loc_vers_glob(TEMPS_tdt,X1,X_tdt,X1,Ass3->Nb_cas_assemb());
      lesMail_->Vect_loc_vers_glob(TEMPS_tdt,V1,vitesse_tdt,V1,Ass3->Nb_cas_assemb());
      lesMail_->Vect_loc_vers_glob(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1,Ass3->Nb_cas_assemb());
         
      // maintenant on met les conditions limites sur les ddls bloqués secondaires c-a-d associés
      // aux ddl bloqués par l'utilisateur, leur calcul dépend de l'algorithme d'où un calcul global
      list <LesCondLim::Gene_asso>::iterator ie,iefin=li_gene_asso.end();; // def d'un iterator adoc
      int ih=1; // indice
      for(ie=li_gene_asso.begin(),ih=1;ie!=iefin;ie++,ih++)
           // comme les valeurs des X V Gamma vont être écrasé par le calcul global, on utilise
           // des conteneurs intermédiaires
           {//trois cas
            LesCondLim::Gene_asso & s = (*ie); // pour simplifier
            int ix=s.pointe(1); // début des Xi 
            int iv=s.pointe(2); // début des Vi 
            int ig=s.pointe(3); // début des gammai
            // on utilise le schéma des différences finis décentré à droite 
            // pour calculer les valeurs des ddl dans le cas de ddl bloqué
            if (PremierDdlFamille(s.ty_prin) == X1) 
            // cas ou les Xi sont imposés, on calcul Vi et Gammai
               { X_Bl(ih) = X_tdt(ix);
                 V_Bl(ih) = (X_tdt(ix) - X_t(ix))*unsurdeltat ;
                 G_Bl(ih)= (V_Bl(ih)-vitesse_t(iv))*unsurdeltat ;
                }
            else if (PremierDdlFamille(s.ty_prin) == V1) 
            // cas ou les Vi sont imposés, calcul des Xi et Gammai
               { V_Bl(ih) = vitesse_tdt(iv);
                 G_Bl(ih) = (vitesse_tdt(iv)-vitesse_t(iv))*unsurdeltat ;
                 X_Bl(ih) = X_t(ix) + delta_t * vitesse_tdt(iv); 
                }
            else if (PremierDdlFamille(s.ty_prin) == GAMMA1) 
            // cas ou les gammai sont imposés, calcul des Vi et Xi
               { G_Bl(ih) = acceleration_tdt(ig);
                 V_Bl(ih) = vitesse_t(iv) + delta_t * acceleration_t(iv);
                 X_Bl(ih) = X_t(ix) + delta_t * vitesse_t(iv) 
                                + deltat2 * acceleration_t(ig);
                }
            acceleration_t(ig) = G_Bl(ih); // pour le cas ou il y a relachement des conditions limites
            // au prochain pas de temps
                
            };

      // ---- choix entre les différentes  phases 
      switch (phasage)
      	{case PREDICTION_bonelli:
          {// ----- calcul de la prédiction de déplacement au point d'intégration temporelle
           tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
           mat_masse->Simple_Resol_systID_2 (pPoint_i,vec_travail1); // M^{-1} * pPoint_i
           tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu
           // q_1 = q_0 + (a_a * delta2_total) * M^{-1} * pPoint_i
           q_1 = q_0 + (a_a * deltat2_total) * vec_travail1;
           // q_2 = q_0 + deltat_total * M^{-1} * p_i + b_b * deltat2_total * M^{-1} * pPoint_i
           tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
           mat_masse->Simple_Resol_systID_2 (p_0,vec_travail2); // M^{-1} * p_i  ,    (p_i = p_0)
           tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu
           q_2 = q_0 + delta_t_total * vec_travail2 + (b_b * deltat2_total) * vec_travail1;
           // -- maintenant on met réellement en place les CL a partir de la sauvegarde 
           // on considère que les X_t ont les bonnes conditions limites  
           for(ie=li_gene_asso.begin(),ih=1;ie!=iefin;ie++,ih++)
                {LesCondLim::Gene_asso & s = (*ie); // pour simplifier
                 int ix=s.pointe(1); // début des Xi 
//                 int iv=s.pointe(2); // début des Vi
//                 int ig=s.pointe(3); // début des gammai
                 q_2(ix) = X_Bl(ih);
                 q_1(ix) = X_t(ix);
                 };
           break;                  
          }
      	 case INTEGRATION_bonelli:
         {// -- calcul du champ de position à t+dt
           X_tdt = q_1 * phii(1) + q_2 * phii(2); // calcul des coordonnées au point d'integ en temps
           // -- calcul du champ de vitesse
           vitesse_tdt =  unsurdeltat_total *( (3. * (phii(1) - phii(2))) * q_1  
                         + (phii(1) + phii(2)) * q_2 + (2. * phii(2) - 4. * phii(1)) * q_0);
                                     
           // -- maintenant on met réellement en place les CL a partir de la sauvegarde   
           for(ie=li_gene_asso.begin(),ih=1;ie!=iefin;ie++,ih++)
                {LesCondLim::Gene_asso & s = (*ie); // pour simplifier
                 int ix=s.pointe(1); // début des Xi 
                 int iv=s.pointe(2); // début des Vi 
                 int ig=s.pointe(3); // début des gammai
                 X_tdt(ix) = X_Bl(ih);
                 vitesse_tdt(iv) = V_Bl(ih);
                 acceleration_tdt(ig) = G_Bl(ih); 
                 };            

           // --    passage des valeurs calculées aux niveaux des maillages
           lesMail_->Vect_glob_vers_local(TEMPS_tdt,X1,X_tdt,X1,Ass3->Nb_cas_assemb());
           lesMail_->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1,Ass3->Nb_cas_assemb());
           lesMail_->Vect_glob_vers_local(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1,Ass3->Nb_cas_assemb());
           break;                  
         }
      	 case CORRECTION_bonelli:
          {// ----- calcul de la correction de déplacement au point d'intégration temporelle
           tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
           q_1 -= delta_t_total * mat_masse->Simple_Resol_systID_2 (r_2_k,vec_travail1); //delta_t* M^{-1} * r_2_k
           q_2 -= delta_t_total * mat_masse->Simple_Resol_systID_2 (r_1_k,vec_travail1); //delta_t* M^{-1} * r_1_k 
           tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu


      //     Vecteur toto1 = delta_t_total * mat_masse->Simple_Resol_systID_2 (r_2_k,vec_travail1);
      //     Vecteur toto2 = delta_t_total * mat_masse->Simple_Resol_systID_2 (r_1_k,vec_travail1);
      //     cout << "\n r_1_k * q2= " << r_1_k * q_1 << " r_2_k * q1= " << r_2_k * q_2 
      //          << " || delta q1 || " << (toto1).Norme()/q_1.Norme()
      //          << " || delta q2 || " << (toto2).Norme()/q_2.Norme();
            
           // -- maintenant on met réellement en place les CL a partir de la sauvegarde 
           // on considère que les X_t ont les bonnes conditions limites  
           for(ie=li_gene_asso.begin(),ih=1;ie!=iefin;ie++,ih++)
                {LesCondLim::Gene_asso & s = (*ie); // pour simplifier
                 int ix=s.pointe(1); // début des Xi 
//                 int iv=s.pointe(2); // début des Vi
//                 int ig=s.pointe(3); // début des gammai
                 q_2(ix) = X_Bl(ih);
                 q_1(ix) = X_t(ix);
                 };
           break;                  
          }
      	 case FIN_DELTA_T_bonelli:
         {// -- calcul du champ de position à t+dt
         
           X_tdt = q_2; 
           vitesse_tdt = unsurdeltat_total * (-3. * q_1 + q_2 + 2. * q_0);
           // calcul de l'accélération du dernier point d'intégration = M^{-1} * (fex-fint)
           // stocker à tdt pour simplifier, mais correspond en fait au dernier point d'integ !!!!!
           tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
           mat_masse->Simple_Resol_systID_2 ((vglobaal),acceleration_tdt);
           tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu
           // -- maintenant on met réellement en place les CL a partir de la sauvegarde
           for(ie=li_gene_asso.begin(),ih=1;ie!=iefin;ie++,ih++)
                {LesCondLim::Gene_asso & s = (*ie); // pour simplifier
                 int ix=s.pointe(1); // début des Xi 
                 int iv=s.pointe(2); // début des Vi 
                 int ig=s.pointe(3); // début des gammai
                 X_tdt(ix) = X_Bl(ih);
                 vitesse_tdt(iv) = V_Bl(ih);
                 acceleration_tdt(ig) = G_Bl(ih); 
                 };            
           // --    passage des valeurs calculées aux niveaux des maillages
           lesMail_->Vect_glob_vers_local(TEMPS_tdt,X1,X_tdt,X1,Ass3->Nb_cas_assemb());
           lesMail_->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1,Ass3->Nb_cas_assemb());
           lesMail_->Vect_glob_vers_local(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1,Ass3->Nb_cas_assemb());
           break;                  
         }
      	};
		
  };
    
// calcul une approximation des différences énergie en jeux dans le cas Bonelli
// affichage éventuelle des ces énergies et du bilan
// V         : ddl de vitesse
// coef_mass : en fait il faut utiliser 1/coef_mass * mat_mass pour la matrice masse, ceci due à la spécificité de l'algo
// les différentes énergie et efforts généralisées sont des variables internes à l'algo
// en sortie: énergie cinétique : E_cin_tdt,  énergie interne : E_int_tdt, énergie externe = E_ext_tdt, bilan : bilan_E
//            idem avec les puissances
//            énergie visqueuse due aux forces visqueuses numériques
// icharge : compteur d'increment
// brestart : booleen qui indique si l'on est en restart ou pas
void AlgoBonelli::CalEnergieAffichageBonelli(const double& coef_mass,int icharge)
  { // -- le calcul est conditionnelle
    if (icharge >= pa.NbIncrCalEnergie())
      {
       // --- cas des énergies ------
       // initialisation 
       Vecteur & v_int = vec_travail1;
       v_int.Change_taille(vitesse_tdt.Taille()); v_int.Zero(); 
       // calcul de l'énergie cinétique
       E_cin_tdt = (0.5/coef_mass) * (vitesse_tdt * (mat_masse_sauve->Prod_vec_mat(vitesse_tdt,v_int)));
       // v_int contient les quantités de mouvement locales à chaque ddl
       // d'où calcul de la quantité de mouvement globale
       q_mov_tdt = v_int.Somme();
       // calcul de l'énergie interne dépensée
       E_int_tdt = E_int_t - (P_q1_k * vitesse_t + P_q2_k * vitesse_tdt);
       // calcul de l'énergie externe dépensée
       E_ext_tdt = E_ext_t + (P_i_1 * vitesse_t + P_i_2 * vitesse_tdt);     
       // bilan des énergies (on retire l'énergie cinétique initiale si elle exite)
       bilan_E = E_cin_tdt - E_cin_0 + E_int_tdt - E_ext_tdt;
       // --- cas des puissances ------
       // calcul de la puissance d'accélération
       // en fait ici correspond au dernier point d'intégration !!!!
       v_int.Zero(); 
       P_acc_tdt = (1./coef_mass) * (vitesse_tdt * (mat_masse_sauve->Prod_vec_mat(acceleration_tdt,v_int)));
       // calcul de la puissance interne au dernier point d'integ
       Vecteur& vitesse = vec_travail1;
       vitesse = dernier_phi(1) * vitesse_tplus + dernier_phi(2) * vitesse_tdt;
       P_int_tdt = vitesse * F_int_tdt;
       // calcul de la puissance externe au dernier point d'integ
       P_ext_tdt = vitesse * F_ext_tdt;
       // bilan des puissances au dernier point d'integ
       bilan_P_tdt = P_acc_tdt - P_int_tdt - P_ext_tdt;
       // cas des forces visqueuses numériques
//       if (pa.Amort_visco_artificielle())
//       	  E_visco_numerique_tdt = E_visco_numerique_t + delta_X * forces_vis_num; 
       // --- affichage ----
       if (( pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde))
           &&(pa.AfficheIncrEnergie()))
         {// cas des énergies
          cout << "\n energies: cin= "<< E_cin_tdt <<" int= " << E_int_tdt << " ext= " 
               << E_ext_tdt << " bilan= " << bilan_E << " qmv= " << q_mov_tdt;
          // cas des puissances
          cout << "\n puissances: acc= "<< P_acc_tdt <<" int= " << P_int_tdt << " ext= " 
               << P_ext_tdt << " bilan= " << bilan_P_tdt;
         };
       }
   };
                               
    //---- 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 AlgoBonelli::ActionInteractiveAlgo()
	{ cout << "\n commande? ";
	  return false; // pour l'instant !!!!!!!
	};
	
    // sortie du schemaXML: en fonction de enu
void AlgoBonelli::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 dynamique explicite dfc ********************  -->"
  	         << "\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;
		}
	};		
  };
	
	
	
	
	
	



  
