// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *     DATE:        24/09/2004                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  Visualisation des isovaleurs en Gid.                       *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     REMARQUE:                                                        *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef ISOVALEURS_GID_T
#define ISOVALEURS_GID_T

#include "OrdreVisu.h"
#include "TypeQuelconque.h"
#include "Mail_initiale_Gid.h"
#include <map>

/// @addtogroup Les_sorties_Gid
///  @{
///


class Isovaleurs_Gid : public OrdreVisu
{
  public :
    // CONSTRUCTEURS :
     // par defaut
     Isovaleurs_Gid () ; 
     
     // constructeur de copie 
     Isovaleurs_Gid (const Isovaleurs_Gid& algo);
               
    // DESTRUCTEUR :
     ~Isovaleurs_Gid () ;  
    
    // METHODES PUBLIQUES :
    // initialisation : permet d'initialiser les différents paramètres de l'ordre
    // lors d'un premier passage des différents incréments
    // en virtuelle, a priori est défini si nécessaire dans les classes dérivées
    // incre : numéro d'incrément qui en cours
    void Initialisation(ParaGlob * ,LesMaillages *,LesReferences*
                      ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*,LesContacts*
                      ,Resultats*,EnumTypeIncre type_incre,int incre
                      ,const map < string, const double * , std::less <string> >& listeVarGlob
                      ,const List_io < TypeQuelconque >& listeVecGlob
                      ,bool fil_calcul) ;
    // execution de l'ordre
    // tab_mail : donne les numéros de maillage concerné
    // incre : numéro d'incrément qui en cours
    // type_incre : indique si c'est le premier le dernier ou l'incrément courant a visualiser ou pas
    // animation : indique si l'on est en animation ou pas
    // unseul_incre : indique si oui ou non il y a un seul increment à visualiser
    void ExeOrdre(ParaGlob * ,const Tableau <int>& tab_mail ,LesMaillages *,bool unseul_incre,LesReferences*
                      ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*,LesContacts*
                      ,Resultats*,UtilLecture & entreePrinc,OrdreVisu::EnumTypeIncre type_incre,int incre
                      ,bool animation,const map < string, const double * , std::less <string> >& listeVarGlob
                      ,const List_io < TypeQuelconque >& listeVecGlob);
    // choix de l'ordre, cet méthode peut entraîner la demande d'informations
    // supplémentaires si nécessaire. qui sont ensuite gérer par la classe elle même
    void ChoixOrdre();                   
            
    // initialisation de la liste des différentes isovaleurs possibles
    void Init_liste_isovaleur(LesMaillages * lesMail,LesContacts* lesContacts,bool fil_calcul);
    // initialisation d'une liaison avec une instance de classe de maillage initiale
    void Jonction_MaillageInitiale(const Mail_initiale_Gid *  mailIni) {mailInitial = mailIni;}; 
        
    // lecture des paramètres de l'ordre dans un flux
    void Lecture_parametres_OrdreVisu(UtilLecture & entreePrinc);
    // écriture des paramètres de l'ordre dans un flux
    void Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc);
    
    // def d'une classe à usage interne
    class P_gauss
     { public :
          friend ostream & operator << (ostream & sort, const P_gauss & a)
            { cout << a.elemgeom->TypeGeometrie() << a.elemgeom->TypeInterpolation() << a.elemgeom->Nbi()
                   << " ptinteg " 
                   << a.nom_groupe_pt_integ << a.enu << a.num_maill <<", " ; return sort;};
          P_gauss(): elemgeom(NULL),nom_groupe_pt_integ(""),enu(NU_DDL),num_maill(1) {}; 
          P_gauss(const ElemGeomC0* eg,string nom,Enum_ddl en,const int& num_m):
             elemgeom(eg),nom_groupe_pt_integ(nom),enu(en),num_maill(num_m) {};
          P_gauss(const P_gauss& p):
             elemgeom(p.elemgeom),nom_groupe_pt_integ(p.nom_groupe_pt_integ)
             ,enu(p.enu),num_maill(p.num_maill) {};
             
          bool operator== (const P_gauss& pg) const // égalité uniquement si même elem
                        {return ((pg.elemgeom==this->elemgeom)&&(num_maill==pg.num_maill));}; // géom et même maillage
          bool operator!= (const P_gauss& pg) const // inégalité sur l'élément géom ou 
                        {return (!(pg==(*this)));}; // sur le maillage 
          // les données              
          const ElemGeomC0* elemgeom;
          string nom_groupe_pt_integ;
          Enum_ddl enu;
          // numéro de maillage associé
          int num_maill; 
      };
            
