

// 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 "ReferenceNE.h"
#include "ReferenceAF.h"
#include "CharUtil.h"
#include "TypeQuelconqueParticulier.h"

    

 	 // retourne la liste des types de ddl actuellement imposés
	 // aux noeuds pour chaque maillage, la liste est exhaustive
	 // elle contiend tous les types au moins une fois utilisée
	 // cela ne signifie pas que le ddl en question soit présent
	 // pour tous les noeud du maillage considéré
	 // - le tableau de retour est indicé par le numéro de maillage correspondant
	 // - il y a une liste par maillage
Tableau <List_io < Ddl_enum_etendu> > LesCondLim::Les_type_de_ddl_en_reaction() const
 { // définition du tableau de retour
   Tableau <List_io <Ddl_enum_etendu> > tab_li(nb_maillage);
   // on boucle sur les réactions en cours pour remplir le tableau
   int nb_reac=reaction.Taille();
   for (int i=1;i<=nb_reac;i++)
    { List_io <Ddl_enum_etendu>& li=tab_li(reaction(i).numMail);
      Ddl_enum_etendu ddl_enu = (reaction(i).ddl.Id_nom());
      if (find(li.begin(),li.end(),ddl_enu) == li.end())
         li.push_back(ddl_enu);
    };
   // retour du tableau de listes
   return tab_li; 
 };
 
/*     // retourne les réactions aux conditions limites à un noeud noe d'un maillage mail
     // en paramètre il y a un pointeur sur la liste de retour, pour éviter la création
     // d'une liste intermédiaire
     // s'il n'y a pas de conditions limites : retour d'une liste vide
const list<const LesCondLim::ReactStoc*>& LesCondLim::Reaction_noeud_mail(int numNoeud,int numMail) const
  { string cle("mail"+ChangeEntierSTring(numMail)+"noeud"+ChangeEntierSTring(numNoeud));
    map < string, list<const ReactStoc*> , std::less <string> >::const_iterator it = map_reaction.find(cle);
    if (it != map_reaction.end())
     { return (*it).second;};
    // sinon pas d'existence donc retour d'une liste vide 
    const list<const LesCondLim::ReactStoc*> li; // construction d'une liste vide 
    return li;  
   };  */                                                         
	 
// retourne la liste des torseurs de réaction actuellement actif pour les maillages
// appelons tab_lili la liste:
// - tab_lili(i) concerne le maillage nb i
// - les éléments de tab_lili(i) sont les noms des références qui conduisent à un torseur de réaction
//                               actif, et un indice de gestion utilisé par LesCondLim pour retrouver
//                               rapidemment les informations 
Tableau < List_io <String_et_entier > >  LesCondLim::TabListTorseurReaction(const LesMaillages & lesmail) const
	{ // def de la grandeur de retour
	  Tableau < List_io <String_et_entier > > tab_lili(nb_maillage);
	  string nom; // une variable de travail
	  // on balaie le tableau des torseur
   int ttail = tab_torseurReac.Taille(); // tabBloq, tab_iocondiline et tab_torseurReac n'ont pas la même dimension
   for (int i=1;i<= ttail;i++)
   	  { TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier
   	    if (torseurReac.existe_torseur_reac)
   	  	 {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
            if (tabBloq_i.NomMaillage() != NULL)
               { const string& nom_maillage = *(tabBloq_i.NomMaillage()); // nom de maillage lue
                 tab_lili(lesmail.NumMaillage(nom_maillage)).push_back(String_et_entier(tabBloq_i.NomRef(),i));
               }
            else
               {tab_lili(1).push_back(String_et_entier(tabBloq_i.NomRef(),i));
               };
   	  	    }
   	  	  else
   	  	    // cas où le torseur provient d'une condition CLL
   	  	    {I_O_Condilineaire& iocondiline_i =  tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier
   	  	     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()); 
                   tab_lili(lesmail.NumMaillage(nom_maillage)).push_back
                             (String_et_entier(iocondiline_i.NomRef()+"_CLL",i));
                 }
                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
                   const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux-1); 
                   tab_lili(lesmail.NumMaillage(nom_maillage)).push_back
                     (String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i));
                 };
              }
    	  	    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
    	  	         tab_lili(1).push_back(String_et_entier(iocondiline_i.NomRef()+"_CLL",i));
    	  	      	 }
    	  	       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
    	  	         tab_lili(1).push_back
    	  	           (String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i));
    	  	      	 };
    	  	      };
   	  	    };
  	  	  };
   	  };
   // retour des infos
   return tab_lili;
	};
    
// affichage et definition interactive des commandes pour les conditions limites CL
void LesCondLim::Info_commande_LesCondLim1(UtilLecture & entreePrinc)
{ 
  cout << "\n# ----- definition des conditions limites cinematiques ----- ";
  bool plusieurs_maillages = false;
  string rep="_";
	     
  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
  // écriture de l'entête
  sort << "\n       blocages #------------# "
       << "\n#-----------------------------------------------------------"
       << "\n#  nom du maillage | Ref noeud |  Blocages"
       << "\n#-----------------------------------------------------------";
  // def des conditions
  try 
     {cout << "\n cas d'un seul maillage (par defaut) : rep o "
           << "\n cas de plusieurs maillages          : rep n ";
      rep = lect_return_defaut(true,"o");
      if (rep == "n")
         { plusieurs_maillages = true; cout << "\n --> les prochaines CL seront associees a un nom de maillage ";};
      rep="_"; // init
      // boucle globale
      while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
       { cout << "\n (0 ou f)  (fin)               "
              << "\n (1)  def d'une nouvelle condition "
              << "\n  ";
         rep = lect_return_defaut(false,"f");

         if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
            break;
         int num = ChangeEntier(rep);
         bool choix_valide=false;
         if ((num >= 0)&&(num<=1))
            { choix_valide=true; }
         else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, "
                     << "\n redonnez une bonne valeur"
                     << "\n ou taper f ou 0 pour arreter le programme"; 
                choix_valide=false;
              };
         switch (num)
           { case 0:  // sortie
               { break;} // normalement cela a déjà été filtré avant
             case 1:  // def d'une liste d'elements associe a un nom de loi
	              { DdlLim unddl; // init
                 unddl.Info_commande_DdlLim(sort,plusieurs_maillages);
                 break;
               }		
             default:
               cout << "\n le cas "<<rep<<" n'est pas  traite !!, bizarre, il faut se plaindre !! ";
           };
        };
     }
  catch (ErrSortieFinale)
       // cas d'une direction voulue vers la sortie
       // on relance l'interuption pour le niveau supérieur
     { ErrSortieFinale toto;
       throw (toto);
     }
  catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
     {  cout << "\n Erreur on attendait un des mots cles proposes !!, "
             << "\n redonnez une bonne valeur"
             << "\n ou taper f ou 0 pour sortir "; 
     };
  sort << flush;
};

// affichage et definition interactive des commandes pour les conditions limites CLL
void LesCondLim::Info_commande_LesCondLim2(UtilLecture & entreePrinc)
{ 
  cout << "\n# ----- definition des conditions limites lineaires ----- ";
  bool plusieurs_maillages = false;
  string rep="_";
	     
  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
  // écriture de l'entête
  sort << "\n       condition_limite_lineaire_  #------------# "
       << "\n#-----------------------------------------------------------"
       << "\n#  nom du maillage | Ref noeud |  CLL "
       << "\n#-----------------------------------------------------------";
  // def des conditions
  try 
     {cout << "\n cas d'un seul maillage (par defaut) : rep o "
           << "\n cas de plusieurs maillages          : rep n ";
      rep = lect_return_defaut(true,"o");
      if (rep == "n")
         { plusieurs_maillages = true; cout << "\n --> les prochaines CLL seront associees a un nom de maillage ";};
      rep="_"; // init
      // boucle globale
      while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
       { cout << "\n (0 ou f)  (fin)               "
              << "\n (1)  def d'une nouvelle condition "
              << "\n  ";
         rep = lect_return_defaut(false,"f");

         if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
            break;
         int num = ChangeEntier(rep);
         bool choix_valide=false;
         if ((num >= 0)&&(num<=1))
            { choix_valide=true; }
         else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, "
                     << "\n redonnez une bonne valeur"
                     << "\n ou taper f ou 0 pour arreter le programme"; 
                choix_valide=false;
              };
         switch (num)
           { case 0:  // sortie
               { break;} // normalement cela a déjà été filtré avant
             case 1:  // def d'une liste d'elements associe a un nom de loi
	              { I_O_Condilineaire uneCLL; // init
                 uneCLL.Info_commande_conditionLineaire(sort,plusieurs_maillages);
                 break;
               }		
             default:
               cout << "\n le cas "<<rep<<" n'est pas  traite !!, bizarre, il faut se plaindre !! ";
           };
        };
     }
  catch (ErrSortieFinale)
       // cas d'une direction voulue vers la sortie
       // on relance l'interuption pour le niveau supérieur
     { ErrSortieFinale toto;
       throw (toto);
     }
  catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
     {  cout << "\n Erreur on attendait un des mots cles proposes !!, "
             << "\n redonnez une bonne valeur"
             << "\n ou taper f ou 0 pour sortir "; 
     };
  sort << flush;
};

