
// 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/>.

/************************************************************************
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:   Gestion des differentes conditions limites                *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef LESCONDLIM_H
#define LESCONDLIM_H

#include "LectBloc_T.h"
#include "Tableau_T.h"
#include "DdlLim.h"
#include "UtilLecture.h"
#include "LesReferences.h"
#include "MotCle.h"
#include "LesMaillages.h"
#include "CondLim.h"
#include "Condilineaire.h"
#include "Nb_assemb.h"
#include "LesCourbes1D.h"
#include "LesFonctions_nD.h"
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "Basiques.h" 
#include "I_O_Condilineaire.h"
#include "Temps_CPU_HZpp.h"

/** @defgroup Les_classes_relatives_aux_conditions_limites
*
*     BUT:Gestion des differentes conditions limites
*
* \author    Gérard Rio
* \version   1.0
* \date       23/01/97
* \brief      Gestion des differentes conditions limites
*
*/

/// @addtogroup Les_classes_relatives_aux_conditions_limites
///  @{
///
class LesCondLim
{
  public :
    // CONSTRUCTEURS :
    LesCondLim (); // par defaut
    // DESTRUCTEUR :
    ~LesCondLim ();
    
    // METHODES PUBLIQUES :
    
    // lecture des  conditions limites : ddl bloque
    void Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef);
    
    // lecture des  conditions limites linéaires
    void Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef);
    
    // lecture des  conditions limites : initialisation
    void Lecture3(UtilLecture & entreePrinc,LesReferences& lesRef);
    
    // affichage des informations concernant les conditions limites
    void Affiche() const ; // affichage de tous les infos
    void Affiche1() const ; // affichage des ddl bloques
    void Affiche2() const ; // affichage des conditions limites linéaires
    void Affiche3() const ; // affichage des ddl d'initialisation
    
    // introduction des données et variables pour leurs emplois futures, avec init par défaut
    void IntroductionDonnees (LesMaillages * lesMail,LesReferences* lesRef
                             ,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD);
    
    // initialisation des ddl avec le tableau de ddl d'init
    // verif de l'existence de tous les ddl (initialisation et imposes) 
    // ajout si necessaire, dans ce dernier cas l'initialisation est a zero
    // choix = false  : indique qu'il faut initialiser que les ddl a  t
    // choix = true : indique qu'il faut initialiser les ddl  a t et t+dt
    // vérification de l'existence des courbes de charge adoc si nécessaire
    // cas    : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque
    //          le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont
    //          leur statut modifié de manière équivalente
    //    =0    pas d'association
    //    =1    association X V GAMMA
    void Initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D
                 ,LesFonctions_nD*  lesFonctionsnD,bool choix,int cas);
 
