
  // 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-2021 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 "LesCondLim.h"
#include "CharUtil.h"
#include "SfeMembT.h"
#include "TypeQuelconqueParticulier.h"

    
// --- conteneur pour les réactions -----
      // surcharge de l'operator de lecture typée
istream & operator >> (istream & ent , LesCondLim::ReactStoc & a)
   { // lecture du type et vérification
     string nom_type;
     ent >> nom_type;
     if (nom_type != "ReactStoc")
       Sortie(1);
     // lecture des infos
     ent >>  a.numMail >> a.numNoeud >> a.ddl >> a.casAss; 
     return ent;
    };
       // surcharge de l'operator d'ecriture typée
ostream & operator << (ostream & sort , const LesCondLim::ReactStoc & a)
   { // écriture du type
     sort << "ReactStoc ";
     // les données
     sort << a.numMail << " " << a.numNoeud << " " << a.ddl <<" "<< a.casAss;
     return sort;
   };

      // surcharge de l'operator de lecture typée
istream & operator >> (istream & ent , LesCondLim::TorseurReac & a)
   { // lecture du type et vérification
     string nom_type;
     ent >> nom_type;
     if (nom_type != "TorseurReac")
       Sortie(1);
     // lecture des infos
     ent >>  a.existe_torseur_reac >> a.resultante >> a.moment ; 
     return ent;
   };
       // surcharge de l'operator d'ecriture typée
ostream & operator << (ostream & sort , const LesCondLim::TorseurReac & a)
   { // écriture du type
     sort << " TorseurReac ";
     // les données
     sort << a.existe_torseur_reac << " " << a.resultante << " " << a.moment <<" ";
     return sort;
   };

// --- fin conteneur pour les réactions -----

// CONSTRUCTEURS :
LesCondLim::LesCondLim () : // par defaut
 tabBloq(),tabInit(),condlim()
 ,reaction(),reaction_CLin(),reactionApresCHrepere()
 ,tab_torseurReac(),ttRG(),ttorBloq()
 ,tab_iocondiline(),tab_CLinApplique(),ttRGCLL(),ttorCLL()
 ,ttRG_noms_ref(),ttRGCLL_noms_ref()
// ,map_reaction()
 ,nb_maillage(0)
 ,tempsCL(),tempsCLL()
   { };
   
    // DESTRUCTEUR :
LesCondLim::~LesCondLim ()
     { };
    
    // METHODES PUBLIQUES :    
    // lecture des  conditions limites : ddl bloque
void LesCondLim::Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef)
  { MotCle motCle; // ref aux mots cle
    // on se positionne sur un mot cle
    while ( !motCle.SimotCle(entreePrinc.tablcar))
            entreePrinc.NouvelleDonnee();
    bool sortie_info = false;        
    if ( (strstr(entreePrinc.tablcar,"blocages")!=NULL) ) // à rajouter tous les cas de lectures éventuelles
      {if (ParaGlob::NiveauImpression() >= 4) 
          cout << " debut de la lecture des conditions limites ddl bloque " << endl;
       sortie_info = true;
      };
            
    // def d'une instance de classe de lecture de Ddl   
    LectBloc <DdlLim> lecDdl;
 
    // lecture eventuelle des blocages en condition limite
    lecDdl.Lecture(entreePrinc,lesRef,"blocages",
                     "lecture des blocages de ddl en condition limite",tabBloq);
    // dimensionnement du tableau des torseurs résultants
    LesCondLim::DimensionneTorseurs();
   
   
    if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info)
      cout << " fin de la lecture des conditions limites ddl bloque " << endl;  
  };

    // lecture des  conditions limites linéaire
void LesCondLim::Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef)
  { MotCle motCle; // ref aux mots cle
    // on se positionne sur un mot cle
    while ( !motCle.SimotCle(entreePrinc.tablcar))
            entreePrinc.NouvelleDonnee();
    bool sortie_info = false;        
    if ( (strstr(entreePrinc.tablcar,"condition_limite_lineaire_")!=NULL) ) // à rajouter tous les cas de lectures éventuelles
      {if (ParaGlob::NiveauImpression() >= 4) 
          cout << " debut de la lecture des conditions limites lineaires " << endl;
       sortie_info = true;
      };
            
    // def d'une instance de classe de lecture de Ddl   
    LectBloc <I_O_Condilineaire> lecI_O_Condli;
 
    // lecture eventuelle des conditions linéaire en condition limite
    lecI_O_Condli.Lecture(entreePrinc,lesRef,"condition_limite_lineaire_",
                     "lecture des conditions limites lineaires ",tab_iocondiline);
    // mise à jour de la dimension du tableau associé: tab_CLinApplique
    tab_CLinApplique.Change_taille(tab_iocondiline.Taille());
   
    // dimensionnement du tableau des torseurs résultants
    LesCondLim::DimensionneTorseurs();

    if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info)
      cout << " fin de la lecture des conditions limites lineaire " << endl;  
   };
    
// lecture des  conditions limites : initialisation
void LesCondLim::Lecture3(UtilLecture & entreePrinc,LesReferences& lesRef)
  { MotCle motCle; // ref aux mots cle
    // on se positionne sur un mot cle
    while ( !motCle.SimotCle(entreePrinc.tablcar))
            entreePrinc.NouvelleDonnee();
            
    bool sortie_info = false;        
    if ( (strstr(entreePrinc.tablcar,"initialisation")!=NULL) ) // à rajouter tous les cas de lectures éventuelles
      {if (ParaGlob::NiveauImpression() >= 4) 
          cout << " debut de la lecture des conditions d'initialisation " << endl;
       sortie_info = true;
      };
    // def d'une instance de classe de lecture de Ddl   
    LectBloc <DdlLim> lecDdl;
 
    // lecture eventuelle des conditions limites d'initialisation
    lecDdl.Lecture(entreePrinc,lesRef,"initialisation",
                     "lecture des conditions limites d\'initialisation",tabInit);
    if ((ParaGlob::NiveauImpression() >= 4) && sortie_info)
      cout << " fin de la lecture des conditions d'initialisation " << endl;  
		
//debug
//Affiche();
//fin debug		
		
   };
     
    // affichage des informations concernant les conditions limites
void LesCondLim::Affiche() const  // affichage de tous les infos
  {  Affiche1();
     Affiche2();
     Affiche3();
   };  
    
void LesCondLim::Affiche1() const 
   { if (tabBloq.Taille() != 0) 
      {cout << "\n ******** conditions limites : ddl bloque  ******** \n";
       cout << tabBloq.Taille() << " reference de conditions limites lue  \n";
       int tabBloqTaille = tabBloq.Taille();
       for (int i=1; i<=tabBloqTaille; i++)
            tabBloq(i).Affiche();
       cout << "\n\n";
      }     
  };
void LesCondLim::Affiche2() const 
 {  
    if (tabInit.Taille() != 0) 
      {cout << "\n ******** conditions limites : lineaire ******** \n";
       cout << tab_iocondiline.Taille() << " reference de conditions limites lue  \n";
       int tabInitTaille = tabInit.Taille();
       for (int i=1; i<=tabInitTaille; i++)
            tabInit(i).Affiche();
       cout << "\n\n";
      }   
  };
void LesCondLim::Affiche3() const 
 {  
    if (tabInit.Taille() != 0) 
      {cout << "\n ******** conditions limites : initialisation ******** \n";
       cout << tabInit.Taille() << " reference de conditions limites lue  \n";
       int tabInitTaille = tabInit.Taille();
       for (int i=1; i<=tabInitTaille; i++)
            tabInit(i).Affiche();
       cout << "\n\n";
      }   
  };
    
// introduction des données et variables pour leurs emplois futures, avec init par défaut
void LesCondLim::IntroductionDonnees(LesMaillages * lesMail,LesReferences* lesRef
                                     ,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD)
  {
    tempsCL.Mise_en_route_du_comptage(); // temps cpu
    // 1) on parcours le tableau de ddl d'initialisation
    int tabInitTaille = tabInit.Taille();
    for (int i=1;i<= tabInitTaille;i++)
      { DdlLim& tabInit_i = tabInit(i);
        // recup de la reference correspondant au mot cle
        const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage());
        if ((refinitial.Indic() == 4) && 
           (tabInit_i.TypeDeCL()==TANGENTE_CL))
         {// cas des références d'arêtes, avec des conditions initiales de tangente imposée
          // ici on vérifie que les données d'entrées sont cohérentes, c'est tout
          const ReferenceAF & ref = ((ReferenceAF &) refinitial);
          // on renseigne les éléments ad hoc
          int refTaille =  ref.Taille();         
          for (int ne =1; ne<= refTaille;ne++)
           {int tabInitiTaille = tabInit_i.Taille();
            // dans le cas d'une référence de champ on vérifie le nombre de ddlLim
            if ((tabInit_i.Champ()) && (tabInitiTaille != ref.Taille()))
              {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
                    << " que le nombre d'element de la reference associee !! "
                    << "\n void LesCondLim::IntroductionDonnees(... ";
               cout << " condition limite : "; tabInit_i.Affiche();
               tempsCL.Arret_du_comptage();
               Sortie(1);       
              };
            // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
            // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
            int idebut=1; int ifinfin = tabInitiTaille;// début normale
            if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;};
            for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
              // affectation de la valeur d'initialisation
              { Ddl ddl1 = tabInit_i.ElemLim(nd);   // récup des 3 ddl
                Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl
                Ddl ddl3 = tabInit_i.ElemLim(nd+2);  // récup des 3 ddl
                
                // on vérifie qu'il s'agit bien de 3 coordonnées
                if (ddl1.Id_nom()!=X1)
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 "
                        << "\n void LesCondLim::IntroductionDonnees(... ";
                  cout << " condition limite : "; tabInit_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                if (ddl2.Id_nom()!=X2)
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 "
                        << "\n void LesCondLim::IntroductionDonnees(... ";
                  cout << " condition limite : "; tabInit_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                if (ddl3.Id_nom()!=X3)
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 "
                        << "\n void LesCondLim::IntroductionDonnees(... ";
                  cout << " condition limite : "; tabInit_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                // on vérifie que le numéro de l'arête existe bien
                int num_elem = ref.NumeroElem(ne);
                int num_ar = ref.NumeroFA(ne);
                // récup de l'élément
                Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem);
                if (!(el.AreteExiste(num_ar))) 
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar 
                       << " pour l'element " << num_elem << " n'existe pas !! "
                       << "\n void LesCondLim::IntroductionDonnees(... ";
                  cout << " condition limite : "; tabInit_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                // on vérifie que c'est un élément sfe
                if (!(ElementSfe(el.Id_interpolation())))
                  {cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre "
                        << " de type SFE : et non l'element=  "; el.Affiche(1);
                   cout << "\n void LesCondLim::IntroductionDonnees(... ";
                   cout << " condition limite : "; tabInit_i.Affiche();
                   tempsCL.Arret_du_comptage();
                   Sortie(1);
                   };                
              }// fin boucle sur tabInit_i
           }// fin boucle sur les éléments de la référence
         }  // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE                     

        else if (refinitial.Indic() != 1) 
          // cas d'element
          { cout << "\n introduction  autre que des noeuds, pas d\'action implentee a ce sujet !!";
            cout << "void LesCondLim::IntroductionDonnees(... " << endl;
            tempsCL.Arret_du_comptage();
            Sortie(1);
           }
        else
          // cas de noeuds
         {// traitement proprement dit
          const ReferenceNE & ref = ((ReferenceNE &) refinitial);
          int refTaille = ref.Taille();          
          for (int nn =1; nn<= refTaille;nn++)
            {int tabInitiTaille = tabInit_i.Taille();
             // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
             // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
             int idebut=1; int ifinfin = tabInitiTaille;// début normale
             if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;};
             for (int nd=idebut;nd<= ifinfin ;nd++)
              // affectation de la valeur d'initialisation
              { Ddl ddl = tabInit_i.ElemLim(nd);
                Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
           // ---modif 10 sep 2017
                // cas ou le ddl n'existe pas
                // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre
                // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose
                // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas
                // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour
                // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être
                // utilisé à t et tdt, donc il ne faut pas le mettre en HS
                // par contre on le met en lisible c-a-d en donnée par défaut
               
                ddl.ChangeVariable_a_Donnee();
                if (!(noe.Existe_ici(ddl.Id_nom())))
                 // cas ou le ddl n'existe pas
                 // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
  //               { if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
                 { if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
                    { // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis 
                      // initialisation a zero et on indique qu'il est hors service (non !! voir la modif 10 sept 2017)
                      noe.PlusDdl(ddl);
                      noe.Change_val_0(ddl.Id_nom(),0.);
                      noe.Change_val_t(ddl.Id_nom(),0.);
// ---modif 10 sep 2017                      // puis on indique que le ddl est bloque et hors service
// ---modif 10 sep 2017                      noe.Met_hors_service(ddl.Id_nom());
                      noe.Met_en_service(ddl.Id_nom());
                     
                      noe.Change_fixe(ddl.Id_nom(),true);                                            
                     }
                  } // fin du   if (!(noe.Existe_ici(ddl.Id_nom())))         
               } // fin de la boucle sur les ddl
              } // fin de la boucle sur les noeuds de la référence
           } // fin du traitement pour les noeuds                       
       } // fin de la boucle sur le tableau générale d'initialisation
       
    // 2) cas des ddl imposes on verifie leurs existences et on crée si besoin
    // on parcours le tableau de ddl bloques
    // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt
    int tabBloqTaille = tabBloq.Taille();
    for (int i=1;i<= tabBloqTaille;i++)
      { DdlLim& tabBloq_i = tabBloq(i);
        // recup de la reference correspondant au mot cle
        const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
        if ((refinitial.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) )
         {// cas des références d'arêtes, avec des conditions de tangente imposée
          // on s'occupe de vérifier la cohérence de l'entrée des données, c'est tout
          const ReferenceAF & ref = ((ReferenceAF &) refinitial);
          // on renseigne les éléments ad hoc
          int refTaille =  ref.Taille();         
          for (int ne =1; ne<= refTaille;ne++)
           {int tabBloqiTaille = tabBloq_i.Taille();
            // dans le cas d'une référence de champ on vérifie le nombre de ddlLim
            if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
              {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
                    << " que le nombre d'element de la reference associee !! "
                    << "\n void LesCondLim::IntroductionDonnees(... ";
               cout << " condition limite : "; tabBloq_i.Affiche();
               tempsCL.Arret_du_comptage();
               Sortie(1);       
              }
            // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
            // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
            int idebut=1; int ifinfin = tabBloqiTaille;// début normale
            if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;};
            for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
              // affectation de la valeur d'initialisation
              { Ddl ddl1 = tabBloq_i.ElemLim(nd);   // récup des 3 ddl
                Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl
                Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl
                
                // on vérifie qu'il s'agit bien de 3 coordonnées
                if (ddl1.Id_nom()!=X1)
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 "
                        << "\n void LesCondLim::InitialDonnees(... ";
                  cout << " condition limite : "; tabBloq_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                if (ddl2.Id_nom()!=X2)
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 "
                        << "\n void LesCondLim::InitialDonnees(... ";
                  cout << " condition limite : "; tabBloq_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                if (ddl3.Id_nom()!=X3)
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 "
                        << "\n void LesCondLim::InitialDonnees(... ";
                  cout << " condition limite : "; tabBloq_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                // on vérifie que le numéro de l'arête existe bien
                int num_elem = ref.NumeroElem(ne);
                int num_ar = ref.NumeroFA(ne);
                // récup de l'élément
                Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem);
                if (!(el.AreteExiste(num_ar))) 
                 {cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar 
                       << " pour l'element " << num_elem << " n'existe pas !! "
                       << "\n void LesCondLim::InitialDonnees(... ";
                  cout << " condition limite : "; tabBloq_i.Affiche();
                  tempsCL.Arret_du_comptage();
                  Sortie(1);
                 };
                // on vérifie que c'est un élément sfe
                if (!(ElementSfe(el.Id_interpolation())))
                  {cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre "
                        << " de type SFE : et non l'element=  "; el.Affiche(1);
                   cout << "\n void LesCondLim::InitialDonnees(... ";
                   cout << " condition limite : "; tabBloq_i.Affiche();
                   tempsCL.Arret_du_comptage();
                   Sortie(1);
                   };
              }// fin boucle sur tabBloq_i
           }// fin boucle sur les noeuds de la référence
         }  // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE                     
        
        else if (refinitial.Indic() != 1) // cas d'une autre référence que des noeuds
          // cas d'element
          { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!";
            cout << "\n void LesCondLim::InitialDonnees(... " << endl;
            tempsCL.Arret_du_comptage();
            Sortie (1);
           }
        else
          // cas de noeuds
         {const ReferenceNE & ref = ((ReferenceNE &) refinitial);
          int refTaille =  ref.Taille();         
          for (int nn =1; nn<= refTaille;nn++)
           {int tabBloqiTaille = tabBloq_i.Taille();
            // dans le cas d'une référence de champ on vérifie le nombre de ddlLim
            if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
              {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
                    << " que le nombre de noeud de la reference associee !! "
                    << "\n void LesCondLim::InitialDonnees(... ";
               cout << " condition limite : "; tabBloq_i.Affiche();
               tempsCL.Arret_du_comptage();
               Sortie(1);       
              }
            // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
            // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
            int idebut=1; int ifinfin = tabBloqiTaille;// début normale
            if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
            for (int nd=idebut;nd<= ifinfin ;nd++)
              // affectation de la valeur d'initialisation
              { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl
                // récup du noeud
                Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
                // on regarde si les temps dépendent d'une fct nD
                // si oui on modifie les bornes du ddl
                if (tabBloq_i.Temps_depend_nD())
                   LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
              
                // on regarde si le temps est actif ou pas
                if ((tabBloq_i.Temps_actif(0.))) {tabBloq_i.ElemLim(nd).Met_en_service();}
                else { tabBloq_i.ElemLim(nd).Met_hors_service();};
                // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé
                // on regarde du coté du noeuds
                if (!noe.Existe_ici(ddl.Id_nom()))
                      // cas ou il faut creer un ddl sup
                      // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
       //               {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
                      { if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
                         {// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis
                          // initialisation a zero et on indique qu'il est hors service
                     // ---modif 10 sep 2017
                          // cas ou le ddl n'existe pas
                          // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre
                          // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose
                          // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas
                          // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour
                          // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être
                          // utilisé à t et tdt, donc il ne faut pas le mettre en HS
                          // par contre on le met en lisible c-a-d en donnée par défaut
                         
                          ddl.ChangeVariable_a_Donnee();
                          noe.PlusDdl(ddl);
                          noe.Change_val_0(ddl.Id_nom(),0.);
                          noe.Change_val_t(ddl.Id_nom(),0.);
// ---modif 10 sep 2017                           // puis on indique que le ddl est bloque et hors service
// ---modif 10 sep 2017                           noe.Met_hors_service(ddl.Id_nom());
                          noe.Met_en_service(ddl.Id_nom());
                          
                          noe.Change_fixe(ddl.Id_nom(),true);
                         };
                      };
                   // pour le reste on ne fait rien, se sera géré par les mises à jour
                   // en fonction de l'évolution du temps 
               } // fin boucle sur tabBloq_i
            } // fin boucle sur les noeuds de la référence
         } // fin du cas des noeuds                      
       } // fin bouble sur tabBloq
    // définition du nombre de maillage en cours dans le calcul
    nb_maillage=lesMail->NbMaillage();   
    tempsCL.Arret_du_comptage(); // temps cpu
  };

    