// affichage et definition interactive des commandes pour les initialisations
void LesCondLim::Info_commande_LesCondLim3(UtilLecture & entreePrinc)
{ cout << "\n *** warning : la partie initialisation n'est pas encore operationnelle *** ";
  return;
 
  cout << "\n# ----- definition des conditions limites cinematiques ----- ";
  bool plusieurs_maillages = false;
  string rep="_";
	     
  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
  // écriture de l'entête
  sort << "\n       blocages #------------# "
       << "\n#-----------------------------------------------------------"
       << "\n#  nom du maillage | Ref noeud |  Blocages"
       << "\n#-----------------------------------------------------------"
       << flush;
  // def des conditions
  try 
     {cout << "\n cas d'un seul maillage (par defaut) : rep o "
           << "\n cas de plusieurs maillages          : rep n ";
      rep = lect_return_defaut(true,"o");
      if (rep == "n")
         { plusieurs_maillages = true; cout << "\n --> les prochaines CL seront associees a un nom de maillage ";};
      rep="_"; // init
      // boucle globale
      while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
       { cout << "\n (0 ou f)  (fin)               "
              << "\n (1)  def d'une nouvelle condition "
              << "\n  ";
         rep = lect_return_defaut(false,"f");

         if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
            break;
         int num = ChangeEntier(rep);
         bool choix_valide=false;
         if ((num >= 0)&&(num<=1))
            { choix_valide=true; }
         else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, "
                     << "\n redonnez une bonne valeur"
                     << "\n ou taper f ou 0 pour arreter le programme"; 
                choix_valide=false;
              };
         switch (num)
           { case 0:  // sortie
               { break;} // normalement cela a déjà été filtré avant
             case 1:  // def d'une liste d'elements associe a un nom de loi
	              { DdlLim unddl; // init
                 unddl.Info_commande_DdlLim(sort,plusieurs_maillages);
                 break;
               }		
             default:
               cout << "\n le cas "<<rep<<" n'est pas  traite !!, bizarre, il faut se plaindre !! ";
           };
        };
     }
  catch (ErrSortieFinale)
       // cas d'une direction voulue vers la sortie
       // on relance l'interuption pour le niveau supérieur
     { ErrSortieFinale toto;
       throw (toto);
     }
  catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
     {  cout << "\n Erreur on attendait un des mots cles proposes !!, "
             << "\n redonnez une bonne valeur"
             << "\n ou taper f ou 0 pour sortir "; 
     };
  sort << flush;
};



// -------------- fonctions internes privées -------------------------

void LesCondLim::Init_appart_groupe(bool une_variable,Enum_ddl enu,bool fixe,Noeud& noe, int cas,bool choix)    
{ // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
  // on vérifie que le ddl appartient au groupe
  if (Dans_combinaison(cas,enu)) // cas d'un ddl du groupe      
	  { // le ddl appartient au groupe
	    // récup des enu_ddl équivalent au groupe
	    Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
	    int taille = tmc.Taille();
	    for (int i=1;i<=taille;i++)
	       {if(tmc(i) != enu) // on ne traite que les cas différents du ddl principal
	          { if (noe.Existe_ici(tmc(i)))
	             { // le ddl existe déjà, on le met à fixe
	               // mais on ne change pas sa valeur
	               if (fixe)
	                   { noe.Change_fixe(tmc(i),true);}
       // en fait on ne met pas à libre si fixe en false, on ne vérifie pas qu'il y a superposition
       // de plusieurs initialisations en libre, celle-ci pouvant venir de plusieurs raisons que l'on ne peut
       // pas gérer ici : par exemple au moment de la création des éléments il y a mise en place des ddl à libre
       // avant l'initialisation donc si l'on impose par exemple la vitesse, X sera en souslibre !! 	                   
	          //     else
	          //         { noe.Change_fixe(tmc(i),false);}
              }
	            else 
	               // sinon on le cré, et on met à zéro
	             { if (fixe)
	                 { if (une_variable) { Ddl inter(tmc(i),0.0,HSFIXE); noe.PlusDdl(inter);}
	                   else              { Ddl inter(tmc(i),0.0,HS_LISIBLE_FIXE); noe.PlusDdl(inter);};
                  }
	               else
	                 { if (une_variable) { Ddl inter(tmc(i),0.0,HSLIBRE); noe.PlusDdl(inter);}
	                   else              { Ddl inter(tmc(i),0.0,HS_LISIBLE_LIBRE); noe.PlusDdl(inter);};
                  };
                noe.Change_val_0(tmc(i),0.);
                noe.Change_val_t(tmc(i),0.);
                if (choix)
                  noe.Change_val_tdt(tmc(i),0.);
              };
           };
        };
   }; //-- fin du cas ou le ddl fait partie d'une combinaison
};

// mise en place du blocage sur un ddl ou un groupe si besoin est
void LesCondLim::Mise_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas)
 {
   // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
   // on vérifie que le ddl appartient au groupe sinon traitement simple
   if (Dans_combinaison(cas,enu))	      
	   { // le ddl appartient au groupe, on modifie  globalement
	     // récup des enu_ddl équivalent au groupe
	     Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
	     int taille = tmc.Taille();
	     for (int i=1;i<=taille;i++)
	         noe.Change_fixe(tmc(i),true);
	     // le ddl du tableau des ddl bloqués est mis en service
      (ddlbloqu.ElemLim(nd)).Met_en_service();
    }
   else // le ddl fixé n'appartient pas au groupe on le traite isolément
	   { noe.Change_fixe(enu,true); // le noeud est  fixé
      // le ddl du tableau est mis en service
      (ddlbloqu.ElemLim(nd)).Met_en_service();
    };
 };
   
   
// on retire le  blocage sur un ddl ou un groupe si besoin est
void LesCondLim::Retire_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas)
 { // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
   // on vérifie que le ddl appartient au groupe sinon traitement simple
   if (Dans_combinaison(cas,enu))	      
	   { // le ddl appartient au groupe, on modifie  globalement
	     // récup des enu_ddl équivalent au groupe
	     Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
	     int taille = tmc.Taille();
	     for (int i=1;i<=taille;i++)
	         noe.Change_fixe(tmc(i),false);
	     // le ddl du tableau des ddl bloqués est mis hors service
      (ddlbloqu.ElemLim(nd)).Met_hors_service();
    }
   else // le ddl fixé n'appartient pas au groupe on le traite isolément
	   { noe.Change_fixe(enu,false); // le noeud est  libéré
      // le ddl du tableau est mis hors service
      (ddlbloqu.ElemLim(nd)).Met_hors_service();
    };
 };

// vérification qu'il n'y a pas de surcharge de blocage
// choix indique si l'on vérifie à t ou à tdt
void LesCondLim::Verif_surcharge_blocage
   (const LesMaillages * lesMail,const LesReferences* lesRef,const double& temps,int cas) 
{ // prépa retour
  bool erreur_blocage = false;
  Tableau <Enum_ddl> tmc; // tableau de travail
   
  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() == 4) &&                 // dans le cas des conditions de tangence sur 
           (tabBloq_i.TypeDeCL()==TANGENTE_CL) )  // les arrêtes on n'applique pas ces vérifs
           )
       {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++)
           {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;
            Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
            // on regarde si l'on a fixé plusieurs fois ou libéré plusieurs foix
             //  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()));
            // récup des enu_ddl équivalent au groupe, pour l'instant on n'a que la combinaison 1 qui comporte plus d'un élément
            if (Dans_combinaison(cas,ddl.Id_nom()))
               {tmc = MemeCombinaison(cas,ddl.Id_nom());}
            else 
               // sinon pour l'instant on fait comme si cas == 0 c'est à dire pas de combinaison
               {tmc = MemeCombinaison(0,ddl.Id_nom());};
            int tailletmc = tmc.Taille();
            for (int itc=1;itc <= tailletmc;itc++)
             {if (noe.Ddl_sous_ou_sur_fixe(tmc(itc)))
               // cas d'un problème éventuel
               { // message d'avertissement   
                 if (ParaGlob::NiveauImpression() >= 6)
                    cout << "\n ***** ATTENTION *****, le ddl " << ddl.Nom()  << " du noeud " << noe.Num_noeud() 
                         << " du maillage " << lesMail->NomMaillage(noe.Num_Mail()) << " est bloque plusieurs fois";
                 if (ParaGlob::NiveauImpression() >= 7)
                       cout << ", cela indique que plusieurs conditions limites sont supperposees";
                 if (ParaGlob::NiveauImpression() >= 8)
                      { cout << " \n temps = " << temps << ",  reference de blocage, et ddl limite correspondant";
                        ref.Affiche(); tabBloq_i.Affiche();  
                        cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
                       } 
                 // remise à normal du ddl pour que le calcul puisse continuer
                 noe.Retour_a_la_normal_sur_ou_sous_fixe(tmc(itc));
                 erreur_blocage = true; // pour un traitement global d'erreur éventuel
               };
             }; //--  fin du for (int itc=1;itc <= tailletmc;itc++)
           }; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++)
         }; //-- fin du for (int nn =1; nn<= reftaille;nn++)
       }; //-- fin du if (!((ref.Indic() == 4) &&(tabBloq_i.TypeDeCL()==TANGENTE_CL) )
    };  //-- fin du for (int i=1;i<= tabBloqTaille;i++)
}; 

// fourni la liste des ddl associé de même dim, pour un du groupe et en fonction du cas d'association
// ramène une référence sur tab_travail qui est mis à jour 
Tableau <Ddl>& LesCondLim::Ddl_associe (Ddl& ddl,Noeud& noe,Tableau <Ddl>& tab_travail,int cas)
  {  //  cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
//      if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) ddl.Change_nom(UxyzXi(ddl.Id_nom()));
     if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom()));
     Enum_ddl enu = ddl.Id_nom(); // pour simplifier
     // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
	    // on vérifie que le ddl appartient au groupe sinon traitement simple
     if (Dans_combinaison(cas,enu))	      
      { // le ddl appartient au groupe, on modifie globalement
        // récup des enu_ddl équivalent au groupe
        Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
        int taille = tmc.Taille();
        for (int i=1;i<=taille;i++)
          { ddl.Change_nom(tmc(i));
            tab_travail(i) = ddl;
          }
      }
     else // le ddl fixé n'appartient pas au groupe on le traite isolément
      { tab_travail.Change_taille(1);
        tab_travail(1) = ddl;
      };
     return tab_travail;
  };

