// 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 "AlgoriNewmark.h"
#include "ConstMath.h"


// CONSTRUCTEURS :
AlgoriNewmark::AlgoriNewmark () : // par defaut
   Algori(),beta_newmark(NULL),gamma_newmark(NULL),hht(NULL),stabilite(false)
       ,delta_t(),delta_t_2(),unSurBetaDeltaTcarre(),betaDelta_t_2()
       ,betaMoinsGammaSurBeta(),unSurGammaDeltat(),unMoinGamma(),unMoinGammasurgamma()
       ,zero5deltatcarreUnMoinDeuxBeta(),zero5deltatcarredeuxBeta(),deltatUnMoinGamma()
       ,deltatGamma(),unsurbetadeltat(),unmoinsdeuxbetasurdeuxbeta(),unSurBetaDeltaTcarre_o()
       ,nuAphaPrime(),coef_masse(),nuBetaPrime(),coef_raideur(),nuAphaPrimeunsurcoef_masse(),unsurcoef_masse()
       //----- cas du masse scaling pilotée
       ,avec_masse_scaling(false)
       ,et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique(false)
       ,ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique(false)
       ,ratioForce_inertieSurStatique(0.)
       ,et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur(false)
       ,ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur(false)
       ,ratioDiag_masseSurRaideur(0.)
       ,cL_a_chaque_iteration(0)

    // --------------------------------------------------------------------------------------
    // -- variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // --------------------------------------------------------------------------------------
       ,Ass1_(NULL),Ass2_(NULL),Ass3_(NULL),cas_combi_ddl(0),icas(0),prepa_avec_remont(false)
       ,brestart(false),type_incre(OrdreVisu::INCRE_0),vglobin(),vglobex(),vglobaal()
       ,vglobal_n(),vglobal_n_inter(),vcontact()
       ,delta_prec_X(),inter_tdt()
       ,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
       ,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_C_pt(NULL)
       ,matglob(NULL),assembMat(NULL),sauve_deltadept(NULL),sauve_dept_a_tdt(NULL)
       ,tab_mato(1)
       ,Vres(NULL),v_travail(NULL)
    // ------------------------------------------------------------------------------------------
    // -- fin variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // ------------------------------------------------------------------------------------------
  {// a priori ce constructeur n'est pas utilisé
   cout << "\n $$$$$$$$$ a priori ce constructeur n'est pas utilisable $$$$$$$ "
        << "\n revoir: AlgoriNewmark::AlgoriNewmark() " << endl;
   Sortie(1);
  };

// constructeur en fonction du type de calcul et du sous type
// il y a ici lecture des parametres attaches au type
AlgoriNewmark::AlgoriNewmark (const bool avec_typeDeCal
            ,const list <EnumSousTypeCalcul>& soustype
            ,const list <bool>& avec_soustypeDeCal
            ,UtilLecture& entreePrinc) :
   Algori(DYNA_IMP,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
        ,beta_newmark(NULL),gamma_newmark(NULL),hht(NULL),stabilite(false)
        ,delta_t(),delta_t_2(),unSurBetaDeltaTcarre(),betaDelta_t_2()
        ,betaMoinsGammaSurBeta(),unSurGammaDeltat(),unMoinGamma(),unMoinGammasurgamma()
        ,zero5deltatcarreUnMoinDeuxBeta(),zero5deltatcarredeuxBeta(),deltatUnMoinGamma()
        ,deltatGamma(),unsurbetadeltat(),unmoinsdeuxbetasurdeuxbeta(),unSurBetaDeltaTcarre_o()
        ,nuAphaPrime(),coef_masse(),nuBetaPrime(),coef_raideur(),nuAphaPrimeunsurcoef_masse(),unsurcoef_masse()
        //----- cas du masse scaling pilotée
        ,avec_masse_scaling(false)
        ,et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique(false)
        ,ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique(false)
        ,ratioForce_inertieSurStatique(0.)
        ,et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur(false)
        ,ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur(false)
        ,ratioDiag_masseSurRaideur(0.)
        ,cL_a_chaque_iteration(0)
    // --------------------------------------------------------------------------------------
    // -- variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // --------------------------------------------------------------------------------------
        ,Ass1_(NULL),Ass2_(NULL),Ass3_(NULL),cas_combi_ddl(0),icas(0),prepa_avec_remont(false)
        ,brestart(false),type_incre(OrdreVisu::INCRE_0),vglobin(),vglobex(),vglobaal()
        ,vglobal_n(),vglobal_n_inter(),vcontact()
        ,delta_prec_X(),inter_tdt()
        ,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
        ,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_C_pt(NULL)
        ,matglob(NULL),assembMat(NULL),sauve_deltadept(NULL),sauve_dept_a_tdt(NULL)
        ,tab_mato(1)
        ,Vres(NULL),v_travail(NULL)
    // ------------------------------------------------------------------------------------------
    // -- fin variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // ------------------------------------------------------------------------------------------
  { //vglobaal = &vglobin;
    // lecture des paramètres attachés au type de calcul (ici aucun)
    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); 
     }  
    // associations pour les tableaux de matrices
    tab_mato(1)=matglob;
   };
      