// initialisation des ddl avec le tableau de ddl d'init
// verif de l'existence de tous les ddl (initialisation et imposes) 
// ajout si necessaire
// choix =false  : indique qu'il faut initialiser que les ddl  t
// choix = true : indique qu'il faut initialiser les ddl  a t et t+dt
// vérification de l'existence des courbes de charge adoc si nécessaire
//  idem pour les fonctions nD  de charge adoc si nécessaire
// cas    : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque
//          le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont
//          leur statut modifié de manière équivalente
//    =0    pas d'association
//    =1    association X V GAMMA
void LesCondLim::Initial(LesMaillages * lesMail,LesReferences* lesRef
                         ,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD
                         ,bool choixtdt,int cas)
  {
    tempsCL.Mise_en_route_du_comptage(); // temps cpu
    // 1) on parcours le tableau de ddl d'initialisation
    int tabInitTaille = tabInit.Taille();
    for (int i=1;i<= tabInitTaille;i++)
      { DdlLim& tabInit_i = tabInit(i);
        // recup de la reference correspondant au mot cle
        const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage());
        if ((refinitial.Indic() == 4) && 
           (tabInit_i.TypeDeCL()==TANGENTE_CL) )
         {// cas des références d'arêtes, avec des conditions de tangente imposée
          const ReferenceAF & ref = ((ReferenceAF &) refinitial);
          // on renseigne les éléments ad hoc
          int refTaille =  ref.Taille();         
          for (int ne =1; ne<= refTaille;ne++)
           {int tabInitiTaille = tabInit_i.Taille();
            // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
            // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
            int idebut=1; int ifinfin = tabInitiTaille;// début normale
            if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;};
            for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
              // affectation de la valeur d'initialisation
              { Ddl ddl1 = tabInit_i.ElemLim(nd);   // récup des 3 ddl
                Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl
                Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl
                // récup de l'élément
                Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
                SfeMembT & elsfe = (SfeMembT&) el;
                // on renseigne l'élément
                Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); 
                elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );  
                
              }// fin boucle sur tabInit_i
           }// fin boucle sur les éléments de la référence
         }  // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE                     

        else if (refinitial.Indic() != 1) 
          // cas d'element
          { cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!";
            cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
            tempsCL.Arret_du_comptage();
            Sortie(1);
          }
        else
          // cas de noeuds
         {// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon
          // la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout
          // cas peut de fois, 
          const ReferenceNE & ref = ((ReferenceNE &) refinitial);
          // traitement proprement dit
          int refTaille = ref.Taille();          
          for (int nn =1; nn<= refTaille;nn++)
            {int tabInitiTaille = tabInit(i).Taille();
             // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
             // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
             int idebut=1; int ifinfin = tabInitiTaille;// début normale
             if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;};
             for (int nd=idebut;nd<= ifinfin ;nd++)
              // affectation de la valeur d'initialisation
              { Ddl ddl = tabInit_i.ElemLim(nd);
                Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
                // on vérifie que le ddl est compatible avec la dimension sinon message d'erreur
                if (!CompatDim(ddl.Id_nom()))
                 {cout << "\n *** erreur, le ddl d'initialisation : " << ddl.Nom()
                       << " pour la reference " << ref.Nom()
                       << " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension()
                       << ") de l'espace de travail "  ;
                  if (ParaGlob::NiveauImpression()>6)
                    cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ;
                  cout << endl;
                  tempsCL.Arret_du_comptage();
                  Sortie (1);
                 };
             
                if (noe.Existe_ici(ddl.Id_nom()))
                  // cas ou le ddl existe deja
                   { noe.Change_val_t(ddl.Id_nom(),ddl.Valeur());
                     if (choixtdt)
                        noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur());
                     // mise a jour des ddl aux temps  0 pour tous les ddl sauf ceux de position
                     // car ces derniers sont les seuls dont la position initiale est déterminées à la lecture
                     // du maillage
                     if (!(Meme_famille(ddl.Id_nom(),X1))) 
                        noe.Change_val_0(ddl.Id_nom(),ddl.Valeur());
                     // on regarde s'il fait partie de la combinaison 
                     // si oui on met en place les ddl correspondant à HSLIBRE
                     Enum_ddl en = ddl.Id_nom();
                     Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); 
                    }                      
                else
                   // cas ou le ddl n'existe pas
                 { // tout d'abord on regarde si c'est un déplacement
            //       if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
                   if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
                    {if(!CompatDim(ddl.Nom())) // vérif de dimension
                      { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
                         << " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
                        cout << " \n cas des ddl bloquees ";  
                        cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
                        tempsCL.Arret_du_comptage();
                        Sortie (1);
                       };
                     // cas ok on impose le déplacement sur le Xi correspondant
                     Enum_ddl en = ddl.Id_nom();
                     //on cherche l'equivalent Ui en Xi
                     en = UxyzXi(en);
                     noe.Ajout_val_t(en,ddl.Valeur());
                     // mise a jour des ddl aux autres temps   
                //     noe.Ajout_val_0(en,ddl.Valeur());
                     if (choixtdt)
                       noe.Ajout_val_tdt(en,ddl.Valeur());                    
                     // puis on regarde si le ddl initial fait partie de la combinaison 
                     // si oui on met en place les ddl correspondant à HSLIBRE
                     Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); 
                    }
                   else
                    { // cas ou il faut creer un ddl sup  
                      //noe.PlusDdl(ddl);
                      cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues"
                           << " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
                      cout << "\n cas des ddl d'initialisation ";     
                      cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
                      tempsCL.Arret_du_comptage();
                      Sortie (1);
                    };
                 };
              };
            };
         };
      };
    // 2) cas des ddl imposes on verifie leurs existences
    //  on vérifie également l'existence des courbes de charge adoc si nécessaire
    //  idem pour les fonctions nD  de charge adoc si nécessaire
    //  on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple
    // vitesse et position ou accélération pour un même ddl
    // on parcours le tableau de ddl bloques
    // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt
    int tabBloqTaille = tabBloq.Taille();
    for (int i=1;i<= tabBloqTaille;i++)
      { DdlLim& tabBloq_i = tabBloq(i);
        // recup de la reference correspondant au mot cle
        const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
        if ((refinitial.Indic() == 4) && 
           (tabBloq_i.TypeDeCL()==TANGENTE_CL) )
         {// cas des références d'arêtes, avec des conditions de tangente imposée
          // ici on s'occupe de renseigner les éléments
          const ReferenceAF & ref = ((ReferenceAF &) refinitial);
          // on renseigne les éléments ad hoc
          int refTaille =  ref.Taille();         
          for (int ne =1; ne<= refTaille;ne++)
           {int tabBloqiTaille = tabBloq_i.Taille();
            // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
            // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
            int idebut=1; int ifinfin = tabBloqiTaille;// début normale
            if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;};
            for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
              // affectation de la valeur d'initialisation
              { Ddl ddl1 = tabBloq_i.ElemLim(nd);   // récup des 3 ddl
                Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl
                Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl
                // récup de l'élément
                Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
                SfeMembT & elsfe = (SfeMembT&) el;
                // on regarde si les temps dépendent d'une fct nD
                // si oui on modifie les bornes du ddl
                if (tabBloq_i.Temps_depend_nD())
                   LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD);
                // on continue que si le temps est actif ou pas
                if ((tabBloq_i.Temps_actif(0.)))
                  { // on renseigne l'élément
                    Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); 
                    elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );  
                  };
              };// fin boucle sur tabBloq_i
           };// fin boucle sur les noeuds de la référence
         }  // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE                     

        else if (refinitial.Indic() != 1) 
          // cas autre d'element par exemple
          { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!";
            cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
            tempsCL.Arret_du_comptage();
            Sortie (1);
          }
        else
          // cas de noeuds
         {const ReferenceNE & ref = ((ReferenceNE &) refinitial);
          int refTaille =  ref.Taille();         
          for (int nn =1; nn<= refTaille;nn++)
           {int tabBloqiTaille = tabBloq_i.Taille();
  /*          // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim
            if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
              {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
                    << " que le nombre de noeud de la reference associee !! ";
               cout << " condition limite : "; tabBloq_i.Affiche();
               Sortie(1);       
              }*/
            // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
            // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
            int idebut=1; int ifinfin = tabBloqiTaille;// début normale
            if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
            for (int nd=idebut;nd<= ifinfin ;nd++)
              // affectation de la valeur d'initialisation
              { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl
                // on vérifie que le ddl est compatible avec la dimension sinon message d'erreur
                if (!CompatDim(ddl.Id_nom()))
                 {cout << "\n *** erreur, le ddl de blocage : " << ddl.Nom()
                       << " pour la reference " << ref.Nom()
                       << " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension()
                       << ") de l'espace de travail "  ;
                  if (ParaGlob::NiveauImpression()>6)
                    cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ;
                  cout << endl;
                  tempsCL.Arret_du_comptage();
                  Sortie (1);
                 };
                // récup du noeud
                Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
                // on regarde si les temps dépendent d'une fct nD
                // si oui on modifie les bornes du ddl
                if (tabBloq_i.Temps_depend_nD())
                   LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
                
                // on regarde si le temps est actif ou pas
                if ((tabBloq_i.Temps_actif(0.)))
                  { // on n'intervient que si le temps initial est actif
                    tabBloq_i.ElemLim(nd).Met_en_service();
                    // récup du noeud                            
                    string nom_courbe = tabBloq_i.Nom_courbe(nd);
                    Courbe1D * pt_courbe = NULL; 
                    if (nom_courbe != "")
                      // cas de l'existence d'une courbe de charge
                      // appel pour récupérer la courbe (juste pour la vérif
                      // car on ne s'en sert pas aprés !)
                      { pt_courbe = lesCourbes1D->Trouve(nom_courbe);
                      };
                    // idem pour les fonctions nD
                    string nom_fctnD = tabBloq_i.NomF_charge(nd);
                    Fonction_nD * pt_fctnD = NULL;
                    if (nom_fctnD != "")
                      // cas de l'existence d'une fonction de charge
                      // appel pour récupérer la fct (juste pour la vérif
                      // car on ne s'en sert pas aprés !)
                      { pt_fctnD = lesFonctionsnD->Trouve(nom_fctnD);
                      };
                    // maintenant on regarde du coté des noeuds
                    if (!noe.Existe_ici(ddl.Id_nom()))
                      // cas ou il faut creer un ddl sup
                      // on regarde le cas eventuel des coordonnees entrainees
                      // si on est en entraine et que le ddl a imposer est un Ui
                      // alors on ne verifie que les dimensions et on indique le blocage
        //              {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
                      {if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
                        { // cas d'un ddl de déplacement, et que le ddl X1 existe déjà
                          if(!CompatDim(ddl.Nom()))
                           { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
                             << " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ;
                             cout << " \n cas des ddl bloquees ";  
                             cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
                             tempsCL.Arret_du_comptage();
                             Sortie (1);
                           }
                          else // cas ou c'est Xi le ddl bloque, on indique le blocage
                           { Enum_ddl en = ddl.Id_nom();
                             //on cherche l'equivalent Ui en Xi
                             en = UxyzXi(en);
                             noe.Change_fixe(en,true);
                             // on regarde s'il fait partie de la combinaison et on fixe les blocages
                             Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); 
                           }
                        }
                       else
                       // cas d'un ddl inexistant diff de U, création puis initialisation a zero 
                       { noe.PlusDdl(ddl);
                         noe.Change_val_0(ddl.Id_nom(),0.);
                         noe.Change_val_t(ddl.Id_nom(),0.);
                         if (choixtdt)
                            noe.Change_val_tdt(ddl.Id_nom(),0.);
                         // puis on indique que le ddl est bloque 
                         noe.Change_fixe(ddl.Id_nom(),true);                                            
                         // on regarde s'il fait partie de la combinaison et on fixe les blocages
                         Enum_ddl en = ddl.Id_nom();
                         Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); 
                       }
                      }
                    else   // cas ou le ddl existe
                       // on indique que le ddl est bloque, mais on ne change pas sa valeur
                       // ce sera fait au moment de la mise à jour à tdt
                      { // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1)
                        // dans ce cas il est libre, on peut le bloquer sans pb, 
                        // soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement
                        noe.Change_fixe(ddl.Id_nom(),true);
                        // on regarde s'il fait partie de la combinaison et on fixe les blocages
                        Enum_ddl en = ddl.Id_nom();
                        Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); 
                      };
                  }
                else
                  {// si le ddl bloqué n'est pas actif pour le temps 0. 
                   tabBloq_i.ElemLim(nd).Met_hors_service();
                   // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé
                   // récup du noeud                            
                   Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
                   // on regarde du coté du noeuds  
                   if (!noe.Existe_ici(ddl.Id_nom()))
                      // cas ou il faut creer un ddl sup
                      // on regarde le cas eventuel des coordonnees entrainees
                      // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
         //             {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
                      {if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
                        { // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis
                          // initialisation a zero et on indique qu'il est hors service (non cf modif qui suit)
                     // ---modif 10 sep 2017
                          // cas ou le ddl n'existe pas
                          // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre
                          // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose
                          // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas
                          // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour
                          // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être
                          // utilisé à t et tdt, donc il ne faut pas le mettre en HS
                          // par contre on le met en lisible c-a-d en donnée par défaut
                          Ddl ddl_inter(ddl); // pour pas que cela influe sur les autres noeuds
                         
                          ddl_inter.ChangeVariable_a_Donnee();
                          noe.PlusDdl(ddl_inter);
                          noe.Change_val_0(ddl_inter.Id_nom(),0.);
                          noe.Change_val_t(ddl_inter.Id_nom(),0.);
                          if (choixtdt) noe.Change_val_tdt(ddl_inter.Id_nom(),0.);
// ---modif 10 sep 2017                          // puis on indique que le ddl est bloque et hors service
// ---modif 10 sep 2017                          noe.Met_hors_service(ddl.Id_nom());
                          noe.Met_en_service(ddl.Id_nom());
                          
                          noe.Change_fixe(ddl.Id_nom(),true);
                        };
                      };
                   // pour le reste on ne fait rien, se sera géré par les mises à jour
                   // en fonction de l'évolution du temps 
                  }; // fin du cas ddl bloqué et pas actif pour le temps 0.
              };
           };
         };
      };
    // on initialise la situation de blocage  et condition linéaires
    Validation_blocage (lesRef,0.);
    // vérif qu'il n'y a pas de surcharge de blocage
    Verif_surcharge_blocage(lesMail,lesRef,0.,cas);
    // pour le tps cpu, il y a une petite part de CLL, mais on la néglige
    tempsCL.Arret_du_comptage(); // temps cpu
 };

 
