
// 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 "Bloc.h"
#include "CharUtil.h"

//================================================ 
//    cas d'un bloc scalaire
//================================================

// Constructeur    
BlocScal::BlocScal () :  // par defaut
 nomref(),val(0.)
  { 
   };
BlocScal::BlocScal (const BlocScal& a) : // de copie
 nomref(a.nomref),val(a.val)
  { 
   };
// destructeur   
BlocScal::~BlocScal () 
 { 
  };
// nom de reference
const string & BlocScal::NomRef() const 
  {return nomref;
   };
// lecture d'un bloc   
void BlocScal::Lecture(UtilLecture & entreePrinc)
    { *(entreePrinc.entree) >> nomref >> val;
     };
// affichage des infos     
void BlocScal::Affiche() const
  { cout << "\n reference = " << nomref
         << " , valeur  = " << val;
   };  
// surcharge des operateurs    
bool BlocScal::operator == (const  BlocScal& a) const 
   {  if ((nomref == a.nomref) && (val == a.val))
         return true;
      else
        return false;
    };
BlocScal& BlocScal::operator = ( const BlocScal& a) 
    { nomref = a.nomref; val = a.val;
      return *this;
     };
bool BlocScal::operator != (const BlocScal& a) const
    { return !(*this == a);}; 
bool BlocScal::operator < (const BlocScal& a) const
    { if (this->nomref < a.nomref) return true;
      else if (this->nomref == a.nomref) return (this->val < a.val);
      else  return false;
      };
    
istream & operator >> (istream & entree, BlocScal & coo)
  { entree >> coo.nomref >> coo.val;
    return entree;      
  };
  
ostream & operator << ( ostream & sort,const  BlocScal & coo)
  { sort << coo.nomref << " " << coo.val <<" " ; 
     return sort;      
  };

//================================================
//    cas d'un bloc scalaire ou non de fonction nD
//================================================
// un bloc qui correspond a une reference
// et soit une seule valeur ou soit le nom d'une fonction nD
// qui doit-être précédé par le mot clé une_fonction_nD_

// Constructeur    
BlocScal_ou_fctnD::BlocScal_ou_fctnD () :  // par defaut
 nomref(),val(NULL),fctnD(NULL)
  { 
   };
BlocScal_ou_fctnD::BlocScal_ou_fctnD (const BlocScal_ou_fctnD& a) : // de copie
 nomref(a.nomref)
  { if (a.val == NULL) val = NULL; else val = new double(*(a.val));
    if (a.fctnD == NULL) fctnD = NULL; else fctnD = new string (*(a.fctnD));
   };
// destructeur   
BlocScal_ou_fctnD::~BlocScal_ou_fctnD ()
 { if (val != NULL) delete val;
   if (fctnD != NULL) delete fctnD;
  };
// nom de reference
const string & BlocScal_ou_fctnD::NomRef() const
  {return nomref;
   };
// lecture d'un bloc   
void BlocScal_ou_fctnD::Lecture(UtilLecture & entreePrinc)
    { *(entreePrinc.entree) >> nomref ;
      string toto;
      *(entreePrinc.entree) >> toto ;
      if (toto == "une_fonction_nD_") // cas d'une fonction
       { *(entreePrinc.entree) >> toto ; // on lit le nom de la fonction
         if (fctnD == NULL)
           fctnD = new string (toto);
         else *fctnD = toto;
         if (val != NULL) // il ne peut y avoir val et fctnD définies en même temps
          {delete val; val = NULL;};
       }
      else // cas d'une valeur numérique
       { if (val != NULL) {*val = ChangeReel(toto);}
         else {val = new double(ChangeReel(toto));};
         if (fctnD != NULL) // il ne peut y avoir val et fctnD définies en même temps
          {delete fctnD; fctnD = NULL;};
       };
     };
// affichage des infos     
void BlocScal_ou_fctnD::Affiche() const
  { cout << "\n reference = " << nomref;
    if (val != NULL)
         cout << " , valeur  = " << *val << " ";
    else if (fctnD != NULL)
         cout << " fctnD= "<<(*fctnD) << " ";
    else
         cout << " pas_de_valeur_affectee ";
  };