// constructeur de copie
AlgoriNewmark::AlgoriNewmark (const AlgoriNewmark& algo):
    Algori(algo)
       ,beta_newmark(NULL),gamma_newmark(NULL),hht(NULL),stabilite(false)
       ,delta_t(),delta_t_2(),unSurBetaDeltaTcarre(),betaDelta_t_2()
       ,betaMoinsGammaSurBeta(),unSurGammaDeltat(),unMoinGamma(),unMoinGammasurgamma()
       ,zero5deltatcarreUnMoinDeuxBeta(),zero5deltatcarredeuxBeta(),deltatUnMoinGamma()
       ,deltatGamma(),unsurbetadeltat(),unmoinsdeuxbetasurdeuxbeta(),unSurBetaDeltaTcarre_o()
       ,nuAphaPrime(),coef_masse(),nuBetaPrime(),coef_raideur(),nuAphaPrimeunsurcoef_masse(),unsurcoef_masse()
       //----- cas du masse scaling pilotée
       ,avec_masse_scaling(algo.avec_masse_scaling)
       ,et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique
           (algo.et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique)
       ,ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique
           (algo.ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique)
       ,ratioForce_inertieSurStatique(algo.ratioForce_inertieSurStatique)
       ,et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur
           (algo.et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur)
       ,ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur
           (algo.ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur)
       ,ratioDiag_masseSurRaideur(algo.ratioDiag_masseSurRaideur)
       ,cL_a_chaque_iteration(algo.cL_a_chaque_iteration)
    // --------------------------------------------------------------------------------------
    // -- variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // --------------------------------------------------------------------------------------
       ,Ass1_(NULL),Ass2_(NULL),Ass3_(NULL),cas_combi_ddl(0),icas(0)  
       ,prepa_avec_remont(false)
       ,brestart(false),type_incre(OrdreVisu::INCRE_0),vglobin(),vglobex(),vglobaal()
       ,vglobal_n(),vglobal_n_inter(),vcontact()
       ,delta_prec_X(),inter_tdt()
       ,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
       ,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_C_pt(NULL)
       ,matglob(NULL),assembMat(NULL),sauve_deltadept(NULL),sauve_dept_a_tdt(NULL)
       ,tab_mato(1)
       ,Vres(NULL),v_travail(NULL)
    // ------------------------------------------------------------------------------------------
    // -- fin variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // ------------------------------------------------------------------------------------------
    { //vglobaal = &vglobin;
	     beta_newmark = & paraTypeCalcul(1);
      gamma_newmark = & paraTypeCalcul(2);
      hht = & paraTypeCalcul(3);
      // associations pour les tableaux de matrices
      tab_mato(1)=matglob;
    };
   
// destructeur
AlgoriNewmark::~AlgoriNewmark ()
  {
    // --------------------------------------------------------------------------------------
    // -- variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // --------------------------------------------------------------------------------------
    if (mat_masse != NULL) delete mat_masse; 
    if (mat_C_pt != NULL) delete mat_C_pt;
    if (Ass1_ != NULL) delete Ass1_; 
    if (Ass2_ != NULL) delete Ass2_; 
    if (Ass3_ != NULL) delete Ass3_;
    {int taille = tab_mato.Taille();
     for (int i=1;i<=taille;i++)
       if (tab_mato(i)!= NULL)
          delete tab_mato(i);
    }
//    if (mato != NULL) delete mato;
    if (sauve_deltadept != NULL) delete sauve_deltadept;
    if (sauve_dept_a_tdt != NULL) delete sauve_dept_a_tdt;
    if (Vres != NULL) delete Vres;
    if (v_travail != NULL) delete v_travail;
    // ------------------------------------------------------------------------------------------
    // -- fin variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // ------------------------------------------------------------------------------------------
   }; 

// execution de l'algorithme 
void AlgoriNewmark::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
    // 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 : deux cas, soit avec une lecture initiale du .info, soit une lecture secondaire
        if (paraGlob->EtatDeLaLecturePointInfo() == 0)
          { // initialisation du calcul
         InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
          }
         else
         {MiseAJourAlgo(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
         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
             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
          {//  on fait le calcul d'équilibre
           // initialisation du calcul  : deux cas, soit avec une lecture initiale du .info, soit une lecture secondaire
           if (paraGlob->EtatDeLaLecturePointInfo() == 0)
              {InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
                }
           else {// on est en lecture secondaire
           
                 MiseAJourAlgo(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
           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 );
            };

          };// fin du cas sans commandes interactives
		   // 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 )
                { 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);
                };
              };
        }
       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 )
                { 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);
                };
              };
         };       
	  };
   // si on a forcé la sortie des itérations et incréments, il faut réinitialiser l'indicateur
   if (!(pa.EtatSortieEquilibreGlobal()))
     pa.ChangeSortieEquilibreGlobal(false);

  };

  
