
// 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:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT: Met_abstraite constitue une boite a outil qui permet        *
 *   d'otenir  les diverses grandeurs liées a la metrique.              *
 *  Se rappeler qu'avant la recuperation d'une grandeur il faut la      *
 *  calculer* En phase de mise au point c'a-d avec l'existence de la    *
 *  variable MISE_AU_POINT il y a verification des tailles etc, en phase*
 *  normale il n'y a plus de verif !                                    *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/

#ifndef MET_ABSTRAITE_H
#define MET_ABSTRAITE_H

#include <math.h>
#include "ParaGlob.h"
#include "DdlElement.h"
#include "Mat_pleine.h"
#include "Tableau_3D.h"
#include "Tenseur.h"
#include "NevezTenseur.h"
#include "Base.h"
#include "Noeud.h"
#include "Tableau2_T.h"
#include "Enum_variable_metrique.h"
#include "Enum_dure.h"

/** @defgroup groupe_des_metrique
*
*     BUT: Met_abstraite constitue une boite a outil qui permet
*   d'otenir  les diverses grandeurs liées a la metrique.
*  Se rappeler qu'avant la recuperation d'une grandeur il faut la
*  calculer* En phase de mise au point c'a-d avec l'existence de la
*  variable MISE_AU_POINT il y a verification des tailles etc, en phase
*  normale il n'y a plus de verif !
* La metrique est concue pour etre commune a toute une classe d'element
* d'ou une gestion de la memoire particuliere, vu la taille des different tableaux
* en fonctionnement normal les methodes ne testent pas les differentes tailles et si
* les tableaux sont correctement alloue ce qui impose de bien gerer l'allocation
* a l'aide du constructeur et des routines public de gestion, ceci a chaque changement
* de pb par exemple pasage d'explicit a implicit
*
*
* \author    Gérard Rio
* \version   1.0
* \date       23/01/97
* \brief       groupe relatif aux calculs de métriques
*
*/

/// @addtogroup groupe_des_metrique
///  @{
///


// la metrique est concue pour etre commune a toute une classe d'element
// d'ou une gestion de la memoire particuliere, vu la taille des different tableaux
// en fonctionnement normal les methodes ne testent pas les differentes tailles et si 
// les tableaux sont correctement alloue ce qui impose de bien gerer l'allocation
// a l'aide du constructeur et des routines public de gestion, ceci a chaque changement
// de pb par exemple pasage d'explicit a implicit


class Met_abstraite
{	
	public :
	         
	    // Constructeur par defaut
	    Met_abstraite ();
	    // constructeur permettant de dimensionner uniquement certaines variables
	    // dim = dimension de l'espace, nbvec = nb de vecteur des bases, tab = liste
	    // des variables a initialiser
	    Met_abstraite (int dim_base,int nbvec_base,const DdlElement& tabddl,
	                   const Tableau<Enum_variable_metrique>& tab,int nomb_noeud
	                   ,int nbddl_sup_xi = 0);
	    // Constructeur de copie :
	     Met_abstraite (const Met_abstraite& );
              
		   // DESTRUCTEUR VIRTUEL :
		
      virtual ~Met_abstraite ();
     // METHODES PUBLIQUES :
        // Surcharge de l'operateur = : realise l'affectation
	    virtual Met_abstraite& operator= (const Met_abstraite& met);
     
     // affichage minimale des éléments de métrique de base
     virtual void Affiche() const;
     
	    //  ------------------------ calculs ----------------------------------------
	    
//==================================================================================================
// définition des différentes classes conteneurs, utilisés pour ramener les résultats après calcul |
#include "Met_abstraite_struc_donnees.h"          
//==================================================================================================
	    	    