// surcharge des operateurs    
bool BlocScal_ou_fctnD::operator == (const  BlocScal_ou_fctnD& a) const
   {  if (nomref == a.nomref)
       { if (val != NULL)
           { if (*val == *a.val) return true;} // cas d'une valeur
         else if (fctnD != NULL)
           { if (*fctnD == *a.fctnD) return true;} // cas d'un nom de fctnD
         else if ((a.val == NULL) && (a.fctnD == NULL))
           { return true;} // cas rien d'affecté
         else
           { return false;};
       }
      else
        return false;
      // on ne doit pas passer ici
      return false;

    };

BlocScal_ou_fctnD& BlocScal_ou_fctnD::operator = ( const BlocScal_ou_fctnD& a)
    { nomref = a.nomref;
      if (a.val == NULL)
        { if (val != NULL)
            {delete val;val = NULL;}
          if (a.fctnD != NULL)
           {if (fctnD == NULL) {fctnD = new string (*a.fctnD);}
            else {*fctnD = *a.fctnD;}
           }
          else // ici a.fctnD est nulle, donc tout est nul
           {if (fctnD != NULL)
              {delete fctnD; fctnD = NULL;};
           };
        }
      else // cas d'une valeur
        { if (val == NULL)
           {val = new double(*(a.val));}
          else {*val = *a.val;};
          if (fctnD != NULL) {delete fctnD; fctnD = NULL;};
        };
      return *this;
   };

bool BlocScal_ou_fctnD::operator != (const BlocScal_ou_fctnD& a) const
    { return !(*this == a);};

bool BlocScal_ou_fctnD::operator < (const BlocScal_ou_fctnD& a) const
    { if (this->nomref < a.nomref) return true;
      else if (this->nomref == a.nomref)
       {if (a.val == NULL)
         { if (val != NULL)
            {return false;}
           if (a.fctnD != NULL)
            {if (fctnD == NULL) {return true;}
             else {return (*fctnD < *a.fctnD);}
            }
           else // ici a.fctnD est nulle
            {if (fctnD != NULL)
              {return false;}
             else // là on ne peut plus les départager on met arbitrairement à false
              return false;
            };
         }
        else // cas d'une valeur
         { if (val != NULL)
            {return (*val < *a.val);}
         };
       }
      else  return false;
      // on ne doit pas passer ici
      return false;
    };
    
istream & operator >> (istream & entree, BlocScal_ou_fctnD & coo)
  { string toto;
    entree >> coo.nomref >> toto;
    if ((toto != "fctnD=") && (toto != "no_val_"))
      { // c'est une valeur numérique
        if (coo.val != NULL)
          {*coo.val = ChangeReel(toto);}
        else
          {coo.val = new double (ChangeReel(toto));};
        if (coo.fctnD != NULL)
          {delete coo.fctnD; coo.fctnD=NULL;};
      }
    else if (toto == "fctnD=")
      { // c'est un nom de fonction
        if (coo.fctnD != NULL)
          {*coo.fctnD = toto;}
        else
          {coo.fctnD = new string (toto);}
        if (coo.val != NULL)
           {delete coo.val; coo.val = NULL;};
      }
    else // cas où ce n'est pas affecté
      { if (coo.val != NULL)
           {delete coo.val; coo.val = NULL;};
        if (coo.fctnD != NULL)
          {delete coo.fctnD; coo.fctnD=NULL;};
      };
    return entree;
  };

ostream & operator << ( ostream & sort,const  BlocScal_ou_fctnD & coo)
  { sort << coo.nomref << " " ;
    if (coo.val != NULL)
      {sort << *coo.val << " ";}
    else if (coo.fctnD != NULL)
      {sort << " fctnD= " << (*coo.fctnD) << " ";}
    else {sort << " no_val_ ";};
    return sort;      
  };

// modifie la valeur du double: possible uniquement s'il n'y a pas de fonction nD
void BlocScal_ou_fctnD::Change_val(const double a)
  { if (fctnD == NULL) // c'est ok
     { if (val != NULL)
         {*val = a;}
       else {val = new double(a);};
     }
    else // ce n'est pas normal
      { cout << "\n *** erreur dans la methode BlocScal_ou_fctnD::Change_val(..."
             << " on devrait avoir un pointeur de fonction nul !  ce qui n'est pas le cas ";
        Sortie(1);
      };
  };