//// mise à jour de l'initialisation, par exemple après un restart
//// même paramètres que Initial, par contre ici il n'y a aucune création
//void LesCondLim::Re_initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D
//                         ,bool choixtdt,int cas)
//  { // 1) on parcours le tableau de ddl d'initialisation
//    int tabInitTaille = tabInit.Taille();
//    for (int i=1;i<= tabInitTaille;i++)
//      { DdlLim& tabInit_i = tabInit(i);
//        // recup de la reference correspondant au mot cle
//        const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage());
//        if ((refinitial.Indic() == 4) && 
//           (tabInit_i.TypeDeCL()==TANGENTE_CL) )
//         {// cas des références d'arêtes, avec des conditions de tangente imposée
//          const ReferenceAF & ref = ((ReferenceAF &) refinitial);
//          // on renseigne les éléments ad hoc
//          int refTaille =  ref.Taille();         
//          for (int ne =1; ne<= refTaille;ne++)
//           {int tabInitiTaille = tabInit_i.Taille();
//            // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
//            // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
//            int idebut=1; int ifinfin = tabInitiTaille;// début normale
//            if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;};
//            for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
//              // affectation de la valeur d'initialisation
//              { Ddl ddl1 = tabInit_i.ElemLim(nd);   // récup des 3 ddl
//                Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl
//                Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl
//                // récup de l'élément
//                Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
//                SfeMembT & elsfe = (SfeMembT&) el;
//                // on renseigne l'élément
//                Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); 
//                elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );  
//                
//              }// fin boucle sur tabInit_i
//           }// fin boucle sur les éléments de la référence
//         }  // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE                     
//
//        else if (refinitial.Indic() != 1) 
//          // cas d'element
//          { cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!";
//            cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
//            Sortie(1);
//           }
//        else
//          // cas de noeuds
//         {// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon
//          // la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout
//          // cas peut de fois, 
//          const ReferenceNE & ref = ((ReferenceNE &) refinitial);
//          // traitement proprement dit
//          int refTaille = ref.Taille();          
//          for (int nn =1; nn<= refTaille;nn++)
//            {int tabInitiTaille = tabInit(i).Taille();
//             // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
//             // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
//             int idebut=1; int ifinfin = tabInitiTaille;// début normale
//             if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;};
//             for (int nd=idebut;nd<= ifinfin ;nd++)
//              // affectation de la valeur d'initialisation
//              { Ddl ddl = tabInit_i.ElemLim(nd);
//                Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
//                if (noe.Existe_ici(ddl.Id_nom()))
//                  // cas ou le ddl existe deja
//                   { noe.Change_val_t(ddl.Id_nom(),ddl.Valeur());
//                     if (choixtdt)
//                        noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur());
//                     // mise a jour des ddl aux temps  0 pour tous les ddl sauf ceux de position
//                     // car ces derniers sont les seuls dont la position initiale est déterminées à la lecture
//                     // du maillage
//                     if (!(Meme_famille(ddl.Id_nom(),X1))) 
//                        noe.Change_val_0(ddl.Id_nom(),ddl.Valeur());
//                     // on regarde s'il fait partie de la combinaison 
//                     // si oui on met en place les ddl correspondant à HSLIBRE
//                     Enum_ddl en = ddl.Id_nom();
//                     Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); 
//                    }                      
//                else
//                   // cas ou le ddl n'existe pas
//                 { // tout d'abord on regarde si c'est un déplacement
//            //       if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
//                   if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
//                  { if(!CompatDim(ddl.Nom())) // vérif de dimension
//                      { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
//                         << " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
//                        cout << " \n cas des ddl bloquees ";  
//                        cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
//                        Sortie (1);
//                       }
//                     // cas ok on impose le déplacement sur le Xi correspondant
//                     Enum_ddl en = ddl.Id_nom();
//                     //on cherche l'equivalent Ui en Xi
//                     en = UxyzXi(en);
//                     noe.Ajout_val_t(en,ddl.Valeur());
//                     // mise a jour des ddl aux autres temps   
//                //     noe.Ajout_val_0(en,ddl.Valeur());
//                     if (choixtdt)
//                       noe.Ajout_val_tdt(en,ddl.Valeur());                    
//                     // puis on regarde si le ddl initial fait partie de la combinaison 
//                     // si oui on met en place les ddl correspondant à HSLIBRE
//                     Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); 
//                     }  
//                   else
//                    { // cas ou il faut creer un ddl sup  
//                      //noe.PlusDdl(ddl);
//                      cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues"
//                           << " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
//                      cout << "\n cas des ddl d'initialisation ";     
//                      cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
//                      Sortie (1);
//                     }
//                  }           
//               }
//              }
//           }                       
//       }
//    // 2) cas des ddl imposes on verifie leurs existences
//    //  on vérifie également l'existence des courbes de charge adoc si nécessaire
//    //  on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple 
//    // vitesse et position ou accélération pour un même ddl
//    // on parcours le tableau de ddl bloques
//    // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt
//    int tabBloqTaille = tabBloq.Taille();
//    for (int i=1;i<= tabBloqTaille;i++)
//      { DdlLim& tabBloq_i = tabBloq(i);
//        // recup de la reference correspondant au mot cle
//        const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
//        if ((refinitial.Indic() == 4) && 
//           (tabBloq_i.TypeDeCL()==TANGENTE_CL) )
//         {// cas des références d'arêtes, avec des conditions de tangente imposée
//          // ici on s'occupe de renseigner les éléments
//          const ReferenceAF & ref = ((ReferenceAF &) refinitial);
//          // on renseigne les éléments ad hoc
//          int refTaille =  ref.Taille();         
//          for (int ne =1; ne<= refTaille;ne++)
//           {int tabBloqiTaille = tabBloq_i.Taille();
//            // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
//            // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
//            int idebut=1; int ifinfin = tabBloqiTaille;// début normale
//            if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;};
//            for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
//              // affectation de la valeur d'initialisation
//              { Ddl ddl1 = tabBloq_i.ElemLim(nd);   // récup des 3 ddl
//                Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl
//                Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl
//                // récup de l'élément
//                Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
//                SfeMembT & elsfe = (SfeMembT&) el;
//                // on continue que si le temps est actif ou pas
//                if ((tabBloq_i.Temps_actif(0.)))
//                  { // on renseigne l'élément
//                    Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); 
//                    elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );  
//                  };
//              }// fin boucle sur tabBloq_i
//           }// fin boucle sur les noeuds de la référence
//         }  // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE                     
//
//        else if (refinitial.Indic() != 1) 
//          // cas autre d'element par exemple
//          { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!";
//            cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
//            Sortie (1);
//           }
//        else
//          // cas de noeuds
//         {const ReferenceNE & ref = ((ReferenceNE &) refinitial);
//          int refTaille =  ref.Taille();         
//          for (int nn =1; nn<= refTaille;nn++)
//           {int tabBloqiTaille = tabBloq_i.Taille();
//  /*          // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim
//            if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
//              {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
//                    << " que le nombre de noeud de la reference associee !! ";
//               cout << " condition limite : "; tabBloq_i.Affiche();
//               Sortie(1);       
//              }*/
//            // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
//            // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
//            int idebut=1; int ifinfin = tabBloqiTaille;// début normale
//            if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
//            for (int nd=idebut;nd<= ifinfin ;nd++)
//              // affectation de la valeur d'initialisation
//              { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl
//                // on regarde si le temps est actif ou pas
//                if ((tabBloq_i.Temps_actif(0.)))
//                  { // on n'intervient que si le temps initial est actif
//                    tabBloq_i.ElemLim(nd).Met_en_service();
//                    // récup du noeud                            
//                    Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
//                    string nom_courbe = tabBloq_i.Nom_courbe(nd);
//                    Courbe1D * pt_courbe = NULL; 
//                    if (nom_courbe != "")
//                      // cas de l'existence d'une courbe de charge
//                      // appel pour récupérer la courbe (juste pour la vérif
//                      // car on ne s'en sert pas aprés !)
//                      { pt_courbe = lesCourbes1D->Trouve(nom_courbe);
//                       }
//                    // maintenant on regarde du coté des noeuds  
//                    if (!noe.Existe_ici(ddl.Id_nom()))
//                      // cas ou il faut creer un ddl sup
//                      // on regarde le cas eventuel des coordonnees entrainees
//                      // si on est en entraine et que le ddl a imposer est un Ui
//                      // alors on ne verifie que les dimensions et on indique le blocage
//        //              {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
//                      {if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
//                        { // cas d'un ddl de déplacement, et que le ddl X1 existe déjà
//                          if(!CompatDim(ddl.Nom()))
//                           { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
//                             << " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ;
//                             cout << " \n cas des ddl bloquees ";  
//                             cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
//                             Sortie (1);
//                            }
//                          else // cas ou c'est Xi le ddl bloque, on indique le blocage
//                           { Enum_ddl en = ddl.Id_nom();
//                             //on cherche l'equivalent Ui en Xi
//                             en = UxyzXi(en);
//                             noe.Change_fixe(en,true);
//                             // on regarde s'il fait partie de la combinaison et on fixe les blocages
//                             Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); 
//                            }                       
//                          }                           
//                       else
//                       // cas d'un ddl inexistant diff de U, création puis initialisation a zero 
//                       { noe.PlusDdl(ddl);
//                         noe.Change_val_0(ddl.Id_nom(),0.);
//                         noe.Change_val_t(ddl.Id_nom(),0.);
//                         if (choixtdt)
//                            noe.Change_val_tdt(ddl.Id_nom(),0.);
//                         // puis on indique que le ddl est bloque 
//                         noe.Change_fixe(ddl.Id_nom(),true);                                            
//                         // on regarde s'il fait partie de la combinaison et on fixe les blocages
//                         Enum_ddl en = ddl.Id_nom();
//                         Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); 
//                        }
//                       }
//                     else   // cas ou le ddl existe   
//                       // on indique que le ddl est bloque, mais on ne change pas sa valeur
//                       // ce sera fait au moment de la mise à jour à tdt
//                      { // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1)
//                        // dans ce cas il est libre, on peut le bloquer sans pb, 
//                        // soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement
//                        noe.Change_fixe(ddl.Id_nom(),true);
//                        // on regarde s'il fait partie de la combinaison et on fixe les blocages
//                        Enum_ddl en = ddl.Id_nom();
//                        Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); 
//                      }
//                  }
//                 else
//                  {// si le ddl bloqué n'est pas actif pour le temps 0. 
//                   tabBloq_i.ElemLim(nd).Met_hors_service();
//                   // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé
//                   // récup du noeud                            
//                   Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
//                   // on regarde du coté du noeuds  
//                   if (!noe.Existe_ici(ddl.Id_nom()))
//                      // cas ou il faut creer un ddl sup
//                      // on regarde le cas eventuel des coordonnees entrainees
//                      // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
//         //             {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
//                      {if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
//                       {// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis 
//                        // initialisation a zero et on indique qu'il est hors service
//                         noe.PlusDdl(ddl);
//                         noe.Change_val_0(ddl.Id_nom(),0.);
//                         noe.Change_val_t(ddl.Id_nom(),0.);
//                         if (choixtdt) noe.Change_val_tdt(ddl.Id_nom(),0.);
//                         // puis on indique que le ddl est bloque et hors service
//                         noe.Met_hors_service(ddl.Id_nom());                                            
//                         noe.Change_fixe(ddl.Id_nom(),true);                                            
//                        }
//                       }
//                   // pour le reste on ne fait rien, se sera géré par les mises à jour
//                   // en fonction de l'évolution du temps 
//                   } // fin du cas ddl bloqué et pas actif pour le temps 0.
//               }
//            }
//         }                      
//       }
//     // on initialise la situation de blocage  et condition linéaires
//     Validation_blocage (lesRef,0.);
//     // vérif qu'il n'y a pas de surcharge de blocage
//     Verif_surcharge_blocage(lesMail,lesRef,0.,cas);  
//   };


    // incrementation des coordonnees a t+dt et des ddl en fonctions des ddl imposes
    // et du chargement
    // coef: est un facteur multiplicatif des ddl sans courbes de charge,
    //       est supposé intégrer déjà le multiplicateur général
    // en fait du chargement impose
    // mult_gene : multiplicateur général de tous les chargements
    // deltat : le pas de temps en cours
    // temps : le temps courant où sont calculées les conditions
    // ch_statut : indique s'il y a changement ou non de statut des conditions limites (pour les ddl aux noeuds)
    //            c-a-d un ddl qui passe de bloqué à non bloqué ou inversement: il s'agit uniquement des ddl aux noeuds
    //            c-a-d ceux qui ont une influence sur la mise en place des cl sur la raideur et le résidu 
    // cas    : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque
    //          le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont
    //          leur statut modifié de manière équivalente
    //    =0    pas d'association
    //    =1    association X V GAMMA
    // lorsque en_ddl est égal à  NU_DDL, cela signifie que l'on met les conditions limites sur tous les
    // ddl de noeud actifs
    // lorsque en_ddl est différent de NU_DDL, il donne le type des seules ddl pour lesquels on met les 
    // conditions de blocage: par exemple X1 -> blocage sur X1,X2,X3 selon la dimension
    
    
    void LesCondLim::MiseAJour_tdt
                  (const double& mult_gene,LesMaillages * lesMail,const double& deltat,const LesReferences* lesRef
                  ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD
                  ,const double& coef,bool& ch_statut
                  ,int cas,Enum_ddl en_ddl) 
{
 tempsCL.Mise_en_route_du_comptage(); // temps cpu
 // préparation
 bool tous_les_blocages = true;
 if (en_ddl != NU_DDL) tous_les_blocages = false;
 // la mise en place des blocages s'effectue en deux temps, ceci pour préparer la vérification
 // de la non sur imposition de ddl: ceci pour les ddl aux noeuds
 // 1- au premier passage : on met en libre les ddl qui sont relachés, on met tous les ddl actifs
 //    en libre 
 // 2- au second passage : les ddl au temps actifs sont fixés (et éventuellement surfixé si pb)
 //
 // pour les ddl d'encastrement ou de symétrie pour les sfe, tout ce fait au premier passage uniquement
 //    ---- premier passage ----   
 int tabBloqTaille =tabBloq.Taille();
 for (int i=1;i<= tabBloqTaille;i++)
   { DdlLim& tabBloq_i = tabBloq(i);
     // on regarde si les temps dépendent d'une fct nD
     // si oui on modifie les bornes du ddl
     if (tabBloq_i.Temps_depend_nD())
        LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD);
     // pour le ddlLim, si le temps est inférieur au temps actif
     // ou si d'une part le temps n'est pas actif et qu'au pas précédent
     // il n'était pas également actif on ne fait rien
     if (!(tabBloq_i.Pas_a_prendre_en_compte(temps)))
      {bool actif_pour_le_temps =  tabBloq_i.Temps_actif(temps); // pour simplifier
       // recup de la reference correspondant au mot cle
       const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
       if ((refinitial.Indic() == 4) && 
           (tabBloq_i.TypeDeCL()==TANGENTE_CL) )
        {// cas des références d'arêtes, avec des conditions de tangente imposée
         bool devient_actif = (actif_pour_le_temps && (!tabBloq_i.Etat_validation()));
         bool devient_inactif = ((!actif_pour_le_temps) && (tabBloq_i.Etat_validation()));
         // on n'intervient que s'il y a un changement d'état
         if (devient_actif || devient_inactif)
         {//int tabBloqitaille = tabBloq_i.Taille();
          const ReferenceAF & ref = ((ReferenceAF &) refinitial);
          int reftaille = ref.Taille();
          // on boucle sur les numéros de la référence
          for (int ne =1; ne<= reftaille;ne++)
          {// on regarde si le temps est actif ou pas
           if (devient_actif)   
            // cas ou on veut le blocage mais qu'au temps précédent ce n'était pas valide
            { // récup de l'élément
              SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
              // que ce soit dans le cas d'un champ ou normal, on n'a pas besoin d'itérer sur les ddl du ddlLim
              // car d'un part pour le champ, on a autant de dim_espace ddl que d'élément dans la référence
              // et d'autre part dans le cas normal on a uniquement un seul dim_espace ddl -> vecteur
              // !!!!!! pour l'instant on considère que c'est en 3D 
              #ifdef MISE_AU_POINT
                 if ((ParaGlob::Dimension() < 3) || (tabBloq_i.Taille() != 3))
                 	{ cout << "\n erreur, pour l'instant les conditions de type TANGENTE_CL ne sont operationnelles "
                 	       << " que pour la dimension 3 !! ";
                 	  cout << "\n reference concernee: "; ref.Affiche();
                 	  cout << "\n condition limite concernee: ";tabBloq_i.Affiche();
                    tempsCL.Arret_du_comptage();
                 	  Sortie(1);      
                 	};
              #endif
              int tabBloqitaille = tabBloq_i.Taille(); // normalement = 3 ici
              Tableau <Ddl> t_ddl(tabBloqitaille); // les valeurs du vecteur qui permet le calcul de la tangence
              for (int nd=1;nd<=tabBloqitaille;nd++)
              	{Ddl ddl = tabBloq_i.ElemLim(nd);
              	 // choix entre valeur simple et valeur qui varie
                if(tabBloq_i.Nom_courbe(nd) != "")
                   { // cas d'une courbe de charge, récup de la courbe
                     Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd));
                     // on change la valeur du ddl
                     if (tabBloq_i.BlocageRelatif())  // cas d'une modif relativement au temps précédent
                      { // pour l'instant ce n'est pas implanté
                        // en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la
                        // position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à
                        // l'élément qui updaterait sa position (qui peut être différente pour chaque élément)
                        // $$$ à faire s'il y a une demande, pour l'instant on attend $$$$
                        cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant"
                             << " ce cas n'est pas implante, donc le demander !!! "
                             << "\n LesCondLim::MiseAJour_tdt(.... ";
                        tempsCL.Arret_du_comptage();
                        Sortie(1);
                      }
                     else
                        { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
                          ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd);
                        };
                     t_ddl(nd) = ddl;
                   }
                 else if (tabBloq_i.NomF_charge(nd) != "")
                    { // cas d'une fonction nD de charge, récup
                     Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd));
                     // on change la valeur du ddl
                     if (tabBloq_i.BlocageRelatif())  // cas d'une modif relativement au temps précédent
                      { // pour l'instant ce n'est pas implanté
                        // en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la
                        // position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à
                        // l'élément qui updaterait sa position (qui peut être différente pour chaque élément)
                        // $$$ à faire s'il y a une demande, pour l'instant on attend $$$$
                        cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant"
                             << " ce cas n'est pas implante, donc le demander !!! "
                             << "\n LesCondLim::MiseAJour_tdt(.... ";
                        tempsCL.Arret_du_comptage();
                        Sortie(1);
                      }
                     else
                      {// pour l'instant on limite l'utilisation des fonctions aux seules grandeurs globales
                       if (pt_fctnD->NbVariable_locale() != 0)
                        {cout << "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements, pour l'instant"
                             << " seule une dependance a des variables globales est possible !!! "
                             << "\n LesCondLim::MiseAJour_tdt(.... ";
                         tempsCL.Arret_du_comptage();
                         Sortie(1);
                        };
                      Tableau <double> & tab_ret = pt_fctnD->Valeur_pour_variables_globales();
                      #ifdef MISE_AU_POINT
                       if (tab_ret.Taille() != 1)
                        {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte "
                              << "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements"
                              << "\n LesCondLim::MiseAJour_tdt(.... ";
                         tempsCL.Arret_du_comptage();
                         Sortie(1);
                        };
                      #endif
                        // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
                        ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd);
                      };
                     t_ddl(nd) = ddl;
                    }
                  else // cas d'un ddl à valeur fixe
                   { // cas d'un ddl à valeur fixe
                     t_ddl(nd) = ddl;
                   };
              	};
              // on renseigne l'élément
              Coordonnee3 vpla(t_ddl(1).Valeur(),t_ddl(2).Valeur(),t_ddl(3).Valeur()); 
              elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );
            }
           else if (devient_inactif)
            // on relache le blocage si nécessaire, pour cela  on regarde donc s'il y a changement de statut
            { // récup de l'élément
              SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
              // on renseigne l'élément
              Coordonnee3 vpla; // initalisé à 0 par défaut, ne sert pas ici
              elsfe.DefCondLim(RIEN_TYPE_CL,vpla, ref.NumeroFA(ne) );  
             };
          // sinon on ne fait rien   
          }; //-- fin de la boucle sur ne
         }//-- fin du test sur devient_actif ou devient_inactif
        }//-- fin du cas ref d'encastrement ou de symétrie
        else // cas d'une référence de noeud
        {const ReferenceNE & ref = ((ReferenceNE &) refinitial);
         int reftaille = ref.Taille();
         for (int nn =1; nn<= reftaille;nn++)
          {int tabBloqitaille = tabBloq_i.Taille();
           // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
           // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
           int idebut=1; int ifinfin = tabBloqitaille;// début normale
           if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
           for (int nd=idebut;nd<= ifinfin ;nd++)
             // incrementation en fonction de la valeur de blocage et du coef
            {Ddl ddl = tabBloq_i.ElemLim(nd);
             // concernant le temps, soit le ddlLim est actif ou il change de statut: actif à non actif
             Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
             if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
               //  cas de deplacements imposes en entraine on change les Ui en Xi
               ddl.Change_nom(UxyzXi(ddl.Id_nom()));
             bool a_considerer = tous_les_blocages;
             if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux
               {if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;}
             Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier    
             if (a_considerer)
             { if ( noe.En_service(ddlenu) ) 
                { // on regarde si le temps est actif ou pas
                  if (!actif_pour_le_temps)
                   // cas du temps non actif, on relache le blocage si nécessaire
                   // on regarde donc s'il y a changement de statut
                   {if (tabBloq_i.Etat_validation() && (noe.Ddl_fixe(ddlenu)))
                     {ch_statut = true;
                      Retire_cl(nd,tabBloq_i,ddlenu,noe,cas);
                     }
                    } //-- fin du test ou le temps n'est pas actif
                  else
                   // cas du temps actif
                   // on regarde s'il y a changement de statut                   
                   {if (!(tabBloq_i.Etat_validation())&& (!(noe.Ddl_fixe(ddlenu))))
                      { // on change le statut que si c'est une variable, les données n'influencent pas les raideurs et seconds membres
                        if (noe.UneVariable(ddlenu))
                          ch_statut = true;
//                      Mise_cl(nd,tabBloq_i,ddlenu,noe,cas);
                      };
                    // gestion des surcharges de blocage
                    // au premier passage on met tous les ddl en libre s'ils sont actifs
                    if (noe.Ddl_fixe(ddlenu))
                      Retire_cl(nd,tabBloq_i,ddlenu,noe,cas);
                   }//-- fin du test si le temps est actif                      
                }//-- fin du test si le ddl du noeud est une variable et est en service
             }//-- fin du test si le noeud est à considérer ou pas
            }//-- fin de la boucle sur tabBloq_i: indice nd
          }//-- fin de la boucle nn
        }//-- fin du cas des noeuds
      } // fin du if (!(tabBloq_i.Pas_a_prendre_en_compte(temps)))
   }//-- fin de la boucle sur tabBloq
 
 //    ---- second passage ----   
 for (int i=1;i<= tabBloqTaille;i++)
   { DdlLim& tabBloq_i = tabBloq(i);
     // recup de la reference correspondant au mot cle
     const ReferenceNE & ref = 
         ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
     // on ne continue que si c'est une référence de noeud
     if (ref.Indic() == 1)    
     { int reftaille = ref.Taille();
       // cas particulier des mouvements solides
       if (tabBloq_i.Mouvement_Solide())
         {MiseAjour_tdt_second_passage_mvtSolide(mult_gene,lesMail,deltat,cas
                                   ,lesCourbes1D,lesFonctionsnD,coef,tabBloq_i,ref,temps,en_ddl);
         }
       else
       // cas différent des mouvements solides
       {for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
          // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
          int idebut=1; int ifinfin = tabBloqitaille;// début normale
          if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
          for (int nd=idebut;nd<= ifinfin ;nd++)
            // incrementation en fonction de la valeur de blocage et du coef
           {Ddl ddl = tabBloq_i.ElemLim(nd);
            // pour le ddlLim, si le temps est inférieur au temps actif
            // ou si d'une part le temps n'est pas actif et qu'au pas précédent
            // il n'était pas également actif on ne fait rien
            if (tabBloq_i.Pas_a_prendre_en_compte(temps)) break;
            // maintenant soit le ddlLim est actif ou il change de statut: actif à non actif
            Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
  //          if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
 
////--debug
//if (noe.Num_noeud()==197)
// {cout << "\n debug1: LesCondLim::MiseAJour_tdt(..";
//  noe.Affiche();cout << endl;
// };
////--fin debug
 
 
            if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
              //  cas de deplacements imposes en entraine on change les Ui en Xi
              ddl.Change_nom(UxyzXi(ddl.Id_nom()));
            bool a_considerer = tous_les_blocages;
            if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux
              {if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;}
            Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier    
            if (a_considerer)
             { // on regarde si les temps dépendent d'une fct nD
               // si oui on modifie les bornes du ddl
               if (tabBloq_i.Temps_depend_nD())
                  LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
               bool actif_pour_le_temps =  tabBloq_i.Temps_actif(temps); // pour simplifier
               bool une_variable = noe.UneVariable(ddlenu); // pour simplifier
               // cas des variables: si le ddl du noeud est en service on continue sinon on ne fait rien
               // ou cas d'une donnée et le temps actif
               if (  ( une_variable && noe.En_service(ddlenu)) 
                   ||(!une_variable && actif_pour_le_temps)  )
                { // on regarde si le temps est actif ou pas, seul le cas actif est ici considérer
                  if (actif_pour_le_temps)
                    // gestion des surcharges de blocage
                    // au second  passage on fixe les ddl actifs
                    {Mise_cl(nd,tabBloq_i,ddlenu,noe,cas);   
                     // on choisit entre ddl à valeur fixe ou avec une courbe de charge
                     // coef intègre le multiplicateur global: mult_gene
                     if ((tabBloq_i.Nom_courbe(nd) != "")&&(tabBloq_i.NomF_charge(nd) == ""))
                       { // cas d'une courbe de charge, récup de la courbe
                         Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd));
                         // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle
                         // car au paravant il pouvait être non nul
                         // ici changement et non ajout , prise en compte de la relativité du blocage
                         double val_final = 0.;
                         if (tabBloq_i.BlocageRelatif())  // cas d'une modif relativement au temps précédent
                         	{ // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat
                              ddl.Valeur() = ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) 
                                             * tabBloq_i.Echelle_courbe(nd);
                         	  val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu);	
                         	}
                         else 
                            { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
                              ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd);
                              val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu);
                            };
                         noe.Change_val_tdt(ddlenu,val_final); // mise à jour
                       }
                     else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) == ""))
                       { // cas d'une fonction nD de charge, récup
                         Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd));
                         // on commence par récupérer les conteneurs des grandeurs à fournir
                         List_io <Ddl_enum_etendu>& li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire();
                         List_io <TypeQuelconque >& li_quelc = pt_fctnD->Li_equi_Quel_evolue();
                         // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire
                         Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
                                                        (noe, TEMPS_tdt,li_enu_scal));
                         // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur
                         Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc);
                         // calcul de la valeur et retour dans tab_ret
                         Tableau <double> & tab_ret = pt_fctnD->Valeur_FnD_Evoluee
                                 (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
                         #ifdef MISE_AU_POINT
                          if (tab_ret.Taille() != 1)
                           {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte "
                                 << "\n *** blocage via une fonction nD pour l'evolution du ddl"
                                 << Nom_ddl(ddlenu)
                                 << "\n LesCondLim::MiseAJour_tdt(.... ";
                            tempsCL.Arret_du_comptage();
                            Sortie(1);
                           };
                         #endif
                         // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle
                         // car au paravant il pouvait être non nul
                         // ici changement et non ajout , prise en compte de la relativité du blocage
                         double val_final = 0.;
                         if (tabBloq_i.BlocageRelatif())  // cas d'une modif relativement au temps précédent
                           { // pour l'instant  a priori ce n'est pas possible car le temps
                             // est une variable globale que l'on ne peut pas modifier pour les fonctions nD
                             // il faut donc utiliser conjointement une courbe1D pour le temps et la fonction nD pour le reste
                             cout << "\n *** blocage relatif avec uniquement une fonction nD: ce n'est pas possible"
                                  << " pour avoir un blocage relatif il faut utiliser conjointement une courbe de charge "
                                  << " pour le temps et une fonction nD pour le reste !!!!"
                                  << "\n LesCondLim::MiseAJour_tdt(.... ";
                             tempsCL.Arret_du_comptage();
                             Sortie(1);
                           }
                         else
                           { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
                              ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd);
                              val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu);
                           };
                         noe.Change_val_tdt(ddlenu,val_final); // mise à jour
                       }
                     else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) != ""))
                       { // cas d'une fonction nD de charge, récup
                         Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd));
                         // on commence par récupérer les conteneurs des grandeurs à fournir
                         List_io <Ddl_enum_etendu>& li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire();
                         List_io <TypeQuelconque >& li_quelc = pt_fctnD->Li_equi_Quel_evolue();
                         // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire
                         Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
                                                        (noe, TEMPS_tdt,li_enu_scal));
                         // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur
                         Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc);
                         // calcul de la valeur et retour dans tab_ret
                         Tableau <double> & tab_ret = pt_fctnD->Valeur_FnD_Evoluee
                                 (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
                         #ifdef MISE_AU_POINT
                          if (tab_ret.Taille() != 1)
                           {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte "
                                 << "\n *** blocage via une fonction nD pour l'evolution du ddl"
                                 << Nom_ddl(ddlenu)
                                 << "\n LesCondLim::MiseAJour_tdt(.... ";
                            tempsCL.Arret_du_comptage();
                            Sortie(1);
                           };
                         #endif
                         // idem pour la courbe 1D
                         Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd));
                         // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle
                         // car au paravant il pouvait être non nul
                         // ici changement et non ajout , prise en compte de la relativité du blocage
                         double val_final = 0.;
                         if (tabBloq_i.BlocageRelatif())  // cas d'une modif relativement au temps précédent
                          { // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat
                            ddl.Valeur() = tab_ret(1) *
                                              (((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat)))
                                                * tabBloq_i.Echelle_courbe(nd)
                                              );
                           
                            val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu);
                          }
                         else
                            { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
                              ddl.Valeur() = tab_ret(1) *
                                             (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd);
                              val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu);
                            };
                         noe.Change_val_tdt(ddlenu,val_final); // mise à jour
                       }
                     else
                       { // cas d'un ddl à valeur fixe
                         // du au fait de l'initialisation d'un incrément à l'autre dans les algos globaux on change
                         double val_final=noe.Valeur_t(ddlenu); // récup de la valeur à t
                         val_final += coef * ddl.Valeur(); // mise en place du delta
                         noe.Change_val_tdt(ddlenu,val_final);
                       };

                     }; //-- fin du test si le temps est actif                      
                  }; //-- fin du test si le ddl du noeud est en service
                }; //-- fin du test si le noeud est à considérer ou pas
             }; //-- fin de la boucle sur tabBloq_i
          }; //-- fin de la boucle sur nn
       }; //-- fin du else du if (tabBloq_i.Mouvement_Solide())
     }; //-- fin du du test : if (ref.Indic() == 1)
   };//-- fin de la boucle sur tabBloq
 // vérif qu'il n'y a pas de surcharge de blocage
 Verif_surcharge_blocage(lesMail,lesRef,temps,cas);
 
 tempsCL.Arret_du_comptage(); // temps cpu

};
      
