// FICHIER : Met_Sfe1.h
// CLASSE : Met_Sfe1

// 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:        04/10/2007                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:   La classe Met_Sfe1 est une classe derivee de la classe    *
 *            Met_abstraite  et permet de realiser tous les calculs     *
 *            particuliers lies a la metrique d'un element Sfe.         *
 *            N.B. : La dimension de l'espace des points est 3,         *
 *            et le nombre de vecteur est :                             *
 *              - uniquement 2, les 2 vecteurs de surfaces, s'il n'y    *
 *                pas de degré de liberté d'épaisseur aux noeuds        * 
 *              - 3 = 2 vecteurs de surfaces + un vecteur parallèle     * 
 *                à la normale : cas où il                              * 
 *                y a un degré de liberté d'épaisseur.                  * 
 *                                                                $     * 
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     * 
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/


#ifndef MET_SFE1_H
#define MET_SFE1_H

#include "Met_abstraite.h"
#include "TabOper_T.h"
#include "Coordonnee3.h"
#include "Tenseur2.h"
#include "Enum_interpol.h"
#include "EnuTypeCL.h"
#include "Epai.h"
#include "Util.h"
#include "MathUtil.h"

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


class Met_Sfe1 : public Met_abstraite
{


	public :


		// CONSTRUCTEUR :
		
		// Constructeur par defaut
		Met_Sfe1 ();	
	 // constructeur permettant de dimensionner uniquement certaine variables
	 // dim = dimension de l'espace, ici forcément = 3
	 //  nbvec = nb de vecteur des bases, tab = liste des variables a initialiser
  Met_Sfe1 ( const DdlElement& tabddl,int nbvec
	           ,const  Tableau<Enum_variable_metrique>& tabb, Enum_interpol enui
	           ,int nb_noeud_central);
		// constructeur de copie
		Met_Sfe1 ( const Met_Sfe1&);
		// DESTRUCTEUR :
		
		virtual ~Met_Sfe1 ();
		
	// METHODES PUBLIQUES :
	
  // Surcharge de l'operateur = : realise l'affectation
  // dérivant de virtuel, a ne pas employer -> message d'erreur
	 Met_abstraite& operator= (const Met_abstraite& met);
	 // normale
  virtual Met_Sfe1& operator= (const Met_Sfe1& met);
     
  // affichage minimale des éléments de métrique de base
  virtual void Affiche() const;

	 // attribution de l'indicateur de type de calcul de jacobien:
	 // =1: le jacobien = celui de la facette médiane sans courbure
	 // =2: le jacobien = celui de la facette médiane + la courbure actuelle
	 void ChangeTypeCalculJacobien(int nouveau_type);
		        		        
//==================================================================================================
// définition de différentes classes conteneurs, utilisés pour ramener les résultats après calcul |
//  ici spécifique au cas des éléments sfe (en plus des conteneurs déjà définis dans Met_abstraite.h)
#include "Met_Sfe1_struc_donnees.h"         
//==================================================================================================