//    // mise à jour de l'initialisation, par exemple après un restart
//    // même paramètres que Initial, par contre ici il n'y a aucune création
//    void Re_initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,bool choix,int cas);
 
    // initialisation du nombre de cas d'assemblage
    // si inf au nombre actuel, aucune action
    void InitNombreCasAssemblage(int nb_cas)
      {  if (nb_cas > condlim.Taille())
            condlim.Change_taille(nb_cas);
      };
      
    // incrementation des coordonnees a t+dt et des ddl en fonctions des ddl imposes
    // et du chargement
    // coef: est un facteur multiplicatif des ddl sans courbes de charge,
    //       est suposé intégrer déjà le multiplicateur général
    // en fait du chargement impose
    // mult_gene : multiplicateur général de tous les chargements
    // deltat : incrément de temps actuel
    // temps : le temps courant où sont calculées les conditions
    // ch_statut : indique s'il y a changement ou non de statut des conditions limites (pour les ddl aux noeuds)
    //            c-a-d un ddl qui passe de bloqué à non bloqué ou inversement: il s'agit uniquement des ddl aux noeuds 
    //            c-a-d ceux qui ont une influence sur la mise en place des cl sur la raideur et le résidu 
    // cas    : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque
    //          le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont
    //          leur statut modifié de manière équivalente
    //    =0    pas d'association
    //    =1    association X V GAMMA
    // lorsque en_ddl est égal à  NU_DDL, cela signifie que l'on met les conditions limites sur tous les
    // ddl de noeud actifs
    // lorsque en_ddl est différent de NU_DDL, il donne le type des seules ddl pour lesquels on met les 
    // conditions de blocage: par exemple X1 -> blocage sur X1,X2,X3 selon la dimension
    void MiseAJour_tdt
      (const double& mult_gene,LesMaillages * lesMail,const double& deltat,const LesReferences* lesRef
      ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD
      ,const double& coef,bool& ch_statut
      ,int cas , Enum_ddl en_ddl = NU_DDL);
             
    // 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: voir MiseAJour_tdt
    void MiseAJour_condilineaire_tdt      
                  (const double& mult_gene,LesMaillages * lesMail,const double& deltat,LesReferences* lesRef
                  ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD
                  ,const double& coef,bool& ch_statut
                  ,int cas ,Enum_ddl en_ddl = NU_DDL);
      
    // validation des conditions de blocages et des conditions linéaire, pour l'incrément.
    // concernant l'activité des ddlLim, elle est enregistrée en fonction du temps
    // idem pour les conditions linéaires
    void Validation_blocage (LesReferences* lesRef,const double& temps);      
       
    // test s'il y a changement de statut pour le temps indiqué par rapport à la situation actuelle ou pas
    // n'effectue aucune autre opération
    // si en_ddl est différent de NU_DDL on test le changement de statut uniquement pour le ddl en_ddl
    bool Changement_statut(const LesMaillages * lesMail,const LesReferences* lesRef
                          ,LesFonctions_nD*  lesFonctionsnD
                          ,const double& temps,const Enum_ddl en_ddl = NU_DDL)  ;
    // récupération des tableaux d'indices généraux des ddl bloqués
    // cas : donne le type d'association de ddl que l'on veut
    //      =0 -> pas d'association
    //      =1 -> association de Xi avec Vi avec Gammai
    // t_assemb: donne pour chaque type d'association, le numéro d'assemblage correspondant au different ddl 
    //           de l'association 
    //           cas=1 -> numéro d'assemblage de X1 puis V1 puis GAMMA1
    //    : en sortie une liste de Gene_asso, correspondant à tous les ddl bloqués et les 
    //            les ddl associés 
    
    // définition d'un conteneur pour la routine Tableau_indice
    class Gene_asso
      { public :
           Gene_asso () : ty_prin(NU_DDL),pointe() {};
           Gene_asso (Enum_ddl ty_prin,const Tableau  <int>& pointes) :
                ty_prin(ty_prin),pointe(pointes) {};
           Gene_asso (const Gene_asso& a) : ty_prin(a.ty_prin),pointe(a.pointe) {};
           Gene_asso& operator= (const Gene_asso& a) 
              {ty_prin=a.ty_prin;pointe=a.pointe;return (*this);};
           bool operator== (const Gene_asso& a) const 
              {if((ty_prin==a.ty_prin)&&(pointe==a.pointe)) return true;else return false;};
           bool operator!= (const Gene_asso& a) const
		             {if ( (*this)==a ) return true; else return false;};
           Enum_ddl ty_prin; // le ddl principal bloqué
           Tableau <int> pointe; // la position générale des ddl, principal et secondaire
           //  pour le cas 1 : pointe(k) -> la position du ddl  Xi , puis  Vi puis  Gammai
      };
        
    list <Gene_asso> Tableau_indice(const LesMaillages * lesMail,const Tableau <Nb_assemb> & t_assemb
                                   ,const LesReferences* lesRef,const double& temps,int cas );
     
    // mise en place des conditions limites sur les matrices et second membres
    // (autres que les conditions linéaires)
    // nb_casAssemb : le cas d'assemblage
    // cas : indique un type d'association de ddl 
    //     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
    //     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
    //            a été fixé par l'utilisateur
    // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
    //        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
    void ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef,
                       Mat_abstraite & matglob,Vecteur& vecglob
                       ,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2);
                         
    // mise en place des conditions limites sur le second membres
    // nb_casAssemb : le cas d'assemblage
    // cas : indique un type d'association de ddl 
    //     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
    //     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
    //            a été fixé par l'utilisateur
    // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
    //        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
    void ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef,
                         Vecteur& vecglob,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2);  
                       
    // mise en place des conditions limites sur deux matrices
    // utilisé par exemple pour le flambement 
    // la première matrice est initialisée avec des 1 sur la diagonale
    // la seconde avec des 0 sur la diagonale 
    // nb_casAssemb : le cas d'assemblage
    // cas : indique un type d'association de ddl 
    //     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
    //     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
    //            a été fixé par l'utilisateur
    void ImpConLimtdt2Mat(LesMaillages * lesMail,LesReferences* lesRef,
                       Mat_abstraite & matglob,Mat_abstraite & matgeom
                       ,const Nb_assemb& nb_casAssemb,int cas);  
                       
    // retourne la valeur absolu du maxi des efforts exterieurs
    // et le numero ili du ddl correspondant dans l'assemblage global
    double MaxEffort(int & ili,const Nb_assemb& nb_casAssemb)
      { return condlim(nb_casAssemb.n).MaxEffort(ili);};                   

    // calcul des reactions et stockage des valeurs
    // ceci dans le cas ou il n'y a pas de conditions lineaires appliquee
    // on se sert des valeurs sauvegardees lors de la mise en place des CL bloquees
    // nb_casAssemb : le cas d'assemblage
    // cas : indique un type d'association de ddl 
    //     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
    //     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
    //            a été fixé par l'utilisateur
    void CalculReaction(LesMaillages * lesMail,LesReferences* lesRef
                       ,const Nb_assemb& nb_casAssemb,int cas);
                
    // récupération des reactions initiales, avant les rotations dues aux  conditions linéaires 
    // il s'agit des réactions dues aux ddl bloqués et dues aux conditions linéaires
    // et calcul des torseurs de réaction
    void ReacAvantCHrepere(Vecteur& residu,LesMaillages * lesMail,
                           LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas);            

    // récupération des reactions= residu et stockage des valeurs 
    // NB: après changement de repère, il n'y a plus que des ddl bloqués 
    // cas : indique un type d'association de ddl 
    //     = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
    //     = 1 -> association de Xi  Vi  Gammai, qui sont pris en compte dès lors que l'un 
    //            a été fixé par l'utilisateur
    void ReacApresCHrepere(Vecteur& residu,LesMaillages * lesMail,
                              LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas);            
                
    // affichage sur la sortie sort des reactions  
    void Affiche_reaction(ofstream& sort,const LesMaillages * lesMail) const ;
    
    // ------------------ conditions linéaires externes ----------------------------------------------
 
    // mise en place de condition externe lineaires
    // expression de la raideur et du second membre dans un nouveau repere
    // ramène si oui ou non, il y a eu un changement effectué
    // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
    //        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
    bool CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob
                    ,const Tableau <Condilineaire>& tabCondLine
						  ,const Nb_assemb& nb_casAssemb,Vecteur* vec2);
                     
    // blocage des seconds membres pour les conditions lineaires
    // 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)
    inline void CoLinBlocage(Mat_abstraite & matglob,Vecteur& vecglob
                              ,const Nb_assemb& nb_casAssemb,Vecteur* vec2)
            { condlim(nb_casAssemb.n).CondlineaireImpose ( matglob, vecglob,vec2);};

    // retour des ddl dans le repere general, ceci dans le cas d'utilisation
    // de conditions lineaires
    inline void RepInitiaux( Vecteur& sol,const Nb_assemb& nb_casAssemb) 
             { condlim(nb_casAssemb.n).RepInitiaux(sol); };
 
    // mise en place de condition externe lineaires en une opération
    // retour de la raideur et du second membre sans changement de repere
    // ramène si oui ou non, il y a eu un changement effectué
    // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
    //        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
    bool CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob
                        ,const Tableau <Condilineaire>& tabCondLine
                        ,const Nb_assemb& nb_casAssemb,Vecteur* vec2);


 // -------- conditions linéaires internes: imposées par les conditions limites en entrée -----------
                     
    // 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 CoLinCHrepere_int(Mat_abstraite & matglob,Vecteur& vecglob,const Nb_assemb& nb_casAssemb,Vecteur* vec2);
    // effacement du marquage de ddl bloque du au conditions lineaire imposées par les conditions d'entrée
    void EffMarque();
    
    // 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 Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb,LesMaillages * lesMail,LesReferences* lesRef
	                    ,int& cumule);
    
    // 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 prior 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> >  ConnectionCLL(const LesMaillages * lesMail,const LesReferences* lesRef) const;
 
    // 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>   ConnectionCLL_stricte_egalite
                  (const LesMaillages * lesMail,const LesReferences* lesRef) const;
 
    // récupération du tableau de conditions linéaires en cours
    //résultant de l'application des conditions lues (indépendamment du contact par exemple)
    // mis à jour après la méthode: MiseAJour_condilineaire_tdt
    const Tableau < Tableau <Condilineaire > >& Tab_CLinApplique() const {return tab_CLinApplique;};

    // indique si oui ou non il y a des conditions limites linéaires en entrée
    bool ExisteCondiLimite() const {return tab_iocondiline.Taille();};

 // -----------------------     fin conditions linéaires  -------------------------------------------
    
    //initialisation, mise a zero des  sauvegarde
    void InitSauve(const Nb_assemb& nb_casAssemb); 

    // lecture de donnée en fonction d'un indicateur : int type
    // pour l'instant ne fait rien
    void   LectureDonneesExternes(UtilLecture& ,LesReferences& ,const int ,const string&) {};
    
    // affichage et definition interactive des commandes pour les conditions limites CL
    void Info_commande_LesCondLim1(UtilLecture & entreePrinc);

    // affichage et definition interactive des commandes pour les conditions limites CLL
    void Info_commande_LesCondLim2(UtilLecture & entreePrinc);

    // affichage et definition interactive des commandes pour les initialisations
    void Info_commande_LesCondLim3(UtilLecture & entreePrinc);
 
	 //----- lecture écriture de restart -----
   	// cas donne le niveau de la récupération
    // = 1 : on récupère tout
    // = 2 : on récupère uniquement les données variables (supposées comme telles)
	   void Lecture_base_info(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD);
    // cas donne le niveau de sauvegarde
    // = 1 : on sauvegarde tout
    // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
	   void Ecriture_base_info(ofstream& sort,const int cas);
 
    //------- temps cpu -----
    // retourne temps cumulé pour imposer les CL imposées
    const Temps_CPU_HZpp& Temps_cpu_CL() const {return tempsCL;};
    //  retourne le temps cumulé pour imposer les CLL
    const Temps_CPU_HZpp& Temps_cpu_CLL() const {return tempsCLL;};
 