// validation des conditions de blocages, pour l'incrément.
// concernant l'activité des ddlLim, elle est enregistrée en fonction du temps
// idem pour les conditions linéaires
void LesCondLim::Validation_blocage (LesReferences* lesRef,const double& temps)      
  {
    // tout d'abord les conditions de blocage
    int tabBloqTaille =tabBloq.Taille();
    for (int i=1;i<= tabBloqTaille;i++)
      { DdlLim& tabBloq_i = tabBloq(i);
        // recup de la reference correspondant au mot cle
        const ReferenceNE & ref = 
            ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
        if (ref.Indic() == 1) // ok que si c'est une ref de noeud
        { int reftaille = ref.Taille();
          for (int nn =1; nn<= reftaille;nn++)
           {int tabBloqitaille = tabBloq_i.Taille();
            for (int nd=1;nd<= tabBloqitaille;nd++)
              // validation de l'activité du ddlLim
              tabBloq_i.Validation(temps);
            };                     
         };
      };
    // maintenant les conditions linéaires
    int tabTaille = tab_iocondiline.Taille();
////----- debug
//cout << "\n LesCondLim::Validation_blocage: avant validation \n temps = " << temps << "\n";
//cout << tab_iocondiline;
////--- fin debug
    for (int icondli=1;icondli<= tabTaille; icondli++)
        tab_iocondiline(icondli).Validation(temps);
////----- debug
//cout << "\n LesCondLim::Validation_blocage: après validation \n";
//cout << tab_iocondiline;
////--- fin debug
  };
       
    // test s'il y a changement de statut pour le temps indiqué par rapport à la situation actuelle ou pas
    // n'effectue aucune autre opération
    // si en_ddl est différent de NU_DDL on test le changement de statut uniquement pour le ddl en_ddl
