// FICHIER : Ddl.cp
// CLASSE : Ddl

// 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/>.



#include "Ddl.h"


# include <iostream>
using namespace std;  //introduces namespace std

#include <stdlib.h>
#include "Sortie.h"
	  
#ifndef  Ddl_deja_inclus

#ifndef MISE_AU_POINT
  inline 
#endif
Ddl::Ddl (Enum_ddl id_nom_ddl,double val,Enum_boolddl val_fixe) :
   id_nom(id_nom_ddl),val_ddl(val),fixe(val_fixe)
// Constructeur utile quand l'identificateur de nom  du degre de
// liberte  sont connus
// ( N.B. : Tous les parametres de ce constructeur ont des valeurs par defaut.
//  Ce constructeur peut donc servir de constructeur par defaut. ) 
{};

#ifndef MISE_AU_POINT
  inline 
#endif
Ddl::Ddl (char* nom,double val,Enum_boolddl val_fixe) :
   val_ddl(val),fixe(val_fixe)
// Constructeur utile quand le nom et la valeur du degre de liberte sont
// connus
// ( N.B. : val et val_fixe ont des valeurs par defaut, il n'est par consequent
// pas obligatoire de leur donner des valeurs a l'appel de ce constructeur )
{   id_nom=Id_nom_ddl(nom);
};

#ifndef MISE_AU_POINT
  inline 
#endif
Ddl::Ddl (const Ddl& d)
// Constructeur de copie
{	id_nom=d.id_nom;
	val_ddl=d.val_ddl;
	fixe=d.fixe;	
};

#ifndef MISE_AU_POINT
  inline 
#endif
Ddl::~Ddl ()
// Destructeur
{ };

  
#ifndef MISE_AU_POINT
  inline 
#endif
// Retourne 1 si le degre de liberte a une valeur fixée tout au long du calcul
// Retourne 0 sinon
// ne concerne que les variables (par exemple ne concerne pas les données)
bool Ddl::Fixe() const
{switch (fixe)
		{ case FIXE : case SURFIXE: case LISIBLE_FIXE:  case LISIBLE_SURFIXE:
    case HS_LISIBLE_FIXE: case HS_SURFIXE: case HS_LISIBLE_SURFIXE:
    case HSFIXE: return  true;break;
		  case LIBRE : case SOUSLIBRE: case LISIBLE_LIBRE: case LISIBLE_SOUSLIBRE:
    case HS_LISIBLE_LIBRE: case HS_SOUSLIBRE: case HS_LISIBLE_SOUSLIBRE:
    case HSLIBRE: return  false;break;

    default : 
     #ifdef MISE_AU_POINT
			        cout << "\nErreur : valeur incorrecte du type ddl !\n";
			        cout << "Ddl.Fixe(): val= " << fixe;
			        Sortie(1);
     #endif
     break;
   }   
	 // la ligne suivante ne sert pas mais c'est pour ne pas avoir de Warning
     return false ; 
};

#ifndef MISE_AU_POINT
  inline 
#endif
// test pour savoir si le ddl est une variable ou une donnée
bool Ddl::UneVariable() const
  { switch (fixe)
     { case LIBRE: case FIXE : case SOUSLIBRE: case SURFIXE:
       case HSLIBRE: case HSFIXE: case HS_SOUSLIBRE: case HS_SURFIXE:
            return  true; break;
       case LISIBLE_LIBRE: case LISIBLE_FIXE : 
       case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE:
       case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE:
       case HS_LISIBLE_SOUSLIBRE: case HS_LISIBLE_SURFIXE: 
            return  false;break;
       default : 
              cout << "\nErreur : degre de liberte non defini !\n";
              cout << "\n UneVariable() " << fixe;
              Sortie(1);
     };
	   // la ligne suivante ne sert pas mais c'est pour ne pas avoir de Warning
    return false ;
  };
   
#ifndef MISE_AU_POINT
  inline 