	    // calcul de Expli: cas  entre 0 et t, toutes les grandeurs sont a 0 ou t
	    // gradV_instantane : true : calcul du gradient de vitesse instantannée 
     // premier_calcul : true : cas d'un premier calcul -> toutes les grandeurs sont calculées
     //                  false: uniquement les grandeurs à t+dt sont calculées
		   virtual const Expli& Cal_explicit_t(const  Tableau<Noeud *>& tab_noeud,bool gradV_instantane, const Mat_pleine& tabDphi,
		                     int nombre_noeud,const Vecteur& phi,bool premier_calcul);
	    // calcul de Expli_t_tdt cas explicite entre t=0 et tdt, toutes les grandeurs sont a 0 ou tdt
	    // gradV_instantane : true : calcul du gradient de vitesse instantannée 
     // premier_calcul : true : cas d'un premier calcul -> toutes les grandeurs sont calculées
     //                  false: uniquement les grandeurs à t+dt sont calculées
		   virtual const Expli_t_tdt& Cal_explicit_tdt(const  Tableau<Noeud *>& tab_noeud,bool gradV_instantane, const Mat_pleine& tabDphi,
		                             int nombre_noeud,const Vecteur& phi,bool premier_calcul);
     // récup du conteneur Expli_t_dt
     virtual const Expli_t_tdt& Conteneur_Expli_tdt() const {return ex_expli_t_tdt;};
     // calcul de impli. Par défaut tous les termes de variation sont calculés (le D...)
     // mais dans certain cas ils ne sont pas nécessaire. le paramétre avec_D est alors
     // a mettre à false et le calcul de toutes les variations est omis 	
	    // gradV_instantane : true : calcul du gradient de vitesse instantannée
     // premier_calcul : true : cas d'un premier calcul -> toutes les grandeurs sont calculées
     //                  false: uniquement les grandeurs à t+dt sont calculées
     // avec_var_Xi  : par défaut true, si false indique que l'on ne calcule pas les variations / au ddl Xi
		   virtual const Impli& Cal_implicit(const  Tableau<Noeud *>& tab_noeud,bool gradV_instantane, const  Mat_pleine& tabDphi,
		           int nombre_noeud,const Vecteur& phi,bool premier_calcul,bool avec_var_Xi = true);
     // calcul de gijHH_0 et de giH_0 juste après le calcul implicite ou explicite (sinon il y a erreur)
     virtual const gijHH_0_et_giH_0& Cal_gijHH_0_et_giH_0_apres_im_expli(); 
     // récupération de grandeurs sauvegardées par ailleurs à 0 et t(et non les pointeurs)
     void Recup_grandeur_0_t(BaseB & ggiB_0,BaseH & ggiH_0,BaseB & ggiB_t,BaseH& ggiH_t
                           ,TenseurBB& ggijBB_0,TenseurHH& ggijHH_0,TenseurBB& ggijBB_t,TenseurHH& ggijHH_t
                           ,TenseurBB & ggradVmoyBB_t,double& gjacobien_t,double& gjacobien_0)
          {ex_impli.Recup_grandeur_0_t(ggiB_0,ggiH_0,ggiB_t,ggiH_t,ggijBB_0,ggijHH_0,ggijBB_t
                                            ,ggijHH_t,ggradVmoyBB_t,gjacobien_t,gjacobien_0);
          }; // met à jour en même temps tous les autres conteneurs pour les grandeurs équivalentes 
     // récupération de grandeurs sauvegardées par ailleurs à 0 (et non les pointeurs)
     void Recup_grandeur_0(BaseB & ggiB_0,BaseH & ggiH_0,TenseurBB& ggijBB_0,TenseurHH& ggijHH_0
                           ,double& gjacobien_0) 
          {ex_expli.Recup_grandeur_0(ggiB_0,ggiH_0,ggijBB_0,ggijHH_0,gjacobien_0);
          }; // met à jour en même temps tous les autres conteneurs pour les grandeurs équivalentes 

     // construction d'une métrique umat
     //  - construction d'une métrique qui dépend du paramétrage matériel = X_(0)^a 
     //  - en fonction d'une métrique normale fonction de l'interpolation sur 
     //    les éléments de référence c'est-à-dire theta^i
     virtual const Umat_cont& Construction_Umat(const Met_abstraite::Impli& umat_cont);
     // idem à partir d'une umat_cont
     virtual const Umat_cont& Construction_Umat(const Met_abstraite::Umat_cont& umat_cont);
     // récup du conteneur umat
     virtual const Umat_cont& Conteneur_Umat() const {return umat_cont;};

     // ---------------- cas de la dynamique ----------------------------
     // calcul pour la matrice masse
     virtual const Dynamiq& Cal_pourMatMass(const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi
                                  ,int nombre_noeud,const Vecteur& phi);
     //  ------------------------ flambage linéaire ------------------------------
     // calcul des termes de la classe flambe_lin 	
     virtual const flambe_lin& Cal_flambe_lin(const  Tableau<Noeud *>& tab_noeud,bool gradV_instantane, const  Mat_pleine& tabDphi,
                int nombre_noeud,const Vecteur& phi,bool premier_calcul)
      { return (flambe_lin&) Cal_implicit(tab_noeud,gradV_instantane,tabDphi,nombre_noeud
                                             ,phi,premier_calcul);};          
 
     // ---------------- calcul de données interpolées aux même points d'integ que  la mécanique -------- 
     //       et utilisées par la mécanique (ex: température, taux de cristalinité, vitesse, etc..)    
     virtual double DonneeInterpoleeScalaire
                   (const  Tableau<Noeud *>& tab_noeud,const Vecteur& phi,int nombre_noeud
                    ,Enum_ddl enu,Enum_dure temps) const;
     // --------- calcul de la variation d'une donnée interpolée par rapport aux ddl de la donnée ------
     //       aux même points d'integ que  la mécanique --------
     //       et utilisées par la mécanique (ex: température, taux de cristalinité, vitesse, etc..)
     // en sortie : d_A
     virtual Tableau <double >&  DerDonneeInterpoleeScalaire
                  (Tableau <double >& d_A, const  Tableau<Noeud *>& tab_noeud,const Vecteur& phi
                  ,int nombre_noeud,Enum_ddl enu) const;
     // ---------------- calcul du gradient d'une donnée interpolée aux même points d'integ que  la mécanique --------
     //       et utilisées par la mécanique (ex: température, taux de cristalinité, vitesse, etc..)
     // en sortie : gradB
     virtual CoordonneeB& GradDonneeInterpoleeScalaire
                  (CoordonneeB& gradB,const  Tableau<Noeud *>& tab_noeud,const  Mat_pleine& dphi
                  ,int nombre_noeud,Enum_ddl enu,Enum_dure temps) const;