bool LesCondLim::Changement_statut(const LesMaillages * lesMail,const LesReferences* lesRef
                          ,LesFonctions_nD*  lesFonctionsnD
                          ,const double& temps,const Enum_ddl en_ddl)
//  *************** a mettre en conformité avec miseà jour tdt ***************$



  { cout << "\n methode pas operationnelle, a mettre a jour !!!!"
         << "\n LesCondLim::Changement_statut(....";
    Sortie(1);     
  
     // préparation
    bool tous_les_blocages = true;
    if (en_ddl != NU_DDL) tous_les_blocages = false;
    bool ch_statut = false; // valeur de retour
  
    int tabBloqTaille =tabBloq.Taille();
    // on parcours le tableau de ddl bloques
    for (int i=1;i<= tabBloqTaille;i++)
      { DdlLim& tabBloq_i = tabBloq(i);
        // recup de la reference correspondant au mot cle
        const ReferenceNE & ref = 
            ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
        int reftaille = ref.Taille();
        for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          for (int nd=1;nd<= tabBloqitaille;nd++)
            // incrementation en fonction de la valeur de blocage et du coef
           {Ddl ddl = tabBloq_i.ElemLim(nd);
            Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
            // on regarde si les temps dépendent d'une fct nD
            // si oui on modifie les bornes du ddl
            if (tabBloq_i.Temps_depend_nD())
               LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
            Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier
 //           if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
            if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
              //  cas de deplacements imposes en entraine on change les Ui en Xi
              ddl.Change_nom(UxyzXi(ddlenu));
            bool a_bloquer = tous_les_blocages;
            if (! a_bloquer) // cas ou on ne veut que certain blocage, a_bloque est faux
              {if (Meme_famille(en_ddl,ddlenu)) a_bloquer = true;}   
            if (a_bloquer)
             { if (!(tabBloq_i.Temps_actif(temps)))
                   // cas de la courbe non active pour le temps
                   { // si le ddl du noeud est en service on continue sinon on ne fait rien
                     if ( noe.En_service(ddlenu) )  
                       // on regarde s'il y a changement de statut et que c'est une variable
                       {if ((noe.Ddl_fixe(ddlenu)) && (noe.UneVariable(ddlenu)))
                          ch_statut = true;
                        } //-- fin du test si le ddl du noeud est en service 
                    } //-- fin du test ou le temps n'est pas actif
                else
                   // cas du temps actif
                   { if (ddl.Valeur() != 0)
                     {// si le ddl du noeud est en service on continue sinon on ne fait rien
                     if ( noe.En_service(ddlenu) )  
                       // on regarde s'il y a changement de statut  et que c'est une variable
                      {if ( (!(noe.Ddl_fixe(ddlenu))) && (noe.UneVariable(ddlenu)))
                         ch_statut = true;   
                       } //-- fin du test si le ddl du noeud est en service 
                      } //-- fin du test si la valeur a bloquer est différente de 0
                    } //-- fin du test si le temps est actif 
              } 
             }
          }                     
       }
    return ch_statut;
   };
                                                                                    
      
// récupération des tableaux d'indices généraux des variables ddl bloqués
// cas : donne le type d'association de ddl que l'on veut
//      =0 -> pas d'association
//      =1 -> association de Xi avec Vi avec Gammai
// t_assemb: donne pour chaque type d'association, le numéro d'assemblage correspondant au different ddl 
//           de l'association 
//           cas=1 -> numéro d'assemblage de X1 puis V1 puis GAMMA1
//  : en sortie une liste de Gene_asso, correspondant à tous les ddl bloqués et les 
//            les ddl associés 
list <LesCondLim::Gene_asso> LesCondLim::Tableau_indice  
      (const LesMaillages * lesMail,const Tableau <Nb_assemb> & t_assemb
      ,const LesReferences* lesRef,const double& temps,int cas)
{ // def de la liste de retour
  list <LesCondLim::Gene_asso> li_ret;
  // préparation
  int tabBloqTaille =tabBloq.Taille();
  // on parcours le tableau de ddl bloques
  for (int i=1;i<= tabBloqTaille;i++)
    { DdlLim& tabBloq_i = tabBloq(i);
      // recup de la reference correspondant au mot cle
      const ReferenceNE & ref = 
          ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
      if (ref.Indic() == 1) // ok pour les noeuds uniquement   
       {int reftaille = ref.Taille();
        for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
          // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
          int idebut=1; int ifinfin = tabBloqitaille;// début normale
          if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
          for (int nd=idebut;nd<= ifinfin ;nd++)
            // incrementation en fonction de la valeur de blocage
           {Ddl ddl = tabBloq_i.ElemLim(nd);
            const Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));            
 //           if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
            if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
              //  cas de deplacements imposes en entraine on change les Ui en Xi
              ddl.Change_nom(UxyzXi(ddl.Id_nom()));
            // si le blocage est relatif à une donnée et non à une variable arrêt
            if (!(noe.UneVariable(ddl.Id_nom()))) break;
            // si le ddl concerne la direction 3 et que l'on est en axi, arrêt
            // car le ddl 3 n'est pas utilisé en blocage en axi
            Enum_ddl en_ddl = ddl.Id_nom(); // le type principal de l'élément Gene_asso
            if (ParaGlob::AxiSymetrie() && FoncDim(en_ddl))
              {Enum_ddl prem_ddl = PremierDdlFamille(en_ddl);
               // pour l'instant on ne traite que X, U, V et Gamma
               bool fin_traitement = false; // init
               switch (prem_ddl)
                { case X1: if (en_ddl == X3)fin_traitement = true;
                      break;
                  case V1: if (en_ddl == V3)fin_traitement = true;
                      break;
                  case GAMMA1:if (en_ddl == GAMMA3)fin_traitement = true;
                      break;
                  default:
                    cout << "\n *** erreur pour l'instant en axi, seules les cas "
                         << " Xi, Vi, GAMMAi sont pris en compte pour les CL selon dir 3 "
                         << " \n LesCondLim::Tableau_indice(... "<< endl;
                    break;
                };
               if (fin_traitement) break;
              };
            
            // on regarde si le ddl fait partie de la liste à scruter, si l'on est
            // dans le cas d'une combinaison, sinon c'est ok
            bool choix = true; // vrai a priori, c'est à dire le cas = 0
            // qui convient que dans le cas = 0, sinon:
            if (cas!= 0)
             { if (Dans_combinaison(cas,en_ddl))
                  {choix = true;}
               else
                  {choix = false;} // cas d'une combinaison , et d'un ddl qui ni appartiend pas
             };
            if (choix)
             { // on test que si le temps est actif
               // ici les tmin et tmax du ddl ne sont pas modifiés, on considère que ce sont
               // ceux qui ont été mise à jour à la précédente mise à jour
               if ((tabBloq_i.Temps_actif(temps)))
                 { switch (cas)
	                  { case 0 : // cas pas d'association
                      { // def du tableau de position pour l'élément Gene_asso
                        Tableau <int> pointe(1); // dimension pour Xi,Vi,GAMMAi
                        // recup de la position du ddl
                        pointe(1) = noe.Pointeur_assemblage(en_ddl,t_assemb(1).n);
                        // ajout dans la liste
                        Gene_asso aa(en_ddl,pointe);
                        li_ret.push_back(aa);
                        break;
                      }
		                   case 1 : // cas de l'association X V GAMMA
		                    { // def du tableau de position pour l'élément Gene_asso
                        Tableau <int> pointe(3); // dimension pour Xi,Vi,GAMMAi
                        // récup des ddl secondaire et du ddl principal bloqué
                        Tableau <Enum_ddl> t_enu = MemeCombinaison(cas,en_ddl); 
                        pointe(1) = noe.Pointeur_assemblage(t_enu(1),t_assemb(1).n);
                        pointe(2) = noe.Pointeur_assemblage(t_enu(2),t_assemb(2).n);
                        pointe(3) = noe.Pointeur_assemblage(t_enu(3),t_assemb(3).n);
                        // ajout dans la liste
                        Gene_asso aa(en_ddl,pointe);
                        li_ret.push_back(aa);
////// --debug
//cout << "\n debug LesCondlim::Tableau_indice("
//     << "\n li_ret.size= "<< li_ret.size() << endl;
////// -- fin debug
     
		                      break;
		                    }
	                  }; //-- fin du switch (cas)
                 }; //-- fin du if ((tabBloq_i.Temps_actif(temps)))
             }; //-- fin du if (choix)
           }; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++)
         }; //-- fin du for (int nn =1; nn<= reftaille;nn++)
       }; //-- fin du if (ref.Indic() == 1)
    }; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
//// --debug
//cout << "\n debug LesCondlim::Tableau_indice("
//     << "\n li_ret.size= "<< li_ret.size() ;
//list <LesCondLim::Gene_asso>::iterator ie,iefin=li_ret.end();; // def d'un iterator adoc
//int ih=1; // indice
//for(ie=li_ret.begin(),ih=1;ie!=iefin;ie++,ih++)
//   // comme les valeurs des X V Gamma vont être écrasé par le calcul global, on utilise
//   // des conteneurs intermédiaires
//   {//trois cas
//    LesCondLim::Gene_asso & s = (*ie); // pour simplifier
//    int ix=s.pointe(1); // début des Xi
//    int iv=s.pointe(2); // début des Vi 
//    int ig=s.pointe(3); // début des gammai
//    cout << "\n ix= " << ix << ", iv= "<< iv << ", ig= "<< ig;
//   };
//cout <<  endl;
//// -- fin debug
 
  // retour de la liste     
  return li_ret;
  };  
     
      
      
