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


// Résolution du problème mécanique en explicite dynamique sans contact
void AlgoriTchamwa::Calcul_Equilibre2(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_TCHAMWA); // 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
    // 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);
    // on récupère la courbe de modulation de phi
    // -- on regarde si la courbe existe, si oui on récupère la référence  sinon erreur
    if (lesCourbes1D->Existe(nom_courbe_CGamma_pourVarPhi)) 
         { CGamma_pourVarPhi = lesCourbes1D->Trouve(nom_courbe_CGamma_pourVarPhi);
          }
    else
       	{ cout << "\n erreur la courbe de moderation pour phi :" << nom_courbe_CGamma_pourVarPhi
       	       << " : fonction de gamma n'existe pas !! " 
       	       << "\n AlgoriTchamwa::Calcul_Equilibre2(.... ";
       	  Sortie(1);
    	};
    
    // --<T W>--  on se place dans le cadre de l'algorithme proposé par Tchamwa et Wielgoz
    // dans le cas où l'on calcul des contraintes et/ou déformation et/ou un estimateur d'erreur
    // à chaque incrément, initialisation
    Tableau <Enum_ddl> tenuXVG(3);tenuXVG(1)=X1;tenuXVG(2)=V1;tenuXVG(3)=GAMMA1;
    bool 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);};      
    // 00 --<T W>-- 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);
    // 01 --<T W>--  récup du pas de temps, proposé par l'utilisateur, initialisation et vérif / pas critique
    this->Gestion_pas_de_temps(true,lesMail,1,0.); // 1 signifie qu'il y a initialisation
    // on défini globalement que l'on a une combinaison des ddl X V GAMMA en même temps   
    int 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
    Assemblage Ass1(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
    Assemblage Ass2(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
    Assemblage Ass3(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
    Tableau <Nb_assemb> t_assemb(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
    const int icas = 1; // pour indiquer au module Tableau_indice que l'on travaille avec l'association X V GAMMA
    li_gene_asso = lesCondLim->Tableau_indice (lesMail,t_assemb
                                                   ,lesRef,charge->Temps_courant(),icas); 
    // on définit trois tableau qui serviront à stocker transitoirement les X V GAMMA correspondant au ddl imposés
    int ttsi = li_gene_asso.size();
    Vecteur X_Bl(ttsi),V_Bl(ttsi),G_Bl(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

    //  6 vecteur pour une manipulation globale des positions vitesses et accélérations
    // vecteur qui globalise toutes les positions de l'ensemble des noeuds
    // dans le cas où on initialise les ddl_tdt(n) avec les ddl_t(n)+delta_ddl(n-1), def de grandeurs
    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_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
    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
    // cas de l'utilisation de la modération en moyenne d'accélération
    if (npas_moyacc > 0) 
      {moy_acc.Change_taille(nbddl_X);moy_acc_en_calcul.Change_taille(nbddl_X);
       npas_effectue=0;
       };
    // mise à jour au cas où
    Algori::MiseAJourAlgoMere(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp,diversStockage
                           ,charge,lesCondLim,lesContacts,resultats);

    //  initialisation du compteur d'increments de charge
    icharge = 1;
    //--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
    bool 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(true,lesMail,2,0.); // 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()) 
     { // 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())->seekp(0);
          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())->seekp(debut_increment);
         }                         
      }                           
    //--fin cas de restart et/ou de sauvegarde--------

    // choix de la matrice de masse, qui est en fait celle qui correspond au ddl Xi
    Mat_abstraite* mat_masse=NULL;Mat_abstraite* mat_masse_sauve=NULL;
    // 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);
    Mat_abstraite& matrice_mas = *mat_masse;Mat_abstraite& matrice_mas_sauve = *mat_masse_sauve;
    // choix de la résolution
    if (matrice_mas.Type_matrice() == DIAGONALE)
      // dans le cas d'une matrice diagonale on force la résolution directe quelque soit l'entrée
      matrice_mas.Change_Choix_resolution(DIRECT_DIAGONAL,pa.Type_preconditionnement());
    else
      matrice_mas.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,matrice_mas,diversStockage,lesRef,X1,lesFonctionsnD);
    // on sauvegarde la matrice masse
    matrice_mas_sauve = matrice_mas;
    // dans le cas où l'on utilise de l'amortissement numérique la matrice masse est modifiée
    // en fait ici cela correspond à : ([M] +  [C] delta t) avec [C] = nu [M]
    // pour le second membre il est également nécessaire de tenir compte du terme -[C] V(n)
    // il nous faut donc la matrice de viscosité    
    Mat_abstraite * mat_C_pt=NULL; 
    Vecteur forces_vis_num(0); // forces visqueuses d'origines numériques
    if (pa.Amort_visco_artificielle()) 
      { bool initial = true; // def de la matrice (place et valeurs)
        mat_C_pt = Cal_mat_visqueux_num_expli(matrice_mas,mat_C_pt,delta_X,initial,vitesse_tdt);
        forces_vis_num.Change_taille(nbddl_X);
		  if (Arret_A_Equilibre_Statique())  // si on veut un équilibre statique, on sauvegarde les forces statiques
				    vglob_stat->Change_taille(vglobaal.Taille());
       };         
    Mat_abstraite & mat_C = *mat_C_pt; 
    // 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,matrice_mas,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
    matrice_mas.Preparation_resol();
    OrdreVisu::EnumTypeIncre type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul
    if (amortissement_cinetique)		
        Algori::InitialiseAmortissementCinetique(); // initialisation des compteurs pour l'amortissement au cas ou

    tempsInitialisation.Arret_du_comptage(); // temps cpu
    tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
   
    //  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
    bool arret=false; // booleen pour arrêter indépendamment de la charge
    double max_delta_X=0.; //  le maxi du delta X
    double max_var_delta_X=0.; // idem d'une itération à l'autre
    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)
    { double maxPuissExt;   // maxi de la puissance des efforts externes
      double maxPuissInt;   // maxi de la puissance des efforts internes 
      double maxReaction;   // maxi des reactions 
      int inReaction = 0;   // pointeur d'assemblage pour le maxi de reaction
      int inSol =0 ;        // pointeur d'assemblage du maxi de variation de ddl      
      double maxDeltaDdl=0; // // maxi de variation de ddl
      // initialisation de la variable puissance_précédente d'une itération à l'autre
//      double puis_precedente = 0.;
      
      // 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);
      // 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
      //  gestion du pas de temps, vérif / pas critique
      this->Gestion_pas_de_temps(false,lesMail,2,0.); // 2 signifie cas courant
      bool modif_temps = charge->Avance(); // avancement de la charge et donc du temps courant
      //-- si le temps a changé il faut de nouveau appeler la gestion du pas de temps
      // car il y a des grandeurs reliées au pas de temps qui y sont calculé
      if (modif_temps)
          this->Gestion_pas_de_temps(true,lesMail,2,0.); // 2 signifie cas courant
        
      // affichage de l'increment de charge
      bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier
      if (aff_incr)
        {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
      //  calcul de l'increment
      // initialisation des deux partie du second membre
      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
      // 2_3 --<T W>-- imposition des ddls bloqués
      // initialisation des coordonnees et des ddl a tdt en fonctions des 
      // ddl imposes et de l'increment du chargement et des conditions linéaires imposées
      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);
      //  mise en place des conditions linéaires
      lesCondLim->MiseAJour_condilineaire_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
         matrice_mas = matrice_mas_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,matrice_mas,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
          matrice_mas.Preparation_resol();
        }  
      // 1_0 --<T W>--  récupération (initialisation) des ddl  position, vitesse et accélération 
      lesMail->Vect_loc_vers_glob(TEMPS_t,X1,X_t,X1);
      lesMail->Vect_loc_vers_glob(TEMPS_t,V1,vitesse_t,V1);
      lesMail->Vect_loc_vers_glob(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
      // récupération au niveau global des ddl locaux à tdt avec conditions limite 
      // 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);
      lesMail->Vect_loc_vers_glob(TEMPS_tdt,V1,vitesse_tdt,V1);
      lesMail->Vect_loc_vers_glob(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1);
         
      // 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
            // quelquesoit la valeur de phi du schéma de tchamwa, on utilise le schéma des différences finis
            // centrés 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 temsp
                
            };
            
      // 1_1 --<T W>--  calcul du champ de vitesse
      vitesse_tdt = vitesse_t + delta_t * acceleration_t;
      // 2_0 --<T W>-- calcul du champ de position à t+dt
      // - on boucle sur les ddl, sur lesquels une modération du facteur phi est appliquée
      for (int i=1;i<= nbddl_X;i++)
       { double phi_modif= (*phi_1);
         if (npas_moyacc > 0) // cas de l'utilisation de la modération en moyenne d'accélération
          { double dmoy = Dabs(moy_acc(i));
            if (dmoy >= valmax) {phi_modif =1.;} // dmoy grand, il y a vraiment une augmentation diff des oscillations
            else if (dmoy >= valmin) // cas d'une interpolation linéaire
             { phi_modif = ((dmoy - valmin) * 1. + (valmax - dmoy) * (*phi_1) )/ (valmax - valmin);};
            // dans le dernier cas : dmoy < valmin on a phi_modif= (*phi_1); ce qui est déjà 
          };
        double fact= deltat2 * (1.+CGamma_pourVarPhi->Valeur(Dabs(acceleration_t(i)))*(phi_modif-1.));
        X_tdt(i) = X_t(i) + delta_t * vitesse_t(i) 
                  + fact * acceleration_t(i);
       };
                  
      // -- 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); 
            }            
    // cas de l'utilisation de la modération en moyenne d'accélération
    if (npas_moyacc > 0) 
      {if (npas_effectue < npas_moyacc) // cas normal
          // on intègre en simpson
          {moy_acc_en_calcul += (0.5 * delta_t)* (acceleration_t + acceleration_tdt);
           npas_effectue++;		
          };
        if (npas_effectue == npas_moyacc) // cas où la somme est fini
          {moy_acc = moy_acc_en_calcul / npas_moyacc ;
           moy_acc_en_calcul.Zero();
           if (ParaGlob::NiveauImpression() > 6)
              cout << "\n valeur moyenne  de moy acc = " << moy_acc.Somme()/nbddl_X 
                   << " maxi = " << moy_acc.Max_val_abs(); 
           npas_effectue=0;
          };
       };

      // 2_1 --<T W>--    passage des valeurs calculées aux niveaux des maillages
      lesMail->Vect_glob_vers_local(TEMPS_tdt,X1,X_tdt,X1);
      lesMail->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1);
      // accélération à t : seules celles correspondantes au CL ont variées
      lesMail->Vect_glob_vers_local(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
      // 3 --<T W>-- calcul des puissances internes et externe
      // 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;};
      maxPuissExt = vglobex.Max_val_abs();
      F_ext_tdt = vglobex; // sauvegarde des forces généralisées extérieures
      // 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

      // second membre total
      vglobaal += vglobex ;vglobaal += vglobin ;
      // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée
      if (pa.Amort_visco_artificielle()) 
        { if (Arret_A_Equilibre_Statique())  // si on veut un équilibre statique, on sauvegarde les forces statiques
				          (*vglob_stat) = (vglobaal);
			       Cal_mat_visqueux_num_expli(matrice_mas_sauve,mat_C_pt,delta_X,false,vitesse_tdt); // init de C éventuelle
          vglobaal -=  mat_C.Prod_mat_vec(vitesse_t,forces_vis_num);
         };
      // initialisation des sauvegardes sur second membre (uniquement pour les gammai)
   // non en fait pour les gammai
      lesCondLim->InitSauve(Ass3.Nb_cas_assemb());
      // sauvegarde des reactions aux ddl bloque (uniquement pour les Xi)
   // non en fait pour les gammai
		// 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
//      lesCondLim->ReacApresCHrepere(vglobin,lesMail,lesRef,Ass3.Nb_cas_assemb(),cas_combi_ddl);

      // mise en place des conditions limites sur les Xi
 //     lesCondLim->ImposeConLimtdt(lesMail,lesRef,vglobal,Ass1.Nb_cas_assemb(),cas_combi_ddl);
      // sur les Vi
//      lesCondLim->ImposeConLimtdt(lesMail,lesRef,vglobal,Ass2.Nb_cas_assemb(),cas_combi_ddl);
      // sur les Gammai
      lesCondLim->ImposeConLimtdt(lesMail,lesRef,vglobaal,Ass3.Nb_cas_assemb()
		                          ,cas_combi_ddl,vglob_stat);
      
      // calcul du maxi des reactions (pour les xi)
      maxReaction = lesCondLim->MaxEffort(inReaction,Ass3.Nb_cas_assemb());
      // sortie d'info sur l'increment concernant les réactions 
      if ( aff_incr)
          InfoIncrementReac(lesMail,inReaction,maxReaction,Ass3.Nb_cas_assemb());
      
      // examen de la convergence si nécessaire, utilisant le résidu
		bool arretResidu = false; // pour gérer le cas particulier ou on veut un arrêt et sur le résidu et sur le déplacement
      if (ArretEquilibreStatique() && (icharge>1))// cas d'une convergence en utilisant le résidu
       { double toto=0.; int itera = 0; // valeur par defaut pour ne pas se mettre dans un cas  itératif de type algo de Newton
         bool arret_demande = false; // normalement n'intervient pas ici, car il n'y a pas de prise en compte d'iteration                                          
         arret = Convergence(aff_incr,toto,vglobaal,maxPuissExt,maxPuissInt,maxReaction,itera,arret_demande);
         if (arret) 
           { // sortie des itérations sauf si l'on est en loi simplifiée
             if (lesLoisDeComp->Test_loi_simplife() )
              {lesLoisDeComp->Loi_simplifie(false); // cas d'une loi simplifié on remet normal
               arret = false; 
               } 
             else {if(ArretEquilibreStatique() == 2) { arretResidu=1;} 
				       else { cout << "\n   critere equilibre statique satisfait pour l'increment : "  
						             << icharge << " " <<endl; 
						 break;}
						} // cas normal, 
           };
       };
      
      // 4 --<T W>-- calcul des accélérations
      residu_final = vglobaal; // sauvegarde pour le post-traitement
      // resolution simple (fonction du type de matrice)
      tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
      matrice_mas.Simple_Resol_systID_2 (vglobaal,acceleration_tdt,pa.Tolerance()
                                ,pa.Nb_iter_nondirecte(),pa.Nb_vect_restart());
      tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu
     
      // calcul du maxi de variation de ddl
      maxDeltaDdl = acceleration_tdt.Max_val_abs(inSol);
      // sortie d'info sur l'increment concernant les variations de ddl 
      if ( aff_incr &&(ParaGlob::NiveauImpression() > 1))
         InfoIncrementDdl(lesMail,inSol,maxDeltaDdl,Ass3.Nb_cas_assemb());
      
      // calcul des énergies et affichage des balances
//      delta_X.Zero(); delta_X += X_tdt; delta_X -= X_t; // X_tdt - X_t
      Algori::Cal_Transfert_delta_et_var_X(max_delta_X,max_var_delta_X);
      CalEnergieAffichage(1.,vitesse_tdt,matrice_mas_sauve,delta_X,icharge,brestart,acceleration_tdt,forces_vis_num);
      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,matrice_mas_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);}
      // examen de la convergence éventuelle, utilisant le déplacement et/ou le résidu
		if (Pilotage_fin_relaxation_et_ou_residu(relax_vit_acce,0,icharge,arretResidu,arret)) 
			      break;
			        
      //  passage des accélérations calculées aux niveaux des maillages
      lesMail->Vect_glob_vers_local(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1);
      // actualisation des ddl et des grandeurs actives de t+dt vers t
      lesMail->TdtversT();
      // 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());
      //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);};
      // sauvegarde de l'incrément si nécessaire
      tempsCalEquilibre.Arret_du_comptage(); // on arrête le compteur pour la sortie
      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
      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()
      icharge++;
      Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
     }
    // fin des calculs
    tempsCalEquilibre.Arret_du_comptage(); // temps cpu
    // passage finale dans le cas d'une visualisation  au fil du calcul
    type_incre = OrdreVisu::DERNIER_INCRE;  
    VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge
                          ,lesCondLim,lesContacts,resultats,type_incre,icharge);
    // sauvegarde 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()));                 
  };
  