// cas particulier des mouvements solides, dans le second passage pour la méthode MiseAJour_tdt
void LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(const double& mult_gene,LesMaillages * lesMail
                           ,const double& deltat,int cas
                           ,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD,const double& coef
                           ,DdlLim& tabBloq_i,const ReferenceNE & ref,const double& temps,Enum_ddl en_ddl)
	{   bool tous_les_blocages = true;
     if (en_ddl != NU_DDL) tous_les_blocages = false;
	    int reftaille = ref.Taille();
	    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--;
     // 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))
         return;
     bool actif_pour_le_temps =  tabBloq_i.Temps_actif(temps); // pour simplifier
     if (!actif_pour_le_temps)
        return; // je ne vois pas trop pourquoi, mais semble cohérent avec le prog général (à voir)
     // petite vérif   
     int tabBloqitaille = tabBloq_i.Taille(); // normalement il y a uniquement les déplacements
     #ifdef MISE_AU_POINT
     if (tabBloqitaille != dima) 
		     { cout << "\nErreur : le nombre de ddl bloque pour un mouvement solide doit etre egale a la dimension du pb "
		            << " ici ParaGlob::Dimension() = " << dima << " et le nombre de ddl bloque = " << tabBloqitaille ;
		       cout << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... ";
         if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
		       Sortie(1);
		     };
     #endif

     // --- dans le cas où il y a des centres de rotation qui sont des positions de noeud, on renseigne
     // a) récupération des centres de rotation noeud, éventuellement
     const list <String_et_entier>& lis_centre_noeud = (tabBloq_i.MouvementSolide())->Liste_ident_centreNoeud();
     if (lis_centre_noeud.size() != 0)
      { list <String_et_entier>::const_iterator ict,ictfin=lis_centre_noeud.end();
        list <Coordonnee> list_coor; // liste des coordonnées des noeuds centre de rotation
        for (ict = lis_centre_noeud.begin();ict!=ictfin;ict++)
         {if ((*ict).nom == "")
           // cas où on n'a pas de nom de maillage
           { list_coor.push_back(lesMail->Noeud_LesMaille(1, (*ict).n).Coord2()); }
          else // cas où on a plusieurs maillages
           { int num_maill= lesMail->NumMaillage((*ict).nom);
             list_coor.push_back(lesMail->Noeud_LesMaille(num_maill, (*ict).n).Coord2());
           };
         };
       // b)  maintenant on passe l'info au mouvement solide
       (tabBloq_i.MouvementSolide())->RenseigneCentreNoeud(list_coor);
      };
  
     // maintenant soit le ddlLim est actif ou il change de statut: actif à non actif
     // on boucle sur les noeuds de la référence
     for (int nn =1; nn<= reftaille;nn++)
         {// ici on travaille sur les dima ddl de déplacements en même temps: 
          // mais on se sert du premier comme indicateur
          Ddl ddl = tabBloq_i.ElemLim(1); // le premier ddl normalement est UX
          // on fait une manip sur les UX <-> Xi pour distinguer les cas méca du solide et les autres
          Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
          if (noe.Existe_ici(X1))
              //  cas de deplacements imposes en entraine on change donc 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;};
          if (a_considerer)
          	{ // def du point qui contiendra les coordonnées finales après rotation 
          	  Coordonnee M(dima);  
          	  // traitement en fonction du cas où il y courbe de charge ou pas
             if ((tabBloq_i.Nom_courbe(1) != "")&&(tabBloq_i.NomF_charge(1) == ""))
               { // cas d'une courbe de charge, récup de la courbe
                 // pour les mouvements solides la courbe de charge et l'échelle sont stockées dans le premier ddl
                 Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1));
                 if (tabBloq_i.BlocageRelatif())  // cas d'une modif relativement au temps précédent
                  { // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat
                     M = noe.Coord1(); // on travaille donc à partir des coordonnées à t
                     double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1)
                                      * ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ;
                     (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
                  }
                 else
                   { // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent
                     // et ici on considère la totalité du chargement de 0 au temps actuel
                     M = noe.Coord0(); // on travaille donc avec les coordonnées initiales
                     double amplitude = mult_gene * (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(1);
                    (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
                  };
               }
             else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) == ""))
               { // cas d'une fonction nD de charge, récup
                 Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1));
                 // 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 d'un mouvement solide "
                         << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... ";
                    if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
                    Sortie(1);
                   };
                 #endif
                 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 d'un mouvement solide 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_second_passage_mvtSolide(... ";
                     if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
                     Sortie(1);
                   }
                 else
                   { // la fonction donne la valeur de l'amplitude de 0 au temps présent
                     // et ici on considère la totalité du chargement de 0 au temps actuel
                     M = noe.Coord0(); // on travaille donc avec les coordonnées initiales
                     double amplitude = mult_gene * (tab_ret(1)) * tabBloq_i.Echelle_courbe(1);
                    (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
                  };
               }
             else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) != ""))
               { // cas d'une fonction nD de charge, récup
                 Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1));
                 // 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 d'un mouvement solide "
                         << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... ";
                    if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
                    Sortie(1);
                   };
                 #endif
                 // idem pour la courbe 1D
                 Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1));
                 if (tabBloq_i.BlocageRelatif())  // cas d'une modif relativement au temps précédent
                  { // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat
                     M = noe.Coord1(); // on travaille donc à partir des coordonnées à t
                     double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1) * tab_ret(1)
                                      * ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ;
                     (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
                  }
                 else
                   { // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent
                     // et ici on considère la totalité du chargement de 0 au temps actuel
                     M = noe.Coord0(); // on travaille donc avec les coordonnées initiales
                     double amplitude = mult_gene * (pt_courbe->Valeur(temps))
                                        * tab_ret(1) * tabBloq_i.Echelle_courbe(1);
                    (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
                  };
               }
             else
               // cas d'un mouvement à valeur fixe, on calcul l'accroissement par rapport au pas précédent
               // coef intègre le multiplicateur global: mult_gene, et intègre l'acroissement par rapport au pas précédent
               { M = noe.Coord1();
                 (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,coef);
               };

             // maintenant on s'occupe de la mise à jour ou non des positions du noeud
             for (int nd=1;nd<= tabBloqitaille ;nd++) // en fait ici nd =1 pour UX, =2 pour UY et =3 pour UZ
              {Ddl ddl = tabBloq_i.ElemLim(nd);
               if (noe.Existe_ici(X1))
                 //  cas de deplacements imposes en entraine on change donc les Ui en Xi
                 ddl.Change_nom(UxyzXi(ddl.Id_nom()));
               Enum_ddl ddlenu= ddl.Id_nom(); // 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, mais si on arrive ici le temps est forcément actif
               if (  ( une_variable && noe.En_service(ddlenu)) ||(!une_variable)  )
                  { // gestion des surcharges de blocage
                    // au second  passage on fixe les ddl actifs
                    Mise_cl(nd,tabBloq_i,ddlenu,noe,cas);   
                    // on met à jour les coordonnées finales
                    noe.Change_val_tdt(ddlenu,M(nd));  // car nd =1 pour UX, =2 pour UY, =3 pour UZ
                  };//-- fin du test si le ddl du noeud est en service
              }; //-- fin de la boucle sur tabBloq_i
          	};//-- fin du test si le noeud est à considérer ou pas
         }; //-- fin de la boucle sur nn
	};   

// mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
// --> pour au final obtenir le torseur des efforts globaux résultant de l'application d'un DdlLim
void LesCondLim::CalculTorseurReaction(TorseurReac& tr, const Noeud& noe, ReactStoc& reac)
	{ int dimension = 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
     dimension--;
   switch (dimension)
    { case 1: // pas de moment, et uniquement une résultante suivant x
        if (reac.ddl.Id_nom() == X1) tr.resultante(1) += reac.ddl.Valeur(); 
        break;
      case 2 : // un moment autour de z, et deux composantes de résultante
               // le moment est en dim 2, on stocke le moment dans la première composante !!!
        switch (reac.ddl.Id_nom())
         { case X1:
          { tr.resultante(1) += reac.ddl.Valeur();
            tr.moment(1) -=  noe.Valeur_tdt(X2) * reac.ddl.Valeur(); // correspond à z
            break;	
          };
           case X2:
          { tr.resultante(2) += reac.ddl.Valeur();
            tr.moment(1) +=  noe.Valeur_tdt(X1) * reac.ddl.Valeur(); // correspond à z
            break;	
          };
           default: break;
         }
        break;
      case 3 : // 3 composante de moment et de résultante
        switch (reac.ddl.Id_nom())
         { case X1:
          { tr.resultante(1) += reac.ddl.Valeur();
            tr.moment(2) += noe.Valeur_tdt(X3) * reac.ddl.Valeur();
            tr.moment(3) -=  noe.Valeur_tdt(X2) * reac.ddl.Valeur();
            break;	
          };
           case X2:
          { tr.resultante(2) += reac.ddl.Valeur();
            tr.moment(1) -=  noe.Valeur_tdt(X3) * reac.ddl.Valeur();
            tr.moment(3) +=  noe.Valeur_tdt(X1) * reac.ddl.Valeur();
            break;	
          };
           case X3:
          { tr.resultante(3) += reac.ddl.Valeur();
            tr.moment(1) +=  noe.Valeur_tdt(X2) * reac.ddl.Valeur();
            tr.moment(2) -=  noe.Valeur_tdt(X1) * reac.ddl.Valeur();
            break;	
          };
           default: break;
         }
        break;
          // les autres cas ne sont pas pris en compte	
    };
	};

     
// mise en place  des conditions  linéaires imposées par les données d'entrée
// 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_int(Mat_abstraite & matglob,Vecteur& vecglob
                                  ,const Nb_assemb& nb_casAssemb,Vecteur* vec2)
  {  // on boucle sur le tableau de conditions limites linéaires enregistré
     // et pour chaque element on impose une condition lineaire
	    bool modification = false; // init du retour
     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);