// lecture des paramètres du calcul
void AlgoriNewmark::lecture_Parametres(UtilLecture& entreePrinc)
 { // dimensionnement
   paraTypeCalcul.Change_taille(3); // donc le troisième est nulle par défaut
   Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_IMP); // transfert info
   MotCle motCle; // ref aux mots cle
   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,"hht")!=NULL)
         { // cas de la méthode hht, dans ce cas les paramètres beta et gamma sont fixés
           // le seul paramètre à lire est donc le hht c'est-à-dire alpha
           // lecture du nom du paramètre et vérification
           string st1;
           *(entreePrinc.entree) >> st1 ;
           if (st1 == "beta_et_gamma=")
             { cout << "\n erreur en lecture du parametre de l'algorithme newmark "
                    << "\n on attendait le mot : hht= , au lieu de " << st1
                    << "\n dans la methode hht les parametres beta et gamma sont definit à partir de hht"
                    << "\n AlgoriNewmark::lecture_Parametres( ... ";
               Sortie(1);
           }
           // lecture du paramètre hht     
           *(entreePrinc.entree) >> paraTypeCalcul(3);
           lecture_effective=true;  
           hht = & paraTypeCalcul(3);
           // on calcul les paramètres beta et gamma
           paraTypeCalcul(1) = (1.- (*hht))*(1.- (*hht))/4.;
           paraTypeCalcul(2) = 1./2. - (*hht);
           beta_newmark = & paraTypeCalcul(1);
           gamma_newmark = & paraTypeCalcul(2);
           stabilite=true;
         }
        else
         // cas de la méthode de newmark classique
         { // lecture du nom du paramètre et vérification
           string st1;
           *(entreePrinc.entree) >> st1 ;
           if (st1 != "beta_et_gamma=")
            { cout << "\n erreur en lecture du parametre de l'algorithme de newmark "
                   << "\n on attendait le mot : beta_et_gamma= , au lieu de " << st1
                   << "\n AlgoriNewmark::lecture_Parametres( ... ";
              Sortie(1);
             }     
           // lecture du parametre      
           *(entreePrinc.entree) >> paraTypeCalcul(1) >> paraTypeCalcul(2);
           lecture_effective=true;  
           // on relie les paramètres à béta et gamma
           beta_newmark = & paraTypeCalcul(1);
           gamma_newmark = & paraTypeCalcul(2);
           // si gamma n'est pas supérieur à 0.5 il ne peut pas y avoir stabilité même conditionnelle
           // hughes p.94, an. 1983 (belytschko et hughes)
           if ((*gamma_newmark) < 0.5)
            { cout << "\n erreur sur le parametre gamma de l'algorithme de newmark "
                   << "\n gamma doit etre superieur a 0.5 quelque soit la stabilite requise " << st1
                   << "\n AlgoriNewmark::lecture_Parametres( ... ";
              Sortie(1);
             }
           hht = & paraTypeCalcul(3); // le troisième est nulle par défaut donc ici == 0
           // vérification de la stabilité
           if ((2. *(*beta_newmark)) >= (*gamma_newmark))
            { // cas d'une stabilité inconditionnelle
              stabilite=true;}
           else { stabilite = false;} // stabilité conditionnelle    
         };
	       // si on a déjà lue une ligne on passe à l'enreg suivant
        if ((lecture_effective) && ( !motCle.SimotCle(entreePrinc.tablcar)))
          {entreePrinc.NouvelleDonnee(); // ligne suivante
           lecture_effective = false; // on re-init pour la suite
          };

        // -- cas où on veut faire du masse scaling avec éventuellement du pilotage
        if(strstr(entreePrinc.tablcar,"avec_pilote_masse_scaling_")!=0)
         {avec_masse_scaling = 1;
          string nom;
          entreePrinc.NouvelleDonnee(); // on se positionne sur un nouvel enreg
          // on lit tant que l'on ne rencontre pas la ligne contenant "fin_pilote_masse_scaling_"
          // ou un nouveau mot clé global auquel cas il y a pb !!
          MotCle motCle; // ref aux mots cle
          while (strstr(entreePrinc.tablcar,"fin_pilote_masse_scaling_")==0)
           {
            // si on a  un mot clé global dans la ligne courante c-a-d dans tablcar --> erreur
            if ( motCle.SimotCle(entreePrinc.tablcar))
             { cout << "\n erreur de lecture des parametre de reglage de masse scaling: on n'a pas trouve le mot cle "
                    << " fin_pilote_masse_scaling_ et par contre la ligne courante contient un mot cle global  ";
               entreePrinc.MessageBuffer("** erreur des parametres de pilotage de masse scaling **");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);     
             };
             
            // lecture d'un mot clé
            *(entreePrinc.entree) >> nom;
            
            if ((entreePrinc.entree)->rdstate() == 0)
              {} // lecture normale
            #ifdef ENLINUX 
            else  if ((entreePrinc->entree)->fail())
               // on a atteind la fin de la ligne et on appelle un nouvel enregistrement 
              {   entreePrinc->NouvelleDonnee();  // lecture d'un nouvelle enregistrement
                  *(entreePrinc->entree) >>nom;
              }
            #else
            else  if ((entreePrinc.entree)->eof())
              // la lecture est bonne mais on a atteind la fin de la ligne
              { if(nom != "fin_pilote_masse_scaling_")
                  {entreePrinc.NouvelleDonnee(); *(entreePrinc.entree) >> nom;};
              } 
            #endif  
            else // cas d'une erreur de lecture
             { cout << "\n erreur de lecture inconnue  ";
               entreePrinc.MessageBuffer("** erreur2 des parametres de reglage de masse scaling **");
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);     
             };
            
            // cas et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique
            if(nom == "et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique_")
             {et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique=true;
              // si on a déjà lue ou au lieu de et -> pas possible -> erreur
              if (ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique)
               { cout << "\n erreur en lecture on a auparavant: ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique_ "
                      << " c'est donc incoherent (car incompatible) "
                      << "\n AlgoriNewmark::lecture_Parametres(.. " << endl ;
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);          
               };
              *(entreePrinc.entree) >> ratioForce_inertieSurStatique;
              lecture_effective = true;
             }
            // cas ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique
            else if(nom == "ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique_")
             {ou_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique=true;
              // si on a déjà lue et au lieu de ou -> pas possible -> erreur
              if (et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique)
               { cout << "\n erreur en lecture on a auparavant: et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique_ "
                      << " c'est donc incoherent (car incompatible) "
                      << "\n AlgoriNewmark::lecture_Parametres(.. " << endl ;
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);          
               };
              *(entreePrinc.entree) >> ratioForce_inertieSurStatique;
              lecture_effective = true;
             }

            // cas ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur
            else if(nom == "ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur_")
             {ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur=true;
              // si on a déjà lue et au lieu de ou -> pas possible -> erreur
              if (et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur)
               { cout << "\n erreur en lecture on a auparavant: et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur_ "
                      << " c'est donc incoherent (car incompatible) "
                      << "\n AlgoriNewmark::lecture_Parametres(.. " << endl ;
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);          
               };
              *(entreePrinc.entree) >> ratioDiag_masseSurRaideur;
              lecture_effective = true;
             }
            // cas et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur
            else if(nom == "et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur_")
             {et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur=true;
              // si on a déjà lue ou au lieu de et -> pas possible -> erreur
              if (ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur)
               { cout << "\n erreur en lecture on a auparavant: ou_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur_ "
                      << " c'est donc incoherent (car incompatible) "
                      << "\n AlgoriNewmark::lecture_Parametres(.. " << endl ;
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie(1);          
               };
              *(entreePrinc.entree) >> ratioDiag_masseSurRaideur;
              lecture_effective = true;
             }

            // sinon ce n'est pas un mot clé connu, on le signale
            else if(nom != "fin_pilote_masse_scaling_")
             { cout << "\n erreur en lecture d'un parametre, le mot cle est inconnu "
                    << " on a lu : " << nom << endl;
               if (ParaGlob::NiveauImpression()>3)
                    cout << "\n AlgoriNewmark::lecture_Parametres( " << endl ;
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie(1);          
             }
            
           }; //-- fin du while
         }; //-- fin de la lecture des paramètres de réglage du masse scaling

        // 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
           lecture_effective = false; // on re-init pour la suite
          };

        //---- autres paramètres particuliers ---
        // on s'arrête lorsqu'il n'y a plus de mot clé spécifique à lire
        while ( (strstr(entreePrinc.tablcar,"cL_a_chaque_iteration_")!=NULL)
              )
                
            { string nom_mot_cle="";
              *(entreePrinc.entree) >> nom_mot_cle;
              if (nom_mot_cle == "cL_a_chaque_iteration_")
                { // on lit le paramètre
                  *(entreePrinc.entree) >> cL_a_chaque_iteration;
                  lecture_effective = true;
                }
              // gestion des fins de ligne
             
             
              if (    ((strstr(entreePrinc.tablcar,"cL_a_chaque_iteration_")==NULL)
                      )
                  &&  ((lecture_effective) && ( !motCle.SimotCle(entreePrinc.tablcar)))
                )
                 // s'il n'y a plus rien et que l'on vient de lire dans ce cas on tente la ligne suivante
                 {entreePrinc.NouvelleDonnee(); // ligne suivante
                  lecture_effective = false; // on re-init pour la suite
                 };

              #ifdef ENLINUX
              if ((entreePrinc.entree)->fail())
                     // on a atteind la fin de la ligne et on appelle un nouvel enregistrement
                {   entreePrinc.NouvelleDonnee();  // lecture d'un nouvelle enregistrement
                    }
              #else
              if ((entreePrinc.entree)->eof())
              // la lecture est bonne mais on a atteind la fin de la ligne
              {  entreePrinc.NouvelleDonnee();  // lecture d'un nouvelle enregistrement
               }
       //     #endif
              #endif
                 // sinon ce n'est pas une ligne ad hoc, la lecture s'arrêtera
            }; // -- fin du while sur les paramètres particulier

      }
    else // sinon on met une valeur par défaut 
      {  paraTypeCalcul(1) = 0.25; paraTypeCalcul(2) = 0.5;paraTypeCalcul(3) = 0.;
         beta_newmark = & paraTypeCalcul(1);
         gamma_newmark = & paraTypeCalcul(2);
         hht = & paraTypeCalcul(3); //c-a-d 0 par défaut
         stabilite=true;
         cL_a_chaque_iteration = 0;
       };
   // on vérifie que la valeur hht lue conduit à un algo inconditionnellement stable
   if (((*hht) < -(1./3.)) || ((*hht) > 0))
     cout << "\n *** attention le parametre de la methode HHT est en dehors de l'interval [-1/3,0]"
          << " la stabilite sera donc conditionnellement stable !!"
          << " \n cependant aucune modification du pas de temps propose par l'utilisateur n'est realise"
          << " \n la stabilite est donc a controler par l'utilisateur !!";


   // 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);  
  };     

