
// 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: Calcul des differentes grandeurs liee a la deformation      *
 *     des elements sfe1                                                *
 *     La classe fonctionne comme une boite a outil. On y choisit ce    *
 *     dont on a besoin. Bien faire attention a l'ordre d'appel des     *
 *     differentes methodes  lorsque il faut suivre une chronologie.    *
 *     Cette classe calcul mais ne stock pas.                           *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef DEFORMATIONSFE1_H
#define DEFORMATIONSFE1_H

#include "Tableau_T.h"
#include "Met_abstraite.h"
#include "Deformation.h"
#include "Met_Sfe1.h"
#include "EnuTypeCL.h"
#include "Epai.h"

/// @addtogroup groupe_des_deformations
///  @{
///


///     BUT: Calcul des differentes grandeurs liee a la deformation
///     des elements sfe1
///     La classe fonctionne comme une boite a outil. On y choisit ce
///     dont on a besoin. Bien faire attention a l'ordre d'appel des
///     differentes methodes  lorsque il faut suivre une chronologie.
///     Cette classe calcul mais ne stock pas.
///
///
/// \author    Gérard Rio
/// \version   1.0
/// \date       23/01/97

class  DeformationSfe1 :  public Deformation
{
  public :

    
    // CONSTRUCTEURS :
    DeformationSfe1 () ; // par defaut ne doit pas etre utilise -> message
                       // d'erreur en phase de mise au point
    // constructeur normal dans le cas d'un ou de plusieurs pt d'integration
    // tabDphi et tabPhi sont relatifs aux fonctions d'interpolation
    // la terminaison H est relative aux grandeurs d'épaisseur, S pour la surface 
    DeformationSfe1 (Met_abstraite & ,Tableau<Noeud *>& tabnoeud
           ,Tableau <Mat_pleine> const  & tabDphiH,Tableau <Vecteur>  const & tabPhiH
           ,Tableau <Mat_pleine>  const & tabDphiS,Tableau <Vecteur>  const & tabPhiS); 
    // constructeur de copie       
    DeformationSfe1 (const DeformationSfe1 &);
    // DESTRUCTEUR :
    virtual ~DeformationSfe1 ();
    
    // METHODES PUBLIQUES :
//------------------------------------------------------------------------------------
// //   définition d'une classe conteneur spécifique à chaque point ou la déformation 
// //   est calculée

  		class SaveDefResulSfe1  : public Deformation::SaveDefResul
     { friend class Deformation ;friend class  DeformationSfe1;
       public :
        // Constructeurs
        SaveDefResulSfe1(); // constructeur par défaut-> à ne pas utiliser -> message d'erreur
        SaveDefResulSfe1(const Met_abstraite& meta); // le constructeur recevable
        SaveDefResulSfe1(const SaveDefResulSfe1& a); // constructeur de copie
        ~SaveDefResulSfe1(); // destructeur
        
        // surcharge de l'optérateur d'affectation
        virtual SaveDefResul& operator= (const SaveDefResul& a);  // surcharge d'affectation
        
        // affichage des infos
        virtual void Affiche();
        // idem sur un ostream
        virtual void Affiche(ostream& sort);
        //============= lecture écriture dans base info ==========
           // cas donne le niveau de la récupération
           // = 1 : on récupère tout
           // = 2 : on récupère uniquement les données variables (supposées comme telles)
        virtual void Lecture_base_info (istream& ent,const int cas);
           // cas donne le niveau de sauvegarde
           // = 1 : on sauvegarde tout
           // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
        virtual void Ecriture_base_info(ostream& sort,const int cas);
        
        // mise à jour des informations transitoires en définitif, ou l'inverse
        virtual void TdtversT() {meti_a_t = meti_a_tdt;};
        virtual void TversTdt() {meti_a_tdt = meti_a_t;};
        // mise à jour des grandeurs meti_00
        virtual void MiseAJourGrandeurs_a_0(const Met_abstraite * metrique);
        // mise à jour des grandeurs meti_tdt
        virtual void MiseAJourGrandeurs_a_tdt(const Met_abstraite * metrique,const TenseurBB& Deps_BB);
        // il n'y a pas de mise à jour des grandeurs à t, car celles-ci sont mise à jour à l'aide
        // de la méthode TdtversT !!
        
