// 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:   Def et application de differentes conditions limites.     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef CONDLIM_H 
#define CONDLIM_H

#include "Mat_abstraite.h"
#include "Vecteur.h"
#include <list>
#include "MathUtil.h"
#include "Mat_pleine.h"
   

/// @addtogroup Les_classes_Matrices
///  @{
///


class CondLim 
{ // pour pouvoir faire des tableaux de condlim on introduit les surcharges de lecture
  // écriture, mais en fait elles ne doivent pas être utilisé d'où une sortie d'erreur
    // surcharge de l'operator de lecture typée
    friend istream & operator >> (istream & ent, CondLim &)
     { cout << "\n erreur, la surcharge de lecture n'est pas implanté "
            << " \n operator >> (istream & ent, CondLim &) " ;
       Sortie(1);  return ent;      
      };      
    // surcharge de l'operator d'ecriture typée
    friend ostream & operator << (ostream & sort, const CondLim &)
     { cout << "\n erreur, la surcharge d'écriture n'est pas implanté "
            << " \n operator << (ostream & sort, const CondLim &)";
       Sortie(1);  return sort;      
      };      

  public :
    // CONSTRUCTEURS :
      CondLim(); 
    // DESTRUCTEUR :
      ~CondLim();
    // METHODES PUBLIQUES :
    //=============================================================================
    // IMPORTANT !! = lorsque l'on a des conditions limites a imposer a un second =
    // membre et a une matrice , il faut d'abord impose a la matrice  puis        =
    // apres au second membre                                                     =
    //=============================================================================
     // valeur imposee au second membre
     // vecglob : le second membre, i : la position globale du ddl impose
     // val : la valeur a imposer
	  // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
	  //        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
     void Val_imposee_Sm(Vecteur& vecglob,int i,double val,Vecteur* vec2);
     // valeur imposee a la matrice et au second membre si la valeur est
     // differente de zero
     // matglob : la matrice, i : la position globale du ddl impose
     // val : la valeur a imposer     
	  // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
	  //        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
     void Val_imposee_Mat(Mat_abstraite & matglob,Vecteur& vecglob,
                         int i,double val,Vecteur* vec2);
     // cas particulier de valeur imposee a une matrice 
     // c'a-dire val sur la diagonale 
     // et des zéros sur le reste de la ligne et colonne corsespondantes
     // matglob : la matrice, i : la position globale du ddl impose
     // dans ce cas-ci il n'y a aucune information sauvegardée, des valeurs modifiées
     // cela signifie qu'après cette fonction, les appels aux routines pour la 
     // remontée aux réactions, n'ont aucun sens     
     void Val_imposSimple_Mat(Mat_abstraite & matglob,int i,double val);
     // remontee aux efforts apres resolution
     // ceci pour la ligne i dans le cas de ddl bloque
     // la matrice est utilisee pour restorer les lignes supprimee
     // par les conditions limites, elle est donc modifiee
     // par cette operation, parcontre ses valeurs initiales ne sont pas utilisees
     double RemonteDdlBloqueMat(Mat_abstraite & matglob,Vecteur& solution, int i); 
     
     // retourne la valeur absolu du maxi des efforts exterieurs
     // et le numero d'assemblage correspondant
     double MaxEffort(int & ili);
     
     // retourne la valeur initiale au second membre avant condition limite
     // en fonction du pointeur d'assemblage
     double ValReact(int & ili);
     
     //------------------------------------------------------------------
     //      cas de conditions limites lineaires entre plusieurs ddl
     //------------------------------------------------------------------
     // la condition est imposee sur la matrice et sur le second membre
     // la mise en place des condition lineaire doit ce faire en deux temps
     // premier temps : préparation  des conditions, c'est a dire expression
     // de la raideur et du second membre dans les reperes locaux ceci pour
     // TOUS LES CONDITIONS
     // second temps : seulement une fois que TOUTES LES changements de reperes
     // sont effectuee, on impose les valeurs de second memebres apres ou avant
     // les valeurs fixe.
     
     // pt : tableau des pointeurs de ddl concerne, pt(i) = la position du ddl i
     // dans la matrice globale
     // val : tableau des coefficients de la condition lineaire
     // valeur : valeur a laquelle est egale la condition lineaire
     // cond lineire  -> somme des val(i) * ddl(pt(i)) = valeur
     // la procedure modifie les reperes d'expression des ddl, mais sauvegarde
     // les infos permettant de reconstruire les reperes initiaux
     // !!! par principe, c'est la direction du premier indice qui est bloquee
     // il faut donc ecrire la condition en consequence