// modifie la valeur du nom de la fonction : possible uniquement s'il n'y a pas de valeur
void BlocScal_ou_fctnD::Change_fctnD(const string a)
  { if (val == NULL) // c'est ok
     {if (fctnD != NULL)
       {*fctnD = a;}
      else {fctnD = new string(a);};
     }
    else // ce n'est pas normal
      { cout << "\n *** erreur dans la methode BlocScal_ou_fctnD::Change_fctnD(..."
             << " on devrait avoir un pointeur de valeur nul !  ce qui n'est pas le cas ";
        Sortie(1);
      };
  };

//========================================================
//    cas d'un bloc general de n chaines et de m scalaires 
//========================================================
// 

// Constructeur    
BlocGen::BlocGen (int n1, int m1) :   // par defaut
    pt(m1) , ptnom(n1)
  { };
BlocGen::BlocGen (const  BlocGen& a) :   // par defaut
    pt(a.pt) , ptnom(a.ptnom)
  { };
// destructeur   
BlocGen::~BlocGen () 
 { };
// nom de reference
string & BlocGen::NomRef() const
  { return ptnom(1);
   };
// lecture d'un bloc   
void BlocGen::Lecture(UtilLecture & entreePrinc)
    { // la lecture dépend du fait qu'il y a ou non une fin de bloc
      if (strstr(entreePrinc.tablcar,"fin_bloc_gene_")==NULL)
        // cas d'une taille fixe
        {int ptnomtaille = ptnom.Taille();
         for (int i=1;i<= ptnomtaille;i++)
             *(entreePrinc.entree) >> ptnom(i);
         int pttaille = pt.Taille();
         for (int i=1;i<= pttaille;i++)
             *(entreePrinc.entree) >> pt(i);
        }
     else // cas de l'existence d'un marqueur de fin de bloc
       { // a priori on ne sait pas le nombre d'info que l'on va lire
         // et on stocke tout en string
         list <string> li_nom;  // on utilise une liste intermédiaire
         string nom_lue; // init
         *(entreePrinc.entree) >> nom_lue;
         while (nom_lue != "fin_bloc_gene_")
           {li_nom.push_back(nom_lue);
            *(entreePrinc.entree) >> nom_lue;
           };
         // on redimentionne éventuellement le conteneur
         pt.Change_taille(0);
         int ptnomtaille = li_nom.size();
         ptnom.Change_taille(ptnomtaille);
         // on affecte
         list <string>::iterator ili,ilifin=li_nom.end();
         int i=1;
         for (ili = li_nom.begin();ili!=ilifin;ili++,i++)
           ptnom(i) = (*ili);
       };
     };
// affichage des infos     
void BlocGen::Affiche()  const 
  { cout << "\n reference = " << ptnom(1) << '\n';
    int ptnomtaille = ptnom.Taille();
    for (int i=2;i<=ptnomtaille;i++)  // affichage des noms
        cout <<  ptnom(i) << " ";
    cout << '\n'; 
    int pttaille = pt.Taille();   
    for (int i=1;i<=pttaille;i++)  // affichage des valeurs
        cout << " nb [" << i << "] = " << pt(i); 
   };  
// surcharge des operateurs    
bool BlocGen::operator == (const BlocGen& a) const
  { int ptnomtaille = ptnom.Taille();
    for (int i=1;i<=ptnomtaille;i++)  // affichage des noms
      if (ptnom(i) != a.ptnom(i))
             return false;
    int pttaille = pt.Taille();   
    for (int i=1;i<=pttaille;i++)  // affichage des noms
      if (pt(i) != a.pt(i))
             return false;
    return true;         
    };
BlocGen& BlocGen::operator = (const  BlocGen& a) 
    { int ptnomtaille = a.ptnom.Taille();
      // on modifie la taille du bloc gen si besoin
      if (ptnom.Taille() != ptnomtaille)
        ptnom.Change_taille(ptnomtaille);
      // on recopie
      for (int i=1;i<=ptnomtaille;i++)  
        ptnom(i) = a.ptnom(i);
      // idem pour les scalaires
      int pttaille = a.pt.Taille();
      if (pt.Taille() != pttaille)
        pt.Change_taille(pttaille);
      for (int i=1;i<=pttaille;i++)  
         pt(i) = a.pt(i);
      return *this;
     };
bool BlocGen::operator != (const BlocGen& a) const
    { return !(*this == a);}; 
    
