// fichier: Base.h


// 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                                               *
*                                                                $     *
*     PROJET:      Herezh++                                            *
*                                                                $     *
************************************************************************
* BUT: Les classes Base servent à définir des bases en 1D 2D 3D
*      qui  permettent d'exprimer des coordonnées, en absolue ou en locale.
*      Ces bases correspondent à des bases naturelles ou des bases duales.
*                                                                $     *
*     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
*     MODIFICATIONS:                                                   *
*     !  date  !   auteur   !       but                          !     *
*     ------------------------------------------------------------     *
*                                                                $     *
************************************************************************/

#ifndef BASE_H
#define BASE_H

#include "Tableau_T.h"
#include "Coordonnee1.h"
#include "Mat_pleine.h"


/** @defgroup Les_classes_Base
*
* BUT: Les classes Base servent à définir des bases en 1D 2D 3D
*      qui  permettent d'exprimer des coordonnées, en absolue ou en locale.
*      Ces bases correspondent à des bases naturelles ou des bases duales.
* \author    Gérard Rio
* \version   1.0
* \date       23/01/97
* \brief       Définition des bases naturelles ou  absolues,
*  ou des bases duales.
*
*/



/// @addtogroup Les_classes_Base
///  @{
///

class BaseH;
class Util;

//===============================================================
//! Les base covariantes et absolus
//===============================================================
class   BaseB
{  /// surcharge de l'operator de lecture  avec le type
   friend istream & operator >> (istream &, BaseB &);
   /// surcharge de l'operator d'ecriture
   friend ostream & operator << (ostream &, const BaseB &);
     
  public :
    // VARIABLES PUBLIQUES :
    
    // CONSTRUCTEURS :
    
    /*! \brief
    // constructeur par defaut, defini la Base absolu en dimension 3
    // les vecteurs sont unitaires, ex en dim 2 ->
    // la base : 1,0 et 0,1 */
    BaseB () ;
    
    /// defini la Base absolu en dimension dim
    BaseB (int dim);
    
    /*! \brief
    // defini une Base relative v1(dim)
    // c-a-d differente de la base triviale absolu */
    BaseB (int dim, const Tableau<CoordonneeB > & v1);
    
    /*! \brief
    // defini une Base locale absolue (triviale) de n vecteurs
    // de dimension dim */
    BaseB (int dim,int n);
    
    /// idem dessus mais avec toutes les composantes = s
    BaseB (int dim,int n,double s);
    
    /*! \brief
    // defini une Base locale relative v1(dim)
    // de n vecteurs de dimension dim */
    BaseB (int dim,int n,const Tableau<CoordonneeB > & v1);
                                                  
    /// constructeur de copie
    BaseB (const BaseB &) ;
    
    /// DESTRUCTEUR :
    ~BaseB ();
    // METHODES PUBLIQUES :
    
    /// surcharge de l'affectation
    BaseB & operator = (const BaseB & aB);
    
    // retourne la dimension des vecteurs
    inline const int Dimension ()  const
      {return dimension; };
      
    /// retourne le nombre de vecteurs de la base
    inline const int NbVecteur ()  const
      {return nb_vecteur; };
    /// retourne  le i ieme vecteurs en lecture only
    const CoordonneeB & operator () (int i) const;
    /// retourne  le i ieme vecteurs en I/O
    CoordonneeB&  CoordoB(int i)  ;
    /// acces directe contrôlé à des vecteurs sans variance: uniquement en lecture
    const Coordonnee & Coordo(int i) const ;
 
    /// affichage à l'écran des infos
    void Affiche() const;
 
    /*! \brief
    // affectation trans_variance: utile pour une recopie de mêmes valeurs
    // mais ici l'appel est explicite donc a priori on sait ce que l'on fait
    // il n'y a pas de redimensionnement, donc la dimension et le nombre des vecteurs
    // doivent être identiques */
    void Affectation_trans_variance(const BaseH& aH);
 
    /*! \brief
    // changement de base
    // on suppose que this(i) correspond aux coordonnées dans un premier repère I_a
    // IpH correspond aux coordonnées dans I_a d'un nouveau repère
    // en sortie: apB(i) correspond aux coordonnées dans ipB de this(i) */
    void Change_repere(const BaseH& IpH, BaseB& apB);
 
    /*! \brief
    // la méthode qui suit a pour objectif de calculer les vecteurs de la base naturelle finale
    // associée à un paramétrage cartésien initial */
    
