
// 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:   Gestion des chargements.                                  *
 *         Chargement en temps :                                        *
 *                                                                      *
 *      ^	                                                            *
 *    1 |    t1--------                                                 *
 *      |   /                                                           *
 *      |  /                           Type 1 = une rampe linéaire      * 
 *      | /                             puis un plateau horizontal      *
 *      0------------------> t                                          *
 *                                                                      * 
 *                                                                      *
 *     ^	             Type 2 = une rampe linéaire                    *
 *   1 |    t1-----t2             un plateau puis arrêt                 *
 *     |   /        |                                                   *   
 *     |  /         |                                                   * 
 *     | /          |                                                   *
 *     0------------------> t                                           *
 *                                                                      *
 *     ^	             Type 3 = uniquement un plateau                 *
 *   1 |------------------- .....                                       *
 *     |                                                                *   
 *     |                                                                * 
 *     |                                                                *
 *     0------------------> t                                           *
 *                                                                      *      
 *                      Type 4 = utilisation d'une courbe 1D quelconque *
 *                                                                      *
 *                      Type 5 utilisation d'un fichier de points qui   *
 *      impose la suite de temps de calcul, donc de pas de temps        *
 *                                                                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef CHARGE_H
#define CHARGE_H

#include "LectBloc_T.h"
#include "ParaGlob.h"
#include "Bloc.h"
#include <list>
#include "ParaAlgoControle.h"
#include "LesMaillages.h"
#include "Mat_abstraite.h"
#include "Assemblage.h"
#include "Nb_assemb.h"
#include "Courbe1D.h"
#include "BlocCharge_T.h"
#include "LesCourbes1D.h"
#include "LesFonctions_nD.h"
#include "BlocCharge.h"
#include "Temps_CPU_HZpp.h"


/** @defgroup Groupe_concernant_le_chargement
*
*     BUT:   groupe relatif aux chargements
*
*
* \author      Gérard Rio
* \version     1.0
* \date        23/01/97
* \brief       groupe relatif aux chargements
*
*/

/// @addtogroup Groupe_concernant_le_chargement
///  @{
///


class Charge
{
  public :
    // VARIABLES PUBLIQUES :
    // ---- class intermédiaires ----- 
    class PHydro : public BlocGeneEtVecMultType
     { public : // surcharge de l'operator de lecture
       friend istream & operator >> (istream & entree, PHydro & coo)
         { entree >> ((BlocGeneEtVecMultType&)(coo)); return entree;};
       // surcharge de l'operator d'ecriture
       friend ostream & operator << (ostream & sort, const PHydro & coo)
         { sort << ((const BlocGeneEtVecMultType&)(coo)); return sort; };     
       PHydro(); // constructeur par défaut
       PHydro (const PHydro & a) ; // constructeur par defaut
       ~PHydro () ; // destructeur
      
       // mise en place de l'association des courbes
       // en retour indique si l'association est ok
       bool Mise_en_place_des_courbes(LesCourbes1D& lesCourbes1D);
       const Coordonnee& Direction_N(); // récup de la direction N normée
       const Coordonnee& Point_M(); // récup du point de la surface libre
       protected :
       Tableau <Courbe1D*> N; // courbes permettant de piloter éventuellement la normale
       Tableau <Courbe1D*> M; // courbes permettant de piloter éventuellement le point de la surface neutre
       bool normer; // dans le cas de vecteur N constant, indique si le vecteur a été normé ou pas
     };
    class PHydrodyna : public BlocGen
     { public : // surcharge de l'operator de lecture
       friend istream & operator >> (istream & entree, PHydrodyna & coo)
         { entree >> ((BlocGen&)(coo)); return entree;};
       // surcharge de l'operator d'ecriture
       friend ostream & operator << (ostream & sort, const PHydrodyna & coo)
         { sort << ((const BlocGen&)(coo)); return sort; };     
       PHydrodyna () : BlocGen(5,1),frot_fluid(NULL),coef_aero_n(NULL),coef_aero_t(NULL) {}; 
       // mise en place de l'association des courbes
       // en retour indique si l'association est ok
       bool Mise_en_place_des_courbes(LesCourbes1D& lesCourbes1D);
       Courbe1D* Frot_fluid() const  { return frot_fluid;};
       Courbe1D* Coef_aero_n() const  { return coef_aero_n;};
       Courbe1D* Coef_aero_t() const  { return coef_aero_t;};
       protected :
       Courbe1D* frot_fluid; // courbe de frottement fluide
       Courbe1D* coef_aero_n; // courbe pour l'effort de traînée
       Courbe1D* coef_aero_t; // courbe pour l'effort de portance
     };
 
 
    // ---- fin class intermédiaires ----- 
    
