

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

/************************************************************************
 *     DATE:        1/10/98                                             *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT: Classe générale concernant les hyperélastiques grenoblois.  *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef HYPER3D_H
#define HYPER3D_H

#include "HyperD.h"

//#include < >
//#include " "

/// @addtogroup Les_lois_hyperelastiques
///  @{
///


class Hyper3D : 
//++  public  HyperD<class Tenseur3HH,class Tenseur3BB,class Tenseur3BH,class Tenseur3HB>
  public  HyperD
{
  public :
    // VARIABLES PUBLIQUES :
    
  // CONSTRUCTEURS :
  // Constructeur par defaut
  Hyper3D ();
  // Constructeur utile si l'identificateur du nom de la loi
  // de comportement et le paramètre phase sont connus
  Hyper3D (Enum_comp id_compor,Enum_categorie_loi_comp categorie_comp, bool avec_ph)  ;
  // Constructeur utile si l'identificateur du nom de la loi
  // de comportement et le paramètre phase sont connus		
  Hyper3D (char* nom,Enum_categorie_loi_comp categorie_comp,bool avec_ph) ;	
  // Constructeur de copie
  Hyper3D (const Hyper3D& loi) ;
  // DESTRUCTEUR :
  ~Hyper3D () 
    {};
 
  //  METHODES internes spécifiques à l'hyperélasticité isotrope découlant de
  //  méthodes virtuelles de HyperD


  // Calcul des invariants et, de epsBH, 
  // retour de IdGBH qui pointe sur le bon tenseur
  //++ TensBH * Invariants (TenseurBB&  epsBB_t,TenseurBB& gijBB_t,
  TenseurBH * Invariants (const TenseurBB&  epsBB_t,const TenseurBB& gijBB_t,
           const TenseurHH & gijHH_t,const double& jacobien_0,const double& jacobien_t,
  //++           Invariant & invariant,TensBH & epsBH);
           Invariant & invariant,TenseurBH & epsBH);
  // calcul des invariants et de leurs variations, de epsBH,
  // et de sa variation, puis  retour de IdGBH qui pointe sur le bon tenseur
  //++ TensBH *  Invariants_et_var (TenseurBB&  epsBB_tdt,
  TenseurBH *  Invariants_et_var (const TenseurBB&  epsBB_tdt,
           const TenseurBB& gijBB_tdt,const Tableau <TenseurBB *>& d_gijBB_tdt,
           const TenseurHH & gijHH_tdt,const Tableau <TenseurHH *>& d_gijHH_tdt,
           const double& jacobien_0,const double& jacobien_tdt,const Vecteur& d_jacobien_tdt,
           InvariantVarDdl& invariantVarDdl,
  //++           TensBH & epsBH_tdt,Tableau<TensBH> & depsBH_tdt);
           TenseurBH & epsBH_tdt,Tableau<TenseurBH*> & depsBH_tdt); 
           
  // calcul des invariants  et de leurs variations par rapport aux déformations
  // et de sa variation, puis  retour de IdGBH qui pointe sur le bon tenseur
  TenseurBH *  Invariants_et_varEps (const TenseurBB&  epsBB_tdt,
           const TenseurBB& gijBB_tdt,const TenseurHH & gijHH_tdt,
           const double& jacobien_0,const double& jacobien_tdt,
           InvariantVarEps& invariantVarEps,TenseurBH & epsBH_tdt); 
             
  // calcul du potentiel et de ses dérivées non compris la phase
  PotenSansPhaseSansVar Potentiel
                  (const Invariant & invariant,const double& jacobien0);
  // calcul du potentiel et de ses dérivées avec la phase
  PotenAvecPhaseSansVar PotentielPhase
                  (const Invariant& invariant,const double& jacobien0); 
  // calcul  du potentiel sans phase et dérivées avec  ses variations par rapport aux invariants
  PotenSansPhaseAvecVar Potentiel_et_var
                  (const Invariant& invariant,const double& jacobien0 );
  // calcul  du potentiel avec phase et dérivées avec  ses variations par rapport aux invariants
  PotenAvecPhaseAvecVar PotentielPhase_et_var
                  (const Invariant& invariant,const double& jacobien0);
  // calcul  du potentiel sans phase et dérivées avec  ses variations par rapport à epsBB
  PotenSansPhaseAvecVar Potentiel_et_varEps
                  (const Invariant& invariant,const double& jacobien0 );

 
protected : 

    // classe permettant le passage protégé de grandeur
    // Invariants Qeps et Cosphi seulement 
    class Invariant0QepsCosphi
     { public :
       Invariant0QepsCosphi() : Qeps(0.),cos3phi(0.) {};
       Invariant0QepsCosphi(const double& Qe, const double& cos3p) : Qeps(Qe),cos3phi(cos3p) {};
       double Qeps,cos3phi;
       };
    // Invariants Qeps  ainsi que sa variation première 
    class InvariantQeps
     { public :
       InvariantQeps() : Qeps(0.),dQepsdbIIb(0.) {};
       double Qeps;
       double dQepsdbIIb ; // variation de Qeps par rapport à bIIb
       };
    // Invariants Qeps et Cosphi ainsi que leur variations premières 
    class InvariantQepsCosphi
     { public :
       InvariantQepsCosphi() : Qeps(0.),cos3phi(0.),dQepsdbIIb(0.)
         ,dcos3phidV(0.),dcos3phidIeps(0.),dcos3phidbIIb(0.) {};
       double Qeps,cos3phi;
       double dQepsdbIIb ; // variation de Qeps par rapport à bIIb
       double dcos3phidV;     // variation de Qeps par rapport à V
       double dcos3phidIeps;  // variation de cos3phi par rapport à Ieps
       double dcos3phidbIIb;  // variation de cos3phi par rapport à bIIb
       };
    // Invariants Qeps  ainsi que ses variations premières et secondes 
    class Invariant2Qeps
     { public :
       Invariant2Qeps() : Qeps(0.),dQepsdbIIb(0.),dQepsdbIIb2(0.) {};
       Invariant2Qeps(const double & Q, const double & dQdbIIb, const double & dQdbIIb2):
         Qeps(Q),dQepsdbIIb(dQdbIIb),dQepsdbIIb2(dQdbIIb2)    {};
       double Qeps;
       double dQepsdbIIb ; // variation de Qeps par rapport à bIIb
       double dQepsdbIIb2 ; // variation seconde de Qeps par rapport à bIIb
       };
  // Invariants Qeps et Cosphi ainsi que leur variations premières
    // et secondes 
    class Invariant2QepsCosphi
     { public :
       Invariant2QepsCosphi() : Qeps(0.),cos3phi(0.),dQepsdbIIb(0.)
         ,dcos3phidV(0.),dcos3phidIeps(0.),dcos3phidbIIb(0.),dQepsdbIIb2(0.)
         ,dcos3phidV2(0.),dcos3phidIeps2(0.),dcos3phidbIIb2(0.),dcos3phidVdbIIb(0.)
         ,dcos3phidIepsdbIIb(0.) {};
       double Qeps,cos3phi;
       double dQepsdbIIb ; // variation de Qeps par rapport à bIIb
       double dcos3phidV;     // variation de cos3phi par rapport à V
       double dcos3phidIeps;  // variation de cos3phi par rapport à Ieps
       double dcos3phidbIIb;  // variation de cos3phi par rapport à Ieps
       double dQepsdbIIb2 ; // variation seconde de Qeps par rapport à bIIb
       double dcos3phidV2;     // variation seconde de cos3phi par rapport à V
       double dcos3phidIeps2;  // variation seconde de cos3phi par rapport à Ieps
       double dcos3phidbIIb2;  // variation seconde de cos3phi par rapport à Ieps
       double dcos3phidVdbIIb;  // variation seconde de cos3phi par rapport à V et bIIb
       double dcos3phidIepsdbIIb; // variation seconde de cos3phi par rapport à Ieps et bIIb
       };
    // class pour le potentiel et seulement sa variation suivant V  
    class PoGrenoble_V
     { public :
       PoGrenoble_V() : E(0.),EV(0.),Ks(0) {};
       double E; // valeur du potentiel
       double EV; // variation du potentiel par rapport à V
       double Ks; // module de compressibilité sécant par rapport à log(V)
      }; 
    // class pour le potentiel et seulement les variations suivant V et Q  
    class PoGrenobleSansPhaseSansVar
     { public :
       PoGrenobleSansPhaseSansVar() : E(0.),EV(0.),EQ(0.),Ks(0) {};
       double E; // valeur du potentiel
       double EV; // variation du potentiel par rapport à V
       double EQ; // variation du potentiel par rapport à Q
       double Ks; // module de compressibilité sécant par rapport à log(V)
      };
    // class pour le potentiel et seulement ses variations suivant V  
    class PoGrenoble_VV
     { public :
       PoGrenoble_VV() : E(0.),EV(0.),EVV(0.),Ks(0) {};
       double E; // valeur du potentiel
       double EV; // variation du potentiel par rapport à V
       double EVV;   // variation seconde par rapport à V
       double Ks; // module de compressibilité sécant par rapport à log(V)
      };
    class PoGrenobleSansPhaseAvecVar
     { public :
       PoGrenobleSansPhaseAvecVar() : E(0.),EV(0.),EQ(0.),EVV(0.),EQV(0.),EQQ(0.),Ks(0) {};
       double E; // valeur du potentiel
       double EV; // variation du potentiel par rapport à V
       double EQ; // variation du potentiel par rapport à Q
       double EVV;   // variation seconde par rapport à V
       double EQV; // variation seconde par rapport à Q et V
       double EQQ; // variation seconde par rapport à Q
       double Ks; // module de compressibilité sécant par rapport à log(V)
      };
    class PoGrenobleAvecPhaseSansVar
     { public :
       PoGrenobleAvecPhaseSansVar() : E(0.),EV(0.),EQ(0.),Ecos3phi(0.),Ks(0) {};
       double E; // valeur du potentiel
       double EV; // variation du potentiel par rapport à V
       double EQ; // variation du potentiel par rapport à Q
       double Ecos3phi; // variation du potentiel par rapport à cos3phi
       double Ks; // module de compressibilité sécant par rapport à log(V)
      };
    class PoGrenobleAvecPhaseAvecVar
     { public :
       PoGrenobleAvecPhaseAvecVar () : E(0.),EV(0.),EQ(0.),Ecos3phi(0.)
          ,EVV(0.),EQV(0.),EQQ(0.),EVcos3phi(0.),EQcos3phi(0.),Ecos3phi2(0.),Ks(0) {};
       double E; // valeur du potentiel
       double EV; // variation du potentiel par rapport à V
       double EQ; // variation du potentiel par rapport à Q
       double Ecos3phi; // variation du potentiel par rapport à cos3phi
       double EVV;   // variation seconde par rapport à V
       double EQV; // variation seconde par rapport à Q et V
       double EQQ; // variation seconde par rapport à Q
       double EVcos3phi; // variation seconde par rapport à V cos3phi
       double EQcos3phi; // variation seconde par rapport à Q cos3phi
       double Ecos3phi2; // variation seconde par rapport à cos3phi
       double Ks; // module de compressibilité sécant par rapport à log(V)
     };

   
   
    // METHODES PROTEGEES :
    
              
    // calcul de l'invariant Qeps seul valable même si Qeps est nul
    double Invariant0Qeps(const Invariant & invariant);
    // calcul des invariants Qeps,cos3phi seuls (Qeps doit être non nul)
    Invariant0QepsCosphi Invariant0Specif(const Invariant & invariant);
    // calcul des invariants Qeps,cos3phi en fonction de V, bIIb Ieps
    // on utilise pas l'invariant bIIIb, 
    Invariant0QepsCosphi InvariantDe_V_bIIb_Ieps(const Invariant & invariant);    
    // calcul de l'invariants Qeps ainsi que sa variation par rapport
    // à  bIIb (Qeps doit être non nul)
    InvariantQeps InvariantSpecifSansPhase(const Invariant & invariant);
    // calcul des invariants Qeps,cos3phi, ainsi que leur variation par rapport
    // aux trois invariants Ieps, V et bIIb (Qeps doit être non nul)
    InvariantQepsCosphi InvariantSpecif(const Invariant & invariant);
    // calcul de l'invariants Qeps ainsi que ses variations première et seconde
    // par rapport à bIIb (Qeps doit être non nul)
    Invariant2Qeps Invariant2SpecifSansPhase(const Invariant & invariantVarDdl);
    // calcul des invariants Qeps,cos3phi, ainsi que leur variation première et seconde
    // par rapport aux trois invariants Ieps, V et bIIb (Qeps doit être non nul)
    Invariant2QepsCosphi Invariant2Specif(const Invariant & invariantVarDdl);
    
    /// les fonctions potentielles sont défini dans les classes dérivées
    
    // calcul du potentiel tout seul sans la phase car Qeps est  nul
    // ou très proche de 0
    virtual double PoGrenoble
             (const double & Qeps,const Invariant & invariant) = 0;
    // calcul du potentiel tout seul avec la phase donc dans le cas où Qeps est non nul
    virtual double PoGrenoble
             (const Invariant0QepsCosphi & inv,const Invariant & invariant) = 0;
    // calcul du potentiel tout seul sans la phase car Qeps est  nul
    // ou très proche de 0, et de sa variation suivant V uniquement
    virtual PoGrenoble_V PoGrenoble_et_V
             (const double & Qeps,const Invariant & invariant) = 0;
    // calcul du potentiel et de sa variation suivant V uniquement
    virtual PoGrenoble_V PoGrenoble_et_V
             (const Invariant0QepsCosphi & inv,const Invariant & invariant) = 0;
    // calcul du potentiel tout seul sans la phase car Qeps est  nul
    // ou très proche de 0, et de ses variations première et seconde suivant V uniquement
    virtual PoGrenoble_VV PoGrenoble_et_VV
             (const double & Qeps,const Invariant & invariant) = 0;
    // calcul du potentiel et de sa variation première et seconde suivant V uniquement
    virtual PoGrenoble_VV PoGrenoble_et_VV
             (const Invariant0QepsCosphi & inv,const Invariant & invariant) = 0;
    // calcul du potentiel et de ses dérivées non compris la phase
    virtual PoGrenobleSansPhaseSansVar PoGrenoble
             (const InvariantQeps & inv,const Invariant & invariant) = 0;
    // calcul du potentiel et de ses dérivées avec la phase
    virtual PoGrenobleAvecPhaseSansVar PoGrenoblePhase
             (const InvariantQepsCosphi& inv,const Invariant & invariant) = 0; 
    // calcul  du potentiel sans phase et dérivées avec  ses variations par rapport aux invariants
    virtual PoGrenobleSansPhaseAvecVar PoGrenoble_et_var
             (const Invariant2Qeps& inv,const Invariant & invariantVarDdl) = 0;
    // calcul  du potentiel avec phase et dérivées avec  ses variations par rapport aux invariants
    virtual PoGrenobleAvecPhaseAvecVar PoGrenoblePhase_et_var
             (const Invariant2QepsCosphi& inv,const Invariant & invariantVarDdl) = 0;
             
    ///=============== fonctions pour la vérification et la mise au point ===============
    
    // vérif des dérivées du potentiels par rapport aux invariants, ceci par différences finies
    // cas sans la phase
    void Verif_Potentiel_et_var(const InvariantVarDdl& inv,const double& jacobien0
                                 ,const PotenSansPhaseAvecVar& potret );
    // vérif des dérivées du potentiels par rapport aux invariants, ceci par différences finies
    // cas avec la phase
    void Verif_Potentiel_et_var(const InvariantVarDdl& inv,const double& jacobien0
                                 ,const PotenAvecPhaseAvecVar& potret );
    static int indic_Verif_Potentiel_et_var; // indicateur utilisé par Verif_Potentiel_et_var                           
    static double limite_inf_Qeps; // limite en dessous de laquelles on néglige la phase
    static double limite_inf_bIIb; // limite en dessous de laquelles on fait une ope spécial

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

#endif  