// é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 AlgoriNewmark::Ecrit_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas)
 {
    // récup du flot
    ofstream * sort = entreePrinc.Sort_BI();
//    (*sort) << "\n parametres_algo_specifiques_ "<< Nom_TypeCalcul(this->TypeDeCalcul());
    if (cas == 1)
     { // ecriture des parametres      
       *(sort) << " beta_et_gamma= " << paraTypeCalcul(1) << " "
               <<  paraTypeCalcul(2) << " ";
       // écriture  du paramètre hht
       *(sort) << " hht= " << paraTypeCalcul(3)  << " ";
       // et le paramètre
       *(sort)  << " cL_a_chaque_iteration "<< cL_a_chaque_iteration << " ";
      };
//    (*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  : fonctionnememt 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 AlgoriNewmark::Lecture_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas,bool choix)
{if (cas == 1)
 {// dimensionnement
  paraTypeCalcul.Change_taille(3);
  if (choix)
   {// cas d'une lecture normale
    // récup du flot
    ifstream * ent = entreePrinc.Ent_BI();
    string toto;
    // lecture du premier parametre      
    *(ent) >> toto ;
    if (toto != "beta_et_gamma=")
      { cout << "\n erreur en lecture du parametre de l'algorithme explicite "
             << "\n on attendait le mot : beta_et_gamma= , au lieu de " << toto
             << "\n AlgoriNewmark::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    *(ent) >> paraTypeCalcul(1) >> paraTypeCalcul(2);
    // idem pour le paramètre hht
    *(ent) >> toto >> paraTypeCalcul(3);
    // lecture de cL_a_chaque_iteration
    *(ent) >> toto ;
    if (toto != "cL_a_chaque_iteration")
      { cout << "\n erreur en lecture du parametre cL_a_chaque_iteration"
             << "\n on attendait le mot : cL_a_chaque_iteration , au lieu de " << toto
             << "\n AlgoriNewmark::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }
    *(ent) >> cL_a_chaque_iteration ;
   }
  else
   {// cas où la lecture n'est pas possible, attribution des valeurs par défaut
    paraTypeCalcul(1) = 0.25; paraTypeCalcul(2) = 0.5;paraTypeCalcul(3) = 0.;
    cL_a_chaque_iteration = 0;
    }  
  // on relie les paramètres à béta et gamma
  beta_newmark = & paraTypeCalcul(1);
  gamma_newmark = & paraTypeCalcul(2);
  hht = & paraTypeCalcul(3);
  }    
};

// création d'un fichier de commande: cas des paramètres spécifiques
void AlgoriNewmark::Info_commande_parametres(UtilLecture& entreePrinc)
 {  // écriture dans le fichier de commande
    ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
    sort << "\n#-------------------------------------------------------------------"
         << "\n|  parametres (falcultatifs) associes l'algorithme de Newmark      |"
         << "\n#-------------------------------------------------------------------"
         << "\n"
         << "\n    PARA_TYPE_DE_CALCUL"
         << "\n  #    ..........................................................."
         << "\n  #   / facteur beta  puis facteur gamma,  (ou facteur hht)     /"
         << "\n  #  / (dans le cas de la methode hht: beta et gamma sont fixe)/"
         << "\n  # / ( il ne sont donc pas à indiquer )                      /"
         << "\n  #..........................................................." 
         << "\n      # hht=  0.05 "
         << "\n        beta_et_gamma= 0.25  0.5 "

         << "\n  #  ................................................................"
         << "\n  # / mise en place des conditions limites a chaque iteration       /"
         << "\n  #.................................................................."
         << "\n  # mot cle : cL_a_chaque_iteration_  suivi de 0 ou 1  "
         << "\n  #  par defaut == 0, c-a-d que les CL sont mises en place  "
         << "\n  # au debut de chaque increment et ensuite reste fixe pendant les iterations "
         << "\n  # == 1 : a chaque iteration, les CL sont de nouveaux imposes  "

         << "\n   ";
         
	  // appel de la classe mère
	  Algori::Info_com_parametres(entreePrinc);
   sort << "\n" << endl;
 };

    // gestion et vérification du pas de temps et modif en conséquence si nécessaire
    // cas = 1: initialisation du pas de temps et de l'amortissement numérique si nécessaire
    //          ceci pour le temps t=0
    // cas = 2: initialisation du pas de temps 
    //          ceci pour le temps t
void AlgoriNewmark::Gestion_pas_de_temps(LesMaillages * lesMail,int cas)
 {  bool modif_deltat = false; // booleen pour la prise en compte éventuelle de la modif du temps éventuelle
    static double coef_delta_crit; // coef multiplicateur du pas critique
    if (cas==1) 
      { // dans le cas où le pas de temps ou le pas de temps maxi dépendent d'un pas critique, 
        // ou dans le cas où la stabilitée est conditionnelle on  calcul le pas de temps critique
        // et on met à jour les pas de temps
        if ((pa.DeltatOuDeltatmaxDependantTempsCritique())|| !stabilite)
         // 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
         {  // --<NM>--  on calcul le pas de temps minimal 
            delta_t = pa.Deltat(); double delta_t_old = delta_t;
            double l_sur_c = lesMail->Longueur_arrete_mini_sur_c(TEMPS_0);
            double delta_t_essai = l_sur_c  ;
            if (!stabilite) // calcul du delta t critique conditionnel
               { coef_delta_crit = ConstMath::Pi * pow((0.5 * (*gamma_newmark) - (*beta_newmark)),-0.5);
                 delta_t_essai *=  coef_delta_crit;
                 }
            // mise à jour éventuel du pas de temps et du pas de temps maxi et mini s'ils sont définit à partir du temps critique,
            // par contre il n'y a pas adéquation entre le deltat et les mini et maxi
            modif_deltat = 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 (!stabilite && (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 stabilite conditionnelle de Newmark, "
                     << "\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;	
              };
            // on modifie éventuellement le pas de temps dans les bornes mini et maxi
            if (pa.Modif_Detat_dans_borne(delta_t))
             { cout << "\n **** modification du pas de temps "<<delta_t_old<<"   entre les bornes mini et maxi "
          	         << " le nouveau pas de temps = "<<delta_t<<endl;
             };
         };
        delta_t = pa.Deltat();
        delta_t_2 = delta_t * delta_t; 
        unSurBetaDeltaTcarre = 1./delta_t_2/(*beta_newmark);
        betaDelta_t_2 = (*beta_newmark) * delta_t_2;
        // def de coeffs simplificateurs
        betaMoinsGammaSurBeta = ((*beta_newmark)-(*gamma_newmark))/(*beta_newmark);
        unSurGammaDeltat = 1./( (*gamma_newmark)* delta_t); 
        unMoinGamma = 1. - (*gamma_newmark); 
        unMoinGammasurgamma = unMoinGamma/(*gamma_newmark);     
        zero5deltatcarreUnMoinDeuxBeta= (0.5 * (delta_t*delta_t)) * ((1.- 2. * (*beta_newmark))); 
        zero5deltatcarredeuxBeta =  (0.5 * (delta_t*delta_t)) * (2. * (*beta_newmark)); 
        deltatUnMoinGamma = delta_t * (1.-(*gamma_newmark)); 
        deltatGamma = delta_t * (*gamma_newmark);                                    
        unsurbetadeltat =  1./( (*beta_newmark) * delta_t);                                   
        unmoinsdeuxbetasurdeuxbeta = (1.-2.*(*beta_newmark))/(2.*(*beta_newmark));
        // cas de l'amortissement numérique
        nuAphaPrime=0.; coef_masse = 1.; nuAphaPrimeunsurcoef_masse = 0.;
        unsurcoef_masse =1.;  nuBetaPrime=0.;  coef_raideur = 1.;
        //  dans le cas où l'on utilise de l'amortissement numérique, calcul des coefs 
        // 1° la matrice masse vaux théoriquement : (1/(beta*delta t2) + nu * alphaPrime * gamma/(beta*delta t)) [M]
        //  mais ici dans le programme on utilise [M]/(beta delta t2), donc pour tenir compte de la viscosité il faut 
        //  multiplier cette viscosité dynamique par le coef : coef_masse
        // 2° la matrice raideur vaux théoriquement (1. + nu*betaPrime*gamme / (beta*Delta t))[K] d'où le coef coef_raideur
        // 3° pour le second membre on a pour la partie visqueuse: [C] qPoint = nu(alphaPrime[M] + betaPrime[K]) qPoint
        //    mais on utilisera pour plus de facilité, la prémultiplication des vecteurs ce qui permettra de ne pas 
        //    modifier les matrices d'où les coef nuAphaPrimeBetatDelta_t_2 et nuBetaPrime, le premier étant particulier
        //    parceque l'on utilise une matrice masse modifiée
        if (pa.Amort_visco_artificielle())
         {if (pa.CoefRayleighMasse()!=0.)
            {nuAphaPrime = pa.Visco_artificielle() * pa.CoefRayleighMasse(); 
             coef_masse= betaDelta_t_2 * (unSurBetaDeltaTcarre + nuAphaPrime * (*gamma_newmark)*unsurbetadeltat);
             unsurcoef_masse = 1./coef_masse;
             nuAphaPrimeunsurcoef_masse = nuAphaPrime * unsurcoef_masse;
            };
          if (pa.CoefRayleighRaideur()!=0.)
            { nuBetaPrime = pa.Visco_artificielle() * pa.CoefRayleighRaideur();
              coef_raideur = 1. + nuBetaPrime * (*gamma_newmark)*unsurbetadeltat;
            };
         };
      }
    else if (cas==2)
      {  // dans le cas ou la stabilité est conditionnelle
         // on regarde si le pas de temps n'est pas devenu supérieur au pas critique
         if (!stabilite)
          { double l_sur_c = lesMail->Longueur_arrete_mini_sur_c(TEMPS_t);
            double delta_t_essai = l_sur_c * coef_delta_crit ;double ancien_pas=delta_t; 
            // 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)) 
              { delta_t = pa.Coefficient_pas_critique_deltat() * 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;                 
              }
            } // -- fin du cas de la stabilité conditionnelle
         // maintenant on regarde le cas ou on a définit des temps maxi et/ou min, dépendants du pas de temps critique
         if (pa.DeltatOuDeltatmaxDependantTempsCritique())
         // 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
         {  // --<NM>--  on calcul le pas de temps minimal 
            double delta_t_old = delta_t;
            double l_sur_c = lesMail->Longueur_arrete_mini_sur_c(TEMPS_0);
            double delta_t_essai = l_sur_c  ;
            // mise à jour éventuel du pas de temps et du pas de temps maxi et mini s'ils sont définit à partir du temps critique,
            // par contre il n'y a pas adéquation entre le deltat et les mini et maxi
            modif_deltat = 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
            // on modifie éventuellement le pas de temps dans les bornes mini et maxi
            if (pa.Modif_Detat_dans_borne(delta_t))
             { cout << "\n **** modification du pas de temps "<<delta_t_old<<"   entre les bornes mini et maxi "
          	         << " le nouveau pas de temps = "<<delta_t<<endl;
             };
         };
       
         delta_t = pa.Deltat(); delta_t_2 = delta_t * delta_t; 
         // mise à jour du coef de  la matrice de masse en fonction de la nouvelle
         // valeur de unSurBetaDeltaTcarre
         unSurBetaDeltaTcarre_o = unSurBetaDeltaTcarre; // sauvegarde de l'ancienne facteur de la matrice masse
         unSurBetaDeltaTcarre = 1./delta_t_2/(*beta_newmark); // nouvelle valeur

         betaDelta_t_2 = (*beta_newmark) * delta_t_2;
         // mise à jour des  coeffs simplificateurs
         unSurGammaDeltat = 1./( (*gamma_newmark)* delta_t); 
         zero5deltatcarreUnMoinDeuxBeta= (0.5 * (delta_t*delta_t)) * ((1.- 2. * (*beta_newmark))); 
         zero5deltatcarredeuxBeta =  (0.5 * (delta_t*delta_t)) * (2. * (*beta_newmark)); 
         deltatUnMoinGamma = delta_t * (1.-(*gamma_newmark)); 
         deltatGamma = delta_t * (*gamma_newmark); 
         unsurbetadeltat =  1./( (*beta_newmark) * delta_t);                                   
         //  cas où l'on utilise de l'amortissement numérique, calcul des coefs (cf intro visqueux au début du programme)
         coef_masse = 1.; // initialisation
         if (pa.Amort_visco_artificielle())
           { if (Arret_A_Equilibre_Statique())  // si on veut un équilibre statique, on sauvegarde les forces statiques
				          (*vglob_stat) = vglobaal;
			          if (pa.CoefRayleighMasse()!=0.)
               {nuAphaPrime = pa.Visco_artificielle() * pa.CoefRayleighMasse(); 
                coef_masse= betaDelta_t_2 * (unSurBetaDeltaTcarre + nuAphaPrime * (*gamma_newmark)*unsurbetadeltat);
                unsurcoef_masse = 1./coef_masse;
                nuAphaPrimeunsurcoef_masse = nuAphaPrime * unsurcoef_masse;
               };
             if (pa.CoefRayleighRaideur()!=0.)
              { nuBetaPrime = pa.Visco_artificielle() * pa.CoefRayleighRaideur();
                coef_raideur = 1. + nuBetaPrime * (*gamma_newmark)*unsurbetadeltat;
              };
          };
        } //-- fin du cas == 2                  
 };

 
    // pilotage éventuel du masse scaling
void AlgoriNewmark::Pilotage_masse_scaling(const double& moy_diag_masse,const double& moy_diag_K
                                           ,const int& sauve_indic_convergence)
 {
   // on adapte en fonction de la cible si on a une différence de plus de 3%
   const double diffPermi=0.03;
   double multi=5.; // init
  
 
   if (sauve_indic_convergence >= 0)
    {if (  ((et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur)
          && (Dabs(moy_diag_K)>ConstMath::trespetit)
         )
       && ((et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur)
           && (Dabs(moy_diag_K)>ConstMath::trespetit)
          )
       )
      {// on calcul le rapport
       double ratio_actuel_1 = moy_diag_masse/moy_diag_K;
       double ratio_actuel_2 = (P_acc_t+ConstMath::trespetit)/(Dabs(- P_int_t - P_ext_t)+ConstMath::trespetit);
       if (Dabs(ratioDiag_masseSurRaideur/ratio_actuel_1) > Dabs(ratioDiag_masseSurRaideur/ratio_actuel_2))
         {if (diffpourcent(ratio_actuel_1,ratioDiag_masseSurRaideur,ratioDiag_masseSurRaideur,diffPermi))
           {(*mat_masse) *= Dabs(ratioDiag_masseSurRaideur/ratio_actuel_1);
            if (ParaGlob::NiveauImpression()>3)
              cout << "\n Pilotage_masse_scaling diag : modif coeff mat_mass= "<< Dabs(ratioDiag_masseSurRaideur/ratio_actuel_1)
                   << endl;
           }
          else
           {if (diffpourcent(ratio_actuel_2,ratioForce_inertieSurStatique,ratioForce_inertieSurStatique,diffPermi))
              {(*mat_masse) *= Dabs(ratioForce_inertieSurStatique/ratio_actuel_2);
               if (ParaGlob::NiveauImpression()>3)
                {cout << "\n Pilotage_masse_scaling puiss : modif coeff mat_mass= "<< Dabs(ratioForce_inertieSurStatique/ratio_actuel_2);
                 cout << "\n debug: P_acc_t=  "<<P_acc_t<<",  abs(- P_int_t - P_ext_t)= "<< Dabs(- P_int_t - P_ext_t)
                      << " ratio_actuel= "<<ratio_actuel_2<<", ratio_cible= "<<ratioForce_inertieSurStatique;
                 cout << endl;
                };
              };
           };
         };
      }
     else if ((et_pilotage_masse_scaling_par_maxRatioDiag_masseSurRaideur)
         && (Dabs(moy_diag_K)>ConstMath::trespetit))
      {// on calcul le rapport
       double ratio_actuel = moy_diag_masse/moy_diag_K;
       if (diffpourcent(ratio_actuel,ratioDiag_masseSurRaideur,ratioDiag_masseSurRaideur,diffPermi))
         {(*mat_masse) *= Dabs(ratioDiag_masseSurRaideur/ratio_actuel);
          if (ParaGlob::NiveauImpression()>3)
            cout << "\n Pilotage_masse_scaling: modif coeff mat_mass= "<< Dabs(ratioDiag_masseSurRaideur/ratio_actuel)
                 << endl;
         };
      }
     else if (et_pilotage_masse_scaling_par_maxRatioForce_inertieSurStatique)
      {// on calcul le rapport. Pour cela on se sert des puissances déjà stockées
       // pour éviter des divergences au moment des itérations, on utilise les grandeurs à t
       double ratio_actuel = (P_acc_t+ConstMath::trespetit)/(Dabs(- P_int_t - P_ext_t)+ConstMath::trespetit);
       if (diffpourcent(ratio_actuel,ratioForce_inertieSurStatique,ratioForce_inertieSurStatique,diffPermi))
         {(*mat_masse) *= Dabs(ratioForce_inertieSurStatique/ratio_actuel);
          if (ParaGlob::NiveauImpression()>3)
            {cout << "\n Pilotage_masse_scaling: modif coeff mat_mass= "<< Dabs(ratioForce_inertieSurStatique/ratio_actuel);
             cout << "\n debug: P_acc_t=  "<<P_acc_t<<",  abs(- P_int_t - P_ext_t)= "<< Dabs(- P_int_t - P_ext_t)
                  << " ratio_actuel= "<<ratio_actuel<<", ratio_cible= "<<ratioForce_inertieSurStatique;
             cout << endl;
            };
         };
      };
   }
   // si on a eu une divergence on multiplie par un coef l'augmentation de masse
   else //if (sauve_indic_convergence < 0)
     { if (ParaGlob::NiveauImpression()>3)
          cout << "\n Pilotage_masse_scaling: divergence donc multi mat_mass= "<< multi
               << endl;
       (*mat_masse) *= multi;
     };
 
 
 };




       //---- 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 AlgoriNewmark::ActionInteractiveAlgo()
	{ cout << "\n commande? ";
	  return false;
	};