istream & operator >> (istream & entree, BlocGen & coo)
  { int ptnomTaille; string toto;
    entree >> toto >> ptnomTaille ;
    coo.ptnom.Change_taille(ptnomTaille);
    for (int i=1;i<=ptnomTaille;i++)  
        entree >> coo.ptnom(i) ;
    int ptTaille ;    
    entree >> toto >> ptTaille ;
    coo.pt.Change_taille(ptTaille);
    for (int i=1;i<=ptTaille;i++)  
        entree >> coo.pt(i) ;  
    return entree;      
  };
  
ostream & operator << ( ostream & sort,const  BlocGen & coo)
  { int ptnomTaille = coo.ptnom.Taille();
    sort << "tab_nom " << ptnomTaille << " ";
    for (int i=1;i<=ptnomTaille;i++)  
        sort << coo.ptnom(i) << " ";  
    int ptTaille = coo.pt.Taille();    
    sort << "tab_valeur " << ptTaille << " "; 
    for (int i=1;i<=ptTaille;i++)  
        sort << coo.pt(i) << " ";  
    return sort;      
  };

//================================================ 
//    cas d'un bloc scalaire type
//================================================
// un bloc scalaire type correspond a une reference
// un mot cle, et une seule valeur

// Constructeur    
BlocScalType::BlocScalType () :   // par defaut
 nomref(),motClef()
  { 
   };
BlocScalType::BlocScalType (const BlocScalType& a) : // de copie
 nomref(a.nomref),motClef(a.motClef),val(a.val)
  { 
   };
// destructeur   
BlocScalType::~BlocScalType () 
 { 
  };
// nom de reference
const string & BlocScalType::NomRef() const
  {return nomref;
   };
// lecture d'un bloc   
void BlocScalType::Lecture(UtilLecture & entreePrinc)
    { *(entreePrinc.entree) >> nomref >> motClef >> val;
     };
// affichage des infos     
void BlocScalType::Affiche()  const 
  { cout << "\n reference = " << nomref << " , cle : " << motClef 
         << " , valeur  = " << val;
   };  
// surcharge des operateurs    
bool BlocScalType::operator == (const BlocScalType& a) const
   {  if ((nomref == a.nomref) && (val == a.val) && (motClef == a.motClef ) )
         return true;
      else
        return false;
    };
BlocScalType& BlocScalType::operator = ( const BlocScalType& a) 
    { nomref = a.nomref; val = a.val; motClef = a.motClef;
      return *this;
     };
bool BlocScalType::operator != (const BlocScalType& a) const
    { return !(*this == a);}; 

    
istream & operator >> (istream & entree, BlocScalType & coo)
  { entree >> coo.nomref >> coo.motClef >> coo.val;
    return entree;      
  };
  
ostream & operator << ( ostream & sort,const  BlocScalType & coo)
  { sort << coo.nomref << " " << coo.motClef << " "<< coo.val <<" " ; 
     return sort;      
  };


//================================================ 
//    cas d'un bloc vecteur
//================================================
 
 // Constructeur    
BlocVec::BlocVec ()  : // par defaut
 nomref(),coorpt(ParaGlob::Dimension ())
  {};
BlocVec::BlocVec (const BlocVec & a)  : // de copie
 nomref(),coorpt(a.coorpt)
  { };
// destructeur   
BlocVec::~BlocVec () 
 { };
// nom de reference
const string & BlocVec::NomRef() const
  {return nomref;
   };
// lecture d'un bloc   
void BlocVec::Lecture(UtilLecture & entreePrinc)
    { *(entreePrinc.entree) >> nomref ;
      coorpt.Lecture(entreePrinc);
    //  *(entreePrinc.entree) >> coorpt;
     };
// affichage des infos     
void BlocVec::Affiche()  const 
  { cout << "\n reference = " << nomref  
         << " , coordonnees  : ";
    coorpt.Affiche(cout);      
 //   cout << coorpt;     
   };  
// surcharge des operateurs    
bool BlocVec::operator == (const BlocVec& a) const
   {  if ((nomref == a.nomref)&&(coorpt==a.coorpt)) 
         return true;
      else
        return false;
    };
BlocVec& BlocVec::operator = (const  BlocVec& a) 
    { nomref = a.nomref;
      coorpt = a.coorpt;
      return *this;
     };
bool BlocVec::operator != (const BlocVec& a) const
    { return !(*this == a);}; 
    
istream & operator >> (istream & entree, BlocVec & coo)
  { entree >> coo.nomref >>  coo.coorpt;
    return entree;      
  };
  