    /// donc soit  connue une base naturelle \hat g_i associée à un paramétrage theta^i
    /// \hat g_i est représenté par les vecteurs de this, et représente la situation déformée
    /// soit la base duale de g_i : gammaH^i = g^i c-à-d la base duale en situation non déformée
    /// maintenant: si on considère les coordonnées initiales X^i on cherche
    /// les vecteurs des bases naturelles associées à X^i avant g'_i et après déformation \hat g'_i
    /// \n on a (cf. annexe dans le document théorique d'Herezh)
    /// \n g'_i = I_i par définition et
    /// \n \hat g'_i =  (\vec I_i . \vec g^j) ~\hat g_j c-a-d
    /// \n \hat g'_i = gammaH^j(i) * (*this)(j)
    /// \n c'est le résultat de la méthode qui suit
 
    /// \n changement de base: retourne apB(a) = (*this)(j) . gamma^j_a
    /// il faut que le nombre de vecteur de apB soit identique à la dimension de gammaH
    /// et que le nombre de vecteur de gammaH soit identique au nombre de vecteur de this
    /// et que la dimension de apB soit identique à la dimension de this
    void ChangeBase_theta_vers_Xi(BaseB& apB, const BaseH& gammaH);
 
    /*! \brief
    // la méthode calcule à partir de this qui correspond à g_alpha dans I_a:
    //   apB :  g_alpha dans I'^alpha
    //   apH :  g^alpha dans I'^alpha
    //   IpB :  I'_beta dans I_a  */

    /// soient une base globale orthonormée : I_a et une base locale orthonormée I'_alpha
    /// pour l'instant: I_a est en 3 dimensions et alpha varie de 1 à 2
    /// soient une base naturelle g_alpha et duale associée g^beta
    /// telles que : I'_alpha appartient à l'espace des g_alpha ou g^beta
    /// \n A) on a:
    /// g^alpha = gamma(alpha,beta) * I'^beta  c-a-d : gamma^alpha_beta
    /// \n NB: 1) comme I'est orthonormée: I'^beta = I'_beta
    /// \n     2) chaque ligne de gamma représente un g^alpha
    /// \n B) dans ce contexte on a:
    /// inverse de gamma -> une matrice beta et chaque ligne de beta représente
    /// les coordonnées de g_alpha dans I'^alpha
    /// c-a-d g_alpha = alpha (delta,alpha) * I'_delta
    /// \n C) on peut également calculer les coordonnées de I'_beta dans le repère globale
    /// \n I'_beta = gamma(alpha,beta) * g_alpha
    //
    void ChangeBase_curviligne( const Mat_pleine& gamma, BaseB& apB , BaseH& apH, BaseB& IpB ) const;
 
    /*! \brief
    // calcul des composantes de coordonnées locales  dans la base absolue
    // en argument : A -> une reference sur les coordonnées résultat qui peut avoir une dimension
    // différente des coordonnées locale,  retour d'une reference sur A */
    Coordonnee & BaseAbsolue(Coordonnee & A,const CoordonneeH & B)  const;
	 
    /*! \brief
    // une partie des vecteurs de B est affectée à this,
    // si this contient plus de vecteur que B, les autres vecteurs sont mis à 0 ou non
    // suivant la valeur de  plusZero: = false: les autres vecteurs  sont inchangées, 
    // plusZero = true: les autres vecteurs sont mis à 0 */
    void Affectation_partielle(int nb_vecteur_a_affecter, const BaseB & B,bool plusZero);  

  private :  
    // VARIABLES PROTEGEES :
    int dimension; // dimension des vecteurs de la Base
    int nb_vecteur; // nombre de vecteur de la base
    Tableau<CoordonneeB > v ; // pointeur des vecteurs covariants de la Base
    Tableau<Coordonnee > v_sans ; // pointeur des vecteurs sans variance de la Base
    
    /// on met à la même place les v_sans que les v
    void Meme_place_coordonnee();
 };
 /// @}  // end of group

/// @addtogroup Les_classes_Base
///  @{
///

//===============================================================
//! Les base duales
//===============================================================

class   BaseH
{  /// surcharge de l'operator de lecture  avec le type
   friend istream & operator >> (istream &, BaseH &);
   /// surcharge de l'operator d'ecriture
   friend ostream & operator << (ostream &, const BaseH &);

  public :
    // VARIABLES PUBLIQUES :
    
