
// 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:        25/02/2005                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  échange de structures de données: fortran Umat -> C++      *
 *           La classe est principalement de type conteneur avec        *
 *           accés directe aux informations.                            *
 *    NB: on reste systématiquement en 3D, car cela permet de stocker   *
 *        toutes les informations: par exemple en CP, il nous faut      *
 *        epsilon33, et en CP2, il nous faudrait eps33 et 22            *
 *                                                                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef UMAT_ABAQUS_H
#define UMAT_ABAQUS_H

#include "Tenseur.h"
#include "Vecteur.h"
#include "TenseurQ.h"  
#include <string.h>
#include <string>
#include "ParaGlob.h"
#include "Tableau2_T.h"
#include "PtIntegMecaInterne.h"

// définition d'une union qui lie les réels, les entiers et les caractères 
union Tab_car_double_int
  {  char    tampon[928];
     double  x[116];
	    int     n[232];
  } ;



class UmatAbaqus
{
  public :
    
    // CONSTRUCTEURS : 
    // par défaut
    UmatAbaqus(int dimension_espace = 3, int nb_vecteur = 3);
    // constructeur de copie
    UmatAbaqus(const UmatAbaqus& a);        
    
    // DESTRUCTEUR :
    ~UmatAbaqus();
    
    // METHODES PUBLIQUES :
    
    // Surcharge de l'operateur = 
    UmatAbaqus& operator= (UmatAbaqus& a);
    // >>>>>> 1) >>>>>>  contexte: utilisation  d'herezh comme umat
    // si utilisation_umat_interne: alors il n'y a pas d'utilisation des pipes
    // tout se passe en interne
    // lecture des données Umat
    void LectureDonneesUmat(bool utilisation_umat_interne,const int niveau);
    // écriture des données Umat
    void EcritureDonneesUmat(bool utilisation_umat_interne,const int niveau);
    // <<<<<< 2) <<<<<< contexte: utilisation par herezh d'une umat extérieure
    // écriture des données pour l'umat 
    void EcritureDonneesPourUmat(bool utilisation_umat_interne,const int niveau);
    // Puis lecture des résultats de l'umat
    void LectureResultatUmat(bool utilisation_umat_interne,const int niveau);
    
    // changement du nom des pipes
    void Change_nom_pipe_envoi(const string& env) {envoi=env;};
    void Change_nom_pipe_reception(const string& recep) {reception=recep;};
 
    // initialisation des données d'entrée tous à zéro
    // sauf: nom_materiau: qui reste inchangé
    //       giB_t et BaseB: qui sont initialisée à une base absolue identité
    //       pnewdt: très grand
    // sinon on a:
    //       *eps_meca, *delta_eps_meca : nulles, temps_t=0, temps_tdt et delta_t=0;
    //       temper_t et delta_temper: nulles,
    //       pas de variables aux noeuds, pas de proprietes_materiau
    //       coordonnées à 0, 
    //       longueur caractéristique=0,
    // et tous les indices=0: 
    //       nb_elem nb_pt_integ nb_du_plis nb_pt_dans_le_plis nb_step nb_increment
    void Init_zero();
    
    // initialisation des données d'entrée à un démarrage correcte
    // *t_sigma=0, v_statev de taille nulle, les énergies nulles, pnewdt très grand
    //       *eps_meca, *delta_eps_meca : nulles, temps_t=0, temps_tdt et delta_t=1;
    //       temper_t et delta_temper: nulles,
    //       pas de variables aux noeuds, pas de proprietes_materiau
    //       coordonnées à 0, matrice de rotation identité
    //       longueur caractéristique=1, giB_t et giB_tdt: base identité en absolue
    // et tous les indices=1: 
    //       nb_elem nb_pt_integ nb_du_plis nb_pt_dans_le_plis nb_step nb_increment
    // par défaut la dimension des tenseurs est 3, mais pour les CP par exemple
    // la dimension réelle utilisée est 2
    // de même pour nb_reel_tau_ij qui indique le nombre de contrainte de cisaillement
    // réellement utilisé: qui en CP = 1
    void Init_un(int dim_reel_tens = 3,int nb_reel_tau_ij=3);
	 
	   // transfert de l'Umat vers le point d'intégration à t
	   void Transfert_Umat_ptInteg_t(PtIntegMecaInterne& ptIntegMeca);	 
    // transfert de l'Umat vers le point d'intégration à tdt
    void Transfert_Umat_ptInteg_tdt(PtIntegMecaInterne& ptIntegMeca);
 
    // affichage en fonction d'un niveau
    void Affiche(ostream& sort,const int niveau);
    