// mise en place des conditions limites sur les matrices et/ou second membres
// cas : indique un type d'association de ddl 
//     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
//     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès 
//           lors que l'un a été fixé par l'utilisateur
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
//        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef,
                               Mat_abstraite & matglob,Vecteur& vecglob
                               ,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2)
{
  tempsCL.Mise_en_route_du_comptage(); // temps cpu
  int tabBloqTaille =tabBloq.Taille();
  int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
  Tableau <Enum_ddl> tmc; // tableau de travail
  // on parcours le tableau de ddl bloques
  for (int i=1;i<= tabBloqTaille;i++)
    { DdlLim& tabBloq_i = tabBloq(i);
      // recup de la reference correspondant au mot cle
      const ReferenceNE & ref = 
           ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
      if (ref.Indic() == 1) // ok pour les noeuds uniquement   
       {int reftaille = ref.Taille();
        for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
          // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
          int idebut=1; int ifinfin = tabBloqitaille;// début normale
          if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
          for (int nd=idebut;nd<= ifinfin ;nd++)
            // mise en place de la condition limite
            { Ddl ddl = tabBloq_i.ElemLim(nd);
              Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
              //  cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
//              if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) 
              if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
                  ddl.Change_nom(UxyzXi(ddl.Id_nom()));
              // on continue uniquement si le ddl du tableau de  blocage est en service
              // et si pour le noeud c'est une variable
              if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
               { // récup des enu_ddl équivalent au groupe
	                tmc = MemeCombinaison(cas,ddl.Id_nom());
	                int tailletmc = tmc.Taille();
                 for (int itc=1;itc <= tailletmc;itc++)
                  {// on boucle sur tous les ddl a imposer
                   // calcul du pointeur correspondant au ddl cherche
                   int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
                   // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
                   if ((pt != -1) && (noe.En_service(tmc(itc)))) 
                    {// ce que l'on veut c'est une variation nulle des ddl imposee
                     // -> valeur imposee = 0              
                     // cas de la matrice, et modif du second membre si la valeur imposee
                     // est differente de zero (ce qui n'est pas le cas ici !)
                     condlim(nb_casAss).Val_imposee_Mat(matglob,vecglob,pt,0.,vec2);
                     // cas du second membre et sauvegarde des reactions
                     condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2); 
                     };
                  }; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
               }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
            }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
         }; //-- fin de for (int nn =1; nn<= reftaille;nn++)                      
       }; //-- fin de if (ref.Indic() == 1)
    }; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
  // affichage éventuelle de la matrice de raideur et du second membre     
  if (ParaGlob::NiveauImpression() >= 10)
      { string entete = " affichage de la matrice  apres conditions limites des ddl initialement bloques ";
        matglob.Affichage_ecran(entete); 
        entete = " affichage du second membre apres conditions limites des ddl initialement bloques ";
        vecglob.Affichage_ecran(entete); 
      };
  tempsCL.Arret_du_comptage(); // temps cpu
};
      
// mise en place des conditions limites sur le second membres
// nb_casAssemb : le cas d'assemblage
// cas : indique un type d'association de ddl 
//     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
//     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
//            a été fixé par l'utilisateur
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
//        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef,
                                 Vecteur& vecglob,const Nb_assemb& nb_casAssemb
											,int cas,Vecteur* vec2)
{
  tempsCL.Mise_en_route_du_comptage(); // temps cpu
  int tabBloqTaille =tabBloq.Taille();
  int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
  Tableau <Enum_ddl> tmc; // tableau de travail
  // on parcours le tableau de ddl bloques
  for (int i=1;i<= tabBloqTaille;i++)
    { DdlLim& tabBloq_i = tabBloq(i);
      // recup de la reference correspondant au mot cle
      const ReferenceNE & ref = 
           ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
      if (ref.Indic() == 1) // ok pour les noeuds uniquement   
       {int reftaille = ref.Taille();
        for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
          // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
          int idebut=1; int ifinfin = tabBloqitaille;// début normale
          if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
          for (int nd=idebut;nd<= ifinfin ;nd++)
            // mise en place de la condition limite
            { Ddl ddl = tabBloq_i.ElemLim(nd);
              Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
              //  cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
    //          if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) 
              if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
                  ddl.Change_nom(UxyzXi(ddl.Id_nom()));
              // on continue uniquement si le ddl du tableau de  blocage est en service
              // et si pour le noeud c'est une variable
              if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
               { // récup des enu_ddl équivalent au groupe
	             tmc = MemeCombinaison(cas,ddl.Id_nom());
	             int tailletmc = tmc.Taille();
                 for (int itc=1;itc <= tailletmc;itc++)
                  {// on boucle sur tous les ddl a imposer
                   // calcul du pointeur correspondant au ddl cherche
                   int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
                   // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
                   if ((pt != -1) && (noe.En_service(tmc(itc)))) 
                     {// ce que l'on veut c'est une variation nulle des ddl imposee
                      // -> valeur imposee = 0              
                      // cas du second membre et sauvegarde des reactions
                      condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2); 
                      };
                  }; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
               }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
            }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
         }; //-- fin de for (int nn =1; nn<= reftaille;nn++)                     
       }; //-- fin de if (ref.Indic() == 1)
    }; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
  // affichage éventuelle du second membre     
  if (ParaGlob::NiveauImpression() >= 10)
      { string entete =  " affichage du second membre apres conditions limites des ddl initialement bloques ";
        vecglob.Affichage_ecran(entete); 
      };
  tempsCL.Arret_du_comptage(); // temps cpu
 };
   
// mise en place des conditions limites sur deux matrices
// utilisé par exemple pour le flambement
// la première matrice est initialisée avec des 1 sur la diagonale
// la seconde avec des 0 sur la diagonale 
// cas : indique un type d'association de ddl 
//     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
//     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
//            a été fixé par l'utilisateur
void LesCondLim::ImpConLimtdt2Mat(LesMaillages * lesMail,LesReferences* lesRef,
                       Mat_abstraite & matglob,Mat_abstraite & matgeom
                       ,const Nb_assemb& nb_casAssemb,int cas)  
{
  tempsCL.Mise_en_route_du_comptage(); // temps cpu
  int tabBloqTaille =tabBloq.Taille();
  int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
  Tableau <Enum_ddl> tmc; // tableau de travail
  // on parcours le tableau de ddl bloques
  for (int i=1;i<= tabBloqTaille;i++)
    { DdlLim& tabBloq_i = tabBloq(i);
      // recup de la reference correspondant au mot cle
      const ReferenceNE & ref = 
          ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
      if (ref.Indic() == 1) // ok pour les noeuds uniquement   
       {int reftaille = ref.Taille();
        for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
          // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
          int idebut=1; int ifinfin = tabBloqitaille;// début normale
          if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
          for (int nd=idebut;nd<= ifinfin ;nd++)
            // mise en place de la condition limite
            { Ddl ddl = tabBloq_i.ElemLim(nd);
              Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
              //  cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
     //         if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) 
              if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
                 ddl.Change_nom(UxyzXi(ddl.Id_nom()));
              // on continue uniquement si le ddl du tableau de  blocage est en service
              // et si pour le noeud c'est une variable
              if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
               { // récup des enu_ddl équivalent au groupe
	             tmc = MemeCombinaison(cas,ddl.Id_nom());
	             int tailletmc = tmc.Taille();
                 for (int itc=1;itc <= tailletmc;itc++)
                  {// on boucle sur tous les ddl a imposer
                   // calcul du pointeur correspondant au ddl cherche
                   int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
                   // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
                   if ((pt != -1) && (noe.En_service(tmc(itc)))) 
                     {// ici on ne fait que modifier les matrices -> un 1 sur la diagonale
                      // et 0 sur le reste de la ligne et colonne correspondantes
                      condlim(nb_casAss).Val_imposSimple_Mat(matglob,pt,1.);
                      condlim(nb_casAss).Val_imposSimple_Mat(matgeom,pt,0.);
                      };
                  }; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
               }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
            }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
         }; //-- fin de for (int nn =1; nn<= reftaille;nn++)                      
       }; //-- fin de if (ref.Indic() == 1)
    }; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
  // affichage éventuelle des deux  matrices de raideur      
  if (ParaGlob::NiveauImpression() >= 10)
      { string entete = " affichage de la premiere matrice de raideur apres conditions limites (matglob) ";
        entete +=  " des ddl initialement bloques";
        matglob.Affichage_ecran(entete); 
        entete = " affichage de la seconde matrice de raideur apres conditions limites (matgeom) ";
        entete +=  " des ddl initialement bloques";
        matgeom.Affichage_ecran(entete); 
      };
  tempsCL.Arret_du_comptage(); // temps cpu
};
 
// récupération des reactions initiales, avant les rotations dues aux  conditions linéaires 
// il s'agit des réactions dues aux ddl bloqués et dues aux conditions linéaires
// et calcul des torseurs de réaction
void LesCondLim::ReacAvantCHrepere(Vecteur& residu,LesMaillages * lesMail,
                       LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas)            
{ 
  int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
  Tableau <Enum_ddl> tmc; // tableau de travail
  // on cree une liste de stockage intermediaire
  list <ReactStoc> lili;
  list <int> indice_tabBloq; // tableau de travail, qui sert pour le calcul des torseurs de réaction
  ReactStoc elem; // element courant de stockage des réactions
  
  //----------- cas des ddl bloqués -----------------
  // on parcours le tableau de ddl bloques
  int tabBloqTaille =tabBloq.Taille();
  for (int i=1;i<= tabBloqTaille;i++)
    { DdlLim& tabBloq_i = tabBloq(i);
      // recup de la reference correspondant au mot cle
      const ReferenceNE & ref = 
          ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
      if (!((ref.Indic() == 4) &&                 // le cas des conditions de tangence sur 
           (tabBloq_i.TypeDeCL()==TANGENTE_CL ))  // les arrêtes n'est pas à prendre en compte
           && (ref.Indic() == 1))      // s'applique uniquement au cas des ref de noeuds
       {int reftaille = ref.Taille();
        for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
          // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
          int idebut=1; int ifinfin = tabBloqitaille;// début normale
          if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
          for (int nd=idebut;nd<= ifinfin ;nd++)
            // récupération de la condition limite
            { Ddl ddl = tabBloq_i.ElemLim(nd);
              Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
              //  cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
     //         if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) 
              if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
               ddl.Change_nom(UxyzXi(ddl.Id_nom()));
              // on continue uniquement si le ddl du tableau de  blocage est en service
              // et si pour le noeud c'est une variable
              if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
               { // récup des enu_ddl équivalent au groupe
                 tmc = MemeCombinaison(cas,ddl.Id_nom());
	                int tailletmc = tmc.Taille();
                 for (int itc=1;itc <= tailletmc;itc++)
                  {// on boucle sur tous les ddl a imposer
                   // calcul du pointeur correspondant au ddl cherche
                   int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
                   // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
                   if ((pt != -1) && (noe.En_service(tmc(itc)))) 
                    { // maintenant on peut récupérer la réaction
                      elem.ddl = ddl; 
                      elem.ddl.Valeur() = residu(pt);
                      elem.numMail = ref.Nbmaille();
                      elem.numNoeud = ref.Numero(nn);
                      elem.casAss = nb_casAss;
                      lili.push_back(elem);  // sauvegarde de la réaction
                      indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq
                    };
                  }; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
               }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
            }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
         }; //-- fin de for (int nn =1; nn<= reftaille;nn++)
       }; //-- fin de if (!((ref.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) )
    }; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
       
  //----------- cas des conditions linéaires -----------------
  // on cree une liste de stockage intermediaire
  list <ReactStoc> lili_CLin;List_io <DeuxEntiers> indice_dans_tab_iocondiline;
  
  // on a besoin d'enregistrer une seule fois chaque réaction, or le mode de fabrication des CLL
  // fait que cela conduit à des redondances. Pour les repérer, on va utiliser un conteneur de drapeau
  // de manière à limiter la taille de ce conteneur on utilise une map, c'est moins rapide en acces
  // qu'un tableau, mais c'est mieux qu'une liste et c'est plus petit qu'un tableau, car a priori
  // il y a moins beaucoup moins de ddl bloqué par les CLL que de ddl total du pb
  map < int , bool, std::less <int> > reac_deja_stocke;
  
  // on parcours le tableau des CLL
  // on boucle sur le tableau de conditions limites linéaires  enregistré
  int tabTaille = tab_CLinApplique.Taille();
  for (int i=1;i<= tabTaille; i++)
  	{int sous_taille = tab_CLinApplique(i).Taille();
  	 for (int j=1; j<= sous_taille; j++)
  	 	{ Condilineaire& condi = tab_CLinApplique(i)(j);
       // on met à jour les pointeurs d'assemblage pour bien localiser les infos dans SM et K
       // ce sera refait dans l'assemblage...
       condi.ConditionPourPointeursAssemblage(nb_casAssemb);
       // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
       if (condi.Iddl() > -1)
         { // chaque ddl qui appartient à une CLL et qui est associé
           // à un coefficient non nulle conduit à une condition limite
           const Vecteur& Vectval = condi.Val();
           const Tableau<int>& pt = condi.Pt_t();
           const Tableau<Enum_ddl>& t_enu = condi.Tab_Enum();
           const Tableau < Noeud *>& t_noeud = condi.TabNoeud();

           //  on boucle  sur les noeuds puis sur les ddl de la CLL
           int taille = pt.Taille();
           int nb_noeud = t_noeud.Taille();int itab=1;
           int nbddlfamille = taille / nb_noeud;
           for (int i_noe=1;i_noe <= nb_noeud;i_noe++)
             for (int i_fa =1; i_fa<= nbddlfamille; i_fa++,itab++) 
             { // on ne stocke que si la réaction n'a pas déjà été stockée
               if ((reac_deja_stocke.find(pt(itab))==reac_deja_stocke.end())
                  && (Vectval(itab) != 0.) ) // et que le coef est non nul
						             { // on définit la réaction
							              elem.ddl.Change_nom(t_enu(itab));
                     elem.ddl.Valeur() = residu(pt(itab));
                     elem.numMail = t_noeud(i_noe)->Num_Mail();
                     elem.numNoeud = t_noeud(i_noe)->Num_noeud();
//                     elem.casAss = condi.CasAssemb().n;
                     elem.casAss = nb_casAssemb.n;
                     lili_CLin.push_back(elem);  // on sauvegarde la réaction
                     // sauvegarde de l'indice dans tab_iocondiline car le premier indice "i"
                     // de tab_CLinApplique est celui correspondant à la condition tab_iocondiline(i)
                     // le second indice permet de retrouver la ref
                     indice_dans_tab_iocondiline.push_back(DeuxEntiers(i,i_noe));
                     // on renseigne la map
                     reac_deja_stocke[pt(itab)] = true;             
						             };
             };
			      };
  	 	};
  	};

  //----------- fin du cas des conditions linéaires -----------------