protected :
    // VARIABLES PROTEGEES : 
    bool absolue;       // par défaut on sort en absolue les tenseurs
                        // pour pouvoir correctement les visualiser, même pour les elem 2D
    
    Tableau <List_io < Ddl_enum_etendu > > tabnoeud_type_ddl; // ddl aux noeuds possibles à visualiser
    Tableau < List_io < Ddl_enum_etendu > >  tabnoeud_type_ddl_retenu; // ddl à visualiser
    Tableau <List_io <bool> > choix_var_ddl; // indique si c'est une variation ou le ddl

 Tableau <List_io < Ddl_enum_etendu > > tabnoeud_type_ddlEtendu; // ddl étendu aux noeuds possibles à visualiser
 Tableau <List_io < Ddl_enum_etendu > > tabnoeud_type_ddlEtendu_retenu; // ddl étendu aux noeuds  à visualiser
 // tab de travail: une sous partie de tabnoeud_type_ddlEtendu_retenu,
 // qui ne contient que les grandeurs à accumuler aux noeuds venant des éléments, idem pour les ddl initiauw
 Tableau <List_io < Ddl_enum_etendu > > a_accumuler_tabnoeud_type_ddlEtendu;
 Tableau <List_io < Ddl_enum_etendu > > a_accumuler_tabnoeud_type_ddlEtendu_retenu;

 Tableau <List_io < TypeQuelconque > > tabnoeud_evoluee; // types évolués aux noeuds possibles à visualiser
 Tableau <List_io < TypeQuelconque > > tabnoeud_evoluee_retenu; // types évolués aux noeuds  à visualiser
 // tab de travail: une sous partie de tabnoeud_evoluee_retenu,
 // qui ne contient que les grandeurs à accumuler aux noeuds venant des éléments
 Tableau <List_io < TypeQuelconque > > a_accumuler_tabnoeud_evoluee;
 Tableau <List_io < TypeQuelconque > > a_accumuler_tabnoeud_evoluee_retenu;

 // cas des vecteurs globaux, transférable directement aux noeuds
 List_io < TypeQuelconque >  list_vect_globalPourNoeud; // les vecteurs globaux que l'on peut visualiser
 List_io < TypeQuelconque >  list_vect_globalPourNoeud_retenu; // les vecteurs globaux à visualiser





    Tableau <List_io < Ddl_enum_etendu > > tabelement_type_ddl; // ddl aux elements possibles à visualiser    
    Tableau <List_io < Ddl_enum_etendu > > tabelement_type_ddl_retenu; // ddl aux elements  à visualiser
    
    Tableau <List_io < TypeQuelconque > > tabelement_evoluee; // types evoluee aux elements possibles à visualiser    
    Tableau <List_io < TypeQuelconque > > tabelement_evoluee_retenu; // type evoluee aux elements  à visualiser
    
    Tableau <List_io < TypeQuelconque > > tabelement_typeParti; // types particuliers aux elements possibles à visualiser    
    Tableau <List_io < TypeQuelconque > > tabelement_typeParti_retenu; // types particuliers aux elements  à visualiser

    bool transfert_au_noeud; // indique si oui ou non on transfert aux noeuds
    int cas_transfert; // indique la méthode utilisée pour le transfert aux noeuds

    const Mail_initiale_Gid * mailInitial;  // pour une jonction avec le maillage initial
    LesMaillages * lesMail; // les maillages 
    
    bool ddlSurY_1D ; // indique pour chaque maillage dans le cas 1D si l'on veut les ddl selon y plutôt que x
    
 //--- variables internes pour la sortie Ddl_enum_etendu, de grandeurs quelconque évoluées ou non aux pt d'integ ------
    // dans gid il n'y a pas de notion de maillage, il y a une seule liste de noeud et une seule liste d'éléments
    // (par contre je défini un groupe d'élément particulier pour chaque maillage mais ça n'intervient pas ici en post-traitement)
    // donc on a donc a définir 
    // 1) des groupes de pt_integ : qui indique combien et quel type de répartition ont un groupe de pt d'integ.
    //                              Le groupe est identifié par un nom = "nom de ptgauss", mais au moment de l'écriture (donc de la
    //                              définition du groupe pour gid) on n'indique pas quels sont les grandeurs (ddl) que l'on va écrire
    //                              pour ce groupe, on peut donc ainsi utiliser un même groupe pour plusieurs grandeurs.
    //                              Le nom de groupe contient le numéro du maillage, donc les noms de groupe sont différents pour 
    //                              chaque maillage. Le groupe de pt d'intég contient le  ddl de référence, auquel peuvent se rattacher
    //                              plusieurs ddl secondaires (provenant des types évolués, ou particulier) mais qui sont 
    //                              calculé aux mêmes pt d'integ que le ddl de base.
    
    // 2) des listes de grandeurs à sortir pour un groupes de pt_integ donné, ces listes peuvent être différentes pour chaque maillage
    //
    // --- au bilan on a en stockage globale: ---
    // li_P_gauss_total: contient tous les noms de groupe de pt integ différent et l'élément géométrique associé (nb pt etc), 
    //                   et le  ddl associé
    // tab_point_enum:  permet a partir du ddl de retrouver un élément de li_P_gauss_total associé
    // map_gauss_base:  permet de connaitre pour un nom_groupe_pt_integ donné, la liste des Ddl_enum_etendu à sortir 
    // map_gauss_baseEVol: idem pour les grandeurs évoluées
    // map_gauss_basePQ: idem pour les grandeurs quelconques
    // map_gauss_tab_baseEVol et map_gauss_tab_basePQ : définissent des tableaux de npt conteneurs associés 
    //                                                   à map_gauss_tab_baseEVol et map_gauss_tab_basePQ, ceci pout une manipulation
    //                                                   globale de toutes les grandeurs à tous les pt d'integ d'un groupe
    //     En fait quand on calcul les grandeurs aux pt d'integ, on les stocke dans le tableau (donc l'élément de 
    //     map_gauss_tab_baseEVol ou map_gauss_tab_basePQ) au lieu de la liste map_gauss_baseEVol ou map_gauss_basePQ. Donc le véritable
    //     conteneur c'est le tableau (les 2), les listes initiales (élément de  map_gauss_baseEVol ou map_gauss_basePQ) ne servent que
    //     1) pour les entêtes, 2) à savoir s'il y a des grandeurs à considérer ou non, et 3) à construire les tableaux. 
    //                                                 
    // --- maintenant les grandeurs associées à chaque maillage ---
    // tp_tp_tp_gauss_base : tp_tp_tp_gauss_base(imail)(isous_mail) contient tous les groupe de pt d'integ différent pour un 
    //                                                              sous maillage donné
    
    
    // on crée une liste de P_gauss contenant en  autre une
    // référence d'élément géométrique associés aux ddl
    // pour ne pas créer de groupe de pt_integ inutile car identique à un groupe déjà existant. 
    // li_P_gauss contient "tous" les associations "nom de ptgauss" élément géom et un ddl de référence 
    list < P_gauss > li_P_gauss_total;
    // on utilise un même "nom de ptgauss" pour plusieurs ddl, le rassemblement s'effectue dans l'écriture
    
    //  un tableau de travail que l'on dimentionne qu'en locale dans ExeOrdrePremierIncrement
    //    Tableau < P_gauss *> tab_point_enum; // permet de retrouver le P_gauss dans la liste li_P_gauss
          //associé à un enum de base
          // en fait est construit à partir de li_P_gauss_total,  et est indicer par l'énum du P_gauss,
          
    // le tableau des P_gauss représente les groupes de pt de gauss existants (l'enum ici n'a pas d'importance)
    // pointe sur des éléments de li_P_gauss_total
    // donc tp_gauss_base(imail) (ims) (i) = pour le maillage imail, pour le sous_maillage ims, donne la liste des pt_gauss
    // de base qui permettent de générer tous les ddl (de base ou dérivés)
    Tableau < Tableau < Tableau < P_gauss > > > tp_tp_tp_gauss_base;
    // permet de récolter tous les "nom de ptgauss"  utilisé par le maillage imail
    
    // une map pour faire l'association entre le nom du groupe de pt de gauss et la liste
    // de ddl étendue associée
    map < string, List_io < Ddl_enum_etendu > , std::less <string> > map_gauss_base;
    // une map pour faire l'association entre le nom du groupe de pt de gauss et la liste
    // de type quelconque associée contenant les types évolués 
    map < string, List_io < TypeQuelconque > , std::less <string> > map_gauss_baseEVol;
    // idem mais pour un tableau de liste, indicé par le nombre de ptinteg
    map < string, Tableau < List_io < TypeQuelconque > > , std::less <string> > map_gauss_tab_baseEVol;
    
    // une map pour faire l'association entre le nom du groupe de pt de gauss et la liste
    // de type quelconque associée contenant les grandeurs particulières
    map < string, List_io < TypeQuelconque > , std::less <string> > map_gauss_basePQ;
    // idem mais pour un tableau de liste, indicé par le nombre de ptinteg
    map < string, Tableau < List_io < TypeQuelconque > > , std::less <string> > map_gauss_tab_basePQ;

 //--- fin variables internes pour la sortie Ddl_enum_etendu et type quelconque aux pt d'integ ------
 
 //--- variables internes pour la sortie aux noeuds ------
     // pour les sorties aux noeuds because Gid ne sait pas gérer plusieurs maillages, on globalise toutes les sorties
    // et on definit un tableau de booléen qui indique si oui ou non la grandeur est à sortir en fonction des tableaux
    //  tabelement_type_ddl_retenu, tabelement_evoluee_retenu, tabelement_typeParti_retenu
    
    // .. pour les ddl  aux noeuds 
    List_io < Ddl_enum_etendu >  glob_noe_ddl_retenu; // le global
    Tableau <List_io < bool > > t_g_noeud_ddl_asortir;
    
    // .. pour les ddl étendues définis aux noeuds
    List_io < Ddl_enum_etendu >  glob_noeud_ddl_etendu_retenu; // le global
    Tableau <List_io < bool > > t_g_noeud_ddl_etendu_asortir;
    // .. pour les types évoluées définis aux noeuds
    List_io < TypeQuelconque >  glob_noeud_evol_retenu; // le global
    Tableau <List_io < bool > > t_g_noeud_evoluee_asortir;

    // .. pour les ddl venant d'un transfert aux noeuds des grandeurs aux pt d'integ
    List_io < Ddl_enum_etendu >  glob_elem_ddl_retenu; // le global
    Tableau <List_io < bool > > t_g_elem_ddl_asortir;
    // .. pour les types évoluées venant d'un transfert aux noeuds des grandeurs aux pt d'integ
    List_io < TypeQuelconque >  glob_elem_evol_retenu; // le global
    Tableau <List_io < bool > > t_g_elem_evoluee_asortir;
    // .. pour les types particuliers aux elements venant d'un transfert aux noeuds
    List_io < TypeQuelconque >  glob_elem_Parti_retenu; // le global
    Tableau <List_io < bool > > t_g_elem_typeParti_asortir;
    // .. globalise tous les types quelconques ...
    Tableau <List_io < TypeQuelconque > * > tab_quelconque;
    
    //  -- particularités liées aux contacts: dont les grandeurs sont stockées aux noeuds
    // la liste suivante contient les infos choisies restreintes aux contacts
    List_io < TypeQuelconque > li_glob_restreinte_TQ;

    