    // CONSTRUCTEURS :
    /*! \brief
    // par defaut, defini une Base absolu en dimension 3
    // les vecteurs sont unitaires, ex en dim 2 ->
    // la base : 1,0 et 0,1 */
    BaseH () ;
    /// defini une Base absolu en dimension dim
    BaseH (int dim);
    /*! \brief
    // defini une Base relative v1(dim)
    // c-a-d differente de la base triviale absolue */
    BaseH (int dim, const Tableau<CoordonneeH > & v1);
    /*! \brief
    // defini une Base locale absolue (triviale) de n vecteurs
    // de dimension dim */
    BaseH (int dim,int n);
   /// idem dessus mais avec toutes les composantes = s
    BaseH (int dim,int n,double s);
    /// defini une Base locale relative v1(dim) de n vecteurs de dimension dim
    BaseH (int dim,int n,const Tableau<CoordonneeH >&  v1);
    /// constructeur de copie
    BaseH (const BaseH &) ;
    /// DESTRUCTEUR :
    ~BaseH ();
    // METHODES PUBLIQUES :
    
    /// surcharge de l'affectation
    BaseH & operator = (const BaseH & aB);
    /// retourne la dimension des vecteurs
    inline const int Dimension () const
      {return dimension; };
    /// retourne le nombre de vecteurs de la base
    inline const int NbVecteur () const
      {return nb_vecteur; };
    /// retourne  le i ieme vecteurs en lecture only
    const CoordonneeH & operator () (int i) const;
    /// retourne  le i ieme vecteurs en I/O
    CoordonneeH&  CoordoH(int i) ;
    /// acces directe contrôlé à des vecteurs sans variance: uniquement en lecture
    const Coordonnee & Coordo(int i) const ;
 
    /// affichage à l'écran des infos
    void Affiche() const;
 
    /*! \brief
    // affectation trans_variance: utile pour une recopie de mêmes valeurs
    // mais ici l'appel est explicite donc a priori on sait ce que l'on fait
    // il n'y a pas de redimensionnement, donc la dimension et le nombre des vecteurs
    // doivent être identiques */
    void Affectation_trans_variance(const BaseB& aB);
 
    /*! \brief
    // changement de base
    // on suppose que this(i) correspond aux coordonnées dans un premier repère I_a
    // IpB correspond aux coordonnées dans I_a d'un nouveau repère
    // en sortie: apH(i) correspond aux coordonnées dans ipH de this(i) */
    void Change_repere(const BaseB& IpB, BaseH& apH);
 
    /*! \brief
    // la méthode qui suit a pour objectif de calcul les vecteurs de la base naturelle finale
    // associée à un paramétrage cartésien initiale */
    
    /// donc soit  connue une base duale \hat g^i associée à un paramétrage theta^i
    /// \hat g^i est représenté par les vecteurs de this, et représente la situation déformée
    /// soit la base naturel de g_i : betaB_i = g_i c-à-d la base naturelle en situation non déformée
    /// maintenant: si on considère les coordonnées initiales X^i on cherche
    /// les vecteurs des bases duales associées à X^i avant g'^i et après déformation \hat g'^i
    /// on a (cf. annexe dans le document théorique d'Herezh)
    /// \n g'^i = g'_i =  I_i = I^i par définition et
    /// \n \hat g'^i =  (\vec I_i . \vec g_j) ~\hat g^j c-a-d
    /// \n \hat g'^i = betaB^j(i) * (*this)(j)
    /// \n c'est le résultat de la méthode qui suit

    /// \n changement de base: retourne apH(a) = (*this)(j) . beta_j^a
    /// il faut que le nombre de vecteur de apH soit identique à la dimension de betaB
    /// et que le nombre de vecteur de betaB soit identique au nombre de vecteur de this
    /// et que la dimension de apB soit identique à la dimension de this
    void ChangeBase_theta_vers_Xi(BaseH& apH, const BaseB& betaB);
 
    /*! \brief
    // la méthode calcule à partir de this qui correspond à g^alpha dans I_a:
    //   apB :  g_alpha dans I'^alpha
    //   apH :  g^alpha dans I'^alpha
    //   IpH :  I'^beta dans I_a */

    /// soient une base globale orthonormée : I_a et une base locale orthonormée I'_alpha
    /// pour l'instant: I_a est en 3 dimensions et alpha varie de 1 à 2
    /// soient une base naturelle g_alpha et duale associée g^beta
    /// telles que : I'_alpha appartient à l'espace des g_alpha ou g^beta
    /// \n A) on a:
    /// g^alpha = gamma(alpha,beta) * I'^beta  c-a-d : gamma^alpha_beta
    /// \n NB: 1) comme I'est orthonormée: I'^beta = I'_beta
    ///     2) chaque ligne de gamma représente un g^alpha
    /// \n B) dans ce contexte on a:
    /// inverse de gamma -> une matrice beta et chaque ligne de beta représente
    /// les coordonnées de g_alpha dans I'^alpha
    /// c-a-d g_alpha = alpha (delta,alpha) * I'_delta
    /// \n C) on peut également calculer les coordonnées de I'_beta dans le repère globale
    /// \n I'_beta = gamma(alpha,beta) * g_alpha
    //
    void ChangeBase_curviligne( const Mat_pleine& gamma, BaseB& apB , BaseH& apH, BaseH& IpH ) const;
 