    // CONSTRUCTEURS :
    Charge () ;  // constructeur par defaut
    // DESTRUCTEUR :
    ~Charge () ;
    
    // METHODES PUBLIQUES :
    
    // affichage des differents chargements
    void Affiche() const ;  // affiche la totalite
    void Affiche1() const ; // affiche que la premiere lecture
    void Affiche2() const ; // affiche que la seconde lecture
    
    // lecture des differents chargements actions exterieurs imposees
    void Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD);
    
    // lecture du type d'application du chargements
    void Lecture2(UtilLecture & entreePrinc,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD);
    
    // initialisation du chargement
    //  on verifie egalement la bonne adequation des references
    void Initialise(LesMaillages * lesMail,LesReferences* lesRef,ParaAlgoControle& pa
                    ,const LesCourbes1D& lesCourbes1D,const LesFonctions_nD&  lesFonctionsnD);
    // dans le cas où on utilise plusieurs algorithmes, il faut pouvoir changer
    // de paramètres de contrôle
    void ChangeParaAlgoControle(ParaAlgoControle& pa)
     {paAlgo = & pa;};
     
    // avancement de la charge
    // il peut y avoir plusieurs type d'avancement
    // en fonction des donnees ( transparent pour l'utilisateur)
    // mais aussi en fonction des parametres 
    // incrémentation d'un compteur, permet de limiter le nombre d'appel
    // retourne false par défaut, mais si le pas de temps a été modifié
    // retourne true !!, car par exemple de la fin du chargement, d'où une modif du pas
    // pour obtenir exactement la fin
    bool Avance(); // premier version
    
    // retour de la charge au cas précédent, c'est à dire
    // avant le dernier ordre d'avancement
    // valeur par défaut de "exacte " 
    // si exacte n'est pas présent ou faux: le compteur d'appel de Avance(), n'est pas décrémenté
    // exacte=true:  le compteur d'appel est décrémenté, en fait on revient exactement au départ
    // ce qui permet d'utiliser plusieurs fois Avance() dans un même pas de temps
    // en comptabilisant par exemple qu'une seule fois un appel de Avance(), cas d'une intégration
    // temporelle par exemple
    void Precedant(bool exacte=false);
    
    // diminution de l'incrément de charge dans le cas par exemple d'une non convergence
    // ramène true si la diminution est effective, sinon false
    bool Diminue_inc_charge(double diminue);
    // augmentation de l'incrément de charge dans le cas de bonne convergence
    // ramène true si l'augmentation est effective, sinon false
    bool Augmente_inc_charge(double augmente);

    // declaration de la fin en fonction du type de chargement
    // retour:
    // retour:
    //  0 : la fin n'est pas valide, on continue
    //  1 : temps fin dépassé
    //  2 : compteur_increment dépassé
    //  3 : compteur_essai_increment dépassé
    // NB: c'est d'abort le temps fin qui est testé: qui donc conduit à un arrêt normal
    //     puis ensuite le compteur d'incréments
    //     puis le nombre d'essai maxi, puis enfin le cas normal
    // si affichage est true, affichage d'un message
    int Fin(const int & icharge,bool affichage = true);
    
    // retourne l'increment du coef multiplicateur de charge, courant    
    inline double MultCharge()  
      { return multi;};

    // retourne le coef multiplicateur de charge, courant    
    inline double IntensiteCharge()  
      { return coeff;};
      
    // retourne le temps courant ou en est le calcul
    inline double Temps_courant () {return paAlgo->Variables_de_temps().TempsCourant();};  
    // incrément de temps courant
    inline double Increment_de_Temps() {return paAlgo->Variables_de_temps().IncreTempsCourant();};
 
    // la manière dont on vise le temps fin
    // = 0 par défaut pour les schéma implicite: indique
    // que l'on doit viser le temps fin de manière stricte (pas le dépasser)
    // = 1 : on doit juste le dépasser -> a priori c'est le fonctionnement par défaut des
    //       algo explicites, compte tenu qu'il n'y a pas de prise en compte précise
    //       de la variation du pas de temps
    // mise à jour avec la méthode :
    void Change_temps_fin_non_stricte(int methode)
      {temps_fin_non_stricte = methode;};
 
    // retourne le temps cumulés relatif à tous les chargements
    const Temps_CPU_HZpp& Temps_cpu_chargement() const {return temps_cpu_chargement;};

    // mise en place du chargement impose sur le second membre global
    // cas explicite
    // la variable relative à la classe assemblage est passé en argument ce qui permet d'utiliser
    // éventuellement plusieurs type d'assemblage
    // retour false si problème de calcul
    bool ChargeSecondMembre_Ex_mecaSolid
          (Assemblage & assemb,LesMaillages * lesMail,LesReferences* lesRef,Vecteur& vecglob
           ,const ParaAlgoControle & pa,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD);
    
    // cas implicite avec également modification de la raideur quand le chargement dépend
    // de la géométrie, en fonction des paramètres de pa
    // la variable relative à la classe assemblage est passé en argument ce qui permet d'utiliser
    // éventuellement plusieurs type d'assemblage
    // de plus il faut prévoir un pointeur d'assemblage pour séparer le cas d'assemblage symétrique ou non
    // d'où la variable pointeur de fonction membre d'assemblage
    // retour false si problème de calcul
    bool ChargeSMembreRaideur_Im_mecaSolid(Assemblage & assemb,LesMaillages * lesMail,LesReferences* lesRef
                                 ,Vecteur& vecglob, Mat_abstraite& matglob
                                 ,void (Assemblage::* assembMat) // le pointeur de fonction
                                       (Mat_abstraite & matglob,const Mat_abstraite & matloc,
                                        const DdlElement& tab_ddl,const Tableau<Noeud *>&tab_noeud)
                                 ,const ParaAlgoControle & pa
                                 ,LesCourbes1D* lesCourbes1D,LesFonctions_nD*  lesFonctionsnD);

    // lecture de donnée en fonction d'un indicateur : int type
    // pour l'instant ne fait rien
    void   LectureDonneesExternes(UtilLecture& ,LesReferences& ,const int,const string& ) {};
    
    // affichage et definition interactive des commandes
    void Info_commande_LesCharges1(UtilLecture & entreePrinc);
    
    // affichage et definition interactive des commandes
    void Info_commande_LesCharges2(UtilLecture & entreePrinc);
	 
	   //----- 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)
	   void Lecture_base_info(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD);
    // 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(ofstream& sort,const int cas);

  private :  
    // VARIABLES PROTEGEES :
    // les forces sont les entitees duales des degres de liberte
    // par exemple, force ponctuelle est duale de Xi ou Ui ou Vi
       
     // densite de force volumique dans le repère absolu     
    Tableau < BlocCharge< BlocDdlLim<BlocForces> > > tabFvol;
     // densite de force surfacique dans le repère absolu     
    Tableau < BlocCharge< BlocDdlLim<BlocForces> > > tabFsurfac;
    // pression uniformement reparti, appliquee normalement a la surface
    Tableau < BlocCharge< BlocDdlLim<BlocIntensite> > > tabPresUnif;
    // force ponctuelle sur un noeud
    Tableau < BlocCharge< BlocDdlLim<BlocForces> > > tabPonctuel;
    // pression unidirectionnelle type pression  des fluides
    Tableau < BlocCharge< BlocDdlLim<BlocForces> > > PresUniDir;
    // pression hydrostatique
    Tableau < BlocCharge< BlocDdlLim<PHydro> > > PresHydro; 
    // pression hydrodynamique
    Tableau < BlocCharge< BlocDdlLim<PHydrodyna> > > coefHydroDyna; 
     // densite de force lineique dans le repère absolu     
    Tableau < BlocCharge< BlocDdlLim<BlocForces> > > tabFlineique;
    // densite de force lineique suiveuse, c'est-à-dire qui suit le repère
    // locale (possible uniquement pour des éléments 2D)
    Tableau < BlocCharge< BlocDdlLim<BlocForces> > > tabFlineiqueSuiv;
    // torseur d'effort via une répartition de charges ponctuelles
    Tableau < BlocCharge< BlocDdlLim<PTorseurPonct> > > tabTorseurPonct;
    Tableau < Tableau < Coordonnee > > tab_P; // tableau de travail pour tabTorseurPonct
    Tableau < Tableau < Coordonnee > > t_force; // idem
    
    // ---- type d'application du chargement -----
    string nomtypeCharge; // mot cle du type de chargement
    Tableau<double> tabType; // les parametres
	   Courbe1D* f_charge; // courbe de chargement éventuelle
	   bool interne_f_charge; // indique si oui ou non la courbe interne
	   int ancien_num_pt_type5, num_pt_courant_type5; // variables de travaille pour le type 5
    
    // les paramètres globaux 
    ParaAlgoControle* paAlgo;
    // le parametre global d'avancement de la charge