//--  fin variables internes pour la sortie aux noeuds ------
 
    
    // METHODES PROTEGEES :
          
    // constructeur utilisé par les classes dérivées
    // en fait il s'agit de transmettre directement les infos à la classe mère Visu
    Isovaleurs_Gid(const string& comment_som, const string& explication
                              , const string& ordre) :
                    OrdreVisu(comment_som,explication,ordre) 
                              {};
      
    // définition interactives des paramètres généraux des isovaleurs
    void ParametresGeneraux(const string& choix);
    // choix de l'isovaleur à visualiser calculée à partir des noeuds
    void ChoixIsovaleur_noeud(const string& choix);
    // choix de l'isovaleur à visualiser calculée à partir des ddl etendu aux noeuds
    void ChoixIsovaleur_ddl_etendu_noeud(const string& choix);
    // choix de l'isovaleur à visualiser calculée à partir de grandeurs évoluées aux noeuds
    void ChoixIsovaleur_evoluee_noeud(const string& choix);
    // choix de l'isovaleur à visualiser calculée à partir des ddl aux points d'intégrations
    void ChoixIsovaleur_ddl_ptinteg(const string& choix);
    // choix de l'isovaleur à visualiser calculée à partir des grandeurs évoluées aux points d'intégrations
    void ChoixIsovaleur_tensorielle_ptinteg(const string& choix);
    // choix de l'isovaleur à visualiser calculée à partir des grandeurs quelconques aux points d'intégrations
    void ChoixIsovaleur_quelc_ptinteg(const string& choix);
    // choix de grandeur existantes aux points d'intégrations et à ramener aux noeuds
    // pour préparer une visualisation d'isovaleurs
    void TransfertGrandeursPtIntegAuNoeud();
    // initialisation de l'exécution du  transferts
    void InitPremierIncrExecutionTransfertAuxNoeuds(); 
    // exécution du transfert 
    void ExecutionTransfert();
    // vérification que le transfert peut se faire (pas de doublon de grandeurs)
    void VerificationTransfertPossible();
    // sortie de l'entête des isovaleurs de grandeurs definis aux pt integ pour des grandeurs quelconques
    // et également tout simplement aux noeuds
    // sert pour les sorties aux pt integ et aux noeuds
    // -- 1) le programme général quelque soit la structure (simple, tableau, list ... ) de la grandeur quelconque
    // drap_noeud = false  ---> sortie aux pt integ, =true  ---> sortie aux noeuds
    void EnteteSortieIsovaleurs_G_Quelconque(ostream & sort,TypeQuelconque& typ,bool drap_noeud);
    // -- 2) le programme spécifique pour "une" grandeur de base (utilisé en 1))
    void EnteteSortieIsovaleurs_G_Quelconque_TYPE_SIMPLE(ostream & sort,const TypeQuelconque::Grandeur& grandeur
                                                                ,const string nom_typeQuelconque,int dima);
       
     // -- 3) le programme spécifique pour "une" grandeur de base à un noeud (utilisé en 1))
     void EnteteSortieIsovaleursNoeud_G_Quelconque_TYPE_SIMPLE
                (ostream & sort,const TypeQuelconque::Grandeur& grandeur
                 ,const string nom_typeQuelconque,int dima);

                                                                
    // sortie d'une grandeurs quelconque aux pt integ ou aux noeuds
    // -- a) le programme général quelque soit la structure (simple, tableau, list ... ) de la grandeur quelconque
    void SortieGrandeursQuelconque(ostream & sort,const TypeQuelconque& typ);
    // -- b) le programme spécifique pour "une" grandeur de base (utilisé en a))
    void SortieGrandeursQuelconque_TYPE_SIMPLE(ostream & sort,const TypeQuelconque::Grandeur& grandeur,int dima);
    // initialisation les différentes listes internes qui globalisent tous les maillages
    void GlobalisationListSurTousLesMaillagesPourLesNoeuds();
    // exeoOrdre: cas du premier increments
    void ExeOrdrePremierIncrement(const Tableau <int>& tab_mail,LesMaillages * lesMail,ostream &sort);
    // écriture des grandeurs aux points d'intégration
    void EcritureAuxPtInteg(const Tableau <int>& tab_mail,LesMaillages * lesMail
                           ,ostream &sort,int incre);                                 
    // écriture des grandeurs aux noeuds
    void EcritureAuxNoeuds(const Tableau <int>& tab_mail,LesMaillages * lesMail
                           ,ostream &sort,int incre);


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

#endif