// Résolution du problème mécanique en explicite 
// programme test (regarder les commentaires dans le code)
void AlgoriTchamwa::Calcul_Equilibre4(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_TCHAMWA); // 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
    // 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);
    // on récupère la courbe de modulation de phi
    // -- on regarde si la courbe existe, si oui on récupère la référence  sinon erreur
    if (lesCourbes1D->Existe(nom_courbe_CGamma_pourVarPhi)) 
         { CGamma_pourVarPhi = lesCourbes1D->Trouve(nom_courbe_CGamma_pourVarPhi);
          }
    else
       	{ cout << "\n erreur la courbe de moderation pour phi :" << nom_courbe_CGamma_pourVarPhi
       	       << " : fonction de gamma n'existe pas !! " 
       	       << "\n AlgoriTchamwa::Calcul_Equilibre2(.... ";
       	  Sortie(1);
    	};
    
    // --<T W>--  on se place dans le cadre de l'algorithme proposé par Tchamwa et Wielgoz
    // dans le cas où l'on calcul des contraintes et/ou déformation et/ou un estimateur d'erreur
    // à chaque incrément, initialisation
    Tableau <Enum_ddl> tenuXVG(3);tenuXVG(1)=X1;tenuXVG(2)=V1;tenuXVG(3)=GAMMA1;
    bool 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);};      
    // 00 --<T W>-- 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);
    // 01 --<T W>--  récup du pas de temps, proposé par l'utilisateur, initialisation et vérif / pas critique
    this->Gestion_pas_de_temps(true,lesMail,1,0.); // 1 signifie qu'il y a initialisation
    // on défini globalement que l'on a une combinaison des ddl X V GAMMA en même temps   
    int 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
    Assemblage Ass1(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
    Assemblage Ass2(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
    Assemblage Ass3(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
    Tableau <Nb_assemb> t_assemb(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
    const int icas = 1; // pour indiquer au module Tableau_indice que l'on travaille avec l'association X V GAMMA
    li_gene_asso = lesCondLim->Tableau_indice (lesMail,t_assemb
                                                   ,lesRef,charge->Temps_courant(),icas); 
    // on définit trois tableau qui serviront à stocker transitoirement les X V GAMMA correspondant au ddl imposés
    int ttsi = li_gene_asso.size();
    Vecteur X_Bl(ttsi),V_Bl(ttsi),G_Bl(ttsi);                                               
    // def vecteurs globaux
    // 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
    //  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_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) ;
    //  04 --<T W>--  6 vecteur pour une manipulation globale des positions vitesses et accélérations
    // calcul des énergies
    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
    // mise à jour au cas où
    Algori::MiseAJourAlgoMere(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp,diversStockage
                           ,charge,lesCondLim,lesContacts,resultats);

    //  initialisation du compteur d'increments de charge
    icharge = 1;
    //--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
    bool 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(true,lesMail,2,0.); // 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()) 
     { // 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())->seekp(0);
          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())->seekp(debut_increment);
         }                         
      }                           
    //--fin cas de restart et/ou de sauvegarde--------

    // choix de la matrice de masse, qui est en fait celle qui correspond au ddl Xi
    Mat_abstraite* mat_masse=NULL;Mat_abstraite* mat_masse_sauve=NULL;
    // 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);
    Mat_abstraite& matrice_mas = *mat_masse;Mat_abstraite& matrice_mas_sauve = *mat_masse_sauve;
    // choix de la résolution
    if (matrice_mas.Type_matrice() == DIAGONALE)
      // dans le cas d'une matrice diagonale on force la résolution directe quelque soit l'entrée
      matrice_mas.Change_Choix_resolution(DIRECT_DIAGONAL,pa.Type_preconditionnement());
    else
      matrice_mas.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,matrice_mas,diversStockage,lesRef,X1,lesFonctionsnD);
    // on sauvegarde la matrice masse
    matrice_mas_sauve = matrice_mas;
    // dans le cas où l'on utilise de l'amortissement numérique la matrice masse est modifiée
    // en fait ici cela correspond à : ([M] +  [C] delta t) avec [C] = nu [M]
    // pour le second membre il est également nécessaire de tenir compte du terme -[C] V(n)
    // il nous faut donc la matrice de viscosité    
    Mat_abstraite * mat_C_pt=NULL; 
    Vecteur forces_vis_num(0); // forces visqueuses d'origines numériques
    if (pa.Amort_visco_artificielle()) 
      { bool initial = true; // def de la matrice (place et valeurs)
        mat_C_pt = Cal_mat_visqueux_num_expli(matrice_mas,mat_C_pt,delta_X,initial,vitesse_tdt);
        forces_vis_num.Change_taille(nbddl_X);
		  if (Arret_A_Equilibre_Statique())  // si on veut un équilibre statique, on sauvegarde les forces statiques
	         { if (vglob_stat != NULL)
             {vglob_stat->Change_taille(vglobaal.Taille());}
           else
             {vglob_stat  = new Vecteur(vglobaal.Taille());}
         };
       };         
    Mat_abstraite & mat_C = *mat_C_pt; 
    // 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,matrice_mas,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
    matrice_mas.Preparation_resol();
    OrdreVisu::EnumTypeIncre type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul
    if (amortissement_cinetique)		
        Algori::InitialiseAmortissementCinetique(); // initialisation des compteurs pour l'amortissement au cas ou

    tempsInitialisation.Arret_du_comptage(); // temps cpu
    tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
   
    //  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
    bool arret=false; // booleen pour arrêter indépendamment de la charge
    int decal_fenetre=0;
    double max_delta_X=0.; //  le maxi du delta X
    double max_var_delta_X=0.; // idem d'une itération à l'autre
    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)
    { double maxPuissExt;   // maxi de la puissance des efforts externes
      double maxPuissInt;   // maxi de la puissance des efforts internes 
      double maxReaction;   // maxi des reactions 
      int inReaction = 0;   // pointeur d'assemblage pour le maxi de reaction
      int inSol =0 ;        // pointeur d'assemblage du maxi de variation de ddl      
      double maxDeltaDdl=0; // // maxi de variation de ddl
      // initialisation de la variable puissance_précédente d'une itération à l'autre
//      double puis_precedente = 0.;
      
      // 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);
      // 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
      //  gestion du pas de temps, vérif / pas critique
      this->Gestion_pas_de_temps(false,lesMail,2,0.); // 2 signifie cas courant
      bool modif_temps = charge->Avance(); // avancement de la charge et donc du temps courant
      //-- si le temps a changé il faut de nouveau appeler la gestion du pas de temps
      // car il y a des grandeurs reliées au pas de temps qui y sont calculé
      if (modif_temps)
          this->Gestion_pas_de_temps(true,lesMail,2,0.); // 2 signifie cas courant
     
      // affichage de l'increment de charge
      bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier
      if (aff_incr)
        {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
      //  calcul de l'increment
      // initialisation des deux partie du second membre
      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
      // 2_3 --<T W>-- imposition des ddls bloqués
      // initialisation des coordonnees et des ddl a tdt en fonctions des 
      // ddl imposes et de l'increment du chargement et des conditions linéaires imposées
      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);
      //  mise en place des conditions linéaires
      lesCondLim->MiseAJour_condilineaire_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
         matrice_mas = matrice_mas_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,matrice_mas,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
          matrice_mas.Preparation_resol();
        }  
      // 1_0 --<T W>--  récupération (initialisation) des ddl  position, vitesse et accélération 
      lesMail->Vect_loc_vers_glob(TEMPS_t,X1,X_t,X1);
      lesMail->Vect_loc_vers_glob(TEMPS_t,V1,vitesse_t,V1);
      lesMail->Vect_loc_vers_glob(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
      // récupération au niveau global des ddl locaux à tdt avec conditions limite 
      // 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);
      lesMail->Vect_loc_vers_glob(TEMPS_tdt,V1,vitesse_tdt,V1);
      lesMail->Vect_loc_vers_glob(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1);
         
      // 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
            // quelquesoit la valeur de phi du schéma de tchamwa, on utilise le schéma des différences finis
            // centrés 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 temsp
                
            };
            
      // 1_1 --<T W>--  calcul du champ de vitesse
      vitesse_tdt = vitesse_t + delta_t * acceleration_t;
      // 2_0 --<T W>-- calcul du champ de position à t+dt
      // - on boucle sur les ddl, sur lesquels une modération du facteur phi est appliquée
      for (int i=1;i<= nbddl_X;i++)
       {double fact= deltat2 * (1.+CGamma_pourVarPhi->Valeur(Dabs(acceleration_t(i)))*((*phi_1)-1.));
        X_tdt(i) = X_t(i) + delta_t * vitesse_t(i) 
                  + fact * acceleration_t(i);
       };
                  
      // -- 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); 
            }            

      // 2_1 --<T W>--    passage des valeurs calculées aux niveaux des maillages
      lesMail->Vect_glob_vers_local(TEMPS_tdt,X1,X_tdt,X1);
      lesMail->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1);
      // accélération à t : seules celles correspondantes au CL ont variées
      lesMail->Vect_glob_vers_local(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
      // 3 --<T W>-- calcul des puissances internes et externe
      // 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;};
      maxPuissExt = vglobex.Max_val_abs();
      F_ext_tdt = vglobex; // sauvegarde des forces généralisées extérieures
      // 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

      // second membre total
      vglobaal += vglobex ;vglobaal += vglobin ;

      // dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée
      if (pa.Amort_visco_artificielle()) 
        { if (Arret_A_Equilibre_Statique())  // si on veut un équilibre statique, on sauvegarde les forces statiques
				    ( *vglob_stat) = (vglobaal);
          Cal_mat_visqueux_num_expli(matrice_mas_sauve,mat_C_pt,delta_X,false,vitesse_tdt); // init de C éventuelle
          vglobaal -=  mat_C.Prod_mat_vec(vitesse_t,forces_vis_num);
         };
      // initialisation des sauvegardes sur second membre (uniquement pour les gammai)
   // non en fait pour les gammai
      lesCondLim->InitSauve(Ass3.Nb_cas_assemb());
      // sauvegarde des reactions aux ddl bloque (uniquement pour les Xi)
   // non en fait pour les gammai
		// 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
//      lesCondLim->ReacApresCHrepere(vglobin,lesMail,lesRef,Ass3.Nb_cas_assemb(),cas_combi_ddl);

      // mise en place des conditions limites sur les Xi
 //     lesCondLim->ImposeConLimtdt(lesMail,lesRef,vglobal,Ass1.Nb_cas_assemb(),cas_combi_ddl);
      // sur les Vi
//      lesCondLim->ImposeConLimtdt(lesMail,lesRef,vglobal,Ass2.Nb_cas_assemb(),cas_combi_ddl);
      // sur les Gammai
      lesCondLim->ImposeConLimtdt(lesMail,lesRef,vglobaal,Ass3.Nb_cas_assemb()
		                             ,cas_combi_ddl,vglob_stat);
      
      // calcul du maxi des reactions (pour les xi)
      maxReaction = lesCondLim->MaxEffort(inReaction,Ass3.Nb_cas_assemb());
      // sortie d'info sur l'increment concernant les réactions 
      if ( aff_incr)
          InfoIncrementReac(lesMail,inReaction,maxReaction,Ass3.Nb_cas_assemb());
      
      // examen de la convergence si nécessaire, utilisant le résidu
		bool arretResidu = false; // pour gérer le cas particulier ou on veut un arrêt et sur le résidu et sur le déplacement
      if (ArretEquilibreStatique() && (icharge>1))// cas d'une convergence en utilisant le résidu
       { double toto=0.; int itera = 0; // valeur par defaut pour ne pas se mettre dans un cas  itératif de type algo de Newton
         bool arret_demande = false; // normalement n'intervient pas ici, car il n'y a pas de prise en compte d'iteration                                          
         arret = Convergence(aff_incr,toto,vglobaal,maxPuissExt,maxPuissInt,maxReaction,itera,arret_demande);
         if (arret) 
           { // sortie des itérations sauf si l'on est en loi simplifiée
             if (lesLoisDeComp->Test_loi_simplife() )
              {lesLoisDeComp->Loi_simplifie(false); // cas d'une loi simplifié on remet normal
               arret = false; 
               } 
             else {if(ArretEquilibreStatique() == 2) { arretResidu=1;} 
				       else { cout << "\n   critere equilibre statique satisfait pour l'increment : "  
						             << icharge << " " <<endl; 
						 break;}
						} // cas normal, 
           };
       };
      
      // 4 --<T W>-- calcul des accélérations
      residu_final = vglobaal; // sauvegarde pour le post-traitement
      // resolution simple (fonction du type de matrice)
      tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
      matrice_mas.Simple_Resol_systID_2 (vglobaal,acceleration_tdt,pa.Tolerance()
                                ,pa.Nb_iter_nondirecte(),pa.Nb_vect_restart());
      tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu

      // calcul du maxi de variation de ddl
      maxDeltaDdl = acceleration_tdt.Max_val_abs(inSol);
      // sortie d'info sur l'increment concernant les variations de ddl 
      if ( aff_incr &&(ParaGlob::NiveauImpression() > 1))
         InfoIncrementDdl(lesMail,inSol,maxDeltaDdl,Ass3.Nb_cas_assemb());
      
      // calcul des énergies et affichage des balances
//      delta_X.Zero(); delta_X += X_tdt; delta_X -= X_t; // X_tdt - X_t
      Algori::Cal_Transfert_delta_et_var_X(max_delta_X,max_var_delta_X);
      CalEnergieAffichage(1.,vitesse_tdt,matrice_mas_sauve,delta_X,icharge,brestart,acceleration_tdt,forces_vis_num);
      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,matrice_mas_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);}
      // examen de la convergence éventuelle, utilisant le déplacement et/ou le résidu
		    if (Pilotage_fin_relaxation_et_ou_residu(relax_vit_acce,0,icharge,arretResidu,arret)) 
			      break;
			        
      //  passage des accélérations calculées aux niveaux des maillages
      lesMail->Vect_glob_vers_local(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1);
      // actualisation des ddl et des grandeurs actives de t+dt vers t
      lesMail->TdtversT();
      // 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());      
      //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);};
      // sauvegarde de l'incrément si nécessaire
      tempsCalEquilibre.Arret_du_comptage(); // on arrête le compteur pour la sortie
      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
      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()
      icharge++;
      Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
      
      // ---------------------------------------------------------------------------------
      //    glissement de la fenêtre de calcul 
      // ---------------------------------------------------------------------------------
      
      if ( icharge > type4_inc_deb)
      {if (decal_fenetre < type4_inc_deplace)
      	  {decal_fenetre ++;}
      	else
      	  { // 1) décalage des degrés de libertés de positions
      	   decal_fenetre =0; // re-initialisation pour la suite
      	  };
      };
     }
    // on remet à jour le nombre d'incréments qui ont été effectués:
    icharge--;
    Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
    // fin des calculs
    tempsCalEquilibre.Arret_du_comptage(); // temps cpu
    // passage finale dans le cas d'une visualisation  au fil du calcul
    type_incre = OrdreVisu::DERNIER_INCRE;  
    VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge
                          ,lesCondLim,lesContacts,resultats,type_incre,icharge);
    // sauvegarde 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()));                 
  };
	
    //---- 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 AlgoriTchamwa::ActionInteractiveAlgo()
	{ cout << "\n commande? ";
	  return false;
	};
	
    // sortie du schemaXML: en fonction de enu
void AlgoriTchamwa::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 de Tchamwa ********************  -->"
  	         << "\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;
		}
	};		
  };