     // --------- calcul de la variation du gradient d'une donnée interpolée par rapport aux ddl de la donnée ------
     //       aux même points d'integ que  la mécanique --------
     //       et utilisées par la mécanique (ex: température, taux de cristalinité, vitesse, etc..)
     // en sortie : d_gradB
     virtual Tableau <CoordonneeB >& DerGradDonneeInterpoleeScalaire
             (Tableau <CoordonneeB >& d_gradB,const  Tableau<Noeud *>& tab_noeud
              ,const Vecteur& phi,const  Mat_pleine& dphi,int nombre_noeud,Enum_ddl enu) const;
     // --------- calcul de la variation seconde du gradient d'une donnée interpolée par rapport aux ddl de la donnée ------
     //       aux même points d'integ que  la mécanique --------
     //       et utilisées par la mécanique (ex: température, taux de cristalinité, vitesse, etc..)
     // en sortie : d2_gradB
     //  si d2_gradB est NULL cela signifie qu'il ne faut pas considérer cette grandeur
     virtual Tableau2 <CoordonneeB>*  Der2GradDonneeInterpoleeScalaire
               (Tableau2 <CoordonneeB>* d2_gradB,const  Tableau<Noeud *>& tab_noeud
              ,const Vecteur& phi,const  Mat_pleine& dphi,int nombre_noeud,Enum_ddl enu) const;
//     Vecteur& DonneeInterpoleeVecteur
//                      (const  Tableau<Noeud *>& tab_noeud,const Vecteur& phi,int nombre_noeud
//                       ,Enum_ddl enu,Vecteur& v, Enum_dure temps);

     // ------- variation seconde de la métrique --------
     //   calcul et récupération de la variation seconde de la métrique à t+dt
     //   total = true : indique que le calcul est complet, à partir des données de base 
     //                  c-a-d calcul de la variation de vecteur de base puis calcul de la variation seconde
     //         = false: le calcul est simplifié, on considère que la variation des vecteurs de base vient
     //                  juste d'être calculé, dans un calcul implicit, on ne calcul alors que la variation seconde
     const Tableau2 <TenseurBB * > & CalVar2GijBBtdt(bool total,const  Mat_pleine& dphi,int nombre_noeud,const Vecteur& phi);
 

     // ========== remontee aux informations =========================
     
     // cas sortie d'infoImp
     // calcul des termes de la classe InfoImp 	
     virtual const InfoImp& Cal_InfoImp(const Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,
                                  const  Vecteur& phi, int nombre_noeud);
     // récup du conteneur qui a déjà été calculé                             
     virtual const InfoImp& Recup_InfoImp() {return ex_InfoImp;}; 
                                  
     // cas sortie d'infoExp à 0 et t
     // calcul des termes de la classe InfoExp 	
     virtual const InfoExp_t& Cal_InfoExp_t(const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,
                                const   Vecteur& phi, int nombre_noeud);
     // récup du conteneur qui a déjà été calculé                             
     virtual const InfoExp_t& Recup_InfoExp_t() {return ex_InfoExp_t;}; 
                                
     // cas sortie d'infoExp à 0 et tdt
     // calcul des termes de la classe InfoExp 	
     virtual const InfoExp_tdt& Cal_InfoExp_tdt(const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,
                                const   Vecteur& phi, int nombre_noeud);
     // récup du conteneur qui a déjà été calculé                             
     virtual const InfoExp_tdt& Recup_InfoExp_tdt() {return ex_InfoExp_tdt;}; 
                                
     // cas sortie d'info à 0 t et tdt: point, giB, giH, calcul des termes de la classe Info0_t_tdt 	
     virtual const Info0_t_tdt& Cal_Info0_t_tdt(const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi
                                        ,const   Vecteur& phi, int nombre_noeud);
     // récup du conteneur qui a déjà été calculé                             
     virtual const Info0_t_tdt& Recup_Info0_t_tdt() {return ex_Info0_t_tdt;};
 
     // récup du conteneur avec métrique qui a déjà été calculé
     virtual const Info_et_metrique_0_t_tdt& Recup_Info_et_metrique_0_t_tdt() {return umat_cont;};

     // cas du calcul de la déformation d'Almansi uniquement
     class Pour_def_Almansi{public: TenseurBB * gijBB;TenseurBB * gijBB_0;
            Pour_def_Almansi(): gijBB(NULL), gijBB_0(NULL) {};  
            Pour_def_Almansi(const Pour_def_Almansi& a ) : gijBB(a.gijBB), gijBB_0(a.gijBB_0) {}; 
            };
     virtual const Pour_def_Almansi Cal_pour_def_Almansi_au_temps
          (Enum_dure temps,const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& dphi
          ,int nombre_noeud,const Vecteur& phi); 
     // cas du calcul de la déformation logarithmique uniquement
     class Pour_def_log{public: TenseurBB * gijBB;TenseurHH * gijHH;TenseurBB * gijBB_0;TenseurHH * gijHH_0;
                        Pour_def_log():gijBB(NULL),gijHH(NULL),gijBB_0(NULL),gijHH_0(NULL) {};   
                        Pour_def_log(const Pour_def_log& a) : 
                           gijBB(a.gijBB),gijHH(a.gijHH),gijBB_0(a.gijBB_0),gijHH_0(a.gijHH_0) {};
                         };
     virtual const Pour_def_log Cal_pour_def_log_au_temps
          (Enum_dure temps,const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& dphi
          ,int nombre_noeud,const Vecteur& phi); 
                                  