//debug
//cout << "\n LesCondLim::CoLinCHrepere_int " << condi;
//fin debug
          // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
          if (condi.Iddl() > -1)
     	 	   { // calcul des pointeurs d'assemblage
     	 	     condi.ConditionPourPointeursAssemblage(nb_casAssemb);
     	 	     // application de la condition
             condlim(nb_casAssemb.n).CondlineaireCHRepere
                    ( matglob,vecglob,condi.Pt_t(),condi.Val(),0.,vec2); // ancienne version
//           la valeur imposée est systématiquement 0 comme pour le cas des autres conditions bloquée
//           car la résolution donnera delta_ddl' qui doit être null pour les ddl imposés
             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 changements de reperes dus aux conditions lineaires  ";
        matglob.Affichage_ecran(entete); 
        entete = " affichage du second membre apres changements de reperes dus aux conditions lineaires  ";
        vecglob.Affichage_ecran(entete); 
       };                        
     // retour du fait qu'il y a eu ou non une modification faite
	    return modification;
  };
   
// effacement du marquage de ddl bloque du au conditions lineaire extérieures (hors du contact par exemple)
void LesCondLim::EffMarque()
   { // préparation
     // on boucle sur le tableau des conditions limites linéaires imposées réellement
     int tabTaille = tab_CLinApplique.Taille();
     for (int icondli=1;icondli<= tabTaille; icondli++)
      { Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli);
        int nbcondi = t_condiAppli.Taille();
	       // on boucle sur les conditions
	       for (int ico=1;ico<=nbcondi;ico++)
          { Condilineaire & condi = t_condiAppli(ico); // pour simplifier
            // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
            if (condi.Iddl() > -1)
              { // récup du noeud principal                           
                 Noeud * noe=condi.Noe();
                 noe->Change_fixe(condi.Tab_Enum()(1),false);
              };
          };
      };
   };
    
// def de la largeur de bande  en fonction des conditions linéaire limite en entrée
// casAssemb : donne le cas d'assemblage en cours
// les condi linéaires ne donnent pas des largeurs de bande sup et inf égales !!! 
// demi = la demi largeur de bande , 
// total = le maxi = la largeur sup + la largeur inf +1
// cumule = la somme des maxis, ce qui donnera la largeur finale, due à des multiples multiplications: une par conditions linéaires
//          dans le cas où on tiens compte des conditions linéaires par rotation (c-a-d sans multiplicateur ou pénalisation)
// en retour, ramène un booleen qui :
//  = true : si la largeur de bande en noeud est supérieure à 1
//  = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur
//        en noeud
bool LesCondLim::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb
                               ,LesMaillages * lesMail,LesReferences* lesRef,int& cumule)
   { demi = total = cumule = 0; // initialisation
     bool retour = false; // par défaut
     int nb_ass = casAssemb.n;
     // on boucle sur le tableau et pour chaque condition
     int tabTaille = tab_iocondiline.Taille(); // le nombre de condition
     for (int icondli=1;icondli<= tabTaille; icondli++)
      {I_O_Condilineaire& iocondiline_i =  tab_iocondiline(icondli); // pour simplifier
       // recup de la reference principal correspondant au mot cle
       const ReferenceNE & refp = 
             ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
	      int nb_n_princ = refp.Taille();
       // recup du tableau des références secondaires associées si elles existent
       const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
       const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
       
       int tailrefasso = nomRefassocie.Taille();
       Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
       Tableau <int>  tab_numMail_associe(tailrefasso);
       if (tailrefasso != 0)
         {retour = true; // comme il y a des ref associés, la largeur en noeud sera > à 1
          for (int k=1;k<=tailrefasso;k++)
            {const string * nom_maillage=NULL;
             if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
             const ReferenceNE & refasso = 
              ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
             tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
             tab_numMail_associe(k)= refasso.Nbmaille();
            };
         };
       // on boucles sur les noeuds de la ref principale
       int tail_t_noe = tailrefasso+1;
       Tableau <Noeud *> t_noe(tail_t_noe); // tableau de travail
       // dans la boucle qui suit on définit t_noe, c'est à dire l'ensemble des noeuds
       // concernés par la condition linéaire.
       // puis avec ce tableau, on en déduit la largeur de bande associée
       for (int in=1;in<=nb_n_princ;in++) 
          { // récup du noeud principal                           
            Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
            t_noe(1)= &noe;
            // on ne continue que si le type de ddl de la condition limite est actif pour le noeud
            // et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte
            // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
            Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier 
            if (enu_condline==UX) enu_condline = X1; // les ui sont géré avec les xi 
            if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline))
              {// récupération des noeuds associés, on utilise le même indice dans les ref associées que
               // dans la ref principale
               for (int ia = 1;ia<=tailrefasso;ia++)
                  t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));
               // maintenant on va effectivement pouvoir calculer la largeur de bande correspondant 
               // aux noeuds du tableau t_noe
        
               // 1) on a par défaut au moins une relation entre les ddl du noeud principal
               int diprinc = noe.NB_ddl_actif_casAssemb(nb_ass);
               if ( diprinc-1 > demi)  demi = diprinc-1;
               if ( (2*diprinc-1) > total)  total = 2*diprinc-1;
               cumule += 2*diprinc-1;
               
               // 2) maintenant on s'occupe de la relation entre les différents noeuds de numéros différencts
               int maxiPourLaCondition=0; // stocke le maxi pour chaque condition linéaire
               for (int inoe=1; inoe<= tail_t_noe;inoe++)
                 for ( int jnoe=inoe+1; jnoe<=tail_t_noe;jnoe++)
                   { Noeud & nne = *(t_noe(inoe));
                     Noeud & nno = *(t_noe(jnoe));
                     int di=0;
                     if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass))
                       { di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass) 
                              + nne.NB_ddl_actif_casAssemb(nb_ass);
                       }
                     else
                       { di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass) 
                              + nno.NB_ddl_actif_casAssemb(nb_ass);
                       };
                     if ( di > demi)  demi = di;
                     if ( di > maxiPourLaCondition) maxiPourLaCondition = di;
                     if ( di > total) total = di;
   //							cumule += di;
                   };
               cumule += maxiPourLaCondition;
              };
          }; // -- fin de la boucle sur les noeuds de la liste principale
      }; // -- fin de la boucle sur le tableau des conditions linéaire
     // prise en compte de la diagonale
	    demi += 1; total += 1;
     // retour
     return retour;
   };