ostream & operator << ( ostream & sort,const  BlocVec & coo)
  { sort << coo.nomref << " " << coo.coorpt <<" " ; 
     return sort;      
  };

//================================================ 
//    cas d'un bloc vecteur type
//================================================
// un bloc vecteur type correspond a une reference et
// un mot cle et un vecteur, fonction de la dimension du pb 
 // Constructeur 
    
BlocVecType::BlocVecType () :  // par defaut
 nomref(),motClef(),coorpt(ParaGlob::Dimension ())
  { 
   };
BlocVecType::BlocVecType (const BlocVecType& a) : // de copie
  nomref(a.nomref),motClef(a.motClef),coorpt(a.coorpt)
  {  };
 
// destructeur   
BlocVecType::~BlocVecType () 
 { 
  };
// nom de reference
const string & BlocVecType::NomRef() const
  {return nomref;
   };
// lecture d'un bloc   
void BlocVecType::Lecture(UtilLecture & entreePrinc)
    { *(entreePrinc.entree) >> nomref >> motClef;
      coorpt.Lecture(entreePrinc);
     };
// affichage des infos     
void BlocVecType::Affiche()  const 
  { cout << "\n ref = " << nomref << ", cle: " << motClef 
         << " , coord  : ";
    coorpt.Affiche(cout);     
//    cout << coorpt;     
   };  
// surcharge des operateurs    
bool BlocVecType::operator == (const BlocVecType& a) const 
   {  if ((nomref == a.nomref) && (motClef == a.motClef)
          && (coorpt==a.coorpt))
         return true;
      else
        return false;
    };
BlocVecType& BlocVecType::operator = (const  BlocVecType& a) 
    { nomref = a.nomref;motClef = a.motClef;
      coorpt = a.coorpt;
      return *this;
     };
bool BlocVecType::operator != (const BlocVecType& a) const
    { return !(*this == a);}; 
     
istream & operator >> (istream & entree, BlocVecType & coo)
  { entree >> coo.nomref >> coo.motClef >> coo.coorpt;
    return entree;      
  };
  
ostream & operator << ( ostream & sort,const  BlocVecType & coo)
  { sort << coo.nomref << " " << coo.motClef << " " << coo.coorpt <<" " ; 
     return sort;      
  };

//================================================ 
//    cas d'un bloc de n vecteur type
//================================================
// un bloc de plusieurs vecteurs et plusieurs scalaires type correspond a une reference et
// un mot cle et des vecteurs, fonction de la dimension du pb et des scalaires
 // Constructeur 
    
BlocVecMultType::BlocVecMultType (int n,int m) :  // par defaut
 nomref(),motClef(),vect_coorpt(n,Coordonnee(ParaGlob::Dimension ()))
 ,pt(m)
  { 
   };
BlocVecMultType::BlocVecMultType (const BlocVecMultType& a) : // de copie
  nomref(a.nomref),motClef(a.motClef),vect_coorpt(a.vect_coorpt),pt(a.pt)
  {  };
 
// destructeur   
BlocVecMultType::~BlocVecMultType () 
 { 
  };
// nom de reference
const string & BlocVecMultType::NomRef() const
  {return nomref;
   };
// lecture d'un bloc   
void BlocVecMultType::Lecture(UtilLecture & entreePrinc)
    { *(entreePrinc.entree) >> nomref >> motClef;
      int taille = vect_coorpt.Taille();
      for (int i=1;i<=taille;i++)
        vect_coorpt(i).Lecture(entreePrinc);
      int pttaille = pt.Taille();    
      for (int i=1;i<= pttaille;i++)
          *(entreePrinc.entree) >> pt(i);  
     };
// affichage des infos     
void BlocVecMultType::Affiche()  const 
  { cout << "\n ref = " << nomref << ", cle: " << motClef; 
    int taille = vect_coorpt.Taille();
    for (int i=1;i<=taille;i++)
      {cout << " , coord "<< i <<" : "; vect_coorpt(i).Affiche(cout);};
    int pttaille = pt.Taille();
    cout << ", " << pttaille << " scal(s) ";   
    for (int i=1;i<= pttaille;i++)
          cout << pt(i) << " ";  
   };  
// surcharge des operateurs    
bool BlocVecMultType::operator == (const BlocVecMultType& a) const
   {  if ((nomref == a.nomref) && (motClef == a.motClef)
          && (vect_coorpt==a.vect_coorpt) && (pt == a.pt))
         return true;
      else
        return false;
    };