        // lecture des infos des métriques
        const Deformation::Stmet& Meti_a_00() const {return meti_a_00;}
        const Deformation::Stmet& Meti_a_t() const {return meti_a_t;}
        const Deformation::Stmet& Meti_a_tdt() const {return meti_a_tdt;}

        protected :   // VARIABLES PROTEGEES :
        // ici il s'agit des données de la facette, et dans SaveDefResul on met les infos
        // correspondant aux métriques dans  l'épaisseur
   // en fait ne sert à rien d'une manière pratique !!   si pour les calculs de variation d'épaisseur !!!
        Deformation::Stmet meti_a_00,meti_a_t,meti_a_tdt; // les infos à 0 à t et à tdt
     };

    // création d'une instance de SaveDefResulSfe1 et initialisation.
		  virtual SaveDefResul * New_et_Initialise() {return (new SaveDefResulSfe1(*metrique));};
    // affichage des donnees particulieres a l'elements
    // de matiere traite ( c-a-dire au pt calcule)
    virtual void AfficheDataSpecif(ostream& sort,SaveDefResul * a) const {a->Affiche(sort);};
    // met à jour les données spécifiques du point considéré
    void Mise_a_jour_data_specif(Deformation::SaveDefResul* don) {saveDefResul=don;};

//  //  fin de définition relatif à la  classe conteneur spécifique à chaque point  
//  //  ou la déformation est calculée
//------------------------------------------------------------------------------------
	// ========== changement de grandeurs stockees =========================
      
    // définition du déformation du même type, permet d'utiliser des types dérivée surchargé
    virtual Deformation * Nevez_deformation(Tableau <Noeud *> & tabN) const 
      { DeformationSfe1* def = new DeformationSfe1(*this);def->PointeurTableauNoeud(tabN);return def;} ; 
    
    // Surcharge de l'operateur = : realise l'affectation
    // fonction virtuelle
    inline Deformation& operator= (const Deformation& def)
      { return (Deformation::operator=(def));};
      
    // on renseigne les conditions limites éventuelles
    void RenseigneCondLim(const Tableau <EnuTypeCL> & arTypeCL,const Tableau <Coordonnee3>& vpla )
    	                   {tabTypeCL = &arTypeCL; vplan = &vpla;};
    // ==== affichage ====
    // affichage des informations
    virtual void Affiche() const;

    // ========== calcul des raideurs =========================
    // calcul explicit à t : tous les parametres sont des resultats
    virtual const Met_abstraite::Expli&  Cal_explicit_t
                     ( const Tableau <double>& def_equi_t,TenseurBB & epsBB_t,Tableau <TenseurBB *> & d_epsBB
					   ,Tableau <double>&  def_equi,TenseurBB& DepsBB,TenseurBB& DeltaEpsBB,bool premier_calcul);
    // calcul explicit à tdt : tous les parametres sont des resultats
    virtual const Met_abstraite::Expli_t_tdt&  Cal_explicit_tdt
                     (const Tableau <double>& def_equi_t, TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB
							   ,Tableau <double>&  def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB_tdt,bool premier_calcul);
	   // cas implicite
	   const Met_abstraite::Impli& Cal_implicit
         (const Tableau <double>&  def_equi_t,TenseurBB & epsBB_tdt,Tableau <TenseurBB *> & d_epsBB
           ,Tableau <double>&  def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul);
	   