// --- conteneur pour les réactions -----
    class ReactStoc
      {  public :
           // surcharge de l'operator de lecture typée
           friend istream & operator >> (istream &, ReactStoc &);
           // surcharge de l'operator d'ecriture typée
           friend ostream & operator << (ostream &, const ReactStoc &);
      
           //Surcharge d'operateur logique
           bool operator == ( const ReactStoc& a) const
            { return  ((numMail==a.numMail)&&(numNoeud==a.numNoeud)
                       &&(ddl==a.ddl)&&(casAss==a.casAss));
            };
           bool operator != ( const ReactStoc& a) const { return !(*this == a);};
           // !*!*!*!  classement uniquement sur le numéro de noeud !*!*!*!
           // --->> non: changement 3/1/2018
           bool operator < ( const ReactStoc& a) const
              {if (numMail < a.numMail) return true;
               else if (numMail == a.numMail) return (numNoeud < a.numNoeud);
               else // cas où numMail > a.numMail
                 return false;
               //return (numNoeud < a.numNoeud);
              };
           bool operator > ( const ReactStoc& a) const { return !(*this < a);};;

           public : int numMail; // numero de maillage
           int numNoeud ; // numero de noeud
           Ddl ddl; // le ddl bloque
       int casAss; // cas d'assemblage
      };
       
    class TorseurReac
      {// surcharge de l'operator de lecture typée
       friend istream & operator >> (istream &, TorseurReac &);
       // surcharge de l'operator d'ecriture typée
       friend ostream & operator << (ostream &, const TorseurReac &);
       
       public : 
       // constructeurs
       TorseurReac():existe_torseur_reac(false),resultante(),moment(),bloque_ou_CLL(true) {};
       TorseurReac(const TorseurReac& a):
         existe_torseur_reac(a.existe_torseur_reac),resultante(a.resultante)
         ,moment(a.moment),bloque_ou_CLL(a.bloque_ou_CLL) {};
       // méthodes  
       void Activation(int dima) {existe_torseur_reac=true;resultante.Change_dim(dima);
                                  moment.Change_dim(dima);};
       void Zero_init_torseur()	{resultante.Zero();moment.Zero();};
                                  
       // données                           
       bool existe_torseur_reac; // indique si le Torseur doit-être calculé ou non
       Coordonnee resultante; // la résultante du torseur 
       Coordonnee moment;  // le moment du torseur par rapport à l'origine 
       bool bloque_ou_CLL; // true provient d'un ddl bloqué, false provient d'une CLL
      };
       
 
    // retourne les réactions aux conditions limites à un noeud noe d'un maillage mail
    // s'il n'y a pas de conditions limites : retour d'une liste vide