BlocVecMultType& BlocVecMultType::operator = (const  BlocVecMultType& a) 
    { nomref = a.nomref;motClef = a.motClef;
      vect_coorpt = a.vect_coorpt; pt = a.pt;
      return *this;
     };
bool BlocVecMultType::operator != (const BlocVecMultType& a) const
    { return !(*this == a);}; 
     
istream & operator >> (istream & entree, BlocVecMultType & coo)
  { entree >> coo.nomref >> coo.motClef;
    string toto; int taille;
    entree >> taille >> toto ;
    coo.vect_coorpt.Change_taille(taille);
    for (int i=1;i<=taille;i++)
      entree >> coo.vect_coorpt(i) ;
    entree >> taille >> toto ;
    coo.pt.Change_taille(taille);
    for (int i=1;i<=taille;i++)
      entree >> coo.pt(i);      
    return entree;      
  };
  
ostream & operator << ( ostream & sort,const  BlocVecMultType & coo)
  { sort << coo.nomref << " " << coo.motClef << " " ;
    int taille = coo.vect_coorpt.Taille();
    sort << taille << " vect(s) ";
    for (int i=1;i<=taille;i++)
      sort << coo.vect_coorpt(i) << " ";
    int pttaille = coo.pt.Taille(); 
    sort << " " << pttaille << " scal(s) ";   
    for (int i=1;i<= pttaille;i++)
          sort << coo.pt(i) << " ";  
     return sort;      
  };

//=======================================================================
//    cas d'un bloc general de n chaines, de m scalaires, de p Coordonnees
//    avec un choix en lecture et définition des coordonnees ou de chaine
//=======================================================================
// 

// n: le nombre de vecteurs, m le nombre de scalaires, n le nombre de ptnom_vect
BlocGeneEtVecMultType::BlocGeneEtVecMultType (int n,int m) :  // par defaut
 nomref(),motClef()
 ,vect_coorpt(n,Coordonnee(ParaGlob::Dimension())),ptnom_vect(n)
 ,tab_val(m),ptnom_tab_val(m,"NULL")
  { string init("NULL");
    // on initialise les noms à rien
    for (int i=1; i<= n; i++)
      ptnom_vect(i).Change_taille((ParaGlob::Dimension()),init);
   };
BlocGeneEtVecMultType::BlocGeneEtVecMultType (const BlocGeneEtVecMultType& a) : // de copie
  nomref(a.nomref),motClef(a.motClef),vect_coorpt(a.vect_coorpt),tab_val(a.tab_val)
  ,ptnom_vect(a.ptnom_vect),ptnom_tab_val(a.ptnom_tab_val)
  {  };
 
// destructeur   
BlocGeneEtVecMultType::~BlocGeneEtVecMultType ()
 { 
  };
// lecture d'un bloc
void BlocGeneEtVecMultType::Lecture(UtilLecture & entreePrinc)
    { *(entreePrinc.entree) >> nomref >> motClef;
      int dim = ParaGlob::Dimension();
      int taille = vect_coorpt.Taille();
      for (int i=1;i<=taille;i++)
       for (int j=1;j<= dim;j++)
       {string inter;
        *(entreePrinc.entree) >> inter;
        if (inter == "nom_Xi_")
          // dans ce cas cela signifie qu'on doit lire un nom
          {*(entreePrinc.entree) >> ptnom_vect(i)(j);}
        else // sinon cela veut dire que c'est une valeur numérique
          {vect_coorpt(i)(j) = ChangeReel(inter);};
       };
      int tab_valtaille = tab_val.Taille();
      for (int i=1;i<= tab_valtaille;i++)
       {string inter;
        *(entreePrinc.entree) >> inter;
        if (inter == "nom_VAL_")
          // dans ce cas cela signifie qu'on doit lire un nom
          {*(entreePrinc.entree) >> ptnom_tab_val(i);}
        else // sinon cela veut dire que c'est une valeur numérique
          {tab_val(i) = ChangeReel(inter);};
       };
    };