#endif
// changement du statut de variable à donnée
void Ddl::ChangeVariable_a_Donnee()
  {  switch (fixe)
		{ case LIBRE: fixe = LISIBLE_LIBRE; break;
		  case FIXE : fixe = LISIBLE_FIXE; break;
		  case SOUSLIBRE: fixe = LISIBLE_SOUSLIBRE; break;
		  case SURFIXE: fixe = LISIBLE_SURFIXE; break;
		  case HSLIBRE: fixe = HS_LISIBLE_LIBRE; break;
		  case HSFIXE: fixe = HS_LISIBLE_FIXE; break;
		  case HS_SOUSLIBRE: fixe = HS_LISIBLE_SOUSLIBRE; break;
		  case HS_SURFIXE: fixe = HS_LISIBLE_SURFIXE; break;
          // cas déjà une variable on ne fait rien
		  case LISIBLE_LIBRE: case LISIBLE_FIXE : 
		  case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE:
		  case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE:  
		  case HS_LISIBLE_SOUSLIBRE: case HS_LISIBLE_SURFIXE: break;
    
    default : 
			        cout << "\nErreur : degre de liberte non defini !\n";
			        cout << "\n Ddl::ChangeVariable_a_Donnee() " << fixe;
			        Sortie(1);
		   }   
   };

#ifndef MISE_AU_POINT
  inline 
#endif
// changement du statut de donnée à variable
void Ddl::ChangeDonnee_a_Variable()
  {  switch (fixe)
		{ case LISIBLE_LIBRE : fixe = LIBRE; break;
		  case LISIBLE_FIXE  : fixe = FIXE; break;
		  case LISIBLE_SOUSLIBRE : fixe = SOUSLIBRE; break;
		  case LISIBLE_SURFIXE : fixe = SURFIXE; break;
		  case HS_LISIBLE_LIBRE : fixe = HSLIBRE; break;
		  case HS_LISIBLE_FIXE : fixe = HSFIXE; break;
		  case HS_LISIBLE_SOUSLIBRE: fixe = HS_SOUSLIBRE; break;
		  case HS_LISIBLE_SURFIXE: fixe = HS_SURFIXE; break; 
          // cas déjà une variable on ne fait rien
		  case LIBRE: case FIXE : case SOUSLIBRE: case SURFIXE:
		  case HSLIBRE: case HSFIXE:  
		  case HS_SOUSLIBRE: case HS_SURFIXE: break;
    default : 
			        cout << "\nErreur : degre de liberte non defini !\n";
			        cout << "\n ChangeDonnee_a_Variable() " << fixe;
			        Sortie(1);
		   }   
   };

#ifndef MISE_AU_POINT
  inline 
#endif
// Modifie la valeur de fixe, si val est vrai -> blocage , sinon libre
void Ddl::Change_fixe(bool val)
{ if (val)
   {switch (fixe) // cas ou on veut fixer
		  { case SOUSLIBRE   : fixe = LIBRE  ;break;
		    case LIBRE   : fixe = FIXE  ;break;
		    case FIXE    : fixe = SURFIXE  ;break;    
		    case HSLIBRE : fixe = HSFIXE;break;
		    case LISIBLE_SOUSLIBRE : fixe = LISIBLE_LIBRE;break;
		    case LISIBLE_LIBRE : fixe = LISIBLE_FIXE;break;
		    case LISIBLE_FIXE : fixe = LISIBLE_SURFIXE;break;
		    case HS_LISIBLE_LIBRE : fixe = HS_LISIBLE_FIXE;break;
		    case HS_SOUSLIBRE : fixe = HSLIBRE;break;
		    case HS_LISIBLE_SOUSLIBRE : fixe = HS_LISIBLE_LIBRE;break;
		    case HSFIXE : fixe = HS_SURFIXE;break;
		    case HS_LISIBLE_FIXE : fixe = HS_LISIBLE_SURFIXE;break;
      // pour tous les surfixes, on ne fait rien
      case SURFIXE: case LISIBLE_SURFIXE: case HS_SURFIXE: case HS_LISIBLE_SURFIXE:
       break;  
      default :  
			        cout << "\nErreur : degre de liberte non defini !\n";
			        cout << "\n Ddl::Change_fixe(.. " << fixe;
			        Sortie(1);
		    };
		}
	  else	    
      {  switch (fixe) // cas ou on veut rendre libre
		  { case SURFIXE   : fixe = FIXE  ;break;
		    case FIXE   : fixe = LIBRE  ;break;
		    case LIBRE  : fixe = SOUSLIBRE  ;break;
		    case HSFIXE : fixe = HSLIBRE;break;		    
		    case LISIBLE_SURFIXE : fixe = LISIBLE_FIXE;break;
		    case LISIBLE_FIXE : fixe = LISIBLE_LIBRE;break;
		    case LISIBLE_LIBRE : fixe = LISIBLE_SOUSLIBRE;break;		    
		    case HS_LISIBLE_FIXE : fixe = HS_LISIBLE_LIBRE;break;		    
		    case HS_SURFIXE : fixe = HSFIXE;break;		    
		    case HS_LISIBLE_SURFIXE : fixe = HS_LISIBLE_FIXE;break;		    
		    case HSLIBRE : fixe = HS_SOUSLIBRE;break;		    
		    case HS_LISIBLE_LIBRE : fixe = HS_LISIBLE_SOUSLIBRE;break;
      // pour tous les sous libre on ne fait rien
      case SOUSLIBRE: case LISIBLE_SOUSLIBRE: case HS_SOUSLIBRE:
      case HS_LISIBLE_SOUSLIBRE: break;
      default :  
			        cout << "\nErreur : degre de liberte non defini !\n";
			        cout << "\n Ddl::Change_fixe(.. " << fixe;
			        Sortie(1);
		    };
		}
	 };
	 	 
