// FICHIER : DdlLim.h
// CLASSES : DdlLim

// 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:        15/04/1997                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *   BUT: La classe DdlLim permet de declarer un ensemble de ddl coiffe *
 *        par une reference utilise pour les conditions limites.  $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/


#ifndef DDLLIM_H
#define DDLLIM_H


#include "Ddl.h"
#include "Tableau_T.h"
#include <iostream>
#include <stdlib.h>
#include "Sortie.h"
#include "UtilLecture.h"
#include "string.h"
#include "string"
#include <list>
#include "MvtSolide.h"
#include "EnuTypeCL.h"

/// @addtogroup Les_classes_Ddl_en_tout_genre
///  @{
///


///     BUT:    La classe DdlLim permet de declarer un ensemble de ddl coiffe   par une reference utilise pour les conditions limites.
///
/// \author    Gérard Rio
/// \version   1.0
/// \date       15/04/1997
///
///


class DdlLim
{ // surcharge de l'operator de lecture
  // les informations sont typées
  friend istream & operator >> (istream &, DdlLim &);
  // surcharge de l'operator d'ecriture typée
  friend ostream & operator << (ostream &, const DdlLim &);
	
	public:
	
		
		// CONSTRUCTEURS :
		             		
		// Constructeur  defaut
		DdlLim ();
		
		// Constructeur de copie
		DdlLim (const DdlLim& d);
		
		
		// DESTRUCTEUR :
		~DdlLim ();
		
		
		// METHODES :

		// Retourne la reference attache au  degre de liberte
		const string& NomRef ()  const {	return ref;	};
		// retourne un pointeur de string donnant le nom du maillage associé
		// = NULL si aucun maillage
		const string* NomMaillage() const {return nom_maillage;}; 
		// retourne le type de condition limite associé
		EnuTypeCL TypeDeCL() const {return typeCL;};
				
		// retourne la taille du tableau de ddl
		int Taille() const { return tab.Taille();};
		  		  
		// retourne le ddl nb i en lecture/écriture
		Ddl& ElemLim(int i) { return tab(i).ddl;};
		// idem en constant
		const Ddl& ElemLim_const(int i) const { return tab(i).ddl;};
		  
		// retourne le nom de la courbe i ou "" s'il n'y en n'a pas
		// dans le cas d'un mouvement solide, c'est uniquement le premier ddl
		// qui contient la courbe de charge éventuelle
		const string& Nom_courbe(int i) const { return tab(i).co_charge;};
 
		// retourne le nom de la fonctionnD i ou "" s'il n'y en n'a pas
		// dans le cas d'un mouvement solide, c'est uniquement le premier ddl
		// qui contient la courbe de charge éventuelle
  const string & NomF_charge(int i) const {return tab(i).f_charge;};

		// retourne si la référence est celle d'un champ ou pas
		bool Champ() const {return champ;};
		
		// retourne si le blocage est relatif ou pas
		// un blocage relatif signifie que le blocage s'effectue par rapport au pas de temps
		// précédent i.e. t=t
		// un blocage non relatif, donc absolue signifie que le blocage s'effectue par rapport à
		// t = 0
		bool BlocageRelatif() const {return blocage_relatif;};
		
		// indique si c'est un mouvement solide ou pas
		bool Mouvement_Solide() const {return (mvtsolide!=NULL);};
		// récupération du mouvement solide
		const MvtSolide* Const_MouvementSolide() const {return mvtsolide;};
		// récupération du mouvement solide
		MvtSolide* MouvementSolide() const {return mvtsolide;};
		
		// retourne l'échelle pour le ddl nb i
		// dans le cas d'un mouvement solide, c'est uniquement le premier ddl
		// qui contient la courbe de charge éventuelle
		double Echelle_courbe(int i) const {return tab(i).echelle;};
  
  // indique si le temps mini et/ou le temps maxi dépend d'une fonction nD
  // retour:
  //    0 : pas de dépendance
  //    1 : tmin uniquement
  //    2 : tmax uniquement
  //    3 : tmin et tmax
  
  int Temps_depend_nD() const
    {int retour = 0; if (nom_fnD_t_min != "") {if (nom_fnD_t_max != "") return 3;else return 1;}
                     else                      {if (nom_fnD_t_max != "") return 2;else return 0;};
    };

  // retour du nom de la fonction nD qui pilote tmin
  // si == "", pas de fonction
  string Nom_fctnD_tmin() const {return nom_fnD_t_min;};
  // idem pour tmax
  string Nom_fctnD_tmax() const {return nom_fnD_t_max;};
  
  // mise à jour de tmin et/ou tmax
  // uniquement s'ils dépendent d'une fct nD
  void Mise_a_jour_tmin_tmax(double tmin, double tmax)
   { if (nom_fnD_t_min != "") t_min = tmin;
     if (nom_fnD_t_max != "") t_max = tmax;
   };
 // mise à jour de tmin
 // uniquement s'il dépend d'une fct nD
 void Mise_a_jour_tmin(double tmin)
  { if (nom_fnD_t_min != "") t_min = tmin;
  };
 // mise à jour de tmax
 // uniquement s'il dépend d'une fct nD
 void Mise_a_jour_tmax(double tmax)
  { if (nom_fnD_t_max != "") t_max = tmax;
  };

		// retourne un booléen qui indique si oui ou non le temps passé en paramètre
		// est situé entre le temps min et maxi du ddllim
		bool Temps_actif(const double& temps) const
		  {if ((t_min < temps) && (temps <= t_max)) 
		      return true;
		   else return false;
    };
		