// affichage des infos     
void BlocGeneEtVecMultType::Affiche()  const
  { cout << "\n ref = " << nomref << ", cle: " << motClef; 
    int taille = vect_coorpt.Taille();
    int dim = ParaGlob::Dimension();
    for (int i=1;i<=taille;i++)
      {cout << " , coord "<< i <<" : ";
       for (int j=1;j<= dim;j++)
         if (ptnom_vect(i)(j) != "NULL")
           { cout << " nom_Xi_ " << ptnom_vect(i)(j) << " ";}
         else
           { cout << vect_coorpt(i)(j) << " ";};
       };
    int tab_valtaille = tab_val.Taille();
    cout << ", " << tab_valtaille << " scal(s) ";
    for (int i=1;i<= tab_valtaille;i++)
      if (ptnom_tab_val(i) != "NULL")
        { cout << " nom_VAL_ " << ptnom_tab_val(i) << " ";}
      else
        { cout << tab_val(i) << " ";};
  };

// surcharge des operateurs    
bool BlocGeneEtVecMultType::operator == (const BlocGeneEtVecMultType& a) const
   {  if ((nomref == a.nomref) && (motClef == a.motClef)
          && (vect_coorpt==a.vect_coorpt) && (tab_val == a.tab_val)
          && (ptnom_vect==a.ptnom_vect)&& (ptnom_tab_val==a.ptnom_tab_val))
         return true;
      else
        return false;
    };

BlocGeneEtVecMultType& BlocGeneEtVecMultType::operator = (const  BlocGeneEtVecMultType& a)
    { nomref = a.nomref;motClef = a.motClef;
      vect_coorpt = a.vect_coorpt; tab_val = a.tab_val;
      ptnom_vect = a.ptnom_vect;
      ptnom_tab_val = a.ptnom_tab_val;
      return *this;
     };

bool BlocGeneEtVecMultType::operator != (const BlocGeneEtVecMultType& a) const
    { return !(*this == a);};

// change le tableau des coordonnées, la taille des noms associés est modifié
// en conséquence
void BlocGeneEtVecMultType::Change_vect_coorpt(const Tableau <Coordonnee>& vect)
  {vect_coorpt=vect;
   int taille_ptnom_vect= ptnom_vect.Taille();
   int taille_vect = vect.Taille();
   if (taille_ptnom_vect < taille_vect)
    { // il faut agrandir le tableau
      string init("NULL");
      // on change de taille globalement
      ptnom_vect.Change_taille(taille_vect);
      for (int i=taille_ptnom_vect+1;i<=taille_vect;i++)
         ptnom_vect(i).Change_taille((ParaGlob::Dimension()),init);
    }
   else if (taille_ptnom_vect > taille_vect)
    { // il faut diminuer le tableau, c'est plus simple
      // on change de taille globalement
      ptnom_vect.Change_taille(taille_vect);
    };
  };

// change le tableau des coordonnées, la taille des noms associés est modifié
// en conséquence, ici à partir d'une liste
void BlocGeneEtVecMultType::Change_vect_coorpt(const list<Coordonnee>& livect)
 { int taille = livect.size(); vect_coorpt.Change_taille(taille);
   list<Coordonnee>::const_iterator ili=livect.begin();
   for (int i=0;i<taille;i++,ili++)
     vect_coorpt(i+1)=(*ili);
   int taille_ptnom_vect_coorpt=ptnom_vect.Taille();
   ptnom_vect.Change_taille(taille);
   //si la nouvelle taille est plus grande, il faut initialiser à null
   string init("NULL");
   if (taille_ptnom_vect_coorpt < taille)
    for (int i=taille_ptnom_vect_coorpt+1;i<= taille;i++)
     ptnom_vect(i).Change_taille((ParaGlob::Dimension()),init);;
 };

// change le tableau des noms associés aux vecteurs
// la taille du tableau de vecteurs associés est modifié en conséquence
void BlocGeneEtVecMultType::Change_ptnom_vect(const Tableau <Tableau<string> >& t_ptnom_vect)
  {ptnom_vect=t_ptnom_vect;
   int taille_t_ptnom_vect = t_ptnom_vect.Taille();
   int taille_vect_coorpt = vect_coorpt.Taille();
   int dim = ParaGlob::Dimension();
   vect_coorpt.Change_taille(taille_t_ptnom_vect);
   if (taille_t_ptnom_vect > taille_vect_coorpt)
    { // on augmente le tableau avec des vecteurs correctement dimensionnées
      for (int i=taille_vect_coorpt+1;i<=taille_t_ptnom_vect;i++)
         vect_coorpt(i).Change_dim(dim);
    };
  };