#ifndef MISE_AU_POINT
  inline 
#endif
// test si le ddl est SOUSLIBRE ou SURFIXE, ramène true si oui
bool Ddl::SousSurFixe() const
{ switch (fixe)
	{  case SOUSLIBRE : case SURFIXE : case LISIBLE_SOUSLIBRE : 
		  case LISIBLE_SURFIXE : case HS_SOUSLIBRE : case HS_SURFIXE : 
		  case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE   : 
		    return true; break;
    // pour les autres  retour false
    case LIBRE : case FIXE : case HSLIBRE : case HSFIXE : case LISIBLE_LIBRE :
		  case LISIBLE_FIXE :	case HS_LISIBLE_LIBRE :	case HS_LISIBLE_FIXE:
      return false; break;
    default :  
			        cout << "\nErreur : degre de liberte non defini !\n";
			        cout << "\n Ddl::SousSurFixe(.. " << fixe;
			        Sortie(1);
	};
};	


#ifndef MISE_AU_POINT
  inline 
#endif
// remise à normal si le ddl est en souslibre ou surfixe
// s'il est en souslibre il passe en libre et s'il est en surfixe il passe en fixe 
// sinon on ne fait rien 
void Ddl::Retour_normal_sur_ou_sous_fixe()
{switch (fixe) // cas ou on veut rendre libre
	{ case SURFIXE           : fixe = FIXE  ;break;
	  case LISIBLE_SURFIXE   : fixe = LISIBLE_FIXE  ;break;
	  case HS_SURFIXE: fixe = HSFIXE;break;
	  case HS_LISIBLE_SURFIXE: fixe = HS_LISIBLE_FIXE;break;
	  case SOUSLIBRE  : fixe = LIBRE  ;break;
	  case LISIBLE_SOUSLIBRE : fixe = LISIBLE_LIBRE;break;
	  case HS_SOUSLIBRE : fixe = HSLIBRE;break;
	  case HS_LISIBLE_SOUSLIBRE: fixe = HS_LISIBLE_LIBRE;break;
   // pour les autres on ne fait rien
   case LIBRE : 	case FIXE : 	case HSLIBRE : 	case HSFIXE : 
		 case LISIBLE_LIBRE : case LISIBLE_FIXE : case HS_LISIBLE_LIBRE: 
		 case HS_LISIBLE_FIXE : break;
   default :  
			        cout << "\nErreur : degre de liberte non defini !\n";
			        cout << "\n Ddl::Retour_normal_sur_ou_sous_fixe(.. " << fixe;
			        Sortie(1);
	 };
}; 

#ifndef MISE_AU_POINT
  inline 
#endif
void Ddl::Met_hors_service()
// met hors_service le ddl, cela signifie que momentanément il ne sert plus
  {  switch (fixe) // cas ou on veut rendre libre
	{ case LIBRE           : fixe = HSLIBRE  ;break;
	  case SOUSLIBRE           : fixe = HS_SOUSLIBRE  ;break;
	  case FIXE            : fixe = HSFIXE  ;break;
	  case SURFIXE            : fixe = HS_SURFIXE  ;break;
	  case LISIBLE_LIBRE   : fixe = HS_LISIBLE_LIBRE  ;break;
	  case LISIBLE_SOUSLIBRE   : fixe = HS_LISIBLE_SOUSLIBRE  ;break;
	  case LISIBLE_FIXE    : fixe = HS_LISIBLE_FIXE;break;
	  case LISIBLE_SURFIXE    : fixe = HS_LISIBLE_SURFIXE;break;
	  case HSLIBRE: case  HSFIXE: case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE:
	  case HS_SOUSLIBRE : case HS_SURFIXE : case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE :
	      break; // cas déjà HS
	  default:
	    cout << "\n erreur cas non prevu pour le ddl "; this->Affiche();
	    cout << "\n Ddl::Met_hors_service() ";
	    Sortie(1);		    
	 };
   }; 