    /*! \brief
    // calcul des composantes de coordonnées locales  dans la base absolue
    // en argument : A -> une reference sur les coordonnées résultat qui peut avoir une dimension
    // différente des coordonnées locale,  retour d'une reference sur A */
    Coordonnee & BaseAbsolue(Coordonnee & A,const CoordonneeB & B)  const;
	
    /*! \brief
    // une partie des vecteurs de B est affectée à this,
    // si this contient plus de vecteur que B, les autres vecteurs sont mis à 0 ou non
    // suivant la valeur de  plusZero: = false: les autres vecteurs  sont inchangées, 
    // plusZero = true: les autres vecteurs sont mis à 0  */
    void Affectation_partielle(int nb_vecteur_a_affecter, const BaseH & B,bool plusZero);  
 
  private :  
    // VARIABLES PROTEGEES :
    int dimension; // dimension des vecteurs de la Base
    int nb_vecteur; // nombre de vecteur de la base
    Tableau<CoordonneeH > v ; // pointeur des vecteurs contravariant de la Base
    Tableau<Coordonnee > v_sans ; // pointeur des vecteurs sans variance de la Base
    
    // on met à la même place les v_sans que les v
    void Meme_place_coordonnee();
 };
/// @}  // end of group

/// @addtogroup Les_classes_Base
///  @{

//=========================================================================
//! un groupe de 3  bases covariantes et absolus à 0, t et tdt
//=========================================================================
/// il s'agit ici essentiellement d'un conteneur pour optimiser le stockage
//=========================================================================

 class BaseB_0_t_tdt
 { /// surcharge de l'operator de lecture  avec le type
   friend istream & operator >> (istream &, BaseB_0_t_tdt &);
   /// surcharge de l'operator d'ecriture
   friend ostream & operator << (ostream &, const BaseB_0_t_tdt &);
     
  public :
    // VARIABLES PUBLIQUES :
    
    // CONSTRUCTEURS :
    
    /// par defaut, defini les Bases en absolu en dimension 3
    /// les vecteurs sont unitaires, ex en dim 2 ->
    /// la base : 1,0 et 0,1
    BaseB_0_t_tdt () :
      baseB_0(),baseB_t(), baseB() {};
    /// defini les Bases en absolu en dimension dim
    BaseB_0_t_tdt (int dim) :
      baseB_0(dim),baseB_t(dim), baseB(dim) {};
    /// defini 3 Bases relatives v1(dim)
    /// c-a-d differente de la base triviale absolu
    BaseB_0_t_tdt (int dim, const Tableau<CoordonneeB > & v1) :
      baseB_0(dim,v1),baseB_t(dim,v1), baseB(dim,v1) {};
    /// defini les Bases locale absolue (triviale) de n vecteurs
    /// de dimension dim
    BaseB_0_t_tdt (int dim,int n) :
      baseB_0(dim,n),baseB_t(dim,n), baseB(dim,n) {};
    /// idem dessus mais avec toutes les composantes = s
    BaseB_0_t_tdt (int dim,int n,double s) :
       baseB_0(dim,n,s),baseB_t(dim,n,s), baseB(dim,n,s) {};
    /// defini les Bases locale relative v1(dim)
    /// de n vecteurs de dimension dim
    BaseB_0_t_tdt (int dim,int n,const Tableau<CoordonneeB > & v1) :
       baseB_0(dim,n,v1),baseB_t(dim,n,v1), baseB(dim,n,v1) {};
    /// constructeur de copie
    BaseB_0_t_tdt (const BaseB_0_t_tdt & b):
     baseB_0(b.baseB_0),baseB_t(b.baseB_t), baseB(b.baseB) {};
 
    /// DESTRUCTEUR :
    ~BaseB_0_t_tdt () {};
    // METHODES PUBLIQUES :
    /// surcharge de l'affectation
    BaseB_0_t_tdt & operator = (const BaseB_0_t_tdt & b)
     {baseB_0 = b.baseB_0; baseB_t = b.baseB_t; baseB = b.baseB;return *this;
     };
  
    /// récupération de la base,
    ///  a) en constant, la base actuelle
    const BaseB& Const_BaseB_Noeud() const {return baseB;};
    ///  b) en constant, la base à t
    const BaseB& Const_BaseB_Noeud_t() const {return baseB_t;};
    ///  c) en constant, la base initiale
    const BaseB& Const_BaseB_Noeud_0() const {return baseB_0;};

    ///  d) en lecture écriture, la base actuelle
    BaseB& BaseB_Noeud()  {return baseB;};
    ///  e) en lecture écriture, la base à t
    BaseB& BaseB_Noeud_t() {return baseB_t;};
    ///  f) en lecture écriture, la base à 0
    BaseB& BaseB_Noeud_0()  {return baseB_0;};
  
  
    private :
        BaseB  baseB_0;   // à 0
        BaseB  baseB_t;   // à t
        BaseB  baseB;     // actuelle
 };