// change le tableau des noms associés aux scalaires
// la taille du tableau de scalaires associés est modifié en conséquence
void BlocGeneEtVecMultType::Change_ptnom_val(const Tableau<string> & t_ptnom_val)
  {ptnom_tab_val=t_ptnom_val;
   if (tab_val.Taille() != t_ptnom_val.Taille())
     tab_val.Change_taille(t_ptnom_val.Taille());
   };

// change le tableau de scalaires en fonction d'une liste
// la taille des noms associés est modifié en conséquence
void BlocGeneEtVecMultType::Change_tab_val(const list<double>& li)
 { int taille = li.size(); tab_val.Change_taille(taille);
   list<double>::const_iterator ili=li.begin();
   for (int i=0;i<taille;i++,ili++)
     tab_val(i+1)=(*ili);
   int taille_ptnom_tab_val=ptnom_tab_val.Taille();
   ptnom_tab_val.Change_taille(taille);
   //si la nouvelle taille est plus grande, il faut initialiser à null
   if (taille_ptnom_tab_val < taille)
    for (int i=taille_ptnom_tab_val+1;i<= taille;i++)
     ptnom_tab_val(i)="NULL";
 };

// change le tableau des noms associé aux  scalaires en fonction d'une liste
// la taille du tableau de scalaires associés est modifié en conséquence
void BlocGeneEtVecMultType::Change_ptnom_val(const list<string>& li)
 { int taille = li.size(); ptnom_tab_val.Change_taille(taille);
   list<string>::const_iterator ili=li.begin();
   for (int i=0;i<taille;i++,ili++)
     ptnom_tab_val(i+1)=(*ili);
   tab_val.Change_taille(taille);
 };


istream & operator >> (istream & entree, BlocGeneEtVecMultType & coo)
  { entree >> coo.nomref >> coo.motClef;
    string toto; int taille;
    entree >> taille >> toto ;
    coo.vect_coorpt.Change_taille(taille);
    int dim = ParaGlob::Dimension();
    string init("NULL");
    // on initialise les noms à rien
    for (int i=1; i<= taille; i++)
      coo.ptnom_vect(i).Change_taille(dim,init);
   
    for (int i=1;i<=taille;i++)
     for (int j=1;j<= dim;j++)
       {string inter;
        entree >> inter;
        if (inter == "nom_Xi_")
          // dans ce cas cela signifie qu'on doit lire un nom
          {entree >> coo.ptnom_vect(i)(j);}
        else // sinon cela veut dire que c'est une valeur numérique
          {coo.vect_coorpt(i)(j) = ChangeReel(inter);
           coo.ptnom_vect(i)(j) = "NULL";
          };
        };
    entree >> taille >> toto ;
    coo.tab_val.Change_taille(taille);
    for (int i=1;i<=taille;i++)
     {string inter;
      entree >> inter;
      if (inter == "nom_VAL_")
        // dans ce cas cela signifie qu'on doit lire un nom
        {entree >> coo.ptnom_tab_val(i);}
      else // sinon cela veut dire que c'est une valeur numérique
        {coo.tab_val(i) = ChangeReel(inter);
         coo.ptnom_tab_val(i) = "NULL";
        };
     };
    return entree;
  };
  
ostream & operator << ( ostream & sort,const  BlocGeneEtVecMultType & coo)
  { sort << coo.nomref << " " << coo.motClef << " " ;
    int taille = coo.vect_coorpt.Taille();
    sort << taille << " vect(s) ";
   
    int dim = ParaGlob::Dimension();
    for (int i=1;i<=taille;i++)
      {sort << " , coord "<< i <<" : ";
       for (int j=1;j<= dim;j++)
         if (coo.ptnom_vect(i)(j) != "NULL")
           { sort << " nom_Xi_ " << coo.ptnom_vect(i)(j) << " ";}
         else
           { sort << coo.vect_coorpt(i)(j) << " ";};
       };
    int tab_valtaille = coo.tab_val.Taille();
    sort << " " << tab_valtaille << " scal(s) ";
    for (int i=1;i<= tab_valtaille;i++)
      if (coo.ptnom_tab_val(i) != "NULL")
        { sort << " nom_VAL_ " << coo.ptnom_tab_val(i) << " ";}
      else
        { sort << coo.tab_val(i) << " ";};
     return sort;
  };