// dimensionnement du tableau des torseurs ainsi que des tableaux ttRG et ttorBloq     
// en fonction de tabBloq (utilisé plusieurs fois), puis de ttRGCLL en fonction de tab_iocondiline
void LesCondLim::DimensionneTorseurs()
 {  // dimensionnement du tableau des torseurs résultants
    // 1) on s'occupe tout d'abord des ddl bloqués

    int taille = tabBloq.Taille();
    ttRG.Change_taille(taille);
    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--;
    // on remplit le tableau ttRG
    list <Deux_String> li_nomRef; // liste de travail:
    list <string> li_nomRef_CL; // idem, mais spécifique aux CL
                   // sert ensuite pour définir ttRG_noms_ref

    int taille_tors=0;
    // on en profite pour définir un tableau de nom de ref qui contiendra les infos
    // en string nécessaires pour cibler les composantes du torseur, externalisées comme
    // grandeurs globales
    for (int i=1;i<=taille;i++)
      if (tabBloq(i).Existe_ici_un_deplacement())
      	{// on a un candidat possible, on regarde si la référence n'existe pas
      	 Deux_String candid(tabBloq(i).NomRef(),tabBloq(i).NomRef()); // le premier string ici est pour remplir
        string nom_Ref_CL(tabBloq(i).NomRef());
        bool avec_nom_maillage=false;
      	 if (tabBloq(i).NomMaillage() != NULL)
      	 	{candid.nom1 = *(tabBloq(i).NomMaillage());avec_nom_maillage=true;
          nom_Ref_CL = *(tabBloq(i).NomMaillage()) +"_"+ nom_Ref_CL;
         };
      	 list <Deux_String>::iterator ili,ilifin=li_nomRef.end();
      	 int it=1; // future position dans le tableau tab_torseurReac
      	 for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++)
      	   if (*ili == candid) break;
      	 if (ili == li_nomRef.end())
      	 	{// aucun élément trouvé, on ajoute un nouveau
      	 	 li_nomRef.push_back(candid);
          li_nomRef_CL.push_back(nom_Ref_CL);
      	 	 taille_tors++; ttRG(i)=taille_tors;
      	 	}
      	 else // on a trouvé un élément identique déjà existant de numéro it
      	 	{ttRG(i)=it;};
     	};

    // 2) puis on s'occupe des CLL 
    
    int taille_tors_CLL=0;
    list <string> li_nomRef_CLL; // liste de travail, mais spécifique aux CLL
                   // sert ensuite pour définir ttRGCLL_noms_ref

    // on boucle sur le tableau initiale des conditions lineaires en entrée
    int tabCLLTaille = tab_iocondiline.Taille();
    ttRGCLL.Change_taille(tabCLLTaille); // premier dimensionnement
    // on en profite pour définir un tableau de nom de ref qui contiendra les infos
    // en string nécessaires pour cibler les composantes du torseur, externalisées comme
    // grandeurs globales
    for (int icondli=1;icondli<= tabCLLTaille; icondli++)
      {I_O_Condilineaire& iocondiline_i =  tab_iocondiline(icondli); // pour simplifier
       // on regarde s'il faut considérer la condition linéaire, en fonction de en_ddl
       Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
       if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1)))
       	{// récup des références secondaires éventuelles
         const Tableau <string> & tabnomRef = iocondiline_i.ReferenceAssociees();
         int tabnomRefTaille = tabnomRef.Taille();
         const Tableau <string > & nom_mail_associe = iocondiline_i.NomMaillageAssociees();
         // second dimensionnement
         ttRGCLL(icondli).Change_taille(tabnomRefTaille+1);
         // maintenant on rempli le tableau
         // a)  tout d'abord la ref principal (on encapsule)
          {Deux_String candid(iocondiline_i.NomRef()+"CLL",iocondiline_i.NomRef()+"CLL"); 
           string nom_Ref_CLL(iocondiline_i.NomRef()+"CLL");
           bool avec_nom_maillage=false;
           if (iocondiline_i.NomMaillage() != NULL)
            {candid.nom1 = *(iocondiline_i.NomMaillage());avec_nom_maillage=true;
             nom_Ref_CLL = *(iocondiline_i.NomMaillage()) +"_"+ nom_Ref_CLL;
            };
            // on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un
           list <Deux_String>::iterator ili,ilifin=li_nomRef.end();
           int it=1; // future position dans le tableau tab_torseurReac
           for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++)
             if (*ili == candid) break;
           if (ili == li_nomRef.end())
            {// aucun élément trouvé, on ajoute un nouveau
             li_nomRef.push_back(candid);
             li_nomRef_CLL.push_back(nom_Ref_CLL);
             taille_tors++; taille_tors_CLL++; ttRGCLL(icondli)(1)=taille_tors;
            }
           else // on a trouvé un élément identique déjà existant de numéro it
            {ttRGCLL(icondli)(1)=it;
            };
          }; // fin encapsulage
         // b)  maintenant on regarde les références secondaires
         for (int ir=1;ir<=tabnomRefTaille;ir++)
            { Deux_String candid(tabnomRef(ir)+"CLL",tabnomRef(ir)+"CLL");
              string nom_Ref_CLL(tabnomRef(ir)+"CLL");
              if (iocondiline_i.NomMaillage() != NULL)
                {candid.nom1 = nom_mail_associe(ir);
                 nom_Ref_CLL = nom_mail_associe(ir) +"_"+ nom_Ref_CLL;
                };
              // on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un
              list <Deux_String>::iterator ili,ilifin=li_nomRef.end();
              int it=1; // future position dans le tableau tab_torseurReac
              for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++)
                 if (*ili == candid) break;
              if (ili == li_nomRef.end())
               {// aucun élément trouvé, on ajoute un nouveau
                li_nomRef.push_back(candid);
                li_nomRef_CLL.push_back(nom_Ref_CLL);
                taille_tors++;taille_tors_CLL++; ttRGCLL(icondli)(ir+1)=taille_tors;
               }
              else // on a trouvé un élément identique déjà existant de numéro it
               {ttRGCLL(icondli)(ir+1)=it;};
            }; // fin boucle sur les références secondaires
        }; //-- fin du test if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1)))
      }; //-- fin de la boucle sur les conditions linéaires
            	      	
    // maintenant on dimensionne le tableau de torseurs
    int taille_tors_bloqu = taille_tors - taille_tors_CLL;
    tab_torseurReac.Change_taille(taille_tors);
    for (int ia=1;ia<=taille_tors;ia++)
      {tab_torseurReac(ia).Activation(dima);
       // on définit si le torseur correspond à un ddl bloqué ou une CLL
       if (ia > taille_tors_bloqu)
         {tab_torseurReac(ia).bloque_ou_CLL = false;}
       else  
         {tab_torseurReac(ia).bloque_ou_CLL = true;}
      };
    // maintenant on dimensionne et rempli ttorBloq
    ttorBloq.Change_taille(taille_tors_bloqu);
    for (int ib=1;ib<=taille;ib++)
      if (ttRG(ib) != 0 )
         ttorBloq(ttRG(ib)).push_back(ib); // cas d'une ref qui contient un déplacement
    // et ensuite on dimensionne et rempli ttorCLL
    ttorCLL.Change_taille(taille_tors);
    for (int ib=1;ib<=tabCLLTaille;ib++)
     { int tai = ttRGCLL(ib).Taille();
       for (int j=1;j<=tai;j++)
         if (ttRGCLL(ib)(j) != 0 )
          ttorCLL(ttRGCLL(ib)(j)).push_back(DeuxEntiers(ib,j)); // cas d'une ref qui contient un déplacement
     };
  
    // on définit les tableaux ttRG_noms_ref et ttRGCLL_noms_ref
    int nb_RG_noms_ref = li_nomRef_CL.size();
    ttRG_noms_ref.Change_taille(nb_RG_noms_ref);
    {list <string>::iterator ili,ilifin=li_nomRef_CL.end();
     int i=1;
     for (ili = li_nomRef_CL.begin();ili != ilifin; ili++,i++)
       ttRG_noms_ref(i)=(*ili);
    };
    ttRGCLL_noms_ref.Change_taille(li_nomRef_CLL.size());
    {list <string>::iterator ili,ilifin=li_nomRef_CLL.end();
     int i=1;
     for (ili = li_nomRef_CLL.begin();ili != ilifin; ili++,i++)
       ttRGCLL_noms_ref(i)=(*ili);
    };
  
    // on va maintenant définir des grandeurs globales qui permettront de récupérer les réactions par
    // exemple via des fonctions nD
    Ddl_enum_etendu ddl("comp_tors_reaction");
    Ddl_etendu v(ddl);
    int taille_tors_bloquplus1 = taille_tors_bloqu +1;
   {int il = 1;
    for (int ia=1;ia<taille_tors_bloquplus1;ia++,il++)
      {// cas d'un blocage de ddl
       // on va construire la chaine de caractère qui représente la composante
       // 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);
         Grandeur_Ddl_etendu  grand_courant(v,nom_ref);
         // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
         // et on récupère un exemplaire
         TypeQuelconque_enum_etendu enuType =
                     TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                               (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
         // on définit le type quelconque associé
         TypeQuelconque typQ(enuType,X1,grand_courant);
         // et on ajoute une grandeur globale qui sera indexée par le nom de référence
         // si celle-ci n'existe pas déjà
         if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
            ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);

        }
       // 2) le moment
       for (int ic= 1; ic < dimaPlus1; ic++)
        {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
         Grandeur_Ddl_etendu  grand_courant(v,nom_ref);
         // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
         // et on récupère un exemplaire
         TypeQuelconque_enum_etendu enuType =
                     TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                               (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
         // on définit le type quelconque associé
         TypeQuelconque typQ(enuType,X1,grand_courant);
         // et on ajoute une grandeur globale qui sera indexée par le nom de référence
         // si celle-ci n'existe pas déjà
         if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
              ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);
        }
      };
   };
    // maintenant on s'occupe des conditions concernant les CLL
   {int taille_torsPlusUn = taille_tors+1;
    int il = 1;
    for (int ia=taille_tors_bloquplus1;ia<taille_torsPlusUn;ia++,il++)
      {// cas d'un blocage de ddl
       // on va construire la chaine de caractère qui représente la composante
       // 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);
         Grandeur_Ddl_etendu  grand_courant(v,nom_ref);
         // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
         // et on récupère un exemplaire
         TypeQuelconque_enum_etendu enuType =
                     TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                               (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
         // on définit le type quelconque associé
         TypeQuelconque typQ(enuType,X1,grand_courant);
         // et on ajoute une grandeur globale qui sera indexée par le nom de référence
         // si celle-ci n'existe pas déjà
         if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
            ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);
        }
       // 2) le moment
       for (int ic= 1; ic < dimaPlus1; ic++)
        {string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
         Grandeur_Ddl_etendu  grand_courant(v,nom_ref);
         // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
         // et on récupère un exemplaire
         TypeQuelconque_enum_etendu enuType =
                     TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
                               (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
         // on définit le type quelconque associé
         TypeQuelconque typQ(enuType,X1,grand_courant);
         // et on ajoute une grandeur globale qui sera indexée par le nom de référence
         // si celle-ci n'existe pas déjà
         if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
            ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);
        }
      };
   };

  
//--- débug ---
//cout << "\n " << ttorCLL << endl;
//--- fin débug ---      
      
 }; 
          

// DdlLim : mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD
void LesCondLim::Mise_a_jour_t_minmax_ddlLim(Noeud& noe,DdlLim& ddlLim,LesFonctions_nD*  lesFonctionsnD)
 {// on regarde le temps min
  string nom_t_min = ddlLim.Nom_fctnD_tmin();
  if (nom_t_min != "")
   { Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_min); // récup de la fonction
     // récup des valeurs au noeud, pour alimenter la fonction
     Tableau <double>  tab(noe.Valeur_multi_et_Tensorielle
         (fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue())
                          );
     // appel fonction
     Tableau <double> & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL);
     ddlLim.Mise_a_jour_tmin(tab_ret(1));
     #ifdef MISE_AU_POINT
     // on vérifie que la fonction est scalaire
     if (tab_ret.Taille() != 1)
       { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min
              << " qui gere le temps mini "
              << "  elle retourne une grandeur vectorielle  "
              << " ce n'est pas normal !! ,  on arrete le calcul   "
              << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
         Sortie(1);
       };
     #endif
   }
 string nom_t_max = ddlLim.Nom_fctnD_tmax();
 if (nom_t_max != "")
  { Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_max); // récup de la fonction
    // récup des valeurs au noeud, pour alimenter la fonction
    Tableau <double>  tab(noe.Valeur_multi_et_Tensorielle
        (fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue())
                         );
    // appel fonction
    Tableau <double> & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL);
    ddlLim.Mise_a_jour_tmax(tab_ret(1));
    #ifdef MISE_AU_POINT
    // on vérifie que la fonction est scalaire
    if (tab_ret.Taille() != 1)
      { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max
             << " qui gere le temps maxi "
             << "  elle retourne une grandeur vectorielle  "
             << " ce n'est pas normal !! ,  on arrete le calcul   "
             << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
        Sortie(1);
      };
    #endif
  }

 };
 
 // DdlLim général: mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD
 // ici les fct nD doivent dépendre uniquement de grandeur générale
 void LesCondLim::Mise_a_jour_t_minmax_ddlLim(DdlLim& ddlLim,LesFonctions_nD*  lesFonctionsnD)
{// on regarde le temps min
 string nom_t_min = ddlLim.Nom_fctnD_tmin();
 if (nom_t_min != "")
  { Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_min); // récup de la fonction
    // appel fonction
    Tableau <double> & tab_ret = fct->Valeur_pour_variables_globales();
    ddlLim.Mise_a_jour_tmin(tab_ret(1));
    #ifdef MISE_AU_POINT
    // on vérifie que la fonction est scalaire
    if (tab_ret.Taille() != 1)
      { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min
             << " qui gere le temps mini "
             << "  elle retourne une grandeur vectorielle  "
             << " ce n'est pas normal !! ,  on arrete le calcul   "
             << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
        Sortie(1);
      };
    #endif
  }
 string nom_t_max = ddlLim.Nom_fctnD_tmax();
 if (nom_t_max != "")
  { Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_max); // récup de la fonction
    // appel fonction
    Tableau <double> & tab_ret = fct->Valeur_pour_variables_globales();
    ddlLim.Mise_a_jour_tmax(tab_ret(1));
    #ifdef MISE_AU_POINT
    // on vérifie que la fonction est scalaire
    if (tab_ret.Taille() != 1)
      { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max
             << " qui gere le temps maxi "
             << "  elle retourne une grandeur vectorielle  "
             << " ce n'est pas normal !! ,  on arrete le calcul   "
             << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
        Sortie(1);
      };
    #endif
  }

};