//     const list<const LesCondLim::ReactStoc*>& Reaction_noeud_mail(int mail,int noeud) const ;       

 	  // 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> > Les_type_de_ddl_en_reaction() const;
    
    // 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 > >  TabListTorseurReaction(const LesMaillages & lesmail) const;
    // retourne le torseur de réaction correspondant à l'indice i
    const TorseurReac & Torseur_de_reaction(int i) const {return tab_torseurReac(i);};
	
  private :  
    // VARIABLES PROTEGEES :
    Tableau <DdlLim> tabBloq; // tableau des ddl bloques
    Tableau <TorseurReac> tab_torseurReac; // tableau des torseurs de réaction
          // relatif aux ddl bloqués et aux conditions linéaires
          // de 1 à ttRG.Taille() on a les torseurs relatifs à tabBloq
          // puis de ttRG.Taille() à la fin c-a-d ttRG.Taille()+ttRGCLL.Taille(), 
          // on a les torseurs relatifs à tab_iocondiline

    // un tableau, qui permet de passer de tabBloq à tab_torseurReac 
    Tableau <int> ttRG; // tabBloq(i) contribue au torseur tab_torseurReac(ttRG(i))
    // ttorBloq(i) contient tous les numéros de tabBloq qui contribue au torseur i
    Tableau < List_io <int> > ttorBloq; 
    Tableau <DdlLim> tabInit; // tableau des ddl d'initialisation
    Tableau <ReactStoc> reaction; // les reactions pour les ddl bloqués
    Tableau <ReactStoc> reaction_CLin; // les reactions pour les conditions linéaires
    Tableau <ReactStoc> reactionApresCHrepere; // les reactions après CHrepere
    
    // tableau des conditions linéaires a imposer par les données d'entrée
    Tableau <I_O_Condilineaire > tab_iocondiline; 
    Tableau < Tableau <Condilineaire > > tab_CLinApplique; // tableau des conditions linéaires 
                                                  //résultant de l'application de  tab_iocondiline                                                  
    // un tableau à deux dim, qui permet de passer de tab_CLinApplique à tab_torseurReac 
    Tableau < Tableau <int> > ttRGCLL; // tab_CLinApplique(i)(j) contribue au torseur tab_torseurReac(ttRGCLL(i)(j))
    // ttorCLL(i) contient tous les numéros de tab_iocondiline qui contribue au torseur i, avec 
    // le premier élément de l'instantce DeuxEntiers = le numéros dans tab_iocondiline, le second élement = le rang de 
    // la référence dans la condition linéaire
    Tableau < List_io <DeuxEntiers> > ttorCLL; 

    //deux liste de noms de ref qui servent pour accèder aux grandeurs globales correspondantes
    // aux composantes des torseurs de réaction
    // voir: DimensionneTorseurs() :
    //  ttRG_noms_ref + _Re_ + i  -> ième composante de Re a tdt
    // et à la place de Re -> Mo pour le moment
    Tableau <string> ttRG_noms_ref;    // nom générique associé aux torseurs de ddl bloqué
    Tableau <string> ttRGCLL_noms_ref; // idem pour les CLL
 
    // une map pour faire l'association entre numéro de maillage et numéro de noeud d'une part
    // et le tableau de réaction pour un accès quasi-directe
