
// 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:        19/01/2007                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:    gérer les conditions limites linéaires en I/O            *
 *             en particulier comme conteneur.                          *
 *     informations: pour l'instant on considère une conditions         *
 *     linéaires entre les ddl d'une même famille d'un noeud.           *
 *     Une instance de I_O_Condilineaire peut générer un grand nombres  *
 *     de conditions linéaires particulières, en fait autant que de     *
 *     noeuds appartenant à la référence principal. Ces conditions      *
 *     particulières ne sont pas stockées dans I_O_Condilineaire !!     *
 *     par contre, elles peuvent être générées par I_O_Condilineaire.   *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef I_O_CONDILINEAIRE_H
#define I_O_CONDILINEAIRE_H

#include "Condilineaire.h"
#include "Plan.h"
#include "Droite.h"

/// @addtogroup Les_classes_relatives_aux_conditions_limites
///  @{
///
class I_O_Condilineaire : public Condilineaire
{   // surcharge de l'operator de lecture
    // les informations sont typées
    friend istream & operator >> (istream &, I_O_Condilineaire &);
    // surcharge de l'operator d'ecriture typée
    friend ostream & operator << (ostream &, const I_O_Condilineaire &);
    
  public :
    // CONSTRUCTEURS :
    
    // par défaut
    I_O_Condilineaire();
    // de copie
    I_O_Condilineaire(const I_O_Condilineaire& nd);
    // DESTRUCTEUR :
    ~I_O_Condilineaire();
 
    
    // METHODES PUBLIQUES :
    
    // Retourne la reference attache à la condition linéaire
    const string& NomRef ()  const {	return refe;	};
    // retourne un pointeur de string donnant le nom du maillage associé
    // = NULL si aucun maillage
    const string* NomMaillage() const {return nom_maillage;}; 
    
    // retourne le tableau des références associées (peut-être vide !)
    const Tableau <string> & ReferenceAssociees() const {return refs_associe;};
    // retourne le tableau des nom de maillage associées aux noms de ref (peut être = 0)
    // tail = 0 si il n'y a pas de nom de maillage sur la ref principale 
    const Tableau <string > & NomMaillageAssociees() const {return nom_mail_associe;};
	
    // examine si la condition passée 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(I_O_Condilineaire& d);        
    
    // Affiche les donnees 
    void Affiche () const ;
    // Realise l'egalite 		
    I_O_Condilineaire& operator= (const I_O_Condilineaire& d);
    
    //Surcharge d'operateur logique: ne concerne que la condition initiale (pas la condition actuelle,
    // c-a-d les coeff actuelles et les noeuds actuellement en cause etc.)
    bool operator == ( I_O_Condilineaire& a) const ;
	
    bool operator != ( I_O_Condilineaire& a) const { return !(*this == a);};
         		
    // lecture de la condition linéaire sur le fichier d'entree
    void Lecture(UtilLecture & entreePrinc); 
		
    // retourne si la condition est relative ou pas
    // une condition relative signifie que la condition s'effectue par rapport au pas de temps
    // précédent i.e. t=t
    // une condition non relative, donc absolue signifie que la condition s'effectue par rapport à 
    // t = 0
    bool ConditionRelative() const {return condition_relative;};
 
    //--- cas des conditions linéaires type plan ou droite ---------------------------------------------
    
    // ramène true si on a effectivement une condi linéaire type plan ou droite
    bool PlanDroite() const {return def_auto_par_rotation;};
    
    // indique si le blocage qui existe déjà sur les noeuds à projeter, est cohérent
    // avec la projection:
    // typiquement si la direction de blocage est normale au plan de rotation
    // ramène true si on peut concerver la condition de projection
    // en entrée: indi qui donne la direction déjà bloquée
    bool Coherence_condi_PlanDroite(int indi)const;
 
    // ramène true si on a effectivement une condi linéaire type stricte_egalite
    bool StricteEgalite() const {return stricte_egalite;};
 
    //  le nom du maillage éventuellement et le numéro du noeud s'il y a  un noeud rotation
    // sinon ramène un pointeur null
    const String_et_entier* RefNoeudRotation() const {if (type_centre==1){return NULL;}
                                                      else {return &mailEtNumCentreNoeud;};};
    // definition du noeud: centre rotation
    void ChangeCentreNoeudRotation( Noeud* noe);
    // définition de la direction actuelle ou normale pour plan droite
    void ActualiseDirectionPlanDroite();
    // projection (normale) du point M sur le plan ou droite, ramène le point M à la place du
    // projeté, et calcul de la condition linéaire correspondant à la projection
    Coordonnee& ProjectionSurPlanDroite_et_calValCondiLin(Coordonnee& M );
    
    
    
    // --- fin des condi linéaires types plan droite ---------------------------------------------------
    