// mise en place de la répercussion sur les noeuds des conditions linéaires, imposées externes (par les données d'entrées),
// ne prend pas en charge par exemple les CL dues aux contacts(gérés par CL)
// pour les paramètres de passage de la méthode: idem méthode MiseAJour_tdt
void LesCondLim::MiseAJour_condilineaire_tdt      
              (const double& ,LesMaillages * lesMail,const double& deltat,LesReferences* lesRef
              ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD
              ,const double& ,bool& ch_statut
              ,int  ,Enum_ddl en_ddl )

 {
// //----- debug
// cout << "\n ****1 LesCondLim::MiseAJour_condilineaire_tdt  \n temps = " << temps << "\n";
// cout << tab_iocondiline;
// //--- fin debug
   tempsCLL.Mise_en_route_du_comptage(); // temps cpu
   // préparation
   bool tous_les_blocages = true;
   if (en_ddl != NU_DDL) tous_les_blocages = false;
   // 1--- on boucle sur le tableau et pour chaque element on calcule une condition lineaire
	  // on n'impose pas la cl (à tdt) à mesure du balayage car, si une condition dépend de noeuds qui eux même font partie
	  // d'une autre condition, on utiliserait une partie des nouvelles valeurs et une partie des valeurs de l'itérations précédente !! erreur
	  // il y a une exception: celle des conditions de projection, qui sont effectuées dans l'ordre d'apparition. Cela peut poser des pbs si les surfaces
	  // de projection vont elles-même être modifiées par les conditions linéaires finales. Mais l'inverse pourrait également être vrai, donc c'est un peu
	  // inextricable. Donc, on laisse ainsi pour l'instant
     int tabTaille = tab_iocondiline.Taille();
     for (int icondli=1;icondli<= tabTaille; icondli++)
      {I_O_Condilineaire& iocondiline_i =  tab_iocondiline(icondli); // pour simplifier
       // on regarde s'il faut considérer la condition linéaire, en fonction de en_ddl
       bool a_considerer = tous_les_blocages;
       Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier   
       if (enu_condline==UX) enu_condline = X1; // les ui sont géré avec les xi 
       if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux
         {if (Meme_famille(en_ddl,enu_condline)) a_considerer = true;};

       // I)  --- un premier passage  sur les changements de statut ---  
       // recup de la reference principal correspondant au mot cle
       const ReferenceNE & refp = 
             ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
	      int nb_n_princ = refp.Taille();
		     Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli);
       t_condiAppli.Change_taille(0); // a priori 0 c'est-à-dire qu'il n'y en a pas
		
       // on boucle sur les noeuds de la référence principale
       for (int in=1;in<=nb_n_princ;in++) 
         { // récup du noeud principal                           
           Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
           if (a_considerer)
             { bool actif_pour_le_temps =  iocondiline_i.Temps_actif(temps); // pour simplifier
//debug
//cout << "\n LesCondLim::MiseAJour_condilineaire_tdt "
//     << " actif_pour_le_temps= "<< actif_pour_le_temps << endl;
//fin debug
               if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline)) 
                { if ((!actif_pour_le_temps) && (iocondiline_i.Etat_validation()))
                   // cas du temps non actif, mais qui était actif au pas précédent
                    {  ch_statut = true; }
                  else if ((actif_pour_le_temps) && (!iocondiline_i.Etat_validation()))
                    {  ch_statut = true; };
                }; //-- fin du test si le noeud est à considérer ou pas
             };
         }; // fin de la boucle sur les noeuds de la ref principale
	      
       // II)  ---- un deuxième passage pour le traitement des conditions limites de projection ---
       //           sur un plan ou une droite
// ** je ne comprends pas pourquoi il faut l'usine à gaz Pas_a_prendre_en_compte( qui fait que si au
//   temps précédent c'était actif, alors au temps actuel, même en dehors de l'intervalle c'est également à considérer
//   cela conduit à des erreurs  donc je supprime et met un cas plus restrictif : Pas_a_prendre_en_compte_dans_intervalle(
//   mais il faudrait également changer dans tous les chargement les fct du même type : Pas_a_prendre_en_compte(
//       if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte(temps))
       if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte_dans_intervalle(temps))
            && (iocondiline_i.PlanDroite()))
        {// construction des données nécessaires 
         // on regarde si l'on utilise un noeud rotation
         const String_et_entier* mailEtNumCentreNoeud = iocondiline_i.RefNoeudRotation();
         if ( mailEtNumCentreNoeud != NULL) // utilisation d'un noeud rotation, on renseigne
          { if (mailEtNumCentreNoeud->nom == "")
                  // cas par défaut de noeud du premier maillage
                  {iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(1,mailEtNumCentreNoeud->n)));}
            else
                  // sinon il y a un nom de maillage
                  {int imail = lesMail->NumMaillage(mailEtNumCentreNoeud->nom);
                   iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(imail,mailEtNumCentreNoeud->n)));}; 
          };
	     	
         // on regarde s'il y a des fonctions de charge si oui on renseigne
         int nbfct = iocondiline_i.ExisteFonctionChargeCoef();
         if (nbfct)
            {Vecteur valfct(nbfct),deltatvalfct(nbfct);
             for (int ifct = 1; ifct <= nbfct; ifct++)
               {Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct));
                valfct(ifct)=pt_courbe->Valeur(temps);
                deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat)));	
               };
               // on renseigne la condition limite
             iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct);
             // on actualise la direction actuelle ou normale pour plan droite
             iocondiline_i.ActualiseDirectionPlanDroite();
            };
	     
         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 posi = Id_nom_ddl("X1") -1; // position du ddl X1
         // on boucle sur les noeuds de la référence principale pour appliquer la condition
         for (int in=1;in<=nb_n_princ;in++) 
          { // récup du noeud principal                           
            Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
            //si le noeud est par ailleurs bloqué, ce n'est pas possible (sauf cas particulier
            // non pris en compte car c'est trop spécifique, il faut utiliser une CL classique à la place
            // d'utiliser ce type de condition linéaire, on test donc pour éviter des déconvenues
           
            int indi = 0;
            switch (dima)
             { case 3: if (noe.Ddl_fixe(Enum_ddl(posi+3)))
                         { indi=3;
                           if (!iocondiline_i.Coherence_condi_PlanDroite(indi))
                            {break;}
                           else {indi = 0;}; // on remet à 0 si c'est cohérent
                         }
               case 2: if (noe.Ddl_fixe(Enum_ddl(posi+2)))
                         { indi=2;
                           if (!iocondiline_i.Coherence_condi_PlanDroite(indi))
                            {break;}
                           else {indi = 0;}; // on remet à 0 si c'est cohérent
                         }
               case 1: if (noe.Ddl_fixe(Enum_ddl(posi+1)))
                         { indi=1;
                           if (!iocondiline_i.Coherence_condi_PlanDroite(indi))
                            {break;}
                           else {indi = 0;}; // on remet à 0 si c'est cohérent
                         }
               default: break;
             };
           
            if (indi)
             { // cas où il existe un blocage sur le noeud, la condition linéaire n'est pas licite
               cout << "\n erreur concernant une condition lineaire par projection "
                    << ", le noeud : "<<noe.Num_noeud() <<" du maillage "<<  noe.Num_Mail() <<", est "
                    << " deja bloque suivant la direction "<< indi << " on ne peut pas appliquer "
                    << " une condition de projection normale ";
               if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
               Sortie(1);
             };
            // on ne continue que si le type de ddl de la condition limite est actif pour le noeud
            // et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte
            // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
            if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline))
              {// on met la condition limite en déplacement sur les coordonnées de la référence
               Coordonnee M = noe.Coord2();
               iocondiline_i.ProjectionSurPlanDroite_et_calValCondiLin(M);
               noe.Change_coord2(M);
               // il n'y a pas d'indication de blocage. Ce sera fait lors de la mise en place 
               // sur le second membre et sur la matrice
              }; // -- fin du cas ou c'est une variable et qu'elle est active
	      	
	         }; // -- fin de la boucle sur les noeuds de la ref principal
     	  }; // -- fin du test pour savoir si c'est une condition de projection ou non
       

       // III)  --- un troisième passage  pour la construction des coeffs actifs pour l'application pratique -----
       //           de la condition   

		     bool construction_effectuee=false; // pour savoir s'il y a une construction effective ou non