//--débug ---
//cout << "\n " << indice_dans_tab_iocondiline << endl;
//--débug---


   // ----- on initialise le tableau des torseurs de réaction
   int tabtorsTaille = tab_torseurReac.Taille();
   for (int i=1;i<= tabtorsTaille;i++)
   	  if (tab_torseurReac(i).existe_torseur_reac)
   	      tab_torseurReac(i).Zero_init_torseur();
   int dima = ParaGlob::Dimension();
   if(ParaGlob::AxiSymetrie())
       // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
       // dimension-1 coordonnées donc on décrémente
       dima--;

   // --- enregistrement des réactions pour ddl bloqué et calcul des torseurs
  { // on encapsule 
   list <ReactStoc>::iterator i; // def d'un iterator adoc
   reaction.Change_taille((int)lili.size());
//   map_reaction.erase(map_reaction.begin(),map_reaction.end());
   int j;
   list <int>::iterator i_taBloq=indice_tabBloq.begin();
   for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++,i_taBloq++)
       { reaction(j) = *i;
//         map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)]
//                     .push_back(&(reaction(j)));
         // transfert des informations aux noeuds
         ReactStoc& reac = reaction(j); // pour simplifier
         // récup du noeud j du maillage i 
         Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud);
         Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction
         // dans le cas où la réaction n'existe pas on l'ajoute
         // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas
         // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité
         { if (!noe.Existe_ici(enu_reac))
//           { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE);  
            { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE);
              noe.PlusDdl(reac_ddl);
            }
           else 
            // sinon il faut le bloquer car la réaction est imposée 
            { noe.Change_fixe(enu_reac,true);};             
           // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
           if (ttRG(*i_taBloq) != 0) // si = 0 c'est que le ddl n'est pas un déplacement classique
              CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac);
         };
         // mise à jour de la réaction 
	        noe.Change_val_tdt(enu_reac,reac.ddl.Valeur());  // t=tdt
       };
   // on va maintenant exporter les composantes du tenseur vers des grandeurs globales
   int taille_tors_bloqu = ttRG_noms_ref.Taille();
   int taille_tors_bloquplus1 = taille_tors_bloqu +1;
   // cas d'un blocage de ddl
   {int il = 1;
    for (int ia=1;ia<taille_tors_bloquplus1;ia++,il++)
      { TorseurReac& torseur= tab_torseurReac(ia); // tableau des torseurs de réaction
       // 1) la résultante
       int dimaPlus1 = dima+1;
       for (int ic= 1; ic < dimaPlus1; ic++)
        {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Re_"+ChangeEntierSTring(ic);
         // récup du pointeur de conteneur
         const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_ref));
         #ifdef MISE_AU_POINT
         if (pointe == NULL)
           { cout << "\n *** pb dans l'exportation de composantes de torseur  !! "
                  << " la variable globale  "<< (nom_ref)
                  << ", n'est pas disponible, on ne peut pas continuer  "
                  << "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
             Sortie(1);
           };
         #endif
         // on l'affecte:
         TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
         Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
         tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic);
        };
       // 2) le moment
       for (int ic= 1; ic < dimaPlus1; ic++)
        {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
         // récup du pointeur de conteneur
         const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_ref));
         #ifdef MISE_AU_POINT
         if (pointe == NULL)
           { cout << "\n *** pb dans l'exportation de composantes de torseur  !! "
                  << " la variable globale  "<< (nom_ref)
                  << ", n'est pas disponible, on ne peut pas continuer  "
                  << "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
             Sortie(1);
           };
         #endif
         // on l'affecte:
         TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
         Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
         tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic);
        };
      };
   };
  }; // fin encapsulation
         
   // --- enregistrement des réactions pour les CLL et calcul également des torseurs associés
   //  il s'agit des réactions définies précédemment (-- cas des conditions linéaires --)
  { // on encapsule 
   list <ReactStoc>::iterator i; // def d'un iterator adoc
   List_io <DeuxEntiers>::iterator iti = indice_dans_tab_iocondiline.begin();
   reaction_CLin.Change_taille((int)lili_CLin.size());
   int j;
   for (i=lili_CLin.begin(),j=1 ; i != lili_CLin.end(); i++,j++,iti++)
       { reaction_CLin(j) = *i;
         // transfert des informations aux noeuds
         ReactStoc& reac = reaction_CLin(j); // pour simplifier
         // récup du noeud j du maillage i 
         Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud);
         Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction
         // dans le cas où la réaction n'existe pas on l'ajoute
         // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas
         // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité
         { if (!noe.Existe_ici(enu_reac))
//           { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE);  
            { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE);
              noe.PlusDdl(reac_ddl);
            }
           else 
            // sinon il faut le bloquer car la réaction est imposée 
            { noe.Change_fixe(enu_reac,true);};             
           // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
           CalculTorseurReaction(tab_torseurReac(ttRGCLL((*iti).un)((*iti).deux)),noe,reac);
         };
         // mise à jour de la réaction 
	        noe.Change_val_tdt(enu_reac,reac.ddl.Valeur());  // t=tdt
       };
   // exportation en grandeurs globales: cas d'un blocage venant d'une CLL
   int taille_tors_bloqu = ttRG_noms_ref.Taille();
   int taille_tors_bloquplus1 = taille_tors_bloqu +1;
   int taille_torsP1 = tab_torseurReac.Taille() + 1;
   {int il = 1; //ttRGCLL_noms_ref.begin();
    for (int ia=taille_tors_bloquplus1;ia<taille_torsP1;ia++,il++)
      { TorseurReac& torseur= tab_torseurReac(ia); // tableau des torseurs de réaction
       // 1) la résultante
       int dimaPlus1 = dima+1;
       for (int ic= 1; ic < dimaPlus1; ic++)
        {string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Re_"+ChangeEntierSTring(ic);
         // récup du pointeur de conteneur
         const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_ref));
         #ifdef MISE_AU_POINT
         if (pointe == NULL)
           { cout << "\n *** pb dans l'exportation de composantes de torseur  !! "
                  << " la variable globale  "<< (nom_ref)
                  << ", n'est pas disponible, on ne peut pas continuer  "
                  << "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
             Sortie(1);
           };
         #endif
         // on l'affecte:
         TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
         Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
         tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic);
        };
       // 2) le moment
       for (int ic= 1; ic < dimaPlus1; ic++)
        {string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
         // récup du pointeur de conteneur
         const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_ref));
         #ifdef MISE_AU_POINT
         if (pointe == NULL)
           { cout << "\n *** pb dans l'exportation de composantes de torseur  !! "
                  << " la variable globale  "<< (nom_ref)
                  << ", n'est pas disponible, on ne peut pas continuer  "
                  << "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
             Sortie(1);
           };
         #endif
         // on l'affecte:
         TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
         Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
         tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic);
        };
      };
   };
  }; // fin encapsulation
};

// calcul des reactions et stockage des valeurs
// ceci dans le cas ou il n'y a pas de conditions lineaires appliquee
// on se sert des valeurs sauvegardees lors de la mise en place des CL bloquees
// cas : indique un type d'association de ddl 
//     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
//     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
//            a été fixé par l'utilisateur
void LesCondLim::CalculReaction(LesMaillages * lesMail,LesReferences* lesRef
                                ,const Nb_assemb& nb_casAssemb,int cas)
{ 
 int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
 Tableau <Enum_ddl> tmc; // tableau de travail
 // on cree une liste de stockage intermediaire
 list <ReactStoc> lili; 
 list <int> indice_tabBloq; // tableau de travail
 ReactStoc elem; // l'element courant
 // on parcours le tableau de ddl bloques
 int tabBloqTaille =tabBloq.Taille();
 for (int i=1;i<= tabBloqTaille;i++)
    { DdlLim& tabBloq_i = tabBloq(i);
      // recup de la reference correspondant au mot cle
      const ReferenceNE & ref = 
          ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
      if (ref.Indic() == 1) // ok pour les noeuds uniquement   
       {int reftaille = ref.Taille();
        for (int nn =1; nn<= reftaille;nn++)
         {int tabBloqitaille = tabBloq_i.Taille();
          // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
          // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
          int idebut=1; int ifinfin = tabBloqitaille;// début normale
          if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
          for (int nd=idebut;nd<= ifinfin ;nd++)
            // calcul de la reaction
            { Ddl ddl = tabBloq_i.ElemLim(nd);
              Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
              //  cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
   //           if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) 
              if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
                ddl.Change_nom(UxyzXi(ddl.Id_nom()));
              // on continue uniquement si le ddl du tableau de  blocage est en service
              // et si pour le noeud c'est une variable
              if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
               { // récup des enu_ddl équivalent au groupe
	                tmc = MemeCombinaison(cas,ddl.Id_nom());
	                int tailletmc = tmc.Taille();
                 for (int itc=1;itc <= tailletmc;itc++)
                  {// on boucle sur tous les ddl a imposer
                   // calcul du pointeur correspondant au ddl cherche
                   int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
                   // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
                   if ((pt != -1) && (noe.En_service(tmc(itc)))) 
                   { elem.ddl = ddl; 
                     elem.ddl.Valeur() = condlim(nb_casAss).ValReact(pt);
                     elem.numMail = ref.Nbmaille();
                     elem.numNoeud = ref.Numero(nn);
                     elem.casAss = nb_casAss;
                     lili.push_back(elem);
                     indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq 
                    };               
                  }; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
               }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
            }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
         }; //-- fin de  for (int nn =1; nn<= reftaille;nn++)                    
       }; //-- fin de if (ref.Indic() == 1)
    }; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
 // on initialise le tableau des torseurs de réaction
 int tabtorsTaille = tab_torseurReac.Taille();
 for (int i=1;i<= tabtorsTaille;i++)
 	  if (tab_torseurReac(i).existe_torseur_reac)
 	      tab_torseurReac(i).Zero_init_torseur();
     
 // enregistrement
 list <ReactStoc>::iterator i,ilfin = lili.end(); // def d'un iterator adoc
 reaction.Change_taille((int)lili.size());
//   map_reaction.erase(map_reaction.begin(),map_reaction.end());
 int j;
 list <int>::iterator i_taBloq=indice_tabBloq.begin();
 for (i=lili.begin(),j=1 ; i != ilfin; i++,j++,i_taBloq++)
      {reaction(j) = *i;
//         map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)]
//                     .push_back(&(reaction(j)));
       // transfert des informations aux noeuds
       ReactStoc& reac = reaction(j); // pour simplifier
       // récup du noeud j du maillage i 
       Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud);
       Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction
       // dans le cas où la réaction n'existe pas on l'ajoute
       // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas
       // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité
       { if (!noe.Existe_ici(enu_reac))
//            { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE);  
          { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE);  
            noe.PlusDdl(reac_ddl);
          }
         else 
          // sinon il faut le bloquer car la réaction est imposée 
          { noe.Change_fixe(enu_reac,true);};             
         // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
         CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac);
        };   
       // mise à jour de la réaction 
	      noe.Change_val_tdt(enu_reac,reac.ddl.Valeur());  // t=tdt
       };
 // on va maintenant exporter les composantes du tenseur vers des grandeurs globales
 int taille_tors_bloqu = ttRG_noms_ref.Taille();
 int taille_tors_bloquplus1 = taille_tors_bloqu +1;
 int dima = ParaGlob::Dimension();
 if(ParaGlob::AxiSymetrie())
     // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
     // dimension-1 coordonnées donc on décrémente
     dima--;
 // cas d'un blocage de ddl
 {int il = 1;
  for (int ia=1;ia<taille_tors_bloquplus1;ia++,il++)
    {TorseurReac& torseur= tab_torseurReac(ia); // tableau des torseurs de réaction
     // 1) la résultante
     int dimaPlus1 = dima+1;
     for (int ic= 1; ic < dimaPlus1; ic++)
      {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Re_"+ChangeEntierSTring(ic);
       // récup du pointeur de conteneur
       const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_ref));
       #ifdef MISE_AU_POINT
       if (pointe == NULL)
         { cout << "\n *** pb dans l'exportation de composantes de torseur  !! "
                << " la variable globale  "<< (nom_ref)
                << ", n'est pas disponible, on ne peut pas continuer  "
                << "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
           Sortie(1);
         };
       #endif
       // on l'affecte:
       TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
       Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
       tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic);
      };
     // 2) le moment
     for (int ic= 1; ic < dimaPlus1; ic++)
      {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
       // récup du pointeur de conteneur
       const void* pointe =  (ParaGlob::param->GrandeurGlobal(nom_ref));
       #ifdef MISE_AU_POINT
       if (pointe == NULL)
         { cout << "\n *** pb dans l'exportation de composantes de torseur  !! "
                << " la variable globale  "<< (nom_ref)
                << ", n'est pas disponible, on ne peut pas continuer  "
                << "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
           Sortie(1);
         };
       #endif
       // on l'affecte:
       TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
       Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
       tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic);
      };
    };
 };
};
                
// récupération des reactions= residu et stockage des valeurs 
// NB: après changement de repère, il n'y a plus que des ddl bloqués 
// cas : indique un type d'association de ddl 
//     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
//     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
//            a été fixé par l'utilisateur
void LesCondLim::ReacApresCHrepere(Vecteur& residu,LesMaillages * lesMail,
                              LesReferences* ,const Nb_assemb& nb_casAssemb,int )
{ 
  int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
  Tableau <Enum_ddl> tmc; // tableau de travail
  // on cree une liste de stockage intermediaire
  list <ReactStoc> lili;
  list <int> indice_tabBloq; // tableau de travail
  ReactStoc elem; // l'element courant
  
  //----------- cas des ddl bloqués -----------------
  // l'indice des ddl bloqués reste inchangé après chgt de repère on utilise donc les 
  // réactions avant rotation par simplicité
  // a priori ce sont exactement les mêmes conditions qui existent avant et après chgt de repère 
  // sauf la valeur de la réaction
  int nb_reac = reaction.Taille();
  for (int i=1; i<= nb_reac; i++)
    if (reaction(i).casAss == nb_casAss) // si ce n'est pas le bon cas d'assemblage on ne fait rien
     { elem = reaction(i);
       Noeud & noe=lesMail->Noeud_LesMaille(elem.numMail,elem.numNoeud);
       elem.ddl.Valeur() = residu(noe.Position_ddl(elem.ddl.Id_nom(),nb_casAss)  );
       lili.push_back(elem);
     };
  
  // ------- cas des CLL --------------
  // contrairement aux cas des ddl boqués ici on ne peut pas utiliser reaction_CLin
  // car il y a une seule réaction dans le nouveau repère alors qu'il y en avait autant que de ddl
  // dans la CLL, dans le repère initial, donc on reparcours le tableau des CLL
  // on parcours le tableau des CLL
  // on boucle sur le tableau de conditions limites linéaires enregistré
  // et pour chaque element on impose une condition lineaire
  int tabTaille = tab_CLinApplique.Taille();
  for (int i=1;i<= tabTaille; i++)
  	{int sous_taille = tab_CLinApplique(i).Taille();
  	 for (int j=1; j<= sous_taille; j++)
  	 	{ Condilineaire& condi = tab_CLinApplique(i)(j);
  	 	  // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
		  if (condi.Iddl() > -1)
			{ if (condi.CasAssemb() == nb_casAssemb)
           { // la condition limite concerne uniquement un ddl pour chaque CLL
             // il s'agit du premier ddl, pour le premier noeud
             // on définit la réaction
             elem.ddl.Change_nom(condi.Tab_Enum()(1)); 
             elem.ddl.Valeur() = residu(condi.Pt_t()(1));
             elem.numMail = condi.TabNoeud()(1)->Num_Mail();
             elem.numNoeud = condi.TabNoeud()(1)->Num_noeud();
             elem.casAss = condi.CasAssemb().n;
             lili.push_back(elem);  // on sauvegarde la réaction              
           };
			};
  	 	};
  	};
   	  
   // enregistrement
   list <ReactStoc>::iterator i; // def d'un iterator adoc
   reactionApresCHrepere.Change_taille((int)lili.size());
   int j;
   for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++)
       {reactionApresCHrepere(j) = *i;};

   };
                                          
                