	   //----- lecture écriture de restart -----
	   // 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)
	   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)
	   void Ecriture_base_info(ostream& sort,const int cas);
    
    // -------------------------------------------------------------------------------- 
    // ---                  conteneur VARIABLES PUBLIQUES                      -------- 
    // -------------------------------------------------------------------------------- 

    TenseurHH* t_sigma; // contrainte: en entrée à t, puis en sortie à tdt
    Vecteur v_statev; // variables d'état attaché, en entrée à t en sortie doivent être mise à tdt
    TenseurHHHH* d_sigma_deps; // variation de sigma par rapport aux déformations
    double energie_elastique; // différentes énergie: en entrée à t, en sortie
    double dissipation_plastique; double dissipation_visqueuse; // à tdt
    double ener_therm_vol_par_utemps; // énergie thermique volumique générée par 
                                      // le travail mécanique, par unité de temps
    TenseurHH* d_sigma_d_tempera; //variation de sigma par rapport à la thermique
    TenseurHH* d_ener_therm_vol_deps; // variation de l'énergie thermique générée
                                                      // par rapport à la déformation
    double d_ener_therm_dtemper; // variation de l'énergie thermique générée
                                                  // par rapport à la température
    // -- variables qui peuvent être updated 
    double pnewdt; // pilotage de delta t: delta_t_new *= pnewdt; 
                    // en entrée pnewdt est initilaisée à une grande valeur
                    // si l'on veut diminuer le pas de temps-> on met en sortie pnewdt < 1
    // -- variables passées pour information
    TenseurBB* eps_meca; // déformation mécanique
    TenseurBB* delta_eps_meca; // incrément de déformation mécanique
    double temps_t; double temps_tdt; // temps
    double delta_t; // incrément de temps
    double temper_t; // température initiale à t
    double delta_temper;// incrément de température
    Vecteur ddlNoeA_ptinteg; // variables aux noeuds interpolées au point
    Vecteur delta_ddlNoeA_ptinteg; // incréments des variables aux noeuds interpolées
    string nom_materiau; // nom du matériau
    int dim_tens; // nombre de sigma_ii
    int nb_tau_ij; // nombre de sigma_ij avec i différent de j
    int nb_ij_tenseur; // nombre de composantes du tableau stress
    int nb_variables_etat; // nombre de variables d'état attaché
    Vecteur proprietes_materiau; // propriétées du matériau;
    int nb_proprietes_materiau; // nombre de propriétés du matériau
    Coordonnee coor_pt; // coordonnee du point en absolue pour abaqus
    Mat_pleine mat_corota; // matrice de rotation du corotationnelle
    double longueur_characteristique;
    BaseB giB_t; // base naturelle à t
    BaseB giB_tdt; // base natuelle à tdt
    int nb_elem; // numéro de l'élément
    int nb_pt_integ; // numéro du point d'intégration
    int nb_du_plis; // numéro du plis pour les multicouches 
    int nb_pt_dans_le_plis; // numéro du point dans le plis
    int nb_step; // numéro du step
    int nb_increment; // numéro de l'incrément
 
    // --- vecteur normal dans le cas CP
    CoordonneeB N_t,N_tdt;

    // -------------------------------------------------------------------------------- 
    // ---              fin  conteneur VARIABLES PUBLIQUES                     -------- 
    // -------------------------------------------------------------------------------- 

    
  private :  
    // VARIABLES PROTEGEES :
    // -- variables devant être définies
    double* STRESS; // TenseurHH* t_sigma; // contrainte: en entrée à t, puis en sortie à tdt
    double* STATEV; // Vecteur v_statev; // variables d'état attaché, en entrée à t
                                       // en sortie doivent être mise à tdt
    double * DDSDDE; // TenseurHHBB* d_sigma_deps; // variation de sigma par rapport aux déformations
    double*  SSE,* SPD,* SCD; // double energie_elastique; // différentes énergie: en entrée à t, en sortie
                              // double dissipation_plastique; double dissipation_visqueuse; // à tdt
    double*  RPL; // double ener_therm_vol_par_utemps; // énergie thermique volumique générée par 
                                                    // le travail mécanique, par unité de temps
    double* DDSDDT; // TenseurHH* d_sigma_d_tempera; //variation de sigma par rapport à la thermique
    double* DRPLDE; // TenseurHH* d_ener_therm_vol_deps; // variation de l'énergie thermique générée
                                                      // par rapport à la déformation
    double*  DRPLDT; // double d_ener_therm_dtemper; // variation de l'énergie thermique générée
                                                  // par rapport à la température
    // -- variables qui peuvent être updated 
    double*  PNEWDT; // double pnewdt; // pilotage de delta t: delta_t_new *= pnewdt; 
                    // en entrée pnewdt est initilaisée à une grande valeur
                    // si l'on veut diminuer le pas de temps-> on met en sortie pnewdt < 1
    // -- variables passées pour information
    double* STRAN;  // TenseurBB* eps_meca; // déformation mécanique
    double* DSTRAN; // TenseurBB* delta_eps_meca; // incrément de déformation mécanique
    double* TIME;   // step time (ne sert pas pour herezh) puis double temps_t;  // temps
    double* DTIME;  // double delta_t; // incrément de temps
    double* TemP;   // double temper; // température initiale à t
    double* DTEMP;  // double delta_temper;// incrément de température
    double* PREDEF; // Vecteur ddlNoeA_ptinteg; // variables aux noeuds interpolées au point
    double* DPRED;  // Vecteur delta_ddlNoeA_ptinteg; // incréments des variables aux noeuds interpolées
    char*   CMNAME; // string nom_materiau; // nom du matériau
    int*    NDI;    // int dim_tens; // nombre de sigma_ii
    int*    NSHR;   // int nb_tau_ij; // nombre de sigma_ij avec i différent de j
    int*    NTENS;  // int nb_ij_tenseur; // nombre de composantes du tableau stress
    int*    NSTATV; // int nb_variables_etat; // nombre de variables d'état attaché
    double* PROPS;  // Vecteur proprietes_materiau; // propriétées du matériau;
    int*    NPROPS; // int nb_proprietes_materiau; // nombre de propriétés du matériau
    double* COORDS; // Coordonnee coor_pt; // coordonnee du point
    double* DROT;   // Mat_pleine mat_corota; // matrice de rotation du corotationnelle
    double* CELENT; // double longueur_characteristique;
    double* DFGRD0; // BaseB giB_t; // base naturelle à t
    double* DFGRD1; // BaseB giB_tdt; // base natuelle à tdt
    int*    NOEL;   // int nb_elem; // numéro de l'élément
    int*    NPT;    // int nb_pt_integ; // numéro du point d'intégration
    int*    LAYER;  // int nb_du_plis; // numéro du plis pour les multicouches 
    int*    KSPT;   // int nb_pt_dans_le_plis; // numéro du point dans le plis
    int*    KSTEP;  // int nb_step; // numéro du step
    int*    KINC;   // int nb_increment; // numéro de l'incrément
    
    // -- variables pour les tubes nommés ----------
    
    // nom du tube nommé pour l'envoi des données
    string envoi;
    // nom du tube nommé pour la reception des données
    string reception; 
    int passage; // test pour nombre de passage dans l'appel
    Tab_car_double_int t_car_x_n; // tableau de caractères, réels et entiers
 
    // --- gestion   d'index 3D classique ----
    class ChangementIndex
       { public:
         ChangementIndex();
         // passage pour les index de la forme vecteur à la forme i,j
         Tableau <int> idx_i,idx_j;
         // passage pour les index de la forme i,j à la forme vecteur
         Tableau2 <int> odVect;
        };
    static const ChangementIndex  cdex;
 
   //	// --- gestion   d'index 2D CP en 3D ----
   	class ChangementIndexCP
   	   { public:
   	     ChangementIndexCP();
   	     // passage pour les index de la forme vecteur à la forme i,j
   	     Tableau <int> idx_i,idx_j;
   	     // passage pour les index de la forme i,j à la forme vecteur
   	     Tableau2 <int> odVect;
   	    };
   	static const ChangementIndexCP  cdexCP;

    
    // METHODES PROTEGEES :
    // 1)-- utilisation en tant qu'umat
    // copie des grandeurs évoluées dans les grandeurs de base
    // uniquement celles qui varient
    void Copie_evolue_vers_base(const int niveau);
    // copie des grandeurs de base vers les grandeurs évoluées
    // uniquement les grandeurs d'entrée (supposées à lire)
    void Copie_base_vers_evolue(const int niveau);
    // 2) -- utilisation en tant qu'utilisation d 'une umat extérieure
    // copie des grandeurs évoluées dans les grandeurs de base
    // uniquement celles qui sont des données
    void Copie_evolue_vers_base_PourUmat(const int niveau);
    // copie des grandeurs de base vers les grandeurs évoluées
    // uniquement celles qui sont des résultats
    void Copie_base_vers_evolue_PourUmat(const int niveau);
    

 };
 
#endif  