/// @}  // end of group

/// @addtogroup Les_classes_Base
///  @{
///


//=========================================================================
//! un groupe de 3  bases contravariant et absolus à 0, t et tdt
//=========================================================================
/// il s'agit ici essentiellement d'un conteneur pour optimiser le stockage
//=========================================================================

 class BaseH_0_t_tdt
 { /// surcharge de l'operator de lecture  avec le type
   friend istream & operator >> (istream & ent, BaseH_0_t_tdt &)
     { cout << "\n *** operateur non implante !! "
            << " friend istream & operator ecriture ";
       Sortie(1);
       return ent;
     };
   /// surcharge de l'operator d'ecriture
   friend ostream & operator << (ostream & sort, const BaseH_0_t_tdt &);
  
  public :
    // VARIABLES PUBLIQUES :
  
    /// CONSTRUCTEURS :
    /// par defaut, defini les Bases en absolu en dimension 3
    /// les vecteurs sont unitaires, ex en dim 2 ->
    /// la base : 1,0 et 0,1
    BaseH_0_t_tdt () :
      baseH_0(),baseH_t(), baseH() {};
    /// defini les Bases en absolu en dimension dim
    BaseH_0_t_tdt (int dim) :
      baseH_0(dim),baseH_t(dim), baseH(dim) {};
    /// defini 3 Bases relatives v1(dim)
    /// c-a-d differente de la base triviale absolu
    BaseH_0_t_tdt (int dim, const Tableau<CoordonneeH > & v1) :
      baseH_0(dim,v1),baseH_t(dim,v1), baseH(dim,v1) {};
    /// defini les Bases locale absolue (triviale) de n vecteurs
    /// de dimension dim
    BaseH_0_t_tdt (int dim,int n) :
      baseH_0(dim,n),baseH_t(dim,n), baseH(dim,n) {};
    /// idem dessus mais avec toutes les composantes = s
    BaseH_0_t_tdt (int dim,int n,double s) :
       baseH_0(dim,n,s),baseH_t(dim,n,s), baseH(dim,n,s) {};
    /// defini les Bases locale relative v1(dim)
    /// de n vecteurs de dimension dim
    BaseH_0_t_tdt (int dim,int n,const Tableau<CoordonneeH > & v1) :
       baseH_0(dim,n,v1),baseH_t(dim,n,v1), baseH(dim,n,v1) {};
    /// constructeur de copie
    BaseH_0_t_tdt (const BaseH_0_t_tdt & b):
     baseH_0(b.baseH_0),baseH_t(b.baseH_t), baseH(b.baseH) {};
 
    /// DESTRUCTEUR :
    ~BaseH_0_t_tdt () {};
    // METHODES PUBLIQUES :
    /// surcharge de l'affectation
    BaseH_0_t_tdt & operator = (const BaseH_0_t_tdt & b)
     {baseH_0 = b.baseH_0; baseH_t = b.baseH_t; baseH = b.baseH; return *this;
     };
  
    /// récupération de la base,
    ///  a) en constant, la base actuelle
    const BaseH& Const_BaseH_Noeud() const {return baseH;};
    ///  b) en constant, la base à t
    const BaseH& Const_BaseH_Noeud_t() const {return baseH_t;};
    ///  c) en constant, la base initiale
    const BaseH& Const_BaseH_Noeud_0() const {return baseH_0;};

    ///  d) en lecture écriture, la base actuelle
    BaseH& BaseH_Noeud()  {return baseH;};
    ///  e) en lecture écriture, la base à t
    BaseH& BaseH_Noeud_t() {return baseH_t;};
    ///  f) en lecture écriture, la base à 0
    BaseH& BaseH_Noeud_0()  {return baseH_0;};
  
  
    private :
        BaseH  baseH_0;   // à 0
        BaseH  baseH_t;   // à t
        BaseH  baseH;     // actuelle
 };
/// @}  // end of group

 
#ifndef MISE_AU_POINT
  #include "Base.cc"
  #define  BASE_HetB_deja_inclus
#endif
 
#endif