    // Construction de la condition : en particulier les pointeurs de ddl permettant d'imposer la condition
    // et  def des coefficients en fonction éventuellement du temps ou de l'incrément du temps selon
    // le paramètre condition_relative
    // pour cela 
    // 1) on doit renseigner les fonctions de charge si elles existent
    //   a) retour du nombre de fonction de charge
    int ExisteFonctionChargeCoef()const {return tab_co_charge.Taille();};
    //   b) le nom de la courbe
    const string & NomFctch(int i) const {return tab_co_charge(i);};
    //   b) on renseigne les valeurs des fonctions de charge
    void Valeur_fonctionChargeCoef(const Vecteur & fctch_,const Vecteur & delta_fctch_) 
                                            {fctch = fctch_;delta_fctch = delta_fctch_;};
    // 2) 
    // Construction de la condition : 1) mise en place d'une valeur imposée due à la condition linéaire 
    // def des coefficients en fonction éventuellement des fonctions de charges et du  paramètre condition_relative
    // NB: pour les conditions correspondant à une projection sur un plan ou une droite, il faut que la direction du plan
    //     ou de la droite ait déjà été affecté auparavant
    // !! la condition sur le ddl n'est pas imposée à ce niveau, par contre elle est stockée dans Condilineaire
    Condilineaire& ConstructionCondition(Tableau <Noeud *> & t_noe,Condilineaire& condi_actuelle);
    
    // affichage des commandes particulières à la définition d'une condition linéaire
    void Info_commande_conditionLineaire(ofstream & sort,bool plusieurs_maillages);
    
    // récupération de l'énuméré du type de ddl considéré par la condition limite linéaire
    Enum_ddl TypeEnu() const {return enu;};

    // retourne un booléen qui indique si oui ou non le temps passé en paramètre
    // est situé entre le temps min et maxi de la condition linéaire
    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 supérieur au temps max
    // 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;
      };
    // Validation on non de l'activité de la charge
    void Validation(const double& temps) {precedent = Temps_actif(temps);
                                          valeur_precedente_t = beta;};
    // retour du statut de validation
    // vrai signifie que l'état enregistré est actif
    bool Etat_validation() const {return precedent;};

    // initialisation des grandeurs de travail
    void Initialisation_condil();  
   
  protected :  
    // informations: pour l'instant on considère une conditions linéaires entre les ddl d'une même
    // famille d'un noeud.

    // données
    string* nom_maillage; // nom de maillage associé, éventuellement!
    string refe; // reference  principale attachee aux ddl
    Tableau <string> refs_associe;
          // dans le cas où il y a une condition linéaire entre plusieurs
          // noeuds, la méthode retenue est la suivante: à chaque noeud de refe on associe un noeuds
          // de chaque référence du tableau refs_associe, et on prend les ddl de type enu de chaque ref
          // et on a une combinaison linéaire entre chacun. Dans ce cas, il faut donc que toutes les 
          // référence aient le même nombre de noeuds
    Tableau <string > nom_mail_associe; // dans le cas où nom_maillage est non null
          // il faut que toutes les références associées aient un nom de maillage associé      
    double t_min,t_max; // temps mini et maxi de durée des ddl imposés
    double echelle; // échelle globale éventuelle
    Enum_ddl enu; // identificateur du premier  ddl de la famille pour laquelle on a une condition linéaire
       // les ddl s'appliques d'abord à suivre à chaque noeud
    int nbddlfamille; // nombre de ddl de la famille associée à enu       
    int condition_relative; // indique si oui ou non la condition à t+dt s'effectue
       //  par rapport à t ou par rapport à 0
    int precedent; // pour la description de l'évolution d'un temps à l'autre       
    double valeur_precedente_t; // valeur à t
    
    Tableau <string> tab_co_charge; // même dimension que (le nombre de ddl de type enu) * (1+le nombre
          // de ref associé) s'il y a des courbes de charge
          // Permet d'avoir des coefficients  qui varient. S'il y a une courbe de charge 
          // alors toutes existent sinon aucune
    Vecteur fctch,delta_fctch; // vecteur de travail qui contient les valeurs des fonctions de charge
                               // et leur acroissment entre t et t+deltat
                                
    //--- variables particulières pour la définition automatique d'une condition linéaire sur plan ou droite
    bool def_auto_par_rotation;// signale le cas particulier du condition linéaire automatique
    int type_centre;   // = 1 on a un centre fixe c-a-d: centre_rotation, =2 le centre est centre_noeud à t=0
                       // =3 le centre est centre_noeud à t 
    Coordonnee centre_rotation; // position du centre de rotation fixe
    String_et_entier mailEtNumCentreNoeud; // maillage et numéro du centre noeud s'il existe
    Noeud* centre_noeud; 
    Plan pl; 
    Droite dr;
 
    //--- variables particulières pour la condition particulière d'égalité exacte, pour tous les ddl
    //    du type enu, -> traitement particulier
    bool stricte_egalite;

    // 1) cas simple: pas de ref associe cela signifie que la condition linéaire concerne uniquement
    // des ddl de chaque noeud de la ref principal. Pour chaque noeud on applique la même condition (au
    // mvt solide près). La taille de val
    // 1) cas où l'on a des références secondaire, celle-ci doivent avoir tous le même nombre de noeud,
    // identique à la ref principal. Supposons qu'il y a na liste associé. La condition linéaire relie
    // les ddl de na+1 noeud, chacun étant pris dans une ref associé + 1 sur la ref principal. Pour chaque
    // noeud la liste des enu_ddl du même type que enu est parcouru: soit t_enu leur nombre. Donc au final, 
    // la taille de val (qui contient les coeff de la condition linéaire = (na+1)*t_enu
 };
 /// @}  // end of group


#endif  