#ifndef MISE_AU_POINT
  inline 
#endif
// met en service le ddl
void Ddl::Met_en_service()
  {  switch (fixe) // cas ou on veut rendre libre
	{ case HSLIBRE           : fixe = LIBRE  ;break;
	  case HSFIXE            : fixe = FIXE  ;break;
	  case HS_LISIBLE_LIBRE   : fixe = LISIBLE_LIBRE  ;break;
	  case HS_LISIBLE_FIXE    : fixe = LISIBLE_FIXE;break;
	  case HS_SOUSLIBRE : fixe = SOUSLIBRE;break;
	  case HS_SURFIXE : fixe = SURFIXE;break;
	  case HS_LISIBLE_SOUSLIBRE : fixe = LISIBLE_SOUSLIBRE;break;
	  case HS_LISIBLE_SURFIXE :fixe = LISIBLE_SURFIXE;break;
	  
	  case LIBRE: case FIXE: case SOUSLIBRE: case SURFIXE:
	  case LISIBLE_LIBRE: case LISIBLE_FIXE: 
	  case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE:
	      break; // cas déjà OK
	  default:
	    cout << "\n erreur cas non prevu pour le ddl "; this->Affiche();
	    cout << "\n Ddl::Met_hors_service() ";
	    Sortie(1);		    
	 };
   }; 


#ifndef MISE_AU_POINT
  inline
#endif
void Ddl::Met_hors_service_ddl()
// met hors_service le ddl, cela signifie que momentanément il ne sert plus
// ne concerne pas les données
  {  switch (fixe) // cas ou on veut rendre libre
      { case LIBRE           : fixe = HSLIBRE  ;break;
        case SOUSLIBRE           : fixe = HS_SOUSLIBRE  ;break;
        case FIXE            : fixe = HSFIXE  ;break;
        case SURFIXE            : fixe = HS_SURFIXE  ;break;
        // --- cas déjà HS on ne change rien
        case HSLIBRE: case  HSFIXE: case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE:
        case HS_SOUSLIBRE : case HS_SURFIXE : case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE :
            break; // cas déjà HS
        // --- cas des données, on ne fait rien
        case LISIBLE_LIBRE   : case LISIBLE_SOUSLIBRE   :  
        case LISIBLE_FIXE    : case LISIBLE_SURFIXE    :
          break; // pour les données, on ne change rien
        default:
          cout << "\n erreur cas non prevu pour le ddl "; this->Affiche();
          cout << "\n Ddl::Met_hors_service_ddl() ";
          Sortie(1);
       };
   };

#ifndef MISE_AU_POINT
  inline
#endif
// met en service le ddl, ne concerne pas les données
void Ddl::Met_en_service_ddl()
  {  switch (fixe) // cas ou on veut rendre libre
      { case HSLIBRE           : fixe = LIBRE  ;break;
        case HSFIXE            : fixe = FIXE  ;break;
        case HS_SOUSLIBRE      : fixe = SOUSLIBRE;break;
        case HS_SURFIXE        : fixe = SURFIXE;break;

        // --- déjà libre, on ne change rien
        case LIBRE: case FIXE: case SOUSLIBRE: case SURFIXE:
        case LISIBLE_LIBRE: case LISIBLE_FIXE:
        case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE:
            break; // cas déjà OK
            
        // --- on n'intervient pas sur les données
        case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE :
        case HS_LISIBLE_LIBRE   : case HS_LISIBLE_FIXE    :
           break;
           
        default:
          cout << "\n erreur cas non prevu pour le ddl "; this->Affiche();
          cout << "\n Ddl::Met_en_service_ddl() ";
          Sortie(1);
       };
   };

#ifndef MISE_AU_POINT
  inline 
#endif
// surcharge de l'operateur d'ecriture
ostream &  operator << (ostream & sort,const  Ddl & a)
  { // écriture du type
    sort << "Ddl ";
    // les données
    sort << a.id_nom << " "  << a.fixe << " " ;
    sort << setprecision(ParaGlob::NbdigdoCA()) << a.val_ddl << " ";
     return sort;
  };
  