//    double temps;
    // compteur d'increment
    int compteur_essai_increment;
    // multi = l'increment courant de multiplication de la charge
    // coeff =  niveau actuel de la charge
    double multi,coeff;
    // la sauvegarde des paramètres d'un pas sur l'autre
    double temps_sauve;
    double multi_sauve,coeff_sauve;
 
    // la manière dont on vise le temps fin
    int temps_fin_non_stricte; // = 0 par défaut pour les schéma implicite: indique
        // que l'on doit viser le temps fin de manière stricte (pas le dépasser)
        // = 1 : on doit juste le dépasser -> a priori c'est le fonctionnement par défaut des
        //       algo explicites, compte tenu qu'il n'y a pas de prise en compte précise
        //       de la variation du pas de temps
        // mise à jour avec la méthode : Change_temps_fin_non_stricte(int methode)

    Temps_CPU_HZpp temps_cpu_chargement; // le temps cpu du à tous les chargements
 
    // les autres parametres relatif au temps
   //-// double deltatmaxi;  // increment de temps maxi
   //-// double prectemps; // precision sur le temps final
   //-// double deltat;  // increment de temps
   //-// double tempsfin; // temps de fin de calcul
   //-// int maxincre ; // maximum d'increment de temps
   //-// double multiplicateur; // multiplicateur de la charge
    
    // pointeurs des fonctions en cours
    void (Charge::*PtDebut) (void);
    bool (Charge::*PtAvance) (void);
    void (Charge::*PtPrecedent) (void);
    int (Charge::*PtFin) (const int & icharge,bool affichage); // affichage indique si oui ou non on
      // on veut un affichage signifiant que l'on est à la fin du chargement

    // METHODES PROTEGEES :
    // declaration des initialisations en fonction du type de chargement
    void Debut1();
    void Debut2();
    void Debut3();
    void Debut4();
    void Debut5();
    void Debut6();
    void Debut7();
    // declaration de l'avancement en fonction du type de chargement
    bool Avance1();
    bool Avance2();
    bool Avance3();
    bool Avance4();
    bool Avance5();
    bool Avance6();
    bool Avance7();
    // declaration du retour à l'incrément précédent en fonction du type de chargement
    void Precedent1();
    void Precedent2();
    void Precedent3();
    void Precedent4();
    void Precedent5();
    void Precedent6();
    void Precedent7();
    // declaration de la fin en fonction du type de chargement
    //  0 : la fin n'est pas valide, on continue
    //  1 : temps fin dépassé
    //  2 : compteur_increment dépassé
    //  3 : compteur_essai_increment dépassé
    // NB: c'est d'abort le temps fin qui est testé: qui donc conduit à un arrêt normal
    //     puis ensuite le compteur d'incréments
    //     puis le nombre d'essai maxi, puis enfin le cas normal
    // si affichage est true, affichage d'un message
    int Fin1(const int & icharge,bool affichage);
    int Fin2(const int & icharge,bool affichage);
    int Fin3(const int & icharge,bool affichage);
    int Fin4(const int & icharge,bool affichage);
    int Fin5(const int & icharge,bool affichage);
    int Fin6(const int & icharge,bool affichage);
    int Fin7(const int & icharge,bool affichage);
    

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

#endif  