	    //  ------------------------ calculs ----------------------------------------
	    // cas explicite à t, toutes les grandeurs sont a 0 ou t
	    // calcul des termes : gijBB_0,	 gijBB_t, gijHH_t, d_gijBB_t,jacobien
	    // il y a l'interpolation d'épaisseur en plus par rapport à la  fonction originale ds met_abstraite
	    // 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	    
		const Met_abstraite::Expli& CalSfe1_explicit_t( const Tableau<Noeud *>& tab_noeud,bool gradV_instantane
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,bool premier_calcul,Mat_pleine const & tabdphiH,Vecteur const& tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
	    // calcul simplifie, a utiliser lorsque l'on se sert des grandeurs
	    // liers a la facette deja calculee, ainsi que la courbure
	    // 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	    
		const Met_abstraite::Expli& CalSfe1_explicit_simple_t( const Tableau<Noeud *>& tab_noeud,bool gradV_instantane
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,bool premier_calcul,Mat_pleine const & tabdphiH,Vecteur const& tabphiH,const Epai* epais);
	    // cas explicite à tdt, toutes les grandeurs sont a 0 ou t
	    // calcul des termes : gijBB_0,	 gijBB_t, gijHH_t, d_gijBB_t,jacobien
	    // il y a un parametre de plus (phi) que dans la fonction originale ds met_abstraite
	    // 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	    
		const Met_abstraite::Expli_t_tdt& CalSfe1_explicit_tdt( const Tableau<Noeud *>& tab_noeud,bool gradV_instantane
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,bool premier_calcul,Mat_pleine const & tabdphiH,Vecteur const& tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
	    // calcul simplifie, a utiliser lorsque l'on se sert des grandeurs
	    // liers a la facette deja calculee, ainsi que la courbure
	    // 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	    
		const Met_abstraite::Expli_t_tdt& CalSfe1_explicit_simple_tdt( const Tableau<Noeud *>& tab_noeud,bool gradV_instantane
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,bool premier_calcul,Mat_pleine const & tabdphiH,Vecteur const& tabphiH,const Epai* epais);
        // récup du conteneur Expli_t_dtFac : c'est-à-dire des infos de la FACETTE !!!
        virtual const Expli_t_tdt& Conteneur_Expli_tdtFac() const {return ex_expli_t_tdtFac;};
		// cas implicite
		// calcul des termes de la classe impli 	
	    // 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	    
		const Met_abstraite::Impli& CalSfe1_implicit( const Tableau<Noeud *>& tab_noeud,bool gradV_instantane
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,bool premier_calcul,Mat_pleine const & tabdphiH,Vecteur const& tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
	    // calcul simplifie, a utiliser lorsque l'on se sert des grandeurs
	    // liers a la facette deja calculee, ainsi que la courbure et sa variation
	    // 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	    
		const Met_abstraite::Impli& CalSfe1_implicit_simple( const Tableau<Noeud *>& tab_noeud,bool gradV_instantane
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,bool premier_calcul,Mat_pleine const & tabdphiH,Vecteur const& tabphiH,const Epai* epais);
		        		        
		// ---------------- 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);
  // --------------- test sur la courbure ------------------------------
  // test si la courbure est anormalement trop grande
  // inf_normale : indique en entrée le det mini pour la courbure en locale
  // retour 1:  si tout est ok,
  //        0:  une courbure trop grande a été détecté
  int Test_courbure_anormale(Enum_dure temps,double inf_normale, const  Tableau<Noeud *>& tab_noeud
                             ,const  Mat_pleine& dphiS,int nombre_noeud,const Vecteur& phiS);
 
		// -------------- remontee aux informations -------------------------- 
		
		// cas sortie d'infoImp
		// calcul des termes de la classe InfoImp 	
		const Met_abstraite::InfoImp& CalSfe1_InfoImp( const Tableau<Noeud *>& tab_noeud
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,Mat_pleine const & tabdphiH,Vecteur const & tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
		// cas sortie d'infoExp
		// calcul des termes de la classe InfoExp_t 	
		const Met_abstraite::InfoExp_t& CalSfe1_InfoExp_t( const Tableau<Noeud *>& tab_noeud
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,Mat_pleine const & tabdphiH,Vecteur const & tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
		// calcul des termes de la classe InfoExp_tdt 	
		const Met_abstraite::InfoExp_tdt& CalSfe1_InfoExp_tdt( const Tableau<Noeud *>& tab_noeud
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,Mat_pleine const & tabdphiH,Vecteur const & tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
		// calcul des termes de la classe Info0_t_tdt 	
		virtual const Info0_t_tdt& CalSfe1_Info0_t_tdt( const Tableau<Noeud *>& tab_noeud
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,Mat_pleine const & tabdphiH,Vecteur const & tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
		                           
		// cas du calcul de la déformation d'Almansi uniquement
		virtual const Pour_def_Almansi CalSfe1_pour_def_Almansi_au_temps
		     (Enum_dure temps,const Tableau<Noeud *>& tab_noeud
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,Mat_pleine const & tabdphiH,Vecteur const & tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
		// cas du calcul de la déformation logarithmique uniquement
		virtual const Pour_def_log CalSfe1_pour_def_log_au_temps
		     (Enum_dure temps,const Tableau<Noeud *>& tab_noeud
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,Mat_pleine const & tabdphiH,Vecteur const & tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
		          
		// ========== utilise par le contact et autres =========================
		// calcul d'un point M  en fonction des phi et des coordonnees a 0
		virtual const Coordonnee & PointSfe1M_0 // ( stockage a t=0)
		  (const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS,Mat_pleine const & dphiS
		   ,const Epai* epais, const Vecteur& phiH);
		  
		// calcul d'un point M  en fonction des phi et des coordonnees a t
		virtual const Coordonnee & PointSfe1M_t // ( stockage a t=t)
		  (const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS,Mat_pleine const & dphiS
		  ,const Epai* epais, const Vecteur& phiH);
/*
		// calcul de la variation d'un point M  par rapport aux ddl , 
		// en fonction des phi et des coordonnees a t
		virtual const Tableau<Coordonnee> & D_PointSfe1M_t // ( stockage a t)
		  ( const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS,Mat_pleine const & dphiS
		  ,const double& epais_t, const Vecteur& phiH)
*/		  
		// calcul d'un point M  en fonction des phi et des coordonnees a tdt
		virtual const Coordonnee & PointSfe1M_tdt // ( stockage a tdt)
		  (const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS,Mat_pleine const & dphiS
		  ,const Epai* epais, const Vecteur& phiH);
/*
		// calcul de la variation d'un point M  par rapport aux ddl , 
		// en fonction des phi et des coordonnees a tdt
		virtual const Tableau<Coordonnee> & D_PointSfe1M_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 & VitesseSfe1M_0 // ( stockage a t=0)
		  (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
		// idem mais au noeud passé en paramètre  
		virtual const Coordonnee & VitesseSfe1M_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 & VitesseSfe1M_t // ( stockage a t=t)
		  (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
		// idem mais au noeud passé en paramètre  
		virtual const Coordonnee & VitesseSfe1M_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_VitesseSfe1M_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_VitesseSfe1M_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 & VitesseSfe1M_tdt // ( stockage a tdt)
		  (const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
		// idem mais au noeud passé en paramètre  
		virtual const Coordonnee & VitesseSfe1M_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_VitesseSfe1M_tdt (const Noeud* noeud,bool ddl_vitesse);
		  
		// calcul de la base naturel , au point correspondant  au dphi en fonction des coord a t=0
		 virtual const BaseB& BaseSfe1Nat_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& BaseSfe1Nat_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& BaseSfe1Nat_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 BaseSfe1ND_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 BaseSfe1ND_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 BaseSfe1ND_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
	 void PlusInitVariables(Tableau<Enum_variable_metrique>& tab) ;
	 
	 // ---------- récupération particulière à la courbure -------------
	 // doit être utilisé après une méthode qui calcul toutes les grandeurs en questions !!!!! 
	 const Met_Sfe1::Courbure_t_tdt& RecupCourbure () const {return courbure_t_tdt;};

	// ============================ protege ===========================
	
	protected :									  
	// METHODES protegees:						  
    // calcul des normales a la facette		  
    void Calcul_N_0();
    void Calcul_N_t();
    void Calcul_N_tdt();
       
    //== calcul des variations de la normales
    void Cal_d_N_t(); // il faut avant le calcul des ap_alpha_t et de épaisseur à t
    void Cal_d_N_tdt(); // il faut avant le calcul des ap_alpha_tdt et de épaisseur à tdt

    //==  calcul de N,alpha (sur la surface courbe) pour les différents temps
    void Cal_N_alpha_0() 
       {N_alpha_0_1.ConstructionAPartirDe_H( -(curb_0(1,1) * (*aiH_0)(1) + curb_0(1,2) * (*aiH_0)(2)));  
        N_alpha_0_2.ConstructionAPartirDe_H( -(curb_0(2,1) * (*aiH_0)(1) + curb_0(2,2) * (*aiH_0)(2)));};
    void Cal_N_alpha_t() 
       {N_alpha_t_1.ConstructionAPartirDe_H( -(curb_t(1,1) * (*aiH_t)(1) + curb_t(1,2) * (*aiH_t)(2)));  
        N_alpha_t_2.ConstructionAPartirDe_H( -(curb_t(2,1) * (*aiH_t)(1) + curb_t(2,2) * (*aiH_t)(2)));};
    void Cal_N_alpha_tdt() 
       {N_alpha_tdt_1.ConstructionAPartirDe_H( -(curb_tdt(1,1) * (*aiH_tdt)(1) + curb_tdt(1,2) * (*aiH_tdt)(2)));  
        N_alpha_tdt_2.ConstructionAPartirDe_H( -(curb_tdt(2,1) * (*aiH_tdt)(1) + curb_tdt(2,2) * (*aiH_tdt)(2)));};

    //==  calcul de la variation de N,alpha
    void Cal_d_N_alpha_t(); // il faut la courbure, la variation de la courbure, aH et d_aH
    void Cal_d_N_alpha_tdt();

    //==calcul des points, identique a Met_abstraite
	   // calcul du point a t0
    void Calcul_M0 ( const Tableau<Noeud *>& , const  Vecteur& phi, int );
    void Calcul_Mt ( const Tableau<Noeud *>& ,  const Vecteur& phi, int );
    void Calcul_Mtdt ( const Tableau<Noeud *>& ,  const Vecteur& phi, int );
		   	    	    	         
	//== le nombre de vecteur de base pour les Sfe1 est soit 2: cas historique, sans ddl d'épaisseur
	//   soit 3: cas avec ddl d'épaisseurs à chaque noeud
	//== certaines fonctions de calcul de base sont donc redefini
	    // -- calcul des bases médianes : tout d'abord la partie a_alpha
		  void Calcul_a_alpha_B_0(const Tableau<Noeud *>& tab_noeud
		            , const  Mat_pleine& tabDphi, int nombre_noeud,const Vecteur& phi);
		  void Calcul_a_alpha_B_t(const Tableau<Noeud *>& tab_noeud
		            , const  Mat_pleine& tabDphi, int nombre_noeud,const Vecteur& phi);
		  void Calcul_a_alpha_B_tdt(const Tableau<Noeud *>& tab_noeud
		            , const  Mat_pleine& tabDphi, int nombre_noeud,const Vecteur& phi);
	    // -- calcul du vecteur a3 des  bases médianes 
	     // nécessite auparavant d'avoir calculé la normale et l'épaisseur
		  void Calcul_a_3_B_0() {(aiB_0)->CoordoB(3) = N_0 * (epais.epaisseur0 * 0.5);};
		  void Calcul_a_3_B_t() {(aiB_t)->CoordoB(3) = N_t * (epais.epaisseur_t * 0.5);};
		  void Calcul_a_3_B_tdt() {(aiB_tdt)->CoordoB(3) = N_tdt * (epais.epaisseur_tdt * 0.5);}; 
		 
    //==  calcul de la variation des bases sur la surface médiane
    // ici il ne s'agit uniquement que de la variation de a_alpha et pas a_3
    void D_a_alpha_B_t( const  Mat_pleine& tabDphi, 
                       int nbnoeu,const  Vecteur & phi); // avant calcul de : a_alpha_B_t
    void D_a_alpha_B_tdt( const  Mat_pleine& tabDphi,
                         int nbnoeu,const  Vecteur & phi); // avant calcul de : a_alpha_B_tdt
    //==  calcul de la variation de a_3_B
		  void D_a_3_B_t();
		  void D_a_3_B_tdt();                             
                            
	    
    // -- calcul des bases dans l'épaisseur
		  // calcul de la base naturel a t0
    // pendant le traitement il y a calcul de la base aiB et aiH de la facette plane, et éventuellement
    // les 3ième vecteur (proportionnelle à la normale) s'il y a un ddl d'épaisseur
    // la fonction contiend un argument de plus que la routine dans met_abstraite
		  void Calcul_giB_0 (  const  Tableau<Noeud *>& ,  const Mat_pleine& ,
		                    int,  const Vecteur& phi);
		  // calcul de la base naturel a t
		  void Calcul_giB_t (  const  Tableau<Noeud *>& , const  Mat_pleine& ,
		                    int, const   Vecteur& phi); 
		  // calcul de la base naturel a t+dt
		  void Calcul_giB_tdt (  const  Tableau<Noeud *>& , const  Mat_pleine& ,
		                    int,  const  Vecteur& phi);
    //==  calcul de la variation des bases
    void D_giB_t( const  Mat_pleine& , int ,  const  Vecteur & phi); 
    void D_giB_tdt( const  Mat_pleine& , int ,  const  Vecteur & phi);
     
    // cas des épaisseurs interpolées
    void Calcul_epaisseur_0(const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS);    
    void Calcul_epaisseur_t(const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS);    
    void Calcul_epaisseur_tdt(const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS);
    // calcul de la variation de l'épaisseur par rapport aux ddl         
    void D_epaisseur_t(const  Vecteur& phiS);
    void D_epaisseur_tdt(const  Vecteur& phiS);
         
    //-----------// calcul du tenseur de courbure  dans la base naturelle
    // on utilise un tenseur non symétrique, bien qu'en théorie la courbure est symétrique
    // suivant les différentes méthodes de calcul, le tenseur en sortie est symétrique ou pas
    // on peut toujours le symétriser, si l'on veut un tenseur symétrique
    // on a : N,al = - b_{al be} . a^{be}
    // plusieurs cas sont etudies suivant l'instant considere
    // a l'instant t = 0
    Tenseur_ns2BB& courbure_0 ( const Tableau<Noeud *>& tab_noeud
                               ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // a l'instant t 
    Tenseur_ns2BB& courbure_t ( const Tableau<Noeud *>& tab_noeud
                               ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // a l'instant t+dt
    Tenseur_ns2BB& courbure_tdt ( const Tableau<Noeud *>& tab_noeud
                              ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    //--------------// calcul du tenseur de courbure et de sa variation 
    // plusieurs cas sont etudies suivant l'instant considere
    // a l'instant t 
    void Dcourbure_t( const Tableau<Noeud *>& tab_noeud,Tenseur_ns2BB& curb,TabOper<Tenseur_ns2BB>& dcurb
                     ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // a l'instant tdt 
    void Dcourbure_tdt( const Tableau<Noeud *>& tab_noeud,Tenseur_ns2BB& curb,TabOper<Tenseur_ns2BB>& dcurb
                       ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
		   
    // DONNEES PROTEGEES
       
    Tableau <Coordonnee3> Ia; // base absolue
    // calcul de la courbure et de sa variation eventuelle
	   Tenseur_ns2BB curb_0,curb_t,curb_tdt;
	   TabOper<Tenseur_ns2BB> dcurb_t,dcurb_tdt;
	   // calcul de la normale
	   Coordonnee3B N_0,N_t,N_tdt;
	   double norme_N_t, norme_N_tdt; // norme des normales
	   // variation de N_t et N_tdt
	   Tableau < CoordonneeB > * d_N_t, * d_N_tdt;
	   //N,alpha pour les différents temps 
    CoordonneeB  N_alpha_0_1,N_alpha_0_2,N_alpha_t_1,N_alpha_t_2,N_alpha_tdt_1,N_alpha_tdt_2;
    // variation de N,alpha
    Tableau < CoordonneeB > * d_N_alpha_t_1, * d_N_alpha_t_2; // variation par rapport aux Xi de N(t),1 et ,2
    Tableau < CoordonneeB > * d_N_alpha_tdt_1, * d_N_alpha_tdt_2; // idem pour N(tdt)
       
	   int nbNoeudCentral; // nombre de noeud de l'élément central
	   bool tCalEpais; // indique le type de prise en compte de l'épaisseur
	                  // = 0 : épaisseur constante (n'est pas un ddl) passée en paramètre
	                  // = 1 : épaisseur = un ddl stocké au noeud
	   // épaisseurs : soit contient les épaisseurs passées en paramètres d'entrée (tCalEpais = 0)
	   //              soit contient les épaisseurs données interpolées aux noeuds (tCalEpais = 1)
	   Epai  epais; // le conteneur d'épaisseur à 0, t et tdt
	   Tableau <Epai> * d_epais; // variation des épaisseurs
	   // indicateur de type de calcul de jacobien finale :
	   // =1: le jacobien = celui de la facette médiane sans courbure
	   // =2: le jacobien = celui de la facette médiane + la courbure actuelle
       // =3: le jacobien = celui du volume = facette * épaisseur, cas d'une métrique 3D
	   int type_calcul_jacobien;
	   
       //il s'agit ici des infos concernant l'élément centrale, et sur la surface médiane
      
	   Coordonnee3 * P0;  // point a t=0
	   Coordonnee3 * Pt ;  // point a l'instant t
	   Coordonnee3 * Ptdt; // point a l'instant t+dt        BaseB Ia; // la base absolu
	   Tableau <Coordonnee3> * d_Pt ;  // derivées au point a l'instant t, par rapport aux ddl
	   Tableau <Coordonnee3> * d_Ptdt; // derivées au point a l'instant t+dt, par rapport aux ddl
    	    
	   BaseB * aiB_0 ; // base naturelle a t=0
	   BaseB * aiB_t ; // base naturelle a t
	   BaseB * aiB_tdt ; // base naturelle a t+dt
	   
	   BaseH * aiH_0; // vecteur de la base duale a 0
	   BaseH * aiH_t; // vecteur de la base duale a t
	   BaseH * aiH_tdt; // vecteur de la base duale a t+dt
	   
	   TenseurBB * aijBB_0; // composantes de la metrique de la base naturelle a t
    TenseurBB * aijBB_t; // composantes de la metrique de la base naturelle a t
    TenseurBB * aijBB_tdt; // composantes de la metrique de la base naturelle a tdt
    TenseurHH * aijHH_0; // composantes de la metrique de la base duale a t=0
    TenseurHH * aijHH_t; // composantes de la metrique de la base duale a t
    TenseurHH * aijHH_tdt; // composantes de la metrique de la base duale a t+dt
                              
    double ajacobien_0; // jacobien de la facette centrale sans courbure a l'instant t=0
    double ajacobien_t; // jacobien de la facette centrale sans courbure  a l'instant t
    double ajacobien_tdt; // jacobien de la facette centrale sans courbure  a l'instant t+dt

    Tableau <BaseB> * d_aiB_t; // derivees de la base naturelle par rapport 
                // aux degres de liberte a t
    Tableau <BaseB> * d_aiB_tdt; // derivees de la base naturelle par rapport 
                  // aux degres de liberte a t+dt
                  
    Tableau <BaseH> * d_aiH_t; // derivees de la base duale par rapport 
                // aux degres de liberte a t					       
    Tableau <BaseH> * d_aiH_tdt; // derivees de la base duale par rapport 
                 // aux degres de liberte a t+dt
       
    Tableau <TenseurBB * >  d_aijBB_t;// derivees de la metrique de la base naturelle 
                  // a t par rapport aux degres de liberte
    Tableau <TenseurBB * >  d_aijBB_tdt;// derivees de la metrique de la base naturelle 
                    // a t+dt par rapport aux degres de liberte
    Tableau <TenseurHH * >  d_aijHH_t; // derivees de la metrique de la base duale a t
    Tableau <TenseurHH * >  d_aijHH_tdt; // derivees de la metrique de la base duale a t+dt
    
    Vecteur d_ajacobien_t ; // derivees a t du jacobien de la facette centrale sans courbure
             // par rapport aux degres de liberte
    Vecteur d_ajacobien_tdt ; // derivees a tdt du jacobien de la facette centrale sans courbure
                     // par rapport aux degres de liberte 
                     
    // maintenant définition des différents conteneurs de retour des méthodes globales
    // **** ici il s'agit de contenir les infos liées à la facette !!!! *******
    // maintenant définition des différents conteneurs de retour des méthodes globales
    // contrairement au cas de metabstraite
    Courbure_t_tdt courbure_t_tdt;  // cas du calcul de la courbure
  		Impli ex_impliFac;  // cas d'un calcul implicite
  		Expli ex_expliFac;  // calcul explicite 0 t
  		Expli_t_tdt ex_expli_t_tdtFac; // calcul explicite 0 t tdt
  		gijHH_0_et_giH_0 ex_aijHH_0_et_aiH_0Fac; // comme le nom l'indique !
  		Dynamiq ex_DynamiqFac; // calcul pour la dynamique	(partie spécifique à quelques grandeurs)
  		flambe_lin ex_flambe_linFac; // grandeurs pour le flambement linéaire
  		Umat_cont  umat_contFac; // calcul relatif aux Umat						           
  		InfoImp ex_InfoImpFac; // sortie d'info en implicite
  		InfoExp_t ex_InfoExp_tFac; // sortie d'info en explicite à t
  		InfoExp_tdt ex_InfoExp_tdtFac; // sortie d'info en explicite à tdt		           
  		Info0_t_tdt ex_Info0_t_tdtFac; // sortie d'info à 0 t et tdt
  
	   // quelques variables statiques
	   static Tableau <int> indi; // pour de l'indiçage indirecte
    // indicateur utilisé par Verif_Dcourbure
    static int indic_Verif_DcourbureSFE; 

	   // pointeurs des fonctions en cours
    Tenseur_ns2BB (Met_Sfe1::*PtCourbure) ( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH & aiH 
                                   ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    void (Met_Sfe1::*PtDcourbure) (  const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
                                   , const Tableau <BaseB>& DaiB,const BaseH & aiH
                                   , const Tableau <BaseH>& DaiH,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
                                   ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // test si la courbure est anormalement trop grande
    // inf_normale : indique en entrée le det mini pour la courbure en locale
    // retour 1:  si tout est ok,
    //        0:  une courbure trop grande a été détecté
    int (Met_Sfe1::*PtTest_courbure_anormale)(double inf_normale,const Tableau<Coordonnee3>& tab_coor
                                 , const BaseB & aiB , const BaseH & aiH);
 
    // fonctions privees
		  // allocation de la memoire
		  void AllocSfe1 ();
	   // deallocation de la memoire complète, uniquement des grandeurs spécifiques
	   // à Met_Sfe1
	   void DeallocSfe1();               
	   // uniquement des grandeurs de tib            
	   void DeallocSfe1(Tableau<Enum_variable_metrique>& tib); 
	   // copie en fonction de l'instance passée
	   // concerne que les grandeurs pointées
	   void Copie_metSfe1(const  Met_Sfe1& a);              
    // ----------- routines internes pour calculer les différentes formes de courbures 
    // routines (1) generales de calcul de la courbure
    // cas 1: calcul des 3 courbures suivant les 3 cotés
    Tenseur_ns2BB Courbure1
     ( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH & aiH 
                 ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // routine generale de calcul de la courbure et de sa variation
    // en sortie : curb , la courbure  b11,b12,b22
    //            dcurb , la variation de courbure.
    // cas 1: calcul des 3 courbures suivant les 3 cotés
    void Dcourbure1 (  const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
                    , const Tableau <BaseB>& DaiB,const BaseH & aiH
                    , const Tableau <BaseH>& DaiH,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
                    ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // test si la courbure est anormalement trop grande
    // inf_normale : indique en entrée le det mini pour la courbure en locale
    // retour 1:  si tout est ok,
    //        0:  une courbure trop grande a été détecté
    int Test_courbure_anormale1(double inf_normale,const Tableau<Coordonnee3>& tab_coor
                                 , const BaseB & aiB , const BaseH & aiH);

    // routine (2) generale de calcul de la courbure
    // cas 2: moyenne des normales de part et autres des arrêtes
    Tenseur_ns2BB Courbure2
     ( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH & aiH 
                 ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // routine generale de calcul de la courbure et de sa variation
    // en sortie : curb , la courbure  b11,b12,b22
    //            dcurb , la variation de courbure.
    // cas 2: moyenne des normales de part et autres des arrêtes
    void Dcourbure2 (  const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
                    , const Tableau <BaseB>& DaiB,const BaseH & aiH
                    , const Tableau <BaseH>& DaiH,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
                    ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // test si la courbure est anormalement trop grande
    // inf_normale : indique en entrée le det mini pour la courbure en locale
    // retour 1:  si tout est ok,
    //        0:  une courbure trop grande a été détecté
    int Test_courbure_anormale2(double inf_normale,const Tableau<Coordonnee3>& tab_coor
                                 , const BaseB & aiB , const BaseH & aiH);

    // routine (3) generale de calcul de la courbure
    // cas 3: moyenne pondérée des normales de part et autres des arrêtes, et localisation du point sur l'arrête
    Tenseur_ns2BB Courbure3
     ( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH & aiH 
                 ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // routine (3) generale de calcul de la courbure et de sa variation
    // en sortie : curb , la courbure  b11,b12,b22
    //            dcurb , la variation de courbure.
    // cas 3: moyenne pondérée des normales de part et autres des arrêtes, et localisation du point sur l'arrête
    void Dcourbure3 (  const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
                    , const Tableau <BaseB>& DaiB,const BaseH & aiH
                    , const Tableau <BaseH>& DaiH,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
                    ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // test si la courbure est anormalement trop grande
    // inf_normale : indique en entrée le det mini pour la courbure en locale
    // retour 1:  si tout est ok,
    //        0:  une courbure trop grande a été détecté
    int Test_courbure_anormale3(double inf_normale,const Tableau<Coordonnee3>& tab_coor
                                 , const BaseB & aiB , const BaseH & aiH);

    // routine (4) generale de calcul de la courbure
    // cas 4: calcul de la courbure à partir d'un polynôme passant par les 6 points
    Tenseur_ns2BB Courbure4
     ( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH & aiH 
                 ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // routine (4) generale de calcul de la courbure et de sa variation
    // en sortie : curb , la courbure  b11,b12,b22
    //            dcurb , la variation de courbure.
    // cas 4: calcul de la courbure à partir d'un polynôme passant par les 6 points
    void Dcourbure4 (  const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
                    , const Tableau <BaseB>& DaiB,const BaseH & aiH
                    , const Tableau <BaseH>& DaiH,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
                    ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);

    // test si la courbure est anormalement trop grande
    // inf_normale : indique en entrée le det mini pour la courbure en locale
    // retour 1:  si tout est ok,
    //        0:  une courbure trop grande a été détecté
    int Test_courbure_anormale4(double inf_normale,const Tableau<Coordonnee3>& tab_coor
                                 , const BaseB & aiB , const BaseH & aiH);
    
    // programme de vérification par différences finies des dérivées
    void Verif_Dcourbure( const Tableau<Noeud *>& tab_noeud,bool gradV_instantane
		          ,Mat_pleine const & tabdphiS,int nombre_noeud,Vecteur const & tabphiS
		          ,Mat_pleine const & tabdphiH,Vecteur const& tabphiH,const Epai* epais
		          ,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan);
    // initialisation des conteneurs de retour des méthodes
    void Init_conteneur_de_retour_pourFacette();
	                   
		
};
/// @}  // end of group


#endif
		
		
