// 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 "LesPtIntegMecaInterne.h"


// contructeur par défaut
LesPtIntegMecaInterne::LesPtIntegMecaInterne():
  tabPtInt(),tabSigHH(),tabSigHH_t()
    {};
    
// contructeur fonction du nombre de points d'intégration et de la dimension de tenseurs
LesPtIntegMecaInterne::LesPtIntegMecaInterne(int nbpti, int dimtens):
  tabPtInt(nbpti,PtIntegMecaInterne(dimtens)),tabSigHH(nbpti),tabSigHH_t(nbpti)
    { // on relie les tableaux entre eux
      for (int i=1; i<= nbpti; i++)
        {tabSigHH(i)= tabPtInt(i).SigHH();
         tabSigHH_t(i)= tabPtInt(i).SigHH_t();
        };
      };
    
// contructeur de copie
LesPtIntegMecaInterne::LesPtIntegMecaInterne(const LesPtIntegMecaInterne& lespti):
  tabPtInt(lespti.tabPtInt),tabSigHH(lespti.tabSigHH.Taille())
  ,tabSigHH_t(lespti.tabSigHH_t.Taille())
    { // on relie les tableaux entre eux
      int nbpti = tabPtInt.Taille();
      for (int i=1; i<= nbpti; i++)
        {tabSigHH(i)= tabPtInt(i).SigHH();
         tabSigHH_t(i)= tabPtInt(i).SigHH_t();
        };
      };
    
// DESTRUCTEUR :
// normalement il n'y a rien n'a faire car les pointeurs sont des copies
LesPtIntegMecaInterne::~LesPtIntegMecaInterne()
{ };
    
// Surcharge de l'operateur = 
LesPtIntegMecaInterne& LesPtIntegMecaInterne::operator= ( const LesPtIntegMecaInterne& lespti)
{ int newTaille = lespti.NbPti();
  tabPtInt = lespti.tabPtInt;
  tabSigHH.Change_taille(newTaille);
  tabSigHH_t.Change_taille(newTaille);
  // on relie les tableaux entre eux
  int nbpti = tabPtInt.Taille();
  for (int i=1; i<= nbpti; i++)
        {tabSigHH(i)= tabPtInt(i).SigHH();
         tabSigHH_t(i)= tabPtInt(i).SigHH_t();
        };
  // retour
  return *this;
};

// changement de taille donc de nombre de points d'intégration
// fonction du nombre de points d'intégration et de la dimension de tenseurs
// attention: il s'agit d'un dimentionnement pas défaut (les activations diverses
// sont ensuite à faire: par exemple pour les invariants)
void LesPtIntegMecaInterne::Change_taille_PtIntegMeca(int nbpti, int dimtens)
    { // tout d'abord on adapte la taille
      tabPtInt.Change_taille(nbpti,PtIntegMecaInterne(dimtens));
      tabSigHH.Change_taille(nbpti);
      tabSigHH_t.Change_taille(nbpti);
      // on relie les tableaux entre eux
      for (int i=1; i<= nbpti; i++)
        {tabSigHH(i)= tabPtInt(i).SigHH();
         tabSigHH_t(i)= tabPtInt(i).SigHH_t();
        };
    };
// idem, mais les instances ajoutées ou retirer ont la même dimension de tenseur que celles
// qui existent déjà
void LesPtIntegMecaInterne::Change_taille_PtIntegMeca(int nbpti)
    { // tout d'abord on adapte la taille
      tabPtInt.Change_taille(nbpti);
      tabSigHH.Change_taille(nbpti);
      tabSigHH_t.Change_taille(nbpti);
      // on relie les tableaux entre eux
      for (int i=1; i<= nbpti; i++)
        {tabSigHH(i)= tabPtInt(i).SigHH();
         tabSigHH_t(i)= tabPtInt(i).SigHH_t();
        };
      };
      
// retour la dimension des tenseurs gérés
int LesPtIntegMecaInterne::DimTens() const 
 {if (tabPtInt.Taille() != 0) 
	{return tabPtInt(1).EpsBB()->Dimension();}
  else 
  	{return 0;};
 };
    