#ifndef MISE_AU_POINT
  inline 
#endif
  // surcharge de l'operator de lecture
istream & operator >> (istream & entree, Ddl& a)
  { // vérification du type
    string type;
    entree >> type;
    if (type != "Ddl")
      {Sortie (1);
       return entree;
       }
    // entrée des données  
    entree >> a.id_nom;
    entree >> a.fixe;
    entree >> a.val_ddl;
    
    return entree;      
  };

   
#ifndef MISE_AU_POINT
  inline 
#endif
// Affiche les donnees liees au degre de liberte
void Ddl::Affiche () const 
{	
			cout << " " << Nom_ddl(id_nom) ; 
			cout << " = " << val_ddl ; 
   switch (fixe) 
		    { case LIBRE   : cout << " val_libre, ";  break;
		      case FIXE    : cout << " val_fixe, ";  break;  		       
		      case SOUSLIBRE    : cout << " val_sous_libre, ";  break;  
		      case SURFIXE      : cout << " val_sur_fixe, ";  break;  
		      case LISIBLE_LIBRE    : cout << " lisible_libre, ";  break;  
		      case LISIBLE_FIXE     : cout << " lisible_fixe, ";  break;  
		      case LISIBLE_SOUSLIBRE    : cout << " lisible_sous_libre, ";  break;  
		      case LISIBLE_SURFIXE    : cout << " lisible_sur_fixe, ";  break;
         // pour les autres ils sont hors services
		      case HSLIBRE : 
		      case HSFIXE  : 
		      case HS_LISIBLE_LIBRE  : 
		      case HS_LISIBLE_FIXE   : 
		      case HS_SOUSLIBRE         : 
		      case HS_SURFIXE           : 
		      case HS_LISIBLE_SOUSLIBRE : 
		      case HS_LISIBLE_SURFIXE   :
         cout << " hors service, "; break;
/*
		case LIBRE             : result="LIBRE"; break;
		case FIXE              : result="FIXE"; break;
		case HSLIBRE           : result="HSLIBRE"; break;
		case HSFIXE            : result="HSFIXE"; break;
		case SOUSLIBRE         : result="SOUSLIBRE"; break;
		case SURFIXE           : result="SURFIXE"; break;
		case LISIBLE_LIBRE     : result="LISIBLE_LIBRE"; break;
		case LISIBLE_FIXE      : result="LISIBLE_FIXE"; break;
		case LISIBLE_SOUSLIBRE : result="LISIBLE_SOUSLIBRE"; break;
		case LISIBLE_SURFIXE   : result="LISIBLE_SURFIXE"; break;
		case HS_LISIBLE_LIBRE  : result="HS_LISIBLE_LIBRE"; break;
		case HS_LISIBLE_FIXE   : result="HS_LISIBLE_FIXE"; break;
		case HS_SOUSLIBRE         : result="HS_SOUSLIBRE"; break;
		case HS_SURFIXE           : result="HS_SURFIXE"; break;
		case HS_LISIBLE_SOUSLIBRE : result="HS_LISIBLE_SOUSLIBRE"; break;
		case HS_LISIBLE_SURFIXE   : result="HS_LISIBLE_SURFIXE"; break;
*/

	       default:
	          cout << "\n erreur cas non prevu pour le ddl "; this->Affiche();
	          cout << "\n Ddl::Affiche(.. ";
	          Sortie(1);
      };
		};

#ifndef MISE_AU_POINT
  inline 
#endif
//Surcharge d'operateur logique
bool Ddl::operator == (const Ddl& a) const
  {  if ( (id_nom==a.id_nom)
       && (val_ddl == a.val_ddl) && (fixe == a.fixe))
         return true;
     else return false;    
   };
		 
#ifndef MISE_AU_POINT
  inline 
#endif
bool Ddl::operator != (const Ddl& a) const
    { return !(*this == a);}; 
    
#ifndef MISE_AU_POINT
  inline 
#endif
// test si le degre de liberte est complet
// = 1 tout est ok, =0 element incomplet
int Ddl::TestComplet() const
  { if (id_nom == NU_DDL)  
      { cout << "\n pb !! ddl non defini ";
        return false;
       } 
    return true;
   };


#endif  // fin de l'inclusion totale