// affichage sur la sortie sort des reactions  
void LesCondLim::Affiche_reaction(ofstream& sort,const LesMaillages * lesMail) const
  { // l'entete
    sort << "\n==========================================================================";
    sort << "\n    sortie des efforts generes par l\'exterieur sur les noeuds  ";
    sort << "\n==========================================================================\n";
    sort << "\n\n 1)    les reactions individuelles  \n ";
     
    // on balaie le tableau de reaction et on constitue une liste intermédiaire, pour éviter
    // de sortir des doublons
    int reactionTaille = reaction.Taille();
    List_io <ReactStoc>  li_inter;
   
//    Tableau <ReactStoc> reaction; // les reactions pour les ddl bloqués
    for (int i= 1; i<= reactionTaille;i++)
      li_inter.push_back(reaction(i));
    li_inter.sort(); // on organise la liste
    li_inter.unique(); // on supprime les doublons
   
    // *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non
    // le contraire
    List_io <ReactStoc>::iterator il,ilfin=li_inter.end();
    for (il= li_inter.begin(); il != ilfin;il++)
      { sort << "\ncas assemb " << (*il).casAss
             << "  maillage " << (*il).numMail <<", noeud " <<(*il).numNoeud
             << ", ddl = " << (*il).ddl.Nom() << ", valeur = " << (-(*il).ddl.Valeur()) ;
      };
    // on s'occupe maintenant des torseurs de réactions globales si éventuellement il en existe
    sort << "\n\n\n==========================================================================";
    sort << "\n 2)    les torseurs globaux ";
    sort << "\n==========================================================================\n";
    // au niveau des références, il est possible d'avoir une référence qui sert pour plusieurs conditions limites
    // aussi on va globaliser les torseurs de réaction en sortie
    
    int dima = ParaGlob::Dimension();
    if(ParaGlob::AxiSymetrie())
      // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
      // dimension-1 coordonnées donc on décrémente
      dima--;
    int ttail = tab_torseurReac.Taille();
    for (int i=1;i<= ttail;i++)
   	  { TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier
   	    if (torseurReac.existe_torseur_reac)
   	  	 {// tout d'abord l'affichage de l'entête
   	  	 if (torseurReac.bloque_ou_CLL) 
   	  	    // cas où le torseur provient d'une condition ddl bloquée
   	  	    {DdlLim& tabBloq_i = tabBloq(*(ttorBloq(i).begin())); // pour simplifier (on ne prend que le 
   	  	                        // premier des bloqués), tous les autres ont le même nom de maillage et de ref
   	  	     sort << "\n";
   	  	     if (tabBloq_i.NomMaillage() != NULL)
   	  	        sort << " nom_maillage " << *(tabBloq_i.NomMaillage());
   	  	     sort << " nom_ref " << tabBloq_i.NomRef() 
   	  	          << "\n   F= ";
   	  	    }
   	  	  else
   	  	    // cas où le torseur provient d'une condition CLL
   	  	    {I_O_Condilineaire& iocondiline_i =  tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier
    	  	     sort << "\n";
   	  	     if (iocondiline_i.NomMaillage() != NULL)
   	  	        // cas où on considère les noms de maillage
    	  	    { int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier
    	  	      if (num_ref == 1)
    	  	      	{// cas d'une référence principale de CLL
    	  	         const string& nom_maillage = *(iocondiline_i.NomMaillage()); 
   	  	             sort << " nom_maillage " << nom_maillage
   	  	                  << " nom_ref " << iocondiline_i.NomRef() << "_CLL "; 
    	  	      	}
    	  	      else
    	  	      	{// cas d'une référence associé
   	  	          // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris
   	  	          // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1
   	  	          // qui correspond à la référence principale
//debug
//cout << "\n (*(ttorCLL(i).begin())).deux= " << (*(ttorCLL(i).begin())).deux << endl ;
//fin debug						 
    	  	          const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux - 1); 
   	  	             sort << " nom_maillage " << nom_maillage
   	  	                  << " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)
   	  	                  << "_CLL "; 
    	  	      	}	
    	  	     }
    	  	 else
    	  	    {// cas où on ne considère pas les noms de maillage
    	  	     int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier
    	  	      if (num_ref == 1)
    	  	      	// cas d'une référence principale de CLL
   	  	            { sort << " nom_ref " << iocondiline_i.NomRef() << "_CLL "; }
    	  	      else
    	  	      	// cas d'une référence associé
   	  	     // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris
   	  	     // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1
   	  	     // qui correspond à la référence principale
   	  	            { sort << " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1) 
   	  	                   << "_CLL ";
   	  	            };
    	  	    };
   	  	     sort << "\n   F= ";
   	  	    };
   	  	  // et maintenant l'affichage des infos     
   	  	  torseurReac.resultante.Affiche(sort,ParaGlob::NbdigdoCA());
         switch (dima)
          {case 1: break; // pas de moment en dimension 1
           case 2: sort << "\n   M=" << setprecision(ParaGlob::NbdigdoCA())  
                        << torseurReac.moment(1);  // la première composante est le moment
                   break;
           case 3: sort << "\n   M="; 
                   torseurReac.moment.Affiche(sort,ParaGlob::NbdigdoCA());
                   break;
          };
   	  	};
   	  };
    // sortie des réactions dues aux conditions linéaires 
    sort << "\n\n\n==========================================================================";
    sort << "\n 3)    les reactions dues aux conditions lineaires ";
    sort << "\n==========================================================================\n";
     
    // on balaie le tableau de reaction_CLin
    // *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non le contraire
// non, j'ai l'impression qu'il ne faut pas ici changer de signe ??? à voir par la suite en fonction des résultats
// si finalement ??
    int reaction_CLinTaille = reaction_CLin.Taille();
    for (int i= 1; i<= reaction_CLinTaille;i++)
      { sort << "\ncas assemb " << reaction_CLin(i).casAss
             << "  maillage " << reaction_CLin(i).numMail <<", noeud " <<reaction_CLin(i).numNoeud
             << ", ddl = " << reaction_CLin(i).ddl.Nom() << ", valeur = " << (-reaction_CLin(i).ddl.Valeur()) ;
//             << ", ddl = " << reaction_CLin(i).ddl.Nom() << ", valeur = " << (reaction_CLin(i).ddl.Valeur()) ;
      };
// l'entete
    sort << "\n==========================================================================";
    sort << "\n 4)   sortie sous forme de force des efforts de l\'exterieur sur les noeuds  ";
    sort << "\n==========================================================================";
    sort << "\n     les reactions sont ordonnees et sous forme de vecteurs avec 3 composantes  \n ";
   
    // on balaie le tableau de reaction
    // *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non
    // le contraire nb_maillage
    {Tableau <list <DeuxEntiers > > tab_indi(nb_maillage); // un tableau de travail
     for (int i= 1; i<= reactionTaille;i++)  // on remplit le tableau d'adressage indirecte
        tab_indi(reaction(i).numMail).push_back(DeuxEntiers(i,reaction(i).numNoeud));
     // on trie et on ordonne
     for (int i=1;i<=nb_maillage;i++)
      { list <DeuxEntiers >& indica = (tab_indi(i)); // pour simplifier
        indica.sort(); // ordonne en fonction du numéro de noeud
        list <DeuxEntiers >::iterator ili,ilifin=indica.end();
        // --- tout d'abord on sort une ref sur la liste des noeuds en réaction au cas ou
        sort << "\n # pour information la ref des noeuds concernes\n ";
        sort << "\n # nom_mail= "<<lesMail->NomMaillage(i)
             <<"\n# N_list_noe_en_react ";
        int compteur=0; int total_force=0;
        for (ili=indica.begin();ili != ilifin;ili++)
         // là on suit la progression des numéros de noeuds
         { ReactStoc& rea = reaction((*ili).un);
           int num_noeud = (*ili).deux; // le noeud considéré
           bool sortie_valide=false; // la sortie est validée ou non
           while (num_noeud == (*ili).deux)
            {switch (rea.ddl.Id_nom()) // on regarde les ddl
		            { case X1 : sortie_valide=true;break;
                case X2 : sortie_valide=true;break;
                case X3 : sortie_valide=true;break;
                default: break;
              };
             ili++;
            };
          // arrivée ici il y a une incrémentation de trop, on revient en arrière
          ili--;
          if (sortie_valide)
           { total_force++;
             sort << num_noeud << " ";compteur++;
             if (compteur > 20) {sort << "\n"; compteur=0;};
           };
         };
       
        // --- maintenant on sort les forces
        sort << "\n\n # --- les (" <<total_force<<") forces \n";
        for (ili=indica.begin();ili != ilifin;ili++)
         // là on suit la progression des numéros de noeuds
         {
           ReactStoc& rea = reaction((*ili).un);
           int num_noeud = (*ili).deux; // le noeud considéré
           Coordonnee3 force; // la force initialisée à 0.
           bool sortie_valide=false; // la sortie est validée ou non
           while (num_noeud == (*ili).deux)
            {switch (rea.ddl.Id_nom()) // on regarde les ddl
		            { case X1 : force(1)=rea.ddl.Valeur();sortie_valide=true;break;
                case X2 : force(2)=rea.ddl.Valeur();sortie_valide=true;break;
                case X3 : force(3)=rea.ddl.Valeur();sortie_valide=true;break;
                default: break;
              };
             ili++;
             if (ili != ilifin)
                rea = reaction((*ili).un);
            };
          // arrivée ici il y a une incrémentation de trop, on revient en arrière
          ili--;
          if (sortie_valide)
           { sort << num_noeud << "   " ;
             force.Affiche(sort,ParaGlob::NbdigdoCA());
             sort <<"\n";
           };
         };
      };
    };
  };
     
// mise en place de condition externes lineaires
// expression de la raideur et du second membre dans un nouveau repere
// ramène si oui ou non, il y a eu un changement effectué
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
//        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
bool LesCondLim::CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob
                              ,const Tableau <Condilineaire>& tab,const Nb_assemb& nb_casAssemb,Vecteur* vec2)
  {
     tempsCLL.Mise_en_route_du_comptage(); // temps cpu
  
     // on boucle sur le tableau et pour chaque element on impose une condition lineaire
     int tabTaille = tab.Taille();
	    bool modification = false; // init du retour
     for (int i=1;i<= tabTaille; i++)
      {Condilineaire& condi = tab(i);
       // calcul des pointeurs d'assemblage
       condi.ConditionPourPointeursAssemblage(nb_casAssemb);
       // application de la condition
       condlim(nb_casAssemb.n).CondlineaireCHRepere
               ( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2);
       modification=true;
      };
     // affichage éventuelle de la matrice de raideur et du second membre     
     if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0))
      { string entete = " affichage de la matrice  apres changement de repere du aux conditions limites externes (ex contact)";
        matglob.Affichage_ecran(entete); 
        entete = " affichage du second membre apres changement de repere du aux conditions limites externes  (ex contact) ";
        vecglob.Affichage_ecran(entete); 
      };                        
     tempsCLL.Arret_du_comptage(); // temps cpu
     // retour du fait qu'il y a eu ou non une modification faite
	    return modification;
  };

// mise en place de condition externe lineaires en une opération
// retour de la raideur et du second membre sans changement de repere
// ramène si oui ou non, il y a eu un changement effectué
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
//        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
bool LesCondLim::CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob
                    ,const Tableau <Condilineaire>& tab
                    ,const Nb_assemb& nb_casAssemb,Vecteur* vec2)
  {
     tempsCLL.Mise_en_route_du_comptage(); // temps cpu
  
     // on boucle sur le tableau et pour chaque element on impose une condition lineaire
     int tabTaille = tab.Taille();
     bool modification = false; // init du retour
     for (int i=1;i<= tabTaille; i++)
      {Condilineaire& condi = tab(i);
       // calcul des pointeurs d'assemblage
       condi.ConditionPourPointeursAssemblage(nb_casAssemb);
       // application d'une condition linéaire seule, avec en retour, la situation de la condition linéaire
       // imposée, ramené dans le repère initial
       condlim(nb_casAssemb.n).CondiLineaireImposeComplet
               ( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2);
       modification=true;
      };
     // affichage éventuelle de la matrice de raideur et du second membre
     if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0))
      { string entete = " affichage de la matrice  apres application CLL externes (ex contact) ";
        matglob.Affichage_ecran(entete);
        entete = " affichage du second membre apres apres application CLL externes (ex contact) ";
        vecglob.Affichage_ecran(entete);
      };
     tempsCLL.Arret_du_comptage(); // temps cpu
     // retour du fait qu'il y a eu ou non une modification faite
     return modification;
  };


//initialisation, mise a zero des  sauvegarde
 void LesCondLim::InitSauve(const Nb_assemb& nb_casAssemb) 
     { condlim(nb_casAssemb.n).EffaceSauvegarde(); // blocages : second membre et matrice,
       condlim(nb_casAssemb.n).EffaceCoLin();      // conditions lineaires
       // puis les torseurs de réactions
       int taille = tab_torseurReac.Taille();
       for (int i=1; i<= taille; i++)
   	     if (tab_torseurReac(i).existe_torseur_reac)
   	        tab_torseurReac(i).Zero_init_torseur();
     };
      
//----- lecture écriture dans base info -----
      // le cas d'assemblage n'est pas sauvegardé, car ce n'est pas une variable
      // qui appartient réellement à la classe
    	// cas donne le niveau de la récupération
        // = 1 : on récupère tout
        // = 2 : on récupère uniquement les données variables (supposées comme telles)
void LesCondLim::Lecture_base_info(ifstream& ent,const int cas,LesReferences& ,LesCourbes1D&
           ,LesFonctions_nD&  lesFonctionsnD)
 { // les conditions linéaires qui varies par exemples dues au contact sont stockées
   // autre part, dans LesContacts par exemple
   string toto; 
   switch (cas)
    { case 1:
      { cout << "== lecture des conditions limites \n";
        // lecture du type et vérification
        string nomtype;
        ent >> nomtype;
        if (nomtype != "****LesCondLim")
           Sortie(1);
        // lecture des différents tableaux
        ent >> toto >> tabBloq >> toto >> tabInit 
            >> toto >> tab_iocondiline >> toto >> reaction >> toto >> reaction_CLin;
        // dimensionnement du tableau des torseurs résultants
        LesCondLim::DimensionneTorseurs();
        break;
       }
      case 2:
       {// on lit les grandeurs relatives aux réactions
        ent >> toto;
        reaction.Entree(ent);
        ent >> toto;
        reaction_CLin.Entree(ent);
        // lectue des temps cpu de l'algo:
        ent >> toto >> tempsCL;
        ent >> toto >> tempsCLL;
        break;
        }
      default:
       { cout << "\n **** erreur !! cas non prevu: cas = " << cas
              << "\n LesCondLim::Lecture_base_info(...";
         Sortie(1);
       }
     };            
   // on met à jour le tableau map_reaction
//   map_reaction.erase(map_reaction.begin(),map_reaction.end());
//   int tail_reaction=reaction.Taille();
//   for (int j=1; j<=tail_reaction; j++)
//           { map_reaction["mail"+ChangeEntierSTring(reaction(j).numMail)
//                         +"noeud"+ChangeEntierSTring(reaction(j).numNoeud)].push_back(&(reaction(j)));
//            };
  };     
        // cas donne le niveau de sauvegarde
        // = 1 : on sauvegarde tout
        // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LesCondLim::Ecriture_base_info(ofstream& sort,const int cas)
 { // les conditions linéaires qui varies par exemples dues au contact sont stockées
   // autre part, dans LesContacts par exemple
   switch (cas)
    { case 1:
       {// écriture du type
        sort << "\n ****LesCondLim \n";
        // écriture des différents tableaux
        sort << " blocage " << tabBloq; 
        sort << " initialisation " << tabInit; 
        sort << " CLL_en_entree " << tab_iocondiline;
        sort << " reactions " << reaction;
        sort << " reac_CLineaire " << reaction_CLin << " ";
        break;
       }
      case 2:     
       {// on sort les grandeurs relatives aux réactions
        // en fait les réactions sont également sauvé aux noeuds mais peut-être que ce sera utile
        // d'avoir ici le type réaction stocké ?? donc on laisse
        sort << " reac_ddl_bloque ";
        reaction.Sortir(sort);
        sort << " reac_CLineaire ";
        reaction_CLin.Sortir(sort); sort << " ";
        // écriture des temps cpu de l'algo:
        sort << "\n tps_cpu_CL  " << tempsCL;
        sort << "\n tps_cpu_CLL " << tempsCLL;
        break;
        }
      default:
       { cout << "\n **** erreur !! cas non prevu: cas = " << cas
              << "\n LesCondLim::Ecriture_base_info(...";
         Sortie(1);
       }
     };            
  };     
        