     // ========== utilise par le contact et autres =========================
     // calcul d'un point M en fonction de phi et des coordonnees a 0
     virtual const Coordonnee & PointM_0 // ( stockage a t=0)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
       
     // calcul d'un point M en fonction de phi et des coordonnees a t
     virtual const Coordonnee & PointM_t // ( stockage a t=t)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);

     // calcul de la variation d'un point M par rapport aux ddl , 
     // en fonction de phi et des coordonnees a t
     virtual const Tableau<Coordonnee> & D_PointM_t // ( stockage a t)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
       
     // calcul d'un point M en fonction de phi et des coordonnees a tdt
     virtual const Coordonnee & PointM_tdt // ( stockage a tdt)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);

     // calcul de la variation d'un point M par rapport aux ddl , 
     // en fonction de phi et des coordonnees a tdt
     virtual const Tableau<Coordonnee> & D_PointM_tdt // ( stockage a tdt)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);

     // calcul de la vitesse du point M en fonction de phi et des coordonnees a 0
           // dans le cas où les ddl de vitesse existent, ils sont directement interpolés
           // dans le cas où ils n'existent pas, on utilise les vitesses moyennes : delta M / delta t 
     virtual const Coordonnee & VitesseM_0 // ( stockage a t=0)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
     // idem mais au noeud passé en paramètre  
     virtual const Coordonnee & VitesseM_0 (const Noeud* noeud);
       
     // calcul de la vitesse du point M en fonction de phi et des coordonnees a t
           // dans le cas où les ddl de vitesse existent, ils sont directement interpolés
           // dans le cas où ils n'existent pas, on utilise les vitesses moyennes : delta M / delta t 
     virtual const Coordonnee & VitesseM_t // ( stockage a t=t)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
     // idem mais au noeud passé en paramètre  
     virtual const Coordonnee & VitesseM_t (const Noeud* noeud);

     // calcul de la variation de la vitesse du point M par rapport aux ddl , 
     // en fonction de phi et des coordonnees a t
           // dans le cas où les ddl de vitesse existent, ils sont directement interpolés
           // dans le cas où ils n'existent pas, on utilise les vitesses moyennes : delta M / delta t
           // ddl_vitesse : indique si oui ou non il s'agit de variation par rapport 
           //               aux ddl de vitesse ou au ddl de position 
     virtual const Tableau<Coordonnee> & D_VitesseM_t // ( stockage a t)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi,bool ddl_vitesse);
     // idem mais au noeud passé en paramètre  
     virtual const Tableau<Coordonnee> & D_VitesseM_t (const Noeud* noeud,bool ddl_vitesse);
       
     // calcul de la vitesse du point M en fonction de phi et des coordonnees a tdt
           // dans le cas où les ddl de vitesse existent, ils sont directement interpolés
           // dans le cas où ils n'existent pas, on utilise les vitesses moyennes : delta M / delta t 
           // ddl_vitesse : indique si oui ou non il s'agit de variation par rapport 
           //               aux ddl de vitesse ou au ddl de position 
     virtual const Coordonnee & VitesseM_tdt // ( stockage a tdt)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
     // idem mais au noeud passé en paramètre  
     virtual const Coordonnee & VitesseM_tdt (const Noeud* noeud);

     // calcul de la variation de la vitesse du point M par rapport aux ddl , 
     // en fonction de phi et des coordonnees a tdt
           // dans le cas où les ddl de vitesse existent, ils sont directement interpolés
           // dans le cas où ils n'existent pas, on utilise les vitesses moyennes : delta M / delta t 
           // ddl_vitesse : indique si oui ou non il s'agit de variation par rapport 
           //               aux ddl de vitesse ou au ddl de position 
     virtual const Tableau<Coordonnee> & D_VitesseM_tdt // ( stockage a tdt)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi,bool ddl_vitesse);
     // idem mais au noeud passé en paramètre  
     virtual const Tableau<Coordonnee> & D_VitesseM_tdt (const Noeud* noeud,bool ddl_vitesse);

     // calcul de l'accélération du point M en fonction de phi et des coordonnees a 0
           // dans le cas où les ddl d'accélération existent, ils sont directement interpolés
           // sinon erreur
     virtual const Coordonnee & AccelerationM_0 // ( stockage a t=0)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
     // idem mais au noeud passé en paramètre
     virtual const Coordonnee & AccelerationM_0 (const Noeud* noeud);
       
     // idem à t
     virtual const Coordonnee & AccelerationM_t // ( stockage a t=t)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
     // idem mais au noeud passé en paramètre
     virtual const Coordonnee & AccelerationM_t (const Noeud* noeud);
     
