// 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 "AlgoriNonDyna.h"
#include "TypeQuelconqueParticulier.h"

// CONSTRUCTEURS :
AlgoriNonDyna::AlgoriNonDyna() : // par defaut
   Algori()
  {// a priori ce constructeur n'est pas utilisé
   cout << "\n $$$$$$$$$ a priori ce constructeur n'est pas utilisable $$$$$$$ "
        << "\n revoir: AlgoriNonDyna::AlgoriNonDyna() " << endl;
   Sortie(1);
  };
     
// constructeur en fonction du type de calcul et du sous type
// il y a ici lecture des parametres attaches au type
AlgoriNonDyna::AlgoriNonDyna (const bool avec_typeDeCal
                              ,const list <EnumSousTypeCalcul>& soustype
                              ,const list <bool>& avec_soustypeDeCal
                              ,UtilLecture& entreePrinc) :
    Algori(NON_DYNA,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
    // --------------------------------------------------------------------------------------
    // -- variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // --------------------------------------------------------------------------------------
    ,Ass_(NULL),cas_combi_ddl(0),icas(0),compteur(0),prepa_avec_remont(false)
    ,brestart(false),type_incre(OrdreVisu::INCRE_0),vglobin(),vglobex(),vglobaal(),vcontact()
    ,delta_prec_X(),forces_vis_num(0)
    ,matglob(NULL),assembMat(NULL),sauve_deltadept(NULL),sauve_dept_a_tdt(NULL)
    ,tab_mato(1),tab_matsauve(1),tab_tab_matmoysauve(1)
    ,Vres(NULL),v_travail(NULL),matsauve(NULL),tab_matmoysauve(NULL)
    // ------------------------------------------------------------------------------------------
    // -- fin variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // ------------------------------------------------------------------------------------------
        // --- accélération de convergence --------- 
    ,Vi(),Yi(),coef_ai(),mat_ai(),Sm_ai(),X_extrapol(),S_0(),sauve_sol()
    ,nb_vec_cycle(8),cas_acceleration_convergence(1),acceleration_convergence(false)
    // ------------------------------------------------------------------------------------------
    // -- newton modifié --
    // ------------------------------------------------------------------------------------------
    ,deb_newton_modifie(-1) // par défaut pas de Newton modifié
    ,fin_newton_modifie(-1) // par défaut pas de fin
    ,nb_iter_NM(3)
    // ------------------------------------------------------------------------------------------
    // -- moyenne de raideur --
    // ------------------------------------------------------------------------------------------
    ,deb_raideur_moyenne(-1) // par défaut pas de moyenne
    ,fin_raideur_moyenne(-1) // par défaut pas de fin
    ,nb_raideur_moyenne(3) // par défaut on utilise 3 matrice successives
    ,cL_a_chaque_iteration(0)

  { // lecture des paramètres attachés au type de calcul (ici aucun)
    switch (entreePrinc.Lec_ent_info())
    { case 0 : 
       {// appel de la méthode de lecture de paramètre 
        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); 
    };
    // dimensionnement conditionnel
    if (acceleration_convergence)
      { Vi.Change_taille(nb_vec_cycle+2);
        Yi.Change_taille(nb_vec_cycle+2);
        coef_ai.Change_taille(nb_vec_cycle+1);
        mat_ai.Change_taille(nb_vec_cycle+1,nb_vec_cycle+1);
        Sm_ai.Change_taille(nb_vec_cycle+1);
    	 };
    // associations pour les tableaux de matrices
    tab_mato(1)=matglob;tab_matsauve(1)=matsauve;
    tab_tab_matmoysauve(1)= tab_matmoysauve;
   };
      
// constructeur de copie
AlgoriNonDyna::AlgoriNonDyna (const AlgoriNonDyna& algo):
    Algori(algo)
    // --------------------------------------------------------------------------------------
    // -- variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // --------------------------------------------------------------------------------------
    ,Ass_(NULL),cas_combi_ddl(0),icas(0)  
    ,compteur(0),prepa_avec_remont(false)
    ,brestart(false),type_incre(OrdreVisu::INCRE_0),vglobin(),vglobex()
    ,vglobaal(),delta_prec_X(),forces_vis_num(0),vcontact()
    ,matglob(NULL),assembMat(NULL),sauve_deltadept(NULL),sauve_dept_a_tdt(NULL)
    ,tab_mato(1),tab_matsauve(1),tab_tab_matmoysauve(1)
    ,Vres(NULL),v_travail(NULL),matsauve(NULL),tab_matmoysauve(NULL)
    // ------------------------------------------------------------------------------------------
    // -- fin variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // ------------------------------------------------------------------------------------------
        // --- accélération de convergence --------- 
    ,Vi(algo.Vi),Yi(algo.Yi),coef_ai(algo.coef_ai)
    ,mat_ai(algo.mat_ai),Sm_ai(algo.Sm_ai),X_extrapol(algo.X_extrapol),S_0(algo.S_0),sauve_sol()
    ,nb_vec_cycle(algo.nb_vec_cycle),cas_acceleration_convergence(algo.cas_acceleration_convergence)
    ,acceleration_convergence(algo.acceleration_convergence)
    // ------------------------------------------------------------------------------------------
    // -- newton modifié --
    // ------------------------------------------------------------------------------------------
    ,deb_newton_modifie(algo.deb_newton_modifie)
    ,fin_newton_modifie(algo.fin_newton_modifie)
    ,nb_iter_NM(algo.nb_iter_NM)
    // ------------------------------------------------------------------------------------------
    // -- moyenne de raideur --
    // ------------------------------------------------------------------------------------------
    ,deb_raideur_moyenne(algo.deb_raideur_moyenne) // par défaut pas de moyenne
    ,fin_raideur_moyenne(algo.fin_raideur_moyenne) // par défaut pas de fin
    ,nb_raideur_moyenne(algo.nb_raideur_moyenne) // par défaut on utilise 3 matrice successives
    ,cL_a_chaque_iteration(algo.cL_a_chaque_iteration)
    {
      // dimensionnement conditionnel
      if (acceleration_convergence)
        { Vi.Change_taille(nb_vec_cycle+2);
          Yi.Change_taille(nb_vec_cycle+2);
          coef_ai.Change_taille(nb_vec_cycle+1);
          mat_ai.Change_taille(nb_vec_cycle+1,nb_vec_cycle+1);
          Sm_ai.Change_taille(nb_vec_cycle+1);
        };
      // associations pour les tableaux de matrices
      tab_mato(1)=matglob;tab_matsauve(1)=matsauve;
      tab_tab_matmoysauve(1)= tab_matmoysauve;
    };
   
// destructeur
AlgoriNonDyna::~AlgoriNonDyna ()
  {
    // --------------------------------------------------------------------------------------
    // -- variables de transferts internes  entre: InitAlgorithme, CalEquilibre, FinCalcul -- 
    // --------------------------------------------------------------------------------------
    if (Ass_ != NULL ) delete Ass_;
    {int taille = tab_mato.Taille();
     for (int i=1;i<=taille;i++)
       if (tab_mato(i)!= NULL)
          delete tab_mato(i);
    }
//    if (matglob != NULL) delete matglob;
    {int taille = tab_matsauve.Taille();
     for (int i=1;i<=taille;i++)
       if (tab_matsauve(i)!= NULL)
          delete tab_matsauve(i);
    }
//    if (matsauve != NULL) delete matsauve;
    {int taille = tab_tab_matmoysauve.Taille();
     for (int i=1;i<=taille;i++)
       if (tab_tab_matmoysauve(i)!= NULL)
         {Tableau <Mat_abstraite*> * tab_matmoysauve_i = tab_tab_matmoysauve(i); // par simplicité
          int tail = tab_matmoysauve_i->Taille();
          for (int j=1; j<= tail;j++)
            if ((*tab_matmoysauve_i)(j) != NULL)
              delete (*tab_matmoysauve_i)(j);
         };
    };
//    if (tab_matmoysauve.Taille() != 0)
//     { int tail = tab_matmoysauve.Taille();
//       for (int i=1; i<= tail;i++)
//         if (tab_matmoysauve(i) != NULL) {delete tab_matmoysauve(i);}
//     };
    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 -- 
    // ------------------------------------------------------------------------------------------
    // suppression des variables consultables
//    ParaGlob::param->Suppression_place_grandeur_consultable(description_compteur);
//    ParaGlob::param->Suppression_place_grandeur_consultable(description_icharge);

   }; 

// execution de l'algorithme dans le cas non dynamique, implicit, sans contact
void AlgoriNonDyna::Execution(ParaGlob * paraGlob,LesMaillages * lesMail
               ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
               ,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock
               ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats)
  { Tableau < Fonction_nD* > * tb_combiner = NULL; // ici ne sert pas
  #ifdef UTILISATION_MPI
    int proc_en_cours = ParaGlob::Monde()->rank();
  #endif
    // on définit le type de  calcul a effectuer :
    if ( soustypeDeCalcul->size()==0 )
      // cas où il n'y a pas de sous type, on fait le calcul d'équilibre classique
      // signifie que le type principal est forcément valide
       { // initialisation du calcul : 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 {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
         // bref que l'on n'a pas fini, sinon on passe
         if (! (charge->Fin(icharge,true) ) )
          { // calcul de l'équilibre
            CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats
                              ,tb_combiner);
            // fin du calcul, pour l'instant on ne considère pas les autres sous-types
            FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
          };
       }
    else
     {if ( avec_typeDeCalcul )
        // cas où le type principal est valide et qu'il y a des sous_types
      { // on regarde si le sous-type "commandeInteractive" existe, si oui on le met en place
        // détermine si le sous type de calcul existe et s'il est actif
        if (paraGlob->SousTypeCalcul(commandeInteractive))
          {// -- cas avec commandes interactives
           // initialisation du calcul 
           InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
                              ,divStock,charge,lesCondLim,lesContacts,resultats );
           // calcul de l'équilibre tant qu'il y a des commandes
           while (ActionInteractiveAlgo())
           	{// on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
             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 )
                { // en MPI seul le proc 0 fait une sortie sur fichier (I/O classique, normalement le fichier n'est pas gros)
                #ifdef UTILISATION_MPI
                  // seule le process 0 fait la résolution globale
                  if (proc_en_cours == 0)
                   {
                #endif
                    cout << "\n================================================================="
                         << "\n|   ecriture des maillages en cours         en .her et .lis     |"
                         << "\n================================================================="
                         << endl;
           
                    // -----  sort les informations sur fichiers
                    // Affichage des donnees des maillages dans des fichiers dont le nom est construit
                    // à partir du nom de chaque maillage au format  ".her" et ".lis"
                    lesMail->Affiche_maillage_dans_her_lis(TEMPS_tdt,*lesRef);
                #ifdef UTILISATION_MPI
                  };
                #endif
                };
              };
		    }
     else
        // cas ou le type principal n'est pas valide
        // on ne fait que le calcul complémentaire           
        { list <EnumSousTypeCalcul>::const_iterator ili,ili_fin = soustypeDeCalcul->end();
          list <bool>::const_iterator ila;
          for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin();
             ili!=ili_fin;ili++,ila++)
             if (*ila) // cas où le sous type est valide  
               {if (Remonte_in(*ili)) // on test la présence du calcul de remonté
                 { // certaines initialisations sont nécessaires car c'est le premier calcul
                   Algori::InitRemontSigma(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
                   Algori::InitErreur(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
                   Algori::RemontSigma(lesMail);
                   Algori::RemontErreur(lesMail);
                  }
                else if ( (*ili) == sauveMaillagesEnCours )
                { // en MPI seul le proc 0 fait une sortie sur fichier (I/O classique, normalement le fichier n'est pas gros)
                #ifdef UTILISATION_MPI
                  // seule le process 0 fait la résolution globale
                  if (proc_en_cours == 0)
                   {
                #endif
                    cout << "\n================================================================="
                         << "\n|   ecriture des maillages en cours         en .her et .lis     |"
                         << "\n================================================================="
                         << endl;
           
                    // -----  sort les informations sur fichiers
                    // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
                    // à partir du nom de chaque maillage au format  ".her" et ".lis"
                    // a priori ici on n'a pas fait de calcul donc on sort les grandeurs à t
                    lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
                #ifdef UTILISATION_MPI
                  };
                #endif
                };
              };
         }       
      }
    // 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 AlgoriNonDyna::lecture_Parametres(UtilLecture& entreePrinc)
 { MotCle motCle; // ref aux mots cle
   Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(NON_DYNA); // transfert info
   deja_lue_entete_parametre = 1; // a priori pas de lecture d'entête
   // on se positionne sur le prochain mot clé
   do 
     { entreePrinc.NouvelleDonnee();
     }
   while ( !motCle.SimotCle(entreePrinc.tablcar)) ;
   // si le mot clé est "PARA_TYPE_DE_CALCUL" cela signifie 
   // qu'il y a un paramètre à lire
   bool lecture_effective = false;
   if (strstr(entreePrinc.tablcar,"PARA_TYPE_DE_CALCUL")!=NULL)
    { //cas de la définition de paramètres  
      // on signale à Algori qu'il y a eu déjà une lecture de paramètre
      deja_lue_entete_parametre=2; 
      // lecture du premier paramètres de l'algorithme
      entreePrinc.NouvelleDonnee(); // ligne suivante
     
      // on initialise tous les paramètres par défaut
      // non, car cela permettra éventuellement de garder les anciens paramètres
//      acceleration_convergence = false;
//      cas_acceleration_convergence = 1;
//      nb_vec_cycle = 8;
     
        // on s'arrête lorsqu'il n'y a plus de mot clé spécifique à lire
      while (    (strstr(entreePrinc.tablcar,"acceleration_convergence_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"cas_acceleration_convergence_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"nb_vec_cycle_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"deb_newton_modifie_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"fin_newton_modifie_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"nb_iter_NM_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"deb_raideur_moyenne_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"fin_raideur_moyenne_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"nb_raideur_moyenne_=")!=NULL)
         || (strstr(entreePrinc.tablcar,"cL_a_chaque_iteration_")!=NULL)
        )
          
      { string nom_mot_cle="";
        *(entreePrinc.entree) >> nom_mot_cle;
        if (nom_mot_cle == "acceleration_convergence_=")
          { // lecture du parametre
            *(entreePrinc.entree) >> acceleration_convergence;
            lecture_effective = true;
          }
        else if (nom_mot_cle == "cas_acceleration_convergence_=")
          { // on lit cas_acceleration_convergence
            *(entreePrinc.entree) >> cas_acceleration_convergence;
            // on vérifie la valeur lue
            if ((cas_acceleration_convergence<1)||(cas_acceleration_convergence>4))
              { cout << "\n erreur en lecture de  cas_acceleration_convergence "
                     << "\n on attendait une valeur comprise entre 1 et 4 au lieu de: " << cas_acceleration_convergence
                     << "\n AlgoriNonDyna::lecture_Parametres( ... ";
                Sortie(1);
              };
            lecture_effective = true;
          }
        else if (nom_mot_cle == "nb_vec_cycle_=")
          { // on lit nb_vec_cycle
            *(entreePrinc.entree) >> nb_vec_cycle;
            // on vérifie la valeur lue
            if (nb_vec_cycle<1)
              { cout << "\n erreur en lecture de  nb_vec_cycle "
                     << "\n on attendait une valeur positive non nulle " << nb_vec_cycle
                     << "\n AlgoriNonDyna::lecture_Parametres( ... ";
                Sortie(1);
              };
            lecture_effective = true;
            if ((cas_acceleration_convergence==4) && (nb_vec_cycle<4))
              { cout << "\n ***warning**** en lecture de  nb_vec_cycle "
                     << "\n dans le cas ou cas_acceleration_convergence ==  4 , nb_vec_cycle doit etre sup a 2 par defaut ";
                nb_vec_cycle = 2;
              };
          }
        else if (nom_mot_cle == "deb_newton_modifie_=")
          { // on lit deb_newton_modifie
            *(entreePrinc.entree) >> deb_newton_modifie;
            lecture_effective = true;
          }
        else if (nom_mot_cle == "fin_newton_modifie_=")
          { // on lit fin_newton_modifie
            *(entreePrinc.entree) >> fin_newton_modifie;
            lecture_effective = true;
          }
        else if (nom_mot_cle == "nb_iter_NM_=")
          { // on lit nb_iter_NM
            *(entreePrinc.entree) >> nb_iter_NM;
            lecture_effective = true;
          }
        else if (nom_mot_cle == "deb_raideur_moyenne_=")
          { // on lit deb_raideur_moyenne
            *(entreePrinc.entree) >> deb_raideur_moyenne;
            lecture_effective = true;
          }
        else if (nom_mot_cle == "fin_raideur_moyenne_=")
          { // on lit fin_raideur_moyenne
            *(entreePrinc.entree) >> fin_raideur_moyenne;
            lecture_effective = true;
          }
        else if (nom_mot_cle == "nb_raideur_moyenne_=")
          { // on lit nb_raideur_moyenne
            *(entreePrinc.entree) >> nb_raideur_moyenne;
            lecture_effective = true;
          }
        else 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,"acceleration_convergence_=")==NULL)
         && (strstr(entreePrinc.tablcar,"cas_acceleration_convergence_=")==NULL)
         && (strstr(entreePrinc.tablcar,"nb_vec_cycle_=")==NULL)
         && (strstr(entreePrinc.tablcar,"deb_newton_modifie_=")==NULL)
         && (strstr(entreePrinc.tablcar,"fin_newton_modifie_=")==NULL)
         && (strstr(entreePrinc.tablcar,"nb_iter_NM_=")==NULL)
         && (strstr(entreePrinc.tablcar,"deb_raideur_moyenne_=")==NULL)
         && (strstr(entreePrinc.tablcar,"fin_raideur_moyenne_=")==NULL)
         && (strstr(entreePrinc.tablcar,"nb_raideur_moyenne_=")==NULL)
         && (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

        #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
      };
    };
     
// on met en cohérence les pb des raideurs moyennes
   if (deb_raideur_moyenne > -1)
     deb_raideur_moyenne = MaX(deb_raideur_moyenne, nb_raideur_moyenne);
  
//      // lecture du nom du paramètre et vérification
//      string st1;
//      if (strstr(entreePrinc.tablcar,"acceleration_convergence_=")!=NULL)
//       { *(entreePrinc.entree) >> st1 ;
//         if (st1 != "acceleration_convergence_=")
//           { cout << "\n erreur en lecture du parametre de l'algorithme implicite statique "
//                  << "\n on attendait le mot : acceleration_convergence_= , au lieu de " << st1
//                  << "\n AlgoriNonDyna::lecture_Parametres( ... ";
//             Sortie(1);
//            }     
//         // lecture du parametre      
//         *(entreePrinc.entree) >> acceleration_convergence;
//         lecture_effective = true;
//       }
//      else // sinon paramètre par défaut
//      	{acceleration_convergence = false;}; 
//      
//      // cas où le paramètre cas_acceleration_convergence existe
//      if (strstr(entreePrinc.tablcar,"cas_acceleration_convergence_=")!=NULL)
//       { // on lit cas_acceleration_convergence
//         string st1;
//         *(entreePrinc.entree) >> st1 >> cas_acceleration_convergence;
//         if (st1 != "cas_acceleration_convergence_=")
//           { cout << "\n erreur en lecture de cas_acceleration_convergence "
//                  << "\n on attendait le mot : cas_acceleration_convergence_= , au lieu de " << st1
//                  << "\n AlgoriNonDyna::lecture_Parametres( ... ";
//             Sortie(1);
//           };
//         // on vérifie la valeur lue
//         if ((cas_acceleration_convergence<1)||(cas_acceleration_convergence>4))
//           { cout << "\n erreur en lecture de  cas_acceleration_convergence "
//                  << "\n on attendait une valeur comprise entre 1 et 4 au lieu de: " << cas_acceleration_convergence
//                  << "\n AlgoriNonDyna::lecture_Parametres( ... ";
//             Sortie(1);
//           };
//         lecture_effective = true;
//       }
//      else // sinon paramètre par défaut
//      	{cas_acceleration_convergence = 1;}; 
    
//      // cas où le paramètre nb_vec_cycle existe
//      if (strstr(entreePrinc.tablcar,"nb_vec_cycle_=")!=NULL)
//       { // on lit nb_vec_cycle
//         string st1;
//         *(entreePrinc.entree) >> st1 >> nb_vec_cycle;
//         if (st1 != "nb_vec_cycle_=")
//           { cout << "\n erreur en lecture de nb_vec_cycle "
//                  << "\n on attendait le mot : nb_vec_cycle_= , au lieu de " << st1
//                  << "\n AlgoriNonDyna::lecture_Parametres( ... ";
//             Sortie(1);
//           };
//         // on vérifie la valeur lue
//         if (nb_vec_cycle<1)
//           { cout << "\n erreur en lecture de  nb_vec_cycle "
//                  << "\n on attendait une valeur positive non nulle " << nb_vec_cycle
//                  << "\n AlgoriNonDyna::lecture_Parametres( ... ";
//             Sortie(1);
//           };
//         lecture_effective = true;
//         if ((cas_acceleration_convergence==4) && (nb_vec_cycle<4))
//           { cout << "\n ***warning**** en lecture de  nb_vec_cycle "
//                  << "\n dans le cas ou cas_acceleration_convergence ==  4 , nb_vec_cycle doit etre sup a 2 par defaut ";
//				         nb_vec_cycle = 2;
//				       };
//       }
//      else // sinon paramètre par défaut
//      	{if (cas_acceleration_convergence!=4){nb_vec_cycle = 8;}else {nb_vec_cycle = 2;};
//			    };
     
//      // si on a déjà lue une ligne on passe à l'enreg suivant
//      if ((lecture_effective) && ( !motCle.SimotCle(entreePrinc.tablcar)))
//           { entreePrinc.NouvelleDonnee(); lecture_effective=false;}// ligne suivante
//
//      }
//   else // sinon on met une valeur par défaut qui ici correspond au cas
//    // des différences centrées pour l'accélération, mais décalé à gauche
//    // pour la vitesse (ce qui est aussi le cas quand phi est différent de 1.)
//      { acceleration_convergence = false;cas_acceleration_convergence = 1; nb_vec_cycle = 8;
//      };
//   // 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 écrit uniquement les données variables (supposées comme telles)
void AlgoriNonDyna::Ecrit_Base_info_Parametre(ostream& sort,const int& cas)
 {
  if (cas == 1)
   {   // ecriture du parametre      
       sort << "\n acceleration_convergence= " << acceleration_convergence
            << " cas_acceleration_convergence= " << cas_acceleration_convergence 
            << " nb_vec_cycle= " << nb_vec_cycle
            << " nb_vec_cycle= " << nb_vec_cycle
            << " nb_vec_cycle= " << nb_vec_cycle
            << " deb_newton_modifie= " << deb_newton_modifie
            << " fin_newton_modifie= " << fin_newton_modifie
            << " nb_iter_NM= "<< nb_iter_NM
            << " deb_raideur_moyenne= " << deb_raideur_moyenne
            << " fin_raideur_moyenne= " << fin_raideur_moyenne
            << " nb_raideur_moyenne= "<< nb_raideur_moyenne
            << " 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 AlgoriNonDyna::Lecture_Base_info_Parametre(istream& ent,const int& cas,bool choix)
{
 if (cas == 1)
 {// dimensionnement
  if (choix)
   {if ((ParaGlob::NiveauImpression() > 3) || (permet_affichage > 2))
     {cout << "\n Lecture_Base_info_Parametre: cas ou les parametres  sont disponibles"
           << " en lecture, que l'on effectue "<< flush;
     };

    string toto;
    // lecture de acceleration_convergence
    ent >> toto ;
    if (toto != "acceleration_convergence=")
      { cout << "\n erreur en lecture du parametre acceleration_convergence de l'algorithme implicite statique"
             << "\n on attendait le mot : acceleration_convergence= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> acceleration_convergence ;
    // lecture de cas_acceleration_convergence
    ent >> toto ;
    if (toto != "cas_acceleration_convergence=")
      { cout << "\n erreur en lecture du parametre cas_acceleration_convergence"
             << "\n on attendait le mot : acceleration_convergence= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> acceleration_convergence ;
    // lecture de nb_vec_cycle
    ent >> toto ;
    if (toto != "nb_vec_cycle=")
      { cout << "\n erreur en lecture du parametre nb_vec_cycle"
             << "\n on attendait le mot : nb_vec_cycle= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> nb_vec_cycle ;
    // lecture de deb_newton_modifie
    ent >> toto ;
    if (toto != "deb_newton_modifie=")
      { cout << "\n erreur en lecture du parametre deb_newton_modifie"
             << "\n on attendait le mot : deb_newton_modifie= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> deb_newton_modifie ;
    // lecture de fin_newton_modifie
    ent >> toto ;
    if (toto != "fin_newton_modifie=")
      { cout << "\n erreur en lecture du parametre fin_newton_modifie"
             << "\n on attendait le mot : fin_newton_modifie= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> fin_newton_modifie ;
    // lecture de nb_iter_NM
    ent >> toto ;
    if (toto != "nb_iter_NM=")
      { cout << "\n erreur en lecture du parametre nb_iter_NM"
             << "\n on attendait le mot : nb_iter_NM= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> nb_iter_NM ;
    // lecture de deb_raideur_moyenne
    ent >> toto ;
    if (toto != "deb_raideur_moyenne=")
      { cout << "\n erreur en lecture du parametre deb_raideur_moyenne"
             << "\n on attendait le mot : deb_raideur_moyenne= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> deb_raideur_moyenne ;
    // lecture de fin_raideur_moyenne
    ent >> toto ;
    if (toto != "fin_raideur_moyenne=")
      { cout << "\n erreur en lecture du parametre fin_raideur_moyenne"
             << "\n on attendait le mot : fin_raideur_moyenne= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> fin_raideur_moyenne ;
    // lecture de nb_raideur_moyenne
    ent >> toto ;
    if (toto != "nb_raideur_moyenne=")
      { cout << "\n erreur en lecture du parametre nb_raideur_moyenne"
             << "\n on attendait le mot : nb_raideur_moyenne= , au lieu de " << toto
             << "\n AlgoriNonDyna::Lecture_Base_info_Parametre( ... ";
        Sortie(1);
       }     
    ent >> nb_raideur_moyenne ;
    // 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 AlgoriNonDyna::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
    nb_vec_cycle = 8; acceleration_convergence=false; cas_acceleration_convergence=1;
    deb_newton_modifie = -1;fin_newton_modifie = -1;nb_iter_NM = 3;
    deb_raideur_moyenne = -1;fin_raideur_moyenne = -1;nb_raideur_moyenne = 3;
    cL_a_chaque_iteration=0;
    if ((ParaGlob::NiveauImpression() > 3) || (permet_affichage > 2))
     {cout << "\n Lecture_Base_info_Parametre: cas ou les parametres ne sont pas disponibles"
           << " on utilise et initialise les parametres par defaut "<< flush;
     };
   };
  }    
};

// création d'un fichier de commande: cas des paramètres spécifiques
void AlgoriNonDyna::Info_commande_parametres(UtilLecture& entreePrinc)
 { // écriture dans le fichier de commande
   ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
   cout << "\n# exemple des para facultatifs algo AlgoriNonDyna (rep o ou n defaut) ? ";
   string rep;
   // procédure de lecture avec prise en charge d'un retour chariot
   rep = lect_return_defaut(true,"n");
   // si la taille de rep == 0 cela veut dire que c'est un retour chariot
   if (rep.size()==0)
      {rep = "n";
       cout << "--> valeur par defaut : n "<<endl;
      };
   if ((rep == "o") || (rep == "O") ||(rep == "0"))
   { sort << "\n#-----------------------------------------------------------------------"
          << "\n#|  parametres (falcultatifs ) associes au calcul implicite statique   |"
          << "\n#-----------------------------------------------------------------------"
          << "\n"
          << "\n  ##  PARA_TYPE_DE_CALCUL"
          << "\n  #  ................................................................"
          << "\n  # / acceleration  de convergence par extrapolation methode MMPE   /"
          << "\n  #.................................................................." 
          << "\n  ##      acceleration_convergence_= 1 cas_acceleration_convergence_= 1 nb_vec_cycle_= 8 "
          << "\n  # "
          << "\n  # acceleration_convergence_= indique si oui (=1)  ou non (=0) on veut une acceleration "
          << "\n  # cas_acceleration_convergence_= 1 : on projette  sur les vecteurs positions"
          << "\n  #                                2 : on projette  sur les vecteurs residus "
          << "\n  # nb_vec_cycle_= indique le nombre de vecteur maxi que l'on prendre en compte "
          << "\n  #                pour la projection"

          << "\n  #  ................................................................"
          << "\n  # / utilisation de Newton modifie                                 /"
          << "\n  #.................................................................." 
          << "\n  # deb_newton_modifie_= indique le numero d'iteration de demarrage de la methode "
          << "\n  #  (negatif => pas d'utilisation de NM)  "
          << "\n  # nb_iter_NM_= nb de fois consecutive ou l'on utilise la raideur non mise a jour "
          << "\n  #    ensuite la matrice est mise a jour, et on recommence nb_iter_NM "
          << "\n  # fin_newton_modifie_= indique le numero d'iteration de fin de la methode "
          << "\n  #  (negatif => pas de fin)  "
          << "\n  #    ensuite retour sur du Newton classique "

          << "\n  #  ................................................................"
          << "\n  # / utilisation d'une moyenne de raideurs                         /"
          << "\n  #.................................................................." 
          << "\n  # deb_raideur_moyenne_= indique le numero d'iteration de demarrage de la methode "
          << "\n  #  (negatif => pas d'utilisation )  "
          << "\n  # nb_raideur_moyenne_= nb de raideur utilise pour la moyenne "
          << "\n  # fin_raideur_moyenne_= indique le numero d'iteration de fin de la methode "
          << "\n  #  (negatif => pas de fin)  "
          << "\n  #    ensuite retour sur du Newton classique "

          << "\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  #.................................................................."
          << "\n  # /            mode debug                                         /"
          << "\n  #.................................................................." 
          << "\n  ##      mode_debug_= 0              "
          << "\n  # "
          << "\n  # mode_debug_= parametre de debug (=0)  calcul classique "
          << "\n  #             1 : a chaque iteration on sort une visualisation "
          << "\n  # **important**: ce parametre doit etre mis sur une ligne differente de "
          << "\n  #                l'acceleration de convergence"
          << "\n  #   ";
   };
	  // appel de la classe mère
	  Algori::Info_com_parametres(entreePrinc);
   sort << "\n" << endl;
 };