		// ramène vrai si le temps est inférieur au temps actif
		// ou si d'une part le temps n'est pas actif et qu'au pas précédent
		// il n'était pas également actif
		bool Pas_a_prendre_en_compte(const double& temps) const
		  {if ((temps <= t_min) || ((temps > t_max) && !precedent)) 
		      return true;
		   else return false;
    };
  // ramène vrai si le temps est inférieur ou égale au temps actif, ou supérieur au temps max
  bool Pas_a_prendre_en_compte_dans_intervalle(const double& temps) const
      {if ((temps <= t_min) || (temps > t_max))
          return true;
       else return false;
       };
 
  // affichage et definition interactive des commandes
  // plusieurs_maillages : indique si oui ou non, il y a plusieurs maillage
  void Info_commande_DdlLim(ofstream & sort,bool plusieurs_maillages);	 
		
  // Validation on non de l'activité du ddlLim
  void Validation(const double& temps) {precedent = Temps_actif(temps);};
  // retour du statut de validation
  // vrai signifie que l'état enregistré est actif
  bool Etat_validation() const {return precedent;};

		
  // lecture des degres de liberte
  // sur le fichier d'entree
  // util pour la lecture de ddl bloque    
  void Lecture(UtilLecture & entreePrinc); 
  
  // examine si le ddlmin passé en argument possède les mêmes cibles que this
  // mais que les data associés sont différents
  // ramène true si c'est vrai, false sinon
  bool MemeCibleMaisDataDifferents(const DdlLim& d) const;
  
  // ramène true si le DdlLim contient l'enum_ddl passé en argument, false sinon
  bool Existe_ici_leDdl(Enum_ddl enu) const;
  // ramène true si le DdlLim contient au moins un déplacement, false sinon
  bool Existe_ici_un_deplacement() const;
		
		// Affiche les donnees liees aux degres de liberte 
  void Affiche () const ;
		 
		// Realise l'egalite 		
  DdlLim& operator= (const DdlLim& d);
		
		//Surcharge d'operateur logique
		bool operator == ( const DdlLim& a) const ;
		 
  bool operator != ( const DdlLim& a) const { return !(*this == a);};
        
// ----------- définition de conteneurs à usage interne -----------
	 // cependant elles ne peuvent pas être déclaré en protégé ??
//	protected :
	
  // le conteneur des ddl bloqués
  class Ddlbloque
    { public:
       // surcharge de l'operator de lecture
       friend istream & operator >> (istream & entree, Ddlbloque& d);  
       // surcharge de l'operator d'ecriture
       friend ostream & operator << (ostream & sort, const Ddlbloque& d);
       // constructeur
       Ddlbloque() : co_charge(""),f_charge(""),ddl(),echelle(1.) {};
       Ddlbloque(const Ddlbloque& d): co_charge(d.co_charge)
          ,f_charge(d.f_charge),ddl(d.ddl),echelle(d.echelle) {};
       Ddlbloque(Ddl ddl_): co_charge(""),f_charge(""),ddl(ddl_),echelle(1.) {};
       // destructeur
       ~Ddlbloque() {};
       // surcharge de l'opérateur d'affectation
       Ddlbloque& operator= (const Ddlbloque& d);
       //Surcharge d'operateur logique
       bool operator == ( Ddlbloque& a);
       bool operator != ( Ddlbloque& a);
      public:
       Ddl ddl;           // ddl bloqué
       string  co_charge; // nom d'une courbe de charge éventuelle
       string  f_charge; // nom d'une fonction nD utilisant des variables globales et autres
       double echelle;
    };
	
	protected :
	
	 // données 
	 string* nom_maillage; // nom de maillage associé, éventuellement!
  string ref; // reference  attachee aux ddl
  EnuTypeCL typeCL; // indique éventuellement un type de condition limite associé
                    // = RIEN_TYPE_CL par exemple pour les noeuds (donc ne sert à rien dans ce cas)
                    // = TANGENTE_CL par exemple pour une arête, indique une condition de tangente imposée
  Tableau	<Ddlbloque> tab; // tableau des ddl 
  double t_min,t_max; // temps mini et maxi de durée des ddl imposés
  string nom_fnD_t_min; // nom éventuelle de la fonction associée
  string nom_fnD_t_max; // nom éventuelle de la fonction associée
  int precedent; // pour la description de l'évolution du ddlLim
  bool champ; // indique si c'est une référence de champ ou pas
  bool blocage_relatif; // indique si oui ou non le blocage à t+dt s'effectue
        //  par rapport à t ou par rapport à 0
  MvtSolide* mvtsolide; // indique si diff de NULL qu'il s'agit d'un mouvement solide appliqué
       // si oui, tab contient les 3 ddl de position, dont le premier contient éventuellement
       // une courbe de charge si on veut un pilotage du mvt solide par courbe de charge,
       // ainsi qu'une échelle éventuelle globale 
     
 
 // FONCTIONS PROTEGEES
  // verification en fonction de la dimension du pb
  // par exemple en dim 2 d'existance des UZ ou des X3 etc..
  void VerifDimDdl();
  // lecture dans le cas particulier d'un champ
  list <Ddlbloque> Lecture_champ(UtilLecture & entreePrinc);
  // lecture dans le cas particulier d'un mouvement solide
  list <Ddlbloque> Lecture_mvtSolide(UtilLecture & entreePrinc);
  
  // Remplace la reference du degre de
  // liberte par nouveau
  // ATTENTION : Les modifications liees au changement de la reference du degre
  // de liberte sont a la charge de l'utilisateur, en particulier il n'y a pas
  // de vérification par exemple du fait que c'est un champ ou pas .
  void Change_ref (string nouveau);
  // idem pour le changement de nom de maillage
  // le nouveau nom ne doit pas être vide  !! sinon erreur
  void Change_nom_maillage(const string& nouveau);
	
};
/// @}  // end of group



#endif