	  // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
	  //        mais sans sauvegarde (correspond par exemple à une partie de vecglob)
     
          // premier temps: changement de repère

     void CondlineaireCHRepere(Mat_abstraite & matglob,Vecteur& vecglob,
              const Tableau<int> & pt,const Vecteur& val, double valeur,Vecteur* vec2);
     
         // second temps : imposition des blocages correspondant
         //                aux conditions lineaires
         
     void CondlineaireImpose (Mat_abstraite & matglob,Vecteur& vecglob,Vecteur* vec2);  
     
     
     //expression du vecteur resultat dans les reperes initiaux
     // sol : la solution, est modifie et retournee dans les reperes initiaux
     void RepInitiaux( Vecteur& sol);
 
     // application d'une condition linéaire seule, avec en retour, la situation de la condition linéaire
     // imposée, ramené dans le repère initial
     void CondiLineaireImposeComplet(Mat_abstraite & matglob,Vecteur& vecglob,
                       const Tableau<int> & pt,const Vecteur& val, double valeur,Vecteur* vec2);
     
          
     // remise a zero des sauvegardes de second membre et de matrice
     void EffaceSauvegarde();

     // remise a zero des sauvegardes de condition lineaire
     void EffaceCoLin();
     

               
  private :  
    // VARIABLES PROTEGEES :
     // concernant une valeur imposee pour le second membre, on defini une
     // class qui permet d'enregistrer les ddl impose
      class ImpSM
       { public :
         ImpSM () {}; // par defaut
         ImpSM (int i, double val) : iligne(i), valeur(val) {};
         ImpSM (const ImpSM & a) : iligne(a.iligne), valeur(a.valeur) {};
         ~ImpSM () {};
         ImpSM& operator=( const ImpSM& a)  ; // assigment
                  
         int iligne; // ligne ou le ddl est impose
         double valeur; // sauvegarde de la valeur existant avant le ddl impose         
       };
       
     // on definit une liste STL comme container  
     list <ImpSM> VImpSM;     
    
    //concernant une valeur imposee pour la raideur, on defini une
    // class qui permette d'enregistrer les modifications effectuees
    // sur la raideur
     class ImpRaid
       { public :
         ImpRaid (); // par defaut
         ImpRaid (int i,const Vecteur& vL,const Vecteur& vC,double val);
         ImpRaid (const ImpRaid & a) ; // constructeur de copie
         ~ImpRaid() {};  // destructeur
         ImpRaid& operator=( const ImpRaid& a)  ; // assigment         
         
         int ilicol; // ligne et colonne ou le ddl est impose
         Vecteur  ligne; // ligne du ddl impose
         Vecteur  colonne; // colonne  du ddl impose 
         double valeur; // valeur du ddl impose        
       };
     // on definit une liste STL comme container  
     list <ImpRaid> VImpRaid;
          
    //concernant les conditions lineaires, on defini une
    // class qui permette d'enregistrer le changement de repere
     class lineaires
       { public :
         lineaires (); // par defaut
         lineaires (int i,const Vecteur& vL,const Tableau<int> & ptt,double vale);
         lineaires (const lineaires & a) ; // constructeur de copie
         ~lineaires() {};  // destructeur
         lineaires& operator=( const lineaires& a) ; // assigment         
         
         int indice; // numero dans le tableau pt qui permet d'obtenir les 
                      //ligne et colonne du ddl modifie en condition lineaire
         Vecteur  val; // vecteur des coefficients de la condition lineaire
         Tableau<int>  pt; // pt : tableau des pointeurs de ddl concerne, pt(i) = la position du ddl i
                            // dans la matrice globale 
         double valeur; // valeur de la condition lineaire       
       };
     // on definit une liste STL comme container  
     list <lineaires> Vlineaires;
 
     // méthode pour faire une rotation de la matrice et du second membre suivant un vecteur
     // vec2 : est un second vecteur éventuel (si != NULL)
     void Rotation(Mat_abstraite & matglob,Vecteur& vecglob,
                   const Tableau<int> & pt,const Vecteur& val,Vecteur* vec2);
     
     // déclaration d'une variable de travail, utilisée par CondlineaireCHRepere
     static  Mat_pleine matinter; // mise en commun pour éviter des constructions inutiles

     
    // METHODES PROTEGEES :

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

#endif