// ** je ne comprends pas pourquoi il faut l'usine à gaz Pas_a_prendre_en_compte( qui fait que si au
//   temps précédent c'était actif, alors au temps actuel, même en dehors de l'intervalle c'est également à considérer
//   cela conduit à des erreurs  donc je supprime et met un cas plus restrictif : Pas_a_prendre_en_compte_dans_intervalle(
//   mais il faudrait également changer dans tous les chargement les fct du même type : Pas_a_prendre_en_compte(
//       if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte(temps))
       if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte_dans_intervalle(temps)))
     	  {// construction des données nécessaires à l'appel de ConstructionCondition
     	   // recup du tableau des références secondaires associées si elles existent
         const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
         const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
         int tailrefasso = nomRefassocie.Taille();
         Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
         Tableau <int>  tab_numMail_associe(tailrefasso);
         if (tailrefasso != 0)
          {for (int k=1;k<=tailrefasso;k++)
            {const string * nom_maillage=NULL;
             if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
             const ReferenceNE & refasso =
              ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
             tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
             tab_numMail_associe(k)= refasso.Nbmaille();
	     	     };
          };
         // -- maintenant que l'est là, il y a de bonnes raisons de penser que les conditions sont effectives
         //    on dimensionne correctement le tableau finale
         t_condiAppli.Change_taille(nb_n_princ); // mise à jour de la taille au cas où
         // éventuellement, due à la non activité des ddl, la condition peut néanmoins ne pas être construite
         // par défaut on met le Iddl() en négatif, histoire de rendre par défaut la condition non exploitable
         // ceci sera changé durant la construction effective, si elle a lieu. D'autre part au moment de l'utilisation de la condition
         // le test sur le Iddl()  permettra de savoir si la condition est exploitable ou non
         for (int ijk=1;ijk<=nb_n_princ;ijk++)
           t_condiAppli(ijk).ChangeIddl()=-1;

         // on boucles sur les noeuds de la ref principale
         Tableau <Noeud *> t_noe(tailrefasso+1); // tableau de travail
         // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds
         // concernés par la condition linéaire.
         for (int in=1;in<=nb_n_princ;in++) 
         { // récup du noeud principal                           
           Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
           t_noe(1)= &noe;
           // on ne continue que si le type de ddl de la condition limite est actif pour le noeud
           // et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte
           // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
           if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline))
             {// récupération des noeuds associés, on utilise le même indice dans les ref associées que
              // dans la ref principale
              for (int ia = 1;ia<=tailrefasso;ia++)
                 t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));

              // on commence par voir s'il y a des fonctions de charge si oui on renseigne
              int nbfct = iocondiline_i.ExisteFonctionChargeCoef();
              if (nbfct)
               {Vecteur valfct(nbfct),deltatvalfct(nbfct);
                for (int ifct = 1; ifct <= nbfct; ifct++)
                  {Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct));
                   valfct(ifct)=pt_courbe->Valeur(temps);
                   deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat)));	
                  };
                // on renseigne la condition limite
                iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct);
               };
              // on calcul les coefs effectifs de  condition limite
              Condilineaire & condi = t_condiAppli(in); // pour simplifier
              // on constuit la condition et on impose la valeur c-a-d: 
              // on met en place la condition limite sur le ddl ddl_i du noeud principal
              // qui correspond au ddl_i' dans le nouveau repèrere qui recevra  la condition bloqué
              // en fait ddl_i sera la seul modification de ddl due à la mise en place de la CLL
              iocondiline_i.ConstructionCondition(t_noe,condi); 
       
              construction_effectuee = true; // on enregistre
             }; // -- fin du cas ou c'est une variable et qu'elle est active
          
         }; // -- fin de la boucle sur les noeuds de la ref principal
     		
     	  }; // -- fin du test pour savoir s'il faut considérer la condition linéaire ou pas
		  
      }; //-- fin de la boucle sur l'ensemble des conditions linéaire
		
     // 2--- on boucle sur toutes les conditions linéaires effectives, pour imposer les blocages
     for (int icondli=1;icondli<= tabTaille; icondli++)
      {Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli);
       int taille = t_condiAppli.Taille();
       for (int i=1;i<=taille;i++)
         { double Uk_impose = t_condiAppli(i).Val_Uk_impose(); // récup de la valeur a imposer
           // dans le cas où c'est une condition de projection, la condition a déjà été effectuée
           // donc il ne faut pas la faire ici: le test de Uk_impose, permet de le savoir
           if (Uk_impose != ConstMath::tresgrand)
             { Noeud* noe = t_condiAppli(i).Noe(); // pour simplifier
               Enum_ddl leEnuAChanger = t_condiAppli(i).Tab_Enum()(1); // le enu a changer
               noe->Change_val_tdt(leEnuAChanger,Uk_impose);
             };
         };
		    };
   tempsCLL.Arret_du_comptage(); // temps cpu

 };
    
// création d'un tableau de condition linéaire, correspondant à toutes les conditions linéaires d'entrées
// qu'elles soient actives ou pas (a priori cette méthode est conçu pour donner des infos relativement à la largeur
// de bandes en noeuds due aux CLL)
// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL,
Tableau <Tableau <Condilineaire> > LesCondLim::ConnectionCLL
     (const LesMaillages * lesMail,const LesReferences* lesRef) const
   {
     // on boucle sur le tableau et pour chaque element on impose une condition lineaire
     int tabTaille = tab_iocondiline.Taille();
     Tableau <Tableau <Condilineaire> >  t_connectionCLL(tabTaille);
     for (int icondli=1;icondli<= tabTaille; icondli++)
      {I_O_Condilineaire& iocondiline_i =  tab_iocondiline(icondli); // pour simplifier
       Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
       // recup de la reference principal correspondant au mot cle
       const ReferenceNE & refp = 
             ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
       int nb_n_princ = refp.Taille();
       Tableau <Condilineaire>& connectionCLL = t_connectionCLL(icondli); // pour simplifier
       connectionCLL.Change_taille(nb_n_princ); // mise à jour de la taille 
	      
       //  ----  traitement des conditions limites de projection ---
       //           sur un plan ou une droite
       if (iocondiline_i.PlanDroite())
        {Tableau <Noeud *> t_noe(1); // tableau de travail
         for (int in=1;in<=nb_n_princ;in++)
          { // récup du noeud principal                           
            t_noe(1)= &lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
            // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi
            Enum_ddl enu = enu_condline; // init
            if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX))
              enu = UxyzXi(enu_condline);
            // on ne continue que si le type de ddl de la condition limite est une variable
            // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
            if (t_noe(1)->UneVariable(enu))
              // on renseigne la condition uniquement sur le tableau de noeud
              { connectionCLL(in).ChangeTabNoeud(t_noe); };
          }; // -- fin de la boucle sur les noeuds de la ref principal
        }// -- fin du test pour savoir si c'est une condition de projection ou non

       //  ---  cas des conditions linéaires générales --------- 
       else 
        {// recup du tableau des références secondaires associées si elles existent
         const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
         const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
         int tailrefasso = nomRefassocie.Taille();
         Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
         Tableau <int>  tab_numMail_associe(tailrefasso);
         if (tailrefasso != 0)
          {for (int k=1;k<=tailrefasso;k++)
             {const string * nom_maillage=NULL;
              if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
              const ReferenceNE & refasso =
                  ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
              tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
              tab_numMail_associe(k)= refasso.Nbmaille();
             };
          };
         // on boucles sur les noeuds de la ref principale
         Tableau <Noeud *> t_noe(tailrefasso+1); // tableau de travail
         // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds
         // concernés par la condition linéaire.
         for (int in=1;in<=nb_n_princ;in++) 
         { // récup du noeud principal                           
           Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
           t_noe(1)= &noe;
           Condilineaire& condCLL = connectionCLL(in); // pour simplifier
           // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi
           Enum_ddl enu = enu_condline; // init
           if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX))
             enu = UxyzXi(enu_condline);
           // on ne continue que si le type de ddl de la condition limite est une variable, 
           // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
           if (noe.UneVariable(enu) )
             {// récupération des noeuds associés, on utilise le même indice dans les ref associées que
              // dans la ref principale
              for (int ia = 1;ia<=tailrefasso;ia++)
                 t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));
             };
              // on renseigne la condition uniquement sur le tableau de noeud
              condCLL.ChangeTabNoeud(t_noe);
         }; // -- fin du cas ou c'est une variable
	      	
	       }; // -- fin de la boucle sur les noeuds de la ref principal
      }; //-- fin de la boucle sur l'ensemble des conditions linéaire
   
     // retour 
     return t_connectionCLL;
   };

 
// idem ConnectionCLL avec une liste, mais spécifiquement les conditions de type "stricte_egalite" entre ddl de noeud
// correspondant à toutes les conditions linéaires d'entrées actives uniquement
// (a priori cette méthode est conçu pour donner des infos pour condenser les pointeurs d'assemblages:
// LesMaillages::MiseAJourPointeurAssemblage() )
// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, et le type enumere de ddl
list <Condilineaire>  LesCondLim::ConnectionCLL_stricte_egalite
              (const LesMaillages * lesMail,const LesReferences* lesRef) const
   {
     // def de la liste de retour
     list <Condilineaire> list_condi;
     // on boucle sur le tableau et pour chaque element on analyse la condition lineaire
     int tabTaille = tab_iocondiline.Taille();
     for (int icondli=1;icondli<= tabTaille; icondli++)
      {I_O_Condilineaire& iocondiline_i =  tab_iocondiline(icondli); // pour simplifier
       Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
       Tableau <Enum_ddl> tab_enu(1); tab_enu(1) = enu_condline; // servira pour construire les Condilineaires
       // recup de la reference principal correspondant au mot cle
       const ReferenceNE & refp = 
             ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
       int nb_n_princ = refp.Taille();
	      
       // --- on ne continue que s'il s'agit d'une condition stricte_egalite et que la condition
       //     est active pour le temps actuel
       if ((iocondiline_i.StricteEgalite())
            && (iocondiline_i.Temps_actif(ParaGlob::Variables_de_temps().TempsCourant())))
        {// recup du tableau des références secondaires associées si elles existent
         const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
         const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
         int tailrefasso = nomRefassocie.Taille();
         Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
         Tableau <int>  tab_numMail_associe(tailrefasso);
         if (tailrefasso != 0)
          {for (int k=1;k<=tailrefasso;k++)
             {const string * nom_maillage=NULL;
              if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
              const ReferenceNE & refasso =
                  ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
              tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
              tab_numMail_associe(k)= refasso.Nbmaille();
             };
          };
         // on boucles sur les noeuds de la ref principale
         Tableau <Noeud *> t_noe(tailrefasso+1); // tableau de travail
         // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds
         // concernés par la condition linéaire.
         for (int in=1;in<=nb_n_princ;in++) 
         { // récup du noeud principal                           
           Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
           t_noe(1)= &noe;
           // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi
           Enum_ddl enu = enu_condline; // init
           if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX))
             enu = UxyzXi(enu_condline);
           // on ne continue que si le type de ddl de la condition limite est une variable, 
           // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
           if (noe.UneVariable(enu) )
             {// récupération des noeuds associés, on utilise le même indice dans les ref associées que
              // dans la ref principale
              for (int ia = 1;ia<=tailrefasso;ia++)
                 t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));
             };
           // on renseigne une condition uniquement sur le tableau de noeud
           Condilineaire condi_stric_egal(tab_enu,t_noe);
           list_condi.push_back(condi_stric_egal);
         }; // -- fin du cas ou c'est une variable
	      	
	       }; // -- fin de la boucle sur les noeuds de la ref principal

      }; //-- fin de la boucle sur l'ensemble des conditions linéaire
   
     // retour 
     return list_condi;
   };