//    map < string, list<const ReactStoc*> , std::less <string> > map_reaction;
    int nb_maillage; // sauvegarde du nombre de maillage
    
    Tableau < CondLim > condlim; // les fonctions et données qui permettent d'imposer les cl
    // aux matrices, aux second membres, de remonter aux efforts apres
    // resolution etc ..., le tableau est indicé par le numéro de cas d'assemblage
    
    //------- temps cpu -----
    Temps_CPU_HZpp tempsCL; // temps cumulé pour imposer les CL imposées
    Temps_CPU_HZpp tempsCLL; //  temps cumulé pour imposer les CLL

    // ----fonctions internes pour simplifier
    
    //  cas de l'initialisation:  prise en compte de l'appartenance à un groupe
    // fixe : donne le type d'initialisation que l'on veut
    // une_variable: indique si le ddl est une variable (=true) ou une donnée (=false)
    void Init_appart_groupe(bool une_variable,Enum_ddl a,bool fixe,Noeud& noe, int cas,bool choix);    
    //cas courant:  mise en place du blocage sur un ddl ou un groupe si besoin est
    void Mise_cl(int nd,DdlLim& ddl,Enum_ddl a,Noeud& noe, int cas);
    // cas courant : on retire le  blocage sur un ddl ou un groupe si besoin est
    void Retire_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas);
    // vérification qu'il n'y a pas de surcharge de blocage
    // choix indique si l'on vérifie à t ou à tdt
    void Verif_surcharge_blocage(const LesMaillages * lesMail,const LesReferences* lesRef,const double& temps,int cas) ;  
    // 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>& Ddl_associe( Ddl& ddl,Noeud& noe,Tableau <Ddl>& tab_travail,int cas);
    // cas particulier des mouvements solides, dans le second passage pour la méthode MiseAJour_tdt
    void 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);   
    // 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 CalculTorseurReaction(TorseurReac& tr, const Noeud& noe, ReactStoc& reac);
    
    // récupération de  valeurs à un noeud pour les grandeur enu
    // ici il s'agit de grandeur scalaires
    Tableau <double> Valeur_multi_interpoler_ou_calculer
                     (const Noeud& noe, Enum_dure temps,const List_io<Ddl_enum_etendu>& enu);
    // récupération de  valeurs à un noeud pour les grandeur enu
    // ici il s'agit de grandeurs tensorielles
    void Valeurs_Tensorielles_interpoler_ou_calculer
                     (const Noeud& noe, Enum_dure temps,List_io<TypeQuelconque>& enu);
    // 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 DimensionneTorseurs();
    
    // DdlLim à un noeud: mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD
    void Mise_a_jour_t_minmax_ddlLim(Noeud& noe,DdlLim& ddlLim,LesFonctions_nD*  lesFonctionsnD);
    // 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 Mise_a_jour_t_minmax_ddlLim(DdlLim& ddlLim,LesFonctions_nD*  lesFonctionsnD);

 };
 /// @}  // end of group


#endif  