    // ---------------- calcul des variables primaires autre que pour la mécanique --------
    // ------------     donc par de retour relatif aux déformations
    // calcul explicit à t : tous les parametres sont des resultats
    virtual const Met_abstraite::Expli&  Cal_explicit_t(bool premier_calcul);
    // calcul explicit à tdt : tous les parametres sont des resultats
    virtual const Met_abstraite::Expli_t_tdt&  Cal_explicit_tdt(bool premier_calcul);
    // cas implicite
    const Met_abstraite::Impli& Cal_implicit(bool premier_calcul);
    // --------------- 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)
     {return (((Met_Sfe1*) metrique)->Test_courbure_anormale)
                    (temps,inf_normale, *tabnoeud,(*tabDphi)(numInteg_surf),nbNoeud,(*tabPhi)(numInteg_surf));
     };
 
	  // ========== remontee aux informations =========================
 // calcul :
 // M0 : point d'integration numInteg a t = 0
 // Mt ou Mtdt : point d'integration final
 // Aa0 et Aafin : matrice de passage initiale et finale dans un repere ortho tel que
 // la nouvelle base Aa est calculee  par projection de "Ipa" sur Gi
 // gijHH et gijBB : metrique finale
 // Aa(i,a) = Aa^i_{.a}, avec  g^i = Aa^i_{.a} * Ip^a
 // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer

    // cas sortie d'un calcul implicit
    virtual const Met_abstraite::InfoImp RemontImp(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin);
   // idem sans le calcul des matrices de passage
    virtual const Met_abstraite::InfoImp RemontImp();
    // cas sortie d'un calcul explicit à t
    virtual const Met_abstraite::InfoExp_t RemontExp_t(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin);
   // idem sans le calcul des matrices de passage
    virtual const Met_abstraite::InfoExp_t RemontExp_t();
    // cas sortie d'un calcul explicit à tdt
    virtual const Met_abstraite::InfoExp_tdt RemontExp_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin);
   // idem sans le calcul des matrices de passage
    virtual const Met_abstraite::InfoExp_tdt RemontExp_tdt();
    // cas sortie d'un calcul à 0, t et tdt
    virtual const Met_abstraite::Info0_t_tdt Remont0_t_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt);
   // idem sans le calcul des matrices de passage
    virtual const Met_abstraite::Info0_t_tdt Remont0_t_tdt();
    // récupération des infos relatives à la courbure pour 0, t et tdt
    virtual const Met_Sfe1::Courbure_t_tdt& RecupCourbure0_t_tdt()const
             {return ((Met_Sfe1*) metrique)->RecupCourbure();};
                                
    // change le numero d'integration courant
    virtual void ChangeNumInteg(int ni);
    // change les numeros d'integration de surface et d'epaisseur courant
    //  nisurf : nouveau point de surface
    //  niepaiss : nouveau point d'epaisseur
    void ChangeNumIntegSfe1(int nisurf, int niepaiss);
    // gestion du parcours de tous les points d'integration
    void PremierPtInteg();
    bool DernierPtInteg();
    void NevezPtInteg();
    // méthode pour revenir au pti précédant
    virtual void Retour_pti_precedant();

    int Nb_pt_int_surf()const {return (tabPhi->Taille());};
    int Nb_pt_int_epai()const {return (tabPhiH->Taille());};
    // change l'épaisseur stockée, et préparation du stockage si nécessaire
    void Change_epaisseur(const Epai&  epaisse) {*epais=epaisse;};
 
    // calcul de la position dans le repère absolu du point d'intégration
    virtual const Coordonnee& Position_0()  // à t=0
      {return ((Met_Sfe1*) metrique)->PointSfe1M_0(*tabnoeud,(*tabPhi)(numInteg_surf)
                            ,(*tabDphi)(numInteg_surf),epais,(*tabPhiH)(numInteg_ep));};
    virtual const Coordonnee& Position_t() // à t
      {return ((Met_Sfe1*) metrique)->PointSfe1M_t(*tabnoeud,(*tabPhi)(numInteg_surf)
                     ,(*tabDphi)(numInteg_surf),epais,(*tabPhiH)(numInteg_ep));};
    virtual const Coordonnee& Position_tdt() // à t+dt
      {return ((Met_Sfe1*) metrique)->PointSfe1M_tdt(*tabnoeud,(*tabPhi)(numInteg_surf)
                     ,(*tabDphi)(numInteg_surf),epais,(*tabPhiH)(numInteg_ep));};