// récupération de  valeurs à un noeud pour les grandeur enu
// ici il s'agit de grandeur scalaires
Tableau <double> LesCondLim::Valeur_multi_interpoler_ou_calculer
                 (const Noeud& noe, Enum_dure temps,const List_io<Ddl_enum_etendu>& enu)
 {
     // recup de l'incrément de temps
     double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
     double unSurDeltat=0;
     if (Abs(deltat) >= ConstMath::trespetit)
       {unSurDeltat = 1./deltat;}
     else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
       { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
         if (unSurDeltat < 0)
          { cout << "\n le pas de temps est négatif !! "; };
         unSurDeltat = ConstMath::tresgrand;
       };
     // le tableau de retour
     Tableau <double> tab_ret (enu.size());
  
     // on balaie  la liste des grandeurs à sortir
     List_io<Ddl_enum_etendu>::const_iterator ie,iefin=enu.end();
     int it; // it est l'indice dans le tableau de retour
     for (it=1,ie=enu.begin(); ie!=iefin;ie++,it++)
      { if ((Meme_famille((*ie).Enum(),X1)) && ((*ie).Nom_vide()))
         {switch (temps)
           {case TEMPS_0 :  tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1);break;
            case TEMPS_t :  tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1);break;
            case TEMPS_tdt :  tab_ret(it)= noe.Coord2()((*ie).Enum() - X1 +1);break;
            default :
             cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
             cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n";
             Sortie(1);
           };
         }
        else if ((Meme_famille((*ie).Enum(),UX)) && ((*ie).Nom_vide()))
         {int i_cor = (*ie).Enum() - UX +1; // l'indice de coordonnée
          switch (temps)
           {case TEMPS_0 :  tab_ret(it)= 0.;break;
            case TEMPS_t :  tab_ret(it)= noe.Coord1()(i_cor)-noe.Coord0()(i_cor);break;
            case TEMPS_tdt :  tab_ret(it)= noe.Coord2()(i_cor)-noe.Coord0()(i_cor);break;
            default :
             cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
             cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n";
             Sortie(1);
           };
         }
        // cas particulier de la position à t, indépendamment du temps
        else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 123)
         {tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1);
         }
        // cas particulier de la position à t0, indépendamment du temps
        else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 126)
         {tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1);
         }
        else if ((*ie).Nom_vide())
         {// il s'agit d'un ddl pur on le récupère directement
           switch (temps)
           {case TEMPS_0 :  tab_ret(it)= noe.Valeur_0((*ie).Enum());break;
            case TEMPS_t :  tab_ret(it)= noe.Valeur_t((*ie).Enum());break;
            case TEMPS_tdt :  tab_ret(it)= noe.Valeur_tdt((*ie).Enum());break;
            default :
             cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
             cout << "LesCondLim::Valeur_multi_interpoler_ou_calculer(..  \n";
             Sortie(1);
           };
         }
        // --- a complèter ----
        else
          { tab_ret(it) = 0.;
            cout << "\n cas de ddl actuellement non traite "
                << "\n pas de ddl " << (*ie).Nom() << " au noeud "
                << noe.Num_noeud() <<" du maillage "<< noe.Num_Mail()
                << "\n ou cas non implante pour l'instant, on retourne 0"
                << "\n LesCondLim::Valeur_multi_interpoler_ou_calculer(.. ";
           };
      };// -- fin de la boucle sur la liste de Ddl_enum_etendu
     // liberation des tenseurs intermediaires
     LibereTenseur();
     return tab_ret;
    };

// récupération de  valeurs à un noeud pour les grandeur enu
// ici il s'agit de grandeurs tensorielles
void LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer
                 (const Noeud& noe, Enum_dure temps,List_io<TypeQuelconque>& enu)

{  // ----- def de grandeurs de travail
   int dim_espace = ParaGlob::Dimension(); 

   // on initialise ces variables booléennes et les conteneurs
   List_io<TypeQuelconque>::iterator ipq,ipqfin=enu.end();
   for (ipq=enu.begin();ipq!=ipqfin;ipq++)
    {TypeQuelconque_enum_etendu enuq = (*ipq).EnuTypeQuelconque().EnumTQ();
     switch (enuq.Position())
     { case POSITION_GEOMETRIQUE :
        {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
         Coordonnee* M = gr.ConteneurCoordonnee();
         switch (temps)
           {case TEMPS_0 :  (*M)= noe.Coord0();break;
            case TEMPS_t :  (*M)= noe.Coord1();break;
            case TEMPS_tdt :  (*M)= noe.Coord2();break;
            default :
             cout << "\nErreur : valeur incorrecte du temps !\n";
             cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
             if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
             if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
             Sortie(1);
           };
         break;
        }
       case POSITION_GEOMETRIQUE_t :
        {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
         Coordonnee* M = gr.ConteneurCoordonnee();
         (*M)= noe.Coord1();
         break;
        }
       case POSITION_GEOMETRIQUE_t0 :
        {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
         Coordonnee* M = gr.ConteneurCoordonnee();
         (*M)= noe.Coord0();
         break;
        }
       case DEPLACEMENT :
        {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
         Coordonnee* M = gr.ConteneurCoordonnee();
         switch (temps)
           {case TEMPS_0 :  M->Zero();break;
            case TEMPS_t :  (*M)= noe.Coord1()-noe.Coord0();break;
            case TEMPS_tdt :  (*M)= noe.Coord2()-noe.Coord0();break;
            default :
             cout << "\nErreur : valeur incorrecte du temps !\n";
             cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
             if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
             if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
             Sortie(1);
           };
         break;
        }
       case FORCE_GENE_EXT : case FORCE_GENE_INT : case VECT_PRESSION : case VECT_FORCE_VOLUM :
       case VECT_DIR_FIXE : case VECT_SURF_SUIV : case VECT_HYDRODYNA_Fn : case VECT_HYDRODYNA_Ft :
       case VECT_HYDRODYNA_T : case VECT_LINE : case VECT_LINE_SUIV : case VECT_REAC : case VECT_REAC_N :
       case FORCE_CONTACT : case FORCE_GENE_TOT: case RESIDU_GLOBAL:
        {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
         Coordonnee* F = gr.ConteneurCoordonnee();
         // on vérifie l'existante
         #ifdef MISE_AU_POINT
          if (!(noe.Existe_ici(enuq)))
            {cout << "\nErreur : " << enuq.Nom() << " n'existe pas au noeud "
                  << noe.Num_noeud() << " du maillage "<< noe.Num_Mail()
                  << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
             if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
             if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
             Sortie(1);
            };
         #endif
         // récupération de la grandeur quelconque
         const TypeQuelconque& toto = noe.Grandeur_quelconque(enuq);
         const Grandeur_coordonnee&  titi = *((const Grandeur_coordonnee* ) toto.Const_Grandeur_pointee());
         (*F) = titi.ConteneurCoordonnee_const(); // ouf
         break;
        }
       case VITESSE :
        {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
         Coordonnee* V = gr.ConteneurCoordonnee();
         // on vérifie l'existante
         #ifdef MISE_AU_POINT
          if (!(noe.Existe_ici(V1)))
            {cout << "\nErreur : la vitesse n'existe pas au noeud "
                  << noe.Num_noeud() << " du maillage "<< noe.Num_Mail()
                  << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
             if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
             if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
             Sortie(1);
            };
         #endif
         // récupération de la vitesse
         switch (temps)
          { case TEMPS_0 :
             {switch (dim_espace)
               {case 3: (*V)(3) = noe.Valeur_0(V3);
                case 2: (*V)(2) = noe.Valeur_0(V2);
                case 1: (*V)(1) = noe.Valeur_0(V1);
                break;
                default: break;
               };
              break;
             }
            case TEMPS_t :
             {switch (dim_espace)
               {case 3: (*V)(3) = noe.Valeur_t(V3);
                case 2: (*V)(2) = noe.Valeur_t(V2);
                case 1: (*V)(1) = noe.Valeur_t(V1);
                break;
                default: break;
               };
              break;
             }
           case TEMPS_tdt :
             {switch (dim_espace)
               {case 3: (*V)(3) = noe.Valeur_tdt(V3);
                case 2: (*V)(2) = noe.Valeur_tdt(V2);
                case 1: (*V)(1) = noe.Valeur_tdt(V1);
                break;
                default: break;
               };
              break;
             }
           default: break;
         };
        break;
       }
       default :
         {// on initialise la grandeur pour éviter d'avoir des valeurs aléatoires
          ((*ipq).Grandeur_pointee())->InitParDefaut();
          if (ParaGlob::NiveauImpression() > 0)
           {cout << "\nWarning : attention cas non traite: "
                 <<  (*ipq).EnuTypeQuelconque().NomPlein() << "!\n";
            // on initialise la grandeur pour éviter d'avoir des valeurs aléatoires
            if (ParaGlob::NiveauImpression() > 5)
               cout << "\n LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(....";
           };
         }
     };
    };


   // liberation des tenseurs intermediaires
   LibereTenseur();
};