//============= lecture écriture dans base info ==========
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void LesPtIntegMecaInterne::Lecture_base_info (istream& ent,const int cas)
 {switch (cas)
  { case 1 : // ------- on récupère tout -------------------------
     { string nom; ent >> nom; // on ne vérifie pas le nom car on considère que 
                               // ça a été écrit par le prog associé 
       int taille = 0;
       ent >> nom >> taille; // lecture de la taille
       tabPtInt.Change_taille(taille);                        
       tabSigHH.Change_taille(taille);                        
       tabSigHH_t.Change_taille(taille);
       // lecture
       for (int i=1;i<=taille;i++)
         tabPtInt(i).Lecture_base_info (ent,cas);
       // on relie les tableaux entre eux
       for (int i=1; i<= taille; i++)
          {tabSigHH(i)= tabPtInt(i).SigHH();
           tabSigHH_t(i)= tabPtInt(i).SigHH_t();
        };
	      break;
     }
    case  2 : // ----------- lecture uniquement de se qui varie --------------------
     { string nom; ent >> nom; // on ne vérifie pas le nom car on considère que 
                               // ça a été écrit par le prog associé 
       // lecture
       int taille = tabPtInt.Taille();
       int nb=0; // sert pour la lecture, mais n'est pas utilisé
       for (int i=1;i<=taille;i++)
         {ent >> nom >> nb ;
          tabPtInt(i).Lecture_base_info (ent,cas);
         };
	      break;
	    }
    default :
	    { cout << "\nErreur : valeur incorrecte du type de lecture !\n";
	      cout << "LesPtIntegMecaInterne::Lecture_base_info(istream& ent,const "
			         << " cas= " << cas << endl;
	      Sortie(1);
	    };
  }
 };
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LesPtIntegMecaInterne::Ecriture_base_info(ostream& sort,const int cas)
 {switch (cas)
  { case 1 : // ------- on sauvegarde tout -------------------------
     { sort << "\n grandeurs_aux_points_d_integration:" ;
       int taille = tabPtInt.Taille();
       sort << " taille= " << taille << " " ;
       for (int i=1;i<=taille;i++)
          { sort << " \n pti "<< i <<" ";
            tabPtInt(i).Ecriture_base_info(sort,cas);
          };
	      break;
	    }
    case  2 : // ----------- sauvegarde uniquement de se qui varie --------------------
     { sort << "\n grandeurs_aux_points_d_integration:" ;
       int taille = tabPtInt.Taille();
       for (int i=1;i<=taille;i++)
          { sort << " \n pti "<< i <<" ";
            tabPtInt(i).Ecriture_base_info(sort,cas);
          };
	      break;
	    }
    default :
	    { cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
	      cout << "LesPtIntegMecaInterne::Ecriture_base_info(ostream& sort,const int cas)"
			         << " cas= " << cas << endl;
	      Sortie(1);
     };
  };
 };
 
// actualisation des grandeurs actives de t+dt vers t, pour celles qui existent 
// sous ces deux formes    
void LesPtIntegMecaInterne::TdtversT()
	{ int taille = tabPtInt.Taille();
	  for (int i=1;i<=taille;i++)
	     tabPtInt(i).TdtversT();		
	};
	
// actualisation des grandeurs actives de t vers tdt, pour celles qui existent 
// sous ces deux formes          
void LesPtIntegMecaInterne::TversTdt()
	{ int taille = tabPtInt.Taille();
	  for (int i=1;i<=taille;i++)
	     tabPtInt(i).TversTdt();		
	};
    
// ramène la compressibilité moyenne sur tous les points d'intégration
double LesPtIntegMecaInterne::CompressibiliteMoyenne() const
	{ int taille = tabPtInt.Taille();
	  double compress=0.;
	  if (taille != 0)
	   {for (int i=1;i<=taille;i++)
	      compress += tabPtInt(i).ModuleCompressibilite();
	    // moyenne
	    compress /= taille; 
	   };
	  return compress; 
	};

// surcharge de l'operateur de lecture
istream & operator >> (istream & entree, LesPtIntegMecaInterne & lespti)
  { // vérification du type
    string nom;
    entree >> nom;
   #ifdef MISE_AU_POINT
    if (nom != "LesPtIntegMecaInterne")
		{	cout << "\nErreur, en lecture d'une instance  LesPtIntegMecaInterne " 
		         << " on attendait LesPtIntegMecaInterne et on a lue: " << nom ;
			cout << "istream & operator >> (istream & entree, LesPtIntegMecaInterne & pti)\n";
			Sortie(1);
		};
   #endif
    // puis lecture des différents éléments
    lespti.tabPtInt.Entree(entree);
    // on s'occupe des pointeurs
    int nbpti = lespti.tabPtInt.Taille();
    lespti.tabSigHH.Change_taille(nbpti);
    lespti.tabSigHH_t.Change_taille(nbpti);
    // on relie les tableaux entre eux
    for (int i=1; i<= nbpti; i++)
        {lespti.tabSigHH(i)= lespti.tabPtInt(i).SigHH();
         lespti.tabSigHH_t(i)= lespti.tabPtInt(i).SigHH_t();
        };
    return entree;      
  };
  
// surcharge de l'operateur d'ecriture 
ostream & operator << ( ostream & sort,const  LesPtIntegMecaInterne & lespti)
  { // tout d'abord un indicateur donnant le type
    sort << "LesPtIntegMecaInterne " ; 
    // puis les différents éléments (pas les pointeurs qui n'ont aucun intérêt ici)
    lespti.tabPtInt.Sortir(sort);
    return sort;      
  };