/*      // calcul de la  variation dans le repère absolu du point d'intégration
    virtual const Tableau <Coordonnee>& Der_Pos_t() // à t
      {return metrique->D_PointM_t(*tabnoeud,(*tabPhi)(numInteg));};
    virtual const Tableau <Coordonnee>& Der_Posi_tdt() // à t+dt
      {return metrique->D_PointM_tdt(*tabnoeud,(*tabPhi)(numInteg));}; */
 
    // détermination des bases de passages (seules les données en entrées et sortie
    // sont utilisées )
    virtual void BasePassage(bool absolue,const BaseB & giB0,const  BaseB & giB,const  BaseH & giH0,
                              const BaseH & giH, Mat_pleine& Aa0,Mat_pleine& Aafin);
    // cas où l'on veut les matrices de passages à 0 t et tdt
    virtual void BasePassage(bool absolue,const BaseB & giB0,const  BaseB & giB_t,const  BaseB & giB_tdt
                            ,const  BaseH & giH0,const BaseH & giH_t,const BaseH & giH_tdt
                            ,Mat_pleine& Aa0,Mat_pleine& Aa_t,Mat_pleine& Aa_tdt);

protected :      
    // VARIABLES PROTEGEES :
    
    Tableau <Mat_pleine>  const * tabDphiH; // derivees des fonctions d'interpolation suivant H
    Tableau <Vecteur>  const * tabPhiH;     // les fonctions d'interpolation suivant H
    // les tableaux tabDphi et tabPhi définis dans la classe mère Deformation, sont utilisés
    // pour le stockage de l'interpolation suivant l'axe ou le plan.
    
    Epai * epais; // != NULL s'il y a des épaisseurs courantes stocké à l'élément et donc
                  // relayées ici, sinon = NULL
	    
	   // information concernant des conditions limites éventuelles, qui ont des répercutions sur 
	   // le calcul de la métrique
	   Tableau <EnuTypeCL> const * tabTypeCL; // tabTypeCL(i) : si différent de RIEN_TYPE_CL, indique le type de condition
	                                   // limite de l'arête i
	   Tableau <Coordonnee3> const * vplan;   // util pour des conditions de symétrie ou d'encastrement
	                                   // si tabTypeCL(i) = TANGENTE_CL , alors vplan(i) contient 
	                                   // un vecteur du plan normal à la tangente, 
	                                   // l'arête donne un second vecteur                               
 

    // +++++  des variables qui vont varier au cours du calcul: variables transitoires
    int numInteg_ep; // numero du point d'integration en cours dans l'epaisseur
    int numInteg_surf; // numero du point d'integration en cours sur la surface
        // numInteg de la class mère, est égal à numinteg_surf
    // méthode pour la gestion d'un changement momentané de pti
    int sauve_numInteg_ep; /// sauvegarde pour un retour au pti précédant avec la  méthode Retour_pti_precedant();
    int sauve_numInteg_surf;

    // +++++  fin des variables qui vont varier au cours du calcul: variables transitoires
       
    
    // METHODES PROTEGEES :
    // --- méthodes de vérifications ----
    // méthode de vérification par différences finies du calcul des différentes dérivées                       
    void VerifCal_def(bool gradV_instantane,const Met_abstraite::Impli & ex,TenseurBB& epsBB_tdt
                         ,Tableau <TenseurBB *> & d_epsBB_tdt);
    void VerifCal_implicit(bool gradV_instantane,const Met_abstraite::Impli & ex);
    // indicateur utilisé par Verif_par différences finis                           
    static int indic_VerifCal_implicitSfe1; 
 };
 /// @}  // end of group

#endif  