     // idem à tdt
     virtual const Coordonnee & AccelerationM_tdt // ( stockage a tdt)
       (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
     // idem mais au noeud passé en paramètre
     virtual const Coordonnee & AccelerationM_tdt (const Noeud* noeud);
     
     // vérification existance des conteneurs d'accélérations
     bool Existe_conteneur_acceleration0() const {return (gamma0 ==NULL) ? false : true; };
     bool Existe_conteneur_accelerationt() const {return (gammat ==NULL) ? false : true; };
     bool Existe_conteneur_accelerationtdt() const {return (gammatdt ==NULL) ? false : true; };
     bool Existe_conteneur_acceleration() const
       {return ((gammatdt ==NULL)||(gammat ==NULL)||(gamma0 ==NULL)) ? false : true; }
     // calcul de la base naturel , au point correspondant  au dphi en fonction des coord a t=0
     virtual const BaseB& BaseNat_0  // ( stockage a t=0)
       (const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& tabDphi,const Vecteur& phi);

     // calcul de la base naturel , au point correspondant  au dphi en fonction des coord a t
     virtual const BaseB& BaseNat_t  // ( stockage a t)
       (const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& tabDphi,const Vecteur& phi);

     // calcul de la base naturel , au point correspondant  au dphi en fonction des coord a tdt
     virtual const BaseB& BaseNat_tdt // ( stockage a tdt)
       (const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& tabDphi,const Vecteur& phi);
       
     // calcul de la variation de la base naturel, au point correspondant  au dphi en fonction des coord a tdt
     // nécessite que la base naturelle ait été calculée auparavant
     virtual const Tableau <BaseB>& d_BaseNat_tdt // ( stockage a tdt)
       (const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& tabDphi,const Vecteur& phi);
       
     // calcul de la base naturelle et duale ( stockage a t=0) en fonction des coord a 0 
     virtual void BaseND_0(const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& tabDphi,
                            const Vecteur& phi,BaseB& bB,BaseH& bH);
      
     // calcul de la base naturelle et duale ( stockage a t) en fonction des coord a t 
     virtual void BaseND_t(const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& tabDphi,
                            const Vecteur& phi,BaseB& bB,BaseH& bH);
      
     // calcul de la base naturelle et duale ( stockage a tdt) en fonction des coord a tdt 
     virtual void BaseND_tdt(const Tableau<Noeud *>& tab_noeud,const  Mat_pleine& tabDphi,
                              const Vecteur& phi,BaseB& bB,BaseH& bH);

     // ====== informations diverses (mais cohérentes, c-a-d, peuvent être appelées directement sans init) ====
     double JacobienInitial(const  Tableau<Noeud *>& tab_noeud,const Mat_pleine& tabDphi
                             ,int nombre_noeud,const Vecteur& phi);
       
     //   ------------------------ gestion de la memoire -------------------------- 
            
        // Ajout d'initialisation de differentes variables : liste dans tab
	    virtual void PlusInitVariables(Tableau<Enum_variable_metrique>& tab) ;
	    // initialisation de la dimension , du nb de vecteur et du tableau de ddl
	    // cette fonction n'agi qu'une fois , lors des autres appels elle ne fait rien
	    virtual void Dim_NbVec(int dim_base,int nbvec_base,DdlElement & tabddl,int nb_noeud_interpol);
	    // ramène les informations de taille utilisées par la classe
	    const int & Dim_vec_base() const {return dim_base;}; // dimension des vecteurs de base
	    const int & Nbvec_des_bases() const {return nbvec_base;}; // nb de vecteur des bases
	    const int & Nombre_de_noeud() const {return nomb_noeud;}; // nombre de noeud de l'interpolation
	    const DdlElement& Tab_ddl_element() const {return tab_ddl;};  // tableau de ddl de l'element

  //============================ Methodes protegees ================================
  protected:
    //==calcul des points, par defaut la dimension des points est celle du probleme
    //==  transmise par ParaGlob	
    // calcul du point a t0
    virtual void Calcul_M0
       ( const Tableau<Noeud *>& tab_noeud,const Vecteur& phi, int nombre_noeud);
    // calcul du point a t
    virtual void Calcul_Mt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // calcul des variations du point a t
    virtual void Calcul_d_Mt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // calcul du point a tdt
    virtual void Calcul_Mtdt
       (const Tableau<Noeud *>& tab_noeud,const  Vecteur& phi, int nombre_noeud);
    // calcul des variations du point a tdt
    virtual void Calcul_d_Mtdt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
       
    // calcul de la vitesse du point a t0 en fonction des ddl existants de vitesse
    virtual void Calcul_V0
       ( const Tableau<Noeud *>& tab_noeud,const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_V0 (const Noeud* noeud);
    // calcul de la vitesse du point a t en fonction des ddl existants de vitesse
    virtual void Calcul_Vt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_Vt (const Noeud* noeud);
    // calcul des variations de la vitesse du point a t en fonction des ddl existants de vitesse
    virtual void Calcul_d_Vt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_d_Vt (const Noeud* noeud);
    // calcul de la vitesse du point a tdt en fonction des ddl existants de vitesse
    virtual void Calcul_Vtdt
       (const Tableau<Noeud *>& tab_noeud,const  Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_Vtdt (const Noeud* noeud);
    // calcul des variations de la vitesse du point a tdt en fonction des ddl existants de vitesse
    virtual void Calcul_d_Vtdt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_d_Vtdt (const Noeud* noeud);
                      
    // calcul de la vitesse moyenne du point a t0 en fonction des ddl de position
    virtual void Calcul_V_moy0
       ( const Tableau<Noeud *>& tab_noeud,const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_V_moy0 (const Noeud* noeud);
    // calcul de la vitesse moyenne du point a t en fonction des ddl de position 
    virtual void Calcul_V_moyt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_V_moyt (const Noeud* noeud);
    // calcul des variations de la vitesse moyenne du point a t en fonction des ddl de position 
    virtual void Calcul_d_V_moyt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_d_V_moyt (const Noeud* noeud);
    // calcul de la vitesse moyenne du point a tdt en fonction des ddl de position 
    virtual void Calcul_V_moytdt
       (const Tableau<Noeud *>& tab_noeud,const  Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_V_moytdt (const Noeud* noeud);
    // calcul des variations de la vitesse moyenne du point a tdt en fonction des ddl de position
    virtual void Calcul_d_V_moytdt
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre  
    virtual void Calcul_d_V_moytdt (const Noeud* noeud);
    
    //--- cas des accélérations
    // calcul de l'accélération du point a t0 en fonction des ddl existants d'accélération
    virtual void Calcul_gamma0
       ( const Tableau<Noeud *>& tab_noeud,const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre
    virtual void Calcul_gamma0 (const Noeud* noeud);
    // idem a t
    virtual void Calcul_gammat
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre
    virtual void Calcul_gammat (const Noeud* noeud);
    // idem à tdt
    virtual void Calcul_gammatdt 
       (const  Tableau<Noeud *>& tab_noeud, const Vecteur& phi, int nombre_noeud);
    // idem mais au noeud passé en paramètre
    virtual void Calcul_gammatdt (const Noeud* noeud);

    //== par defaut le nombre de vecteur de base est celui de la dimension du
    //== probleme transmis par paraglob
    // calcul de la base naturel a t0
    virtual void Calcul_giB_0
       (const Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi, int nombre_noeud,const Vecteur& phi);
    // calcul de la base naturel a t
    virtual void Calcul_giB_t
       (const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,int nombre_noeud,const Vecteur& phi); 
    // calcul de la base naturel a t+dt
    virtual void Calcul_giB_tdt
       (const Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,int nombre_noeud,const Vecteur& phi);
                 
    //== par defaut la metrique est de type (nbvecteurdela base)au carre
    //== ce qui permet d'avoir une metrique 2*2 en 3D
    //== !! neccessite d'avoir calcule la base naturelle corespondante auparavant
    // Calcul des composantes covariantes de la metrique de la base naturelle a 0 :
    virtual void Calcul_gijBB_0 () ;
    // Calcul des composantes covariantes de la metrique de la base naturelle a t :
    virtual void Calcul_gijBB_t () ;
    // Calcul des composantes covariantes de la metrique de la base naturelle a tdt :
    virtual void Calcul_gijBB_tdt () ;
       // Calcul des composantes contravariantes de la metrique de la base naturelle a 0 :
    virtual void Calcul_gijHH_0 () ;
    // Calcul des composantes contravariantes de la metrique de la base naturelle a t :
    virtual void Calcul_gijHH_t () ;
    // Calcul des composantes contravariantes de la metrique de la base naturelle a tdt :
    virtual void Calcul_gijHH_tdt () ;
 
    //== par défaut le gradient de vitesse est de type (nbvecteurdela base)au carre
    //== nécessite d'avoir calculé les vecteurs giB avant 	
    // calcul du gradient de vitesse à t
    virtual void Calcul_gradVBB_t
       (const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,int nombre_noeud); 
    // calcul gradient de vitesse à t+dt
    virtual void Calcul_gradVBB_tdt
       (const Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,int nombre_noeud);
    //== dans le cas où il n'y a pas de ddl de vitesse on peut utiliser les vitesses moyennes
    //== correspondant à delta x^ar/delta t 
    // calcul du gradient de vitesse moyen à t
          // dans le cas où les ddl à tdt n'existent pas -> utilisation de la  vitesse sécante entre 0 et t !!
    virtual void Calcul_gradVBB_moyen_t
       (const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,int nombre_noeud); 
    // calcul du gradient de vitesse moyen entre t et t+dt
    virtual void Calcul_gradVBB_moyen_tdt 
       (const  Tableau<Noeud *>& tab_noeud, const  Mat_pleine& tabDphi,int nombre_noeud); 
 
    //== par defaut le nombre de vecteur de la base duale est identique
    //== a celui de la base naturelle ainsi on peu etre es 3d est avoir uniquement
    //== un seul vecteur de base (cas d'une biellette par exemple
    //== mais il faut surcaharger le cacul de la base
    //   !!! important : il est necessaire de calculer les composantes covariantes
    //   puis contravariantes de la metrique avant de calculer les bases duales	   
    // calcul de la base duale a t0
    virtual void Calcul_giH_0();
    // calcul de la base duale a t
    virtual void Calcul_giH_t();
    // calcul de la base duale a t+dt
    virtual void Calcul_giH_tdt();
 
    //== calcul du jacobien aux differents temps , il est necessaire d'avoir
    //== calcule le tenseur metrique correspondant
    virtual void Jacobien_0();
    virtual void Jacobien_t();
    virtual void Jacobien_tdt();
        
    //==  calcul de la variation des bases
    //==  par defaut le nombre de ddl est egal a la dimension du pb 
    //==  * le nombre de vecteur de la base
    virtual void D_giB_t( const  Mat_pleine& tabDphi, 
                        int nbnoeu,const  Vecteur & phi); // avant calcul de : giB_t
    virtual void D_giB_tdt( const  Mat_pleine& tabDphi,
                        int nbnoeu,const  Vecteur & phi); // avant calcul de : giB_tdt
    virtual void D_giH_t(); // avant calcul de : d_giB_t et giH_t
    virtual void D_giH_tdt(); // avant calcul de : d_giB_tdt et giH_tdt
 
    //== calcul de la variation du gradient
        // par rapport aux composantes  V^ar (et non les X^ar )	
		  virtual void DgradVBB_t( const  Mat_pleine& dphi); // avant calcul de : giB_t
        // par rapport aux composantes  V^ar (et non les X^ar )	
 		 virtual void DgradVBB_tdt(const  Mat_pleine& dphi); // avant calcul de : giB_tdt
        // par rapport aux composantes  X^ar (et non les V^ar )	
 		 virtual void DgradVmoyBB_t(const  Mat_pleine& dphi,const  Tableau<Noeud *>& tab_noeud); // calcul variation du gradient moyen à t
        // par rapport aux composantes  X^ar (et non les V^ar )	
 		 virtual void DgradVmoyBB_tdt(const  Mat_pleine& dphi); // calcul variation du gradient moyen à tdt

    //==  calcul de la variation des metriques
    virtual void D_gijBB_t();  // avant calcul de :  d_giB_t et giB_t, Prepa_calcul_DgradVmoy_t()
    virtual void D_gijBB_tdt(); // avant calcul de :  d_giB_tdt et giB_tdt, Prepa_calcul_DgradVmoy_tdt()
    virtual void D_gijHH_t(); // avant calcul de :  d_giH_t et giH_t
    virtual void D_gijHH_tdt();// avant calcul de :  d_giH_tdt et giH_tdt

    //==  calcul de la variation seconde des metriques
    // ici on ne considère que la variation première des vecteurs de base, c-a-d que
    // l'on considère que leurs variations secondes sont nulles
    // ce qui est vrai dans le cas d'une cinématique simple
    virtual void D2_gijBB_tdt(); // avant calcul de :  d_giB_tdt et giB_tdt
   
    //==  calcul de la variation des jacobiens
    virtual void Djacobien_t(); // avant calcul de :  d_giB_t et giB_t
    virtual void Djacobien_tdt(); // avant calcul de :  d_giB_tdt et giB_tdt
   
    // donnee protegees
    DdlElement tab_ddl; // tableau de ddl de l'element
    int nbddl_sup_xi; // nombre de ddl supplémentaire à ajouter aux ddl normaux en x,v et gamma
                      // par défaut = 0, mais les classes dérivées ex: les coques
                      // peuvent changer ce nombre, ce qui permet de réserver de la place pour des ddls
                      // spécifiques, exemple l'épaisseur, dans le cas des coques
    int dim_base ; // dimension des vecteurs de base
    int nbvec_base; // nb de vecteur des bases
    int nomb_noeud; // nombre de noeud de l'interpolation
    Tableau<Enum_variable_metrique> tab; // tableau
 
	   Coordonnee * M0;  // point a t=0
	   Coordonnee * Mt ;  // point a l'instant t
	   Coordonnee * Mtdt; // point a l'instant t+dt
	   Tableau <Coordonnee> * d_Mt ;  // derivées au point a l'instant t, par rapport aux ddl
	   Tableau <Coordonnee> * d_Mtdt; // derivées au point a l'instant t+dt, par rapport aux ddl

	   Coordonnee * V0;  // vitesse du point a t=0
	   Coordonnee * Vt ;  // vitesse du point a l'instant t
	   Coordonnee * Vtdt; // vitesse du point a l'instant t+dt
	   Tableau <Coordonnee> * d_Vt ;  // derivées de la vitesse du  point a l'instant t, par rapport aux ddl
	   Tableau <Coordonnee> * d_Vtdt; // derivées de la vitesse du point a l'instant t+dt, par rapport aux ddl
	   
	   Tableau<Coordonnee> V_moy_t,V_moy_tdt; // variable interne: vitesse moyenne à t et tdt en chaque noeud r,
	             // calculé dans le calcul du gradient utilisé, dans le calcul de la variation du gradient moyen
	   BaseB * dmatV_moy_t,* dmatV_moy_tdt; // variable interne: dérivée par rapport au repère
	              // matériel (d/dteta_i) au point interpolé
               
    Coordonnee * gamma0;  // accélération du point a t=0
    Coordonnee * gammat ;  // accélération du point a l'instant t
    Coordonnee * gammatdt; // accélération du point a l'instant t+dt

	   BaseB * giB_0 ; // base naturelle a t=0
	   BaseB * giB_t ; // base naturelle a t
	   BaseB * giB_tdt ; // base naturelle a t+dt
	   
	   BaseH * giH_0; // vecteur de la base duale a 0
	   BaseH * giH_t; // vecteur de la base duale a t
	   BaseH * giH_tdt; // vecteur de la base duale a t+dt
	   
	   TenseurBB * gijBB_0; // composantes de la metrique de la base naturelle a t
    TenseurBB * gijBB_t; // composantes de la metrique de la base naturelle a t
    TenseurBB * gijBB_tdt; // composantes de la metrique de la base naturelle a tdt
    TenseurHH * gijHH_0; // composantes de la metrique de la base duale a t=0
    TenseurHH * gijHH_t; // composantes de la metrique de la base duale a t
    TenseurHH * gijHH_tdt; // composantes de la metrique de la base duale a t+dt
                              
    double jacobien_0; // jacobien a l'instant t=0
    double jacobien_t; // jacobien a l'instant t
    double jacobien_tdt; // jacobien a l'instant t+dt

    Tableau <BaseB> * d_giB_t; // derivees de la base naturelle a t par rapport 
                // aux degres de liberte de position 
    Tableau <BaseB> * d_giB_tdt; // derivees de la base naturelle a t+dt par rapport 
                  // aux degres de liberte  de position 
                  
    Tableau <BaseH> * d_giH_t; // derivees de la base duale a t par rapport 
                // aux degres de liberte de position 					       
    Tableau <BaseH> * d_giH_tdt; // derivees de la base duale a t+dt par rapport 
                 // aux degres de liberte de position 
       
    Tableau <TenseurBB * >  d_gijBB_t;// derivees de la metrique de la base naturelle 
								        // a t par rapport aux degres de liberte de position
    Tableau <TenseurBB * >  d_gijBB_tdt;// derivees de la metrique de la base naturelle
                    // a t+dt par rapport aux degres de liberte de position 
    Tableau2 <TenseurBB * >  d2_gijBB_tdt;// derivees seconde de la metrique de la base naturelle 
                    // a t+dt par rapport aux degres de liberte de position 
    Tableau <TenseurHH * >  d_gijHH_t; // derivees de la metrique de la base duale a t
    Tableau <TenseurHH * >  d_gijHH_tdt; // derivees de la metrique de la base duale a t+dt
    
    Vecteur d_jacobien_t ; // derivees du jacobien à t par rapport aux degres de liberte de position  		
    Vecteur d_jacobien_tdt ; // derivees du jacobien à tdt par rapport aux degres de liberte de position  
    
        // *** convention : grad(i,j) = vi|j ***		
    TenseurBB * gradVmoyBB_t; // composantes du gradient de vitesse moyen à t						           
    TenseurBB * gradVmoyBB_tdt; // composantes du gradient de vitesse moyen à tdt
    TenseurBB * gradVBB_t; // composantes du gradient de vitesse instantatnée à t						           
    TenseurBB * gradVBB_tdt; // composantes du gradient de vitesse instantatnée à tdt
    
    Tableau <TenseurBB * > d_gradVmoyBB_t; // dérivée du gradient de vitesse moyen à t par rapport aux ddl de vitesse						           
    Tableau <TenseurBB * > d_gradVmoyBB_tdt; // dérivée du gradient de vitesse moyen à tdt par rapport aux ddl de vitesse						           
    Tableau <TenseurBB * > d_gradVBB_t; // dérivée du gradient de vitesse instantatnée à t par rapport aux ddl de vitesse						           
    Tableau <TenseurBB * > d_gradVBB_tdt; // dérivée du gradient de vitesse instantatnée à tdt par rapport aux ddl de vitesse	
    
    // maintenant définition des différents conteneurs de retour des méthodes globales
    Impli ex_impli;  // cas d'un calcul implicite
    Expli ex_expli;  // calcul explicite 0 t
    Expli_t_tdt ex_expli_t_tdt; // calcul explicite 0 t tdt
    gijHH_0_et_giH_0 ex_gijHH_0_et_giH_0; // comme le nom l'indique !
    Dynamiq ex_Dynamiq; // calcul pour la dynamique	(partie spécifique à quelques grandeurs)	
    flambe_lin ex_flambe_lin; // grandeurs pour le flambement linéaire
    Umat_cont  umat_cont; // calcul relatif aux Umat						           
    InfoImp ex_InfoImp; // sortie d'info en implicite
    InfoExp_t ex_InfoExp_t; // sortie d'info en explicite à t
    InfoExp_tdt ex_InfoExp_tdt; // sortie d'info en explicite à tdt		           
    Info0_t_tdt ex_Info0_t_tdt; // sortie d'info à 0 t et tdt

    // fonctions privees
        // Calcul des composantes de la metrique d'une base naturelle:
    void  Calcul_gijBB (BaseB & giB,TenseurBB & gijBB) ;
    void  Calcul_giH(BaseB* giB, TenseurHH* gijHH, BaseH * giH);
    //==  Existe, recherche si un element de l'enumeration existe
    // retourne vrai si x appartiend au tableau false sinon
    bool Existe(Tableau<Enum_variable_metrique>& tab,const Enum_variable_metrique& x);
    int posi_tab; // pour le programme exite 
    //==  Existe_num, recherche si un element de l'enumeration existe
    // retourne le numéro si x appartiend au tableau, 0 sinon
    int Existe_num(Tableau<Enum_variable_metrique>& tab,const Enum_variable_metrique& x); 
    // allocation de la memoire
	   void Allocation ();
	   // deallocation de la memoire
	   void Deallocation(); // de toutes les grandeurs  
	   // uniquement des grandeurs de tib            
	   void Deallocation(Tableau<Enum_variable_metrique>& tib); 
	   // copie en fonction de l'instance passée
	   // concerne que les grandeurs pointées
	   void Copie_met(const  Met_abstraite& a);  
	   // initialisation des conteneurs de retour des méthodes
	   void Init_conteneur_de_retour_methode();
	   // changement de nbddl_sup_xi par les classes dérivées
	   void Change_nbddl_sup_xi(int nbddl_sup_xi_new)  {nbddl_sup_xi=nbddl_sup_xi_new;};
	                   
             
};
/// @}  // end of group


#endif
