// FICHIER : Loi_iso_thermo.cp
// CLASSE : Loi_iso_thermo


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


//#include "Debug.h"

# include <iostream>
using namespace std;  //introduces namespace std
#include <math.h>
#include <stdlib.h>
#include "Sortie.h"
#include "TypeConsTens.h"
#include "ConstMath.h"
#include "TypeQuelconqueParticulier.h"
#include "CharUtil.h"


#include "Loi_iso_thermo.h"

//==================== cas de la class de sauvegarde SaveResul ===================

// constructeur  par défaut à ne pas utiliser
Loi_iso_thermo::SaveResul_Loi_iso_thermo::SaveResul_Loi_iso_thermo() :
	stockParaInt(NULL), saveCrista(NULL)
  { }; 

// le constructeur courant
// sCrista s'il est NULL, on en tient pas compte
// s'il est non NULL, on cré l'instances saveCrista par défaut
Loi_iso_thermo::SaveResul_Loi_iso_thermo::SaveResul_Loi_iso_thermo
                        (CompThermoPhysiqueAbstraite::StockParaInt* stock
                         ,CristaliniteAbstraite::SaveCrista* sCrista):
	stockParaInt(NULL),saveCrista(NULL) 
  {if (sCrista != NULL) 
  	saveCrista = sCrista->Nevez_SaveCrista();	
   if (stock != NULL)
   	{ stockParaInt = new CompThermoPhysiqueAbstraite::StockParaInt(*stock);
   	};
  }; 

// constructeur de copie 
Loi_iso_thermo::SaveResul_Loi_iso_thermo::SaveResul_Loi_iso_thermo
                                         (const Loi_iso_thermo::SaveResul_Loi_iso_thermo& sav ):
	stockParaInt(NULL),saveCrista(NULL) 
  {if (sav.saveCrista != NULL) 
  	  saveCrista = sav.saveCrista->Nevez_SaveCrista();  	
   if (sav.stockParaInt != NULL)
   	{ stockParaInt = new CompThermoPhysiqueAbstraite::StockParaInt(*(sav.stockParaInt));
   	};
  }; 

// destructeur
Loi_iso_thermo::SaveResul_Loi_iso_thermo::~SaveResul_Loi_iso_thermo() 
  {if (saveCrista != NULL) delete saveCrista;
   if (stockParaInt != NULL) delete stockParaInt; 
  };
  
// affectation
CompThermoPhysiqueAbstraite::SaveResul &
   Loi_iso_thermo::SaveResul_Loi_iso_thermo::operator = ( const CompThermoPhysiqueAbstraite::SaveResul & a)
  { Loi_iso_thermo::SaveResul_Loi_iso_thermo& sav = *((Loi_iso_thermo::SaveResul_Loi_iso_thermo*) &a);
    if (sav.saveCrista != NULL)
     { if (saveCrista == NULL)
         saveCrista = sav.saveCrista->Nevez_SaveCrista();
       else
         (*saveCrista) = *(sav.saveCrista);
     }
    else
     delete saveCrista;
    if (sav.stockParaInt != NULL)
     { if (stockParaInt == NULL)
         stockParaInt  = new CompThermoPhysiqueAbstraite::StockParaInt(*(sav.stockParaInt));
       else
         (*stockParaInt) = *(sav.stockParaInt);
     }
    else
     delete stockParaInt;
    return *this;
  };


     //============= 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 Loi_iso_thermo::SaveResul_Loi_iso_thermo::Lecture_base_info 
                                                 (ifstream& ent,const int cas)
  {  // ici toutes les données sont toujours a priori variables
     // ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
     string toto; ent >> toto;
     #ifdef MISE_AU_POINT	 	 
      if (toto != "S_R_LoiIso_thermo")
          { cout << "\n erreur en lecture du conteneur pour la loi thermo physique de Loi_iso_thermo"
                 << " \n Loi_iso_thermo::SaveResul_Loi_iso_thermo::Lecture_base_info(..";
            Sortie(1);     
          }
     #endif
     bool test=false;ent >> test;
     if (test)
       {// on regarde si les pointeurs existent sinon erreur
        if (stockParaInt == NULL) 
          { cout << "\n erreur en lecture du conteneur pour la loi thermo physique de Loi_iso_thermo"
                 << " on a detecte qu'il faut lire un conteneur de StockParaInt, mais "
                 << " le conteneur resultat n'a pas ete aloue !! "
                 << " \n Loi_iso_thermo::SaveResul_Loi_iso_thermo::Lecture_base_info(..";
            Sortie(1);     
          }
        else // sinon on peut lire
          { ent  >> stockParaInt->pression  >> stockParaInt->temperature ;};
     	};
     test=false; ent >> test;
// --- pour le débug
//     test=true; ent >> toto; cout << "\n toto= " << toto << endl;
//-- fin débug     
     if (test)
       {// on regarde si les pointeurs existent sinon erreur
        if (saveCrista == NULL) 
          { cout << "\n erreur en lecture du conteneur pour la loi thermo physique de Loi_iso_thermo"
                 << " on a detecte qu'il faut lire un conteneur de cristalinite, mais "
                 << " le conteneur resultat n'a pas ete aloue !! "
                 << " \n Loi_iso_thermo::SaveResul_Loi_iso_thermo::Lecture_base_info(..";
            Sortie(1);     
          }
        else // sinon on peut lire
         { saveCrista->Lecture_base_info (ent,cas);}; 
     	};
    }; 

// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Loi_iso_thermo::SaveResul_Loi_iso_thermo::Ecriture_base_info
                                                 (ofstream& sort,const int cas)
   { // ici toutes les données sont toujours a priori variables
     // ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
     sort << "\n S_R_LoiIso_thermo  ";
     if (stockParaInt == NULL)
     	{sort << " 0  ";} // on sort un indicateur disant qu'il n'y a pas de pointeur
     else
     	{sort << " 1  "  << stockParaInt->pression << " " << stockParaInt->temperature<< " ";
     	};
     if (saveCrista == NULL)
     	{sort << " 0  ";} // on sort un indicateur disant qu'il n'y a pas de pointeur
     else
     	{sort << " 1  "; saveCrista->Ecriture_base_info(sort,cas);};	
	 }; 
	        
// affichage des infos
void Loi_iso_thermo::SaveResul_Loi_iso_thermo::Affiche()	
   { cout << "\n S_R_LoiIso_thermo ";
     if (stockParaInt != NULL)
     	{ cout << " pression= " << stockParaInt->pression
     	       << " temperature= " << stockParaInt->temperature << " ";
     	};
     if (saveCrista != NULL)
     	{ cout << " cristalinite a tdt: "; saveCrista->Affiche();};	
	 }; 
// idem sur un ofstream
void Loi_iso_thermo::SaveResul_Loi_iso_thermo::Affiche(ofstream& sort)			        
   { sort << "\n S_R_LoiIso_thermo ";
     if (stockParaInt != NULL)
     	{ sort << " pression= " << stockParaInt->pression
     	       << " temperature= " << stockParaInt->temperature << " ";
     	};
     if (saveCrista != NULL)
     	{ sort << " cristalinite a tdt: "; saveCrista->Affiche(sort);};	
	 }; 	        

// mise à jour des informations transitoires en définitif s'il y a convergence 
// par exemple (pour la plasticité par exemple)
void Loi_iso_thermo::SaveResul_Loi_iso_thermo::TdtversT() 
 { if (saveCrista != NULL)
 	 saveCrista->TdtversT();
 };

void Loi_iso_thermo::SaveResul_Loi_iso_thermo::TversTdt() 
 { if (saveCrista != NULL)
 	  saveCrista->TversTdt();
 };

      
// def d'une instance de données spécifiques, et initialisation
Loi_iso_thermo::SaveResul * Loi_iso_thermo::New_et_Initialise() 
 { Loi_iso_thermo::SaveResul * cont=NULL; // conteneur de retour
   if (sortie_post || (crista != NULL)) 
     // cas où il faut un conteneur spécifique
     {if (sortie_post && (crista == NULL))
        // cas sans cristalinité
        { cont = new Loi_iso_thermo::SaveResul_Loi_iso_thermo(); }
      else // sinon c'est soit  (sortie_post && (crista != NULL))
           // ou (!sortie_post && (crista != NULL)) 
        { CristaliniteAbstraite::SaveCrista* interr =  crista->New_et_Initialise();
          double  pres=0; double  temper=0.;
          CompThermoPhysiqueAbstraite::StockParaInt* stock =
          new CompThermoPhysiqueAbstraite::StockParaInt();
          cont = new Loi_iso_thermo::SaveResul_Loi_iso_thermo(stock , interr);
          delete interr;
          delete stock;
         };
     }
   else // sinon on ne garde que le conteneur basique hérité
     { cont = new SaveResul_Loi_iso_thermo(NULL,NULL);
     };
   return cont;
 };

//==================== fin du cas de la class de sauvegarde SaveResul ============

Loi_iso_thermo::Loi_iso_thermo () :  // Constructeur par defaut
  CompThermoPhysiqueAbstraite(LOI_ISO_THERMO,CAT_THERMO_PHYSIQUE,4),alphaT(0.),alphaT_temperature(NULL)
  ,compressibilite(ConstMath::trespetit),compressibilite_temperature(NULL)
  ,lambda(0.),lambda_temperature(NULL),cp(0.),cp_temperature(NULL)
  ,sortie_post(false),type_de_calcul(0),crista(NULL)
   { };
	

// Constructeur de copie
Loi_iso_thermo::Loi_iso_thermo (const Loi_iso_thermo& loi) :
	CompThermoPhysiqueAbstraite(loi),alphaT(loi.alphaT),alphaT_temperature(loi.alphaT_temperature)
  ,compressibilite(loi.compressibilite),compressibilite_temperature(loi.compressibilite_temperature)
  ,lambda(loi.lambda),lambda_temperature(loi.lambda_temperature)
  ,cp(loi.cp),cp_temperature(loi.cp_temperature)
  ,sortie_post(loi.sortie_post),type_de_calcul(loi.type_de_calcul),crista(loi.crista)
	 {// on regarde s'il s'agit de courbes locales ou de courbes globales
	  if (alphaT_temperature != NULL)
	   if (alphaT_temperature->NomCourbe() == "_")
        {// comme il s'agit d'une courbe locale on la redéfinie (sinon pb lors du destructeur de loi)
         string non_courbe("_");   
         alphaT_temperature = Courbe1D::New_Courbe1D(*loi.alphaT_temperature);
        };
	  if (lambda_temperature != NULL)
	   if (lambda_temperature->NomCourbe() == "_")
        {// comme il s'agit d'une courbe locale on la redéfinie (sinon pb lors du destructeur de loi)
         string non_courbe("_");   
         lambda_temperature = Courbe1D::New_Courbe1D(*loi.lambda_temperature);
        };
	  if (cp_temperature != NULL)
	   if (cp_temperature->NomCourbe() == "_")
        {// comme il s'agit d'une courbe locale on la redéfinie (sinon pb lors du destructeur de loi)
         string non_courbe("_");   
         cp_temperature = Courbe1D::New_Courbe1D(*loi.cp_temperature);
        };
	  if (compressibilite_temperature != NULL)
	   if (compressibilite_temperature->NomCourbe() == "_")
        {// comme il s'agit d'une courbe locale on la redéfinie (sinon pb lors du destructeur de loi)
         string non_courbe("_");   
         compressibilite_temperature = Courbe1D::New_Courbe1D(non_courbe,loi.compressibilite_temperature->Type_courbe());
        };
	  };

Loi_iso_thermo::~Loi_iso_thermo ()
// Destructeur 
{ if (alphaT_temperature != NULL)
      if (alphaT_temperature->NomCourbe() == "_") delete alphaT_temperature;
  if (lambda_temperature != NULL)
      if (lambda_temperature->NomCourbe() == "_") delete lambda_temperature;
  if (cp_temperature != NULL)
      if (cp_temperature->NomCourbe() == "_") delete cp_temperature;
  if (compressibilite_temperature != NULL)
      if (compressibilite_temperature->NomCourbe() == "_") delete compressibilite_temperature;
  if (crista != NULL)
        delete crista;   
  };

// Lecture des donnees de la classe sur fichier
void Loi_iso_thermo::LectureDonneesParticulieres (UtilLecture * entreePrinc
                   ,LesCourbes1D& lesCourbes1D ,LesFonctions_nD& lesFonctionsnD)
  { // ------------    lecture du coefficient de dilatation
    string nom; *(entreePrinc->entree) >>  nom; 
    if (nom != "alphaT=")
      { cout << "\n erreur en lecture du coefficient de dilatation, on attendait le mot cle alphaT=";
        entreePrinc->MessageBuffer("**erreur1** Loi_iso_thermo::LectureDonneesParticulieres (... ");
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie(1);     
       }
    // on regarde si le coeff est thermo dépendant 
    if(strstr(entreePrinc->tablcar,"alphaT_thermo_dependant_")!=0)
     { thermo_dependant=true;
       *(entreePrinc->entree) >> nom;
       if (nom != "alphaT_thermo_dependant_")
         { cout << "\n erreur en lecture de la thermodependance, on aurait du lire le mot cle alphaT_thermo_dependant_"
                << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
           entreePrinc->MessageBuffer("**erreur2** Loi_iso_thermo::LectureDonneesParticulieres (... ");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
          }
       // lecture de la loi d'évolution du coefficient de dilatation en fonction de la température
       *(entreePrinc->entree) >>  nom;    
       // on regarde si la courbe existe, si oui on récupère la référence 
       if (lesCourbes1D.Existe(nom)) 
         { alphaT_temperature = lesCourbes1D.Trouve(nom);
          }
       else
        { // sinon il faut la lire maintenant
          string non_courbe("_");   
          alphaT_temperature = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
          // lecture de la courbe
          alphaT_temperature->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
         } 
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      }
    else
     { // lecture du coefficient 
       *(entreePrinc->entree) >> alphaT ;
      };
    //   ----------  lecture de la conductivité
    *(entreePrinc->entree) >>  nom; 
    if (nom != "lambda=")
      { cout << "\n erreur en lecture de la conductivite, on attendait le mot cle lambda=";
        entreePrinc->MessageBuffer("**erreur3** Loi_iso_thermo::LectureDonneesParticulieres (... ");
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie(1);     
       }
    // on regarde si le coeff est thermo dépendant 
    if(strstr(entreePrinc->tablcar,"lambda_thermo_dependant_")!=0)
     { thermo_dependant=true;
       *(entreePrinc->entree) >> nom;
       if (nom != "lambda_thermo_dependant_")
         { cout << "\n erreur en lecture de la thermodependance, on aurait du lire le mot cle lambda_thermo_dependant_"
                << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
           entreePrinc->MessageBuffer("**erreur4** Loi_iso_thermo::LectureDonneesParticulieres (... ");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
          }
       // lecture de la loi d'évolution du coefficient  en fonction de la température
       *(entreePrinc->entree) >>  nom;    
       // on regarde si la courbe existe, si oui on récupère la référence 
       if (lesCourbes1D.Existe(nom)) 
         { lambda_temperature = lesCourbes1D.Trouve(nom);
          }
       else
        { // sinon il faut la lire maintenant
          string non_courbe("_");   
          lambda_temperature = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
          // lecture de la courbe
          lambda_temperature->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
         } 
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      }
    else
     { // lecture du coefficient 
       *(entreePrinc->entree) >> lambda ;
      };
    //   ----------  lecture de la capacité calorifique
    *(entreePrinc->entree) >>  nom; 
    if (nom != "cp=")
      { cout << "\n erreur en lecture de la capacite calorifique, on attendait le mot cle cp=";
        entreePrinc->MessageBuffer("**erreur5** Loi_iso_thermo::LectureDonneesParticulieres (... ");
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie(1);     
       }
    // on regarde si le coeff est thermo dépendant 
    if(strstr(entreePrinc->tablcar,"cp_thermo_dependant_")!=0)
     { thermo_dependant=true;
       *(entreePrinc->entree) >> nom;
       if (nom != "cp_thermo_dependant_")
         { cout << "\n erreur en lecture de la thermodependance, on aurait du lire le mot cle cp_thermo_dependant_"
                << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
           entreePrinc->MessageBuffer("**erreur6** Loi_iso_thermo::LectureDonneesParticulieres (... ");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
          }
       // lecture de la loi d'évolution du coefficient  en fonction de la température
       *(entreePrinc->entree) >>  nom;    
       // on regarde si la courbe existe, si oui on récupère la référence 
       if (lesCourbes1D.Existe(nom)) 
         { cp_temperature = lesCourbes1D.Trouve(nom);
          }
       else
        { // sinon il faut la lire maintenant
          string non_courbe("_");   
          cp_temperature = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
          // lecture de la courbe
          cp_temperature->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
         } 
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      }
    else
     { // lecture du coefficient 
       *(entreePrinc->entree) >> cp ;
      };
      
    //   ----------  lecture éventuelle de la compressibilite
    if(strstr(entreePrinc->tablcar,"compressibilite=")!=0)
    {*(entreePrinc->entree) >>  nom; 
     if (nom != "compressibilite=")
      { cout << "\n erreur en lecture de la compressibilite, on attendait le mot cle compressibilite=";
        entreePrinc->MessageBuffer("**erreur7** Loi_iso_thermo::LectureDonneesParticulieres (... ");
        throw (UtilLecture::ErrNouvelleDonnee(-1));
        Sortie(1);     
       }
     // on regarde si le coeff est thermo dépendant 
     if(strstr(entreePrinc->tablcar,"compressibilite_thermo_dependant_")!=0)
     { thermo_dependant=true;
       *(entreePrinc->entree) >> nom;
       if (nom != "compressibilite_thermo_dependant_")
         { cout << "\n erreur en lecture de la thermodependance, on aurait du lire le mot cle compressibilite_thermo_dependant_"
                << " suivi du nom d'une courbe de charge ou de la courbe elle meme ";
           entreePrinc->MessageBuffer("**erreur8** Loi_iso_thermo::LectureDonneesParticulieres (... ");
           throw (UtilLecture::ErrNouvelleDonnee(-1));
           Sortie(1);     
          }
       // lecture de la loi d'évolution du coefficient  en fonction de la température
       *(entreePrinc->entree) >>  nom;    
       // on regarde si la courbe existe, si oui on récupère la référence 
       if (lesCourbes1D.Existe(nom)) 
         { compressibilite_temperature = lesCourbes1D.Trouve(nom);
          }
       else
        { // sinon il faut la lire maintenant
          string non_courbe("_");   
          compressibilite_temperature = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
          // lecture de la courbe
          compressibilite_temperature->LectDonnParticulieres_courbes (non_courbe,entreePrinc);
         } 
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      }
     else
     { // lecture du coefficient 
       *(entreePrinc->entree) >> compressibilite ;
      };
    }
    else 
     {compressibilite=ConstMath::trespetit;}; // valeur par défaut indiquant qu'il n'y  pas de compressibilité 
    //   ----------  fin de la lecture éventuelle de la compressibilite
    // si on n'est pas arrivé à la fin de la lecture on passe à la ligne suivante
    // sinon pour l'instant on y reste
    if (strstr(entreePrinc->tablcar,"fin_thermique_isotrope")==0)
      entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
//    entreePrinc->NouvelleDonnee();  // prepa du flot de lecture 
      
    // lecture éventuelle du paramètre   sortie_post
    if(strstr(entreePrinc->tablcar,"prepa_sortie_post=")!=0)
      {*(entreePrinc->entree) >>  nom >> sortie_post;
       entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
       };
      
    // lecture éventuelle de la cristalinité  
    if(strstr(entreePrinc->tablcar,"type_de_calcul_=")!=0)
      {*(entreePrinc->entree) >>  nom >> type_de_calcul;
       if (type_de_calcul != 0)
       	{ // lecture de loi de cristalinité
       	  string non_crista;
       	  *(entreePrinc->entree) >>  nom >> non_crista;
       	  // on crée la loi
       	  crista = CristaliniteAbstraite::New_Cristalinite(Id_nom_Enum_crista(non_crista.c_str()));
       	  // on lit les données spécifiques à la loi    
          entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
          crista->LectureDonneesLoiCrista(entreePrinc,lesCourbes1D,lesFonctionsnD);
       	}
       else 
         while (strstr(entreePrinc->tablcar,"fin_thermique_isotrope")==0)
            entreePrinc->NouvelleDonnee(); // prepa du flot de lecture
      };
      
    // prepa du flot de lecture
    if (strstr(entreePrinc->tablcar,"fin_thermique_isotrope")==0)
      entreePrinc->NouvelleDonnee();
    // on passe les lignes éventuelles jusqu'au mot clé de fin de lecture de la loi
    bool entete_message_info_en_trop = true; 
    while (strstr(entreePrinc->tablcar,"fin_thermique_isotrope")==0)
    	{ // il y a des lignes qui ne veulent rien dire pour la loi ??
    	  if (entete_message_info_en_trop)
    	     cout << "\n **** warning, loi iso thermo "
    	          << "\n il y a des infos non utiles ! bizarre et est-ce normal "
    	          << ", lire la doc et les supprimer si elles ne servent pas " ;
    	  cout << "\n " <<  entreePrinc->tablcar;        
    	  entete_message_info_en_trop = false;
    	  entreePrinc->NouvelleDonnee();	
    	};
//    // donc maintenant la prochaine ligne doit-être valide, mais on laisse le test (a virer par la suite) 
//    if(strstr(entreePrinc->tablcar,"fin_thermique_isotrope")==0) entreePrinc->NouvelleDonnee(); 
    entreePrinc->NouvelleDonnee();
    };

// affichage de la loi
void Loi_iso_thermo::Affiche() const 
  { cout << " \n loi de comportement thermique isotrope";
    if ( alphaT_temperature != NULL) { cout << " coefficient de dilatation thermo dependant " 
                                            << " courbe alphaT=f(T): " << alphaT_temperature->NomCourbe() <<" ";}
     else                            { cout << " coefficient de dilatation  alphaT = " << alphaT ;} 
    if ( lambda_temperature != NULL) { cout << " conductivite thermo dependante " 
                                            << " courbe lambda=f(T): " << lambda_temperature->NomCourbe() <<" ";}
    else                             { cout << " conductivite lambda= " << lambda ;} 
    if ( cp_temperature != NULL) { cout << " capacite calorifique thermo dependante " 
                                        << " courbe cp=f(T): " << cp_temperature->NomCourbe() <<" ";}
    else                             { cout << " conductivite lambda= " << lambda ;} 
    if ( compressibilite_temperature != NULL) { cout << " compressibilite thermo dependante " 
                                        << " courbe compressibilite=f(T): " << compressibilite_temperature->NomCourbe() <<" ";}
    else                         { cout << " compressibilite= " << compressibilite ;} 
    cout << " \n prepa_sortie_post=" << sortie_post << " ";
    if (type_de_calcul != 0)
      { cout << "\n calcul avec cristalinite: type_de_calcul= " << type_de_calcul;
        crista->Affiche();
      };
    cout << endl;
  };
            
// affichage et definition interactive des commandes particulières à chaques lois
void Loi_iso_thermo::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
 {  ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
	   cout << "\n definition standart (rep o) ou exemples exhaustifs (rep n'importe quoi) ? ";
	   string rep = "_";
    // procédure de lecture avec prise en charge d'un retour chariot
    rep = lect_return_defaut(true,"o");
    if (alphaT == 0.) { alphaT = 100.;}; // on initialise à une valeur arbitraire
    if (lambda == 0.) { lambda = 10.;}; // on initialise à une valeur arbitraire
    if (cp == 0.) { cp = 1.;}; // on initialise à une valeur arbitraire
    if (compressibilite == 0.) { compressibilite = 0.002;}; // on initialise à une valeur arbitraire
      
 //   sort << "\n# .......  loi de comportement thermique isotrope ........"
 //        << "\n#    coefficient de dilatation :"
 //        << "\n "<< setprecision(6) << alphaT << endl;
         
    sort << "\n# ..........................  loi de comportement thermique isotrope ......................"
         << "\n# |  coefficient de     |   conductivite  |  capacite       |      compressibilite         "
         << "\n# |                     |                 |   calorifique   |       (facultatif)           "
         << "\n# | dilatation  alphaT  |        lambda   |       cp        |      compressibilite         "
         << "\n#.........................................................................................."
         << "\n    alphaT= "<< setprecision(8) << alphaT << "    lambda=  " << setprecision(8) << lambda
         << "    cp=  " << setprecision(8) << cp << "  compressibilite= " << setprecision(8) << compressibilite
         << "\n                       fin_thermique_isotrope      ";
    if ((rep != "o") && (rep != "O" ) && (rep != "0") )
      { sort
         << "\n# \n# chaque parametre peut etre remplace par une fonction dependante de la temperature " 
         << "\n# pour ce faire on utilise un mot cle puis une nom de courbe ou la courbe directement comme avec "
         << "\n# les autre loi de comportement "
         << "\n# exemple pour le coefficient de dilatation:     alphaT=    alphaT_thermo_dependant_   courbe1  "
         << "\n# exemple pour la conductivite:                  mlambda=   lambda_thermo_dependant_   courbe2  "
         << "\n# exemple pour la capacite calorifique:          cp=        cp_thermo_dependant_       courbe3  "
         << "\n# exemple pour la compressibilite:  compressibilite=        compressibilite_thermo_dependant_       courbe3  "
         << "\n# IMPORTANT: a chaque fois qu'il y a une thermodependence, il faut passer une ligne apres la description"
         << "\n# de la grandeur thermodependante, mais pas de passage à la ligne si se n'est pas thermo dependant "
         << "\n#"
         << "\n# ensuite une variable booleenne qui indique si oui ou non on sauvegarde des donnees intermediaires"
         << "\n# pour le post-traitement, pour ensuite pouvoir afficher : temperature de transition, volume specifique"
         << "\n# pression, dilatation, conditivité, capacite calorifique, coeff de compressibilite"
         << "\n#   prepa_sortie_post=   0 # valeur par defaut -> pas de sauvegarde "
         << "\n#"
         << "\n#---- prise en compte de la cristalinite ---------"
         << "\n# il est possible de tenir compte d'un tau de cristalinite de la maniere suivante: "
         << "\n# tout d'abord un indicateur (faculatatif) indiquant le type de calcul voulu, par defaut = 0"
         << "\n#   type_de_calcul : =1 -> calcul du taux de cristalinite, mais pas de dependance des variables " 
         << "\n#                        de  ThermoDonnee(alpha, lambda, compressibilite) avec la cristalinite "
         << "\n#                  : =2 -> calcul du taux de cristalinité, avec dépendance des variables de ThermoDonnee "
         << "\n#  Dans le cas ou le type_de_calcul n'est pas nul, il faut ensuite definir la methode de calcul de la cristalinite"
         << "\n#  ex: pour la loi d'hoffman1  "
         << "\n# type_de_calcul_=  2 Cristalinite_= HOFFMAN1 "
         << "\n#  "
         << "\n# on se reportera a la documentation pour plus d'info sur l'introduction de la cristalinite "
         << "\n#";
       };
    // appel de la cristalinité a priori ici le pointeur est nul, mais on laisse pour le futur où l'on pourrait peut-être
    // accéder à des infos sur la critalinité en interactif
    if (crista != NULL)
     	{ crista->Info_commande_LoisCrista(entreePrinc);};
    // appel de la classe mère
    CompThermoPhysiqueAbstraite::Info_commande_don_LoisDeComp(entreePrinc); 
    sort << "\n#   la derniere ligne doit contenir uniquement le mot cle:     fin_thermique_isotrope "
         << endl;     
  };  		  	  

// test si la loi est complete
int Loi_iso_thermo::TestComplet()
    { int ret = LoiAbstraiteGeneral::TestComplet();
       return ret; 
    }; 
   
// récupération des grandeurs particulière (hors ddl )
// correspondant à liTQ
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Loi_iso_thermo::Grandeur_particuliere
              (bool absolue,List_io<TypeQuelconque>& liTQ,CompThermoPhysiqueAbstraite::SaveResul * saveDon,list<int>& )
 {// on passe en revue la liste
  List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
  // on accède aux grandeurs que si sortie_post=true 
  if(sortie_post)
   for (itq=liTQ.begin();itq!=itqfin;itq++)
    {TypeQuelconque& tipParticu = (*itq); // pour simplifier
     if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
     { EnumTypeQuelconque enuTQ = tipParticu.EnuTypeQuelconque().EnumTQ();

       if (enuTQ == TEMPERATURE_LOI_THERMO_PHYSIQUE)
        { SaveResul_Loi_iso_thermo & save_resul = *((SaveResul_Loi_iso_thermo*) saveDon);
          Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          tyTQ=save_resul.stockParaInt->temperature;
         }
       else if (enuTQ == PRESSION_LOI_THERMO_PHYSIQUE)
        { SaveResul_Loi_iso_thermo & save_resul = *((SaveResul_Loi_iso_thermo*) saveDon);
          Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          tyTQ=save_resul.stockParaInt->pression;
         }
       else if ( (enuTQ == COEFF_DILATATION_LINEAIRE)
                || (enuTQ == CONDUCTIVITE)
                || (enuTQ == CAPACITE_CALORIFIQUE)
                || (enuTQ == COEFF_COMPRESSIBILITE)
                || (enuTQ == CRISTALINITE))
        { // dans ce cas il faut recalculer les grandeurs
          SaveResul_Loi_iso_thermo & save_resul = *((SaveResul_Loi_iso_thermo*) saveDon);
          Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*) (*itq).Grandeur_pointee()); // pour simplifier
          // appel fonction interne
          double& P=save_resul.stockParaInt->pression;          // récup des valeurs sauvegardées
          temperature = save_resul.stockParaInt->temperature;  //       "
          // calcul des grandeurs en fonction de la température si nécessaire
          if (alphaT_temperature != NULL) {alphaT= alphaT_temperature->Valeur(temperature);}
          if (lambda_temperature != NULL) {lambda= lambda_temperature->Valeur(temperature);}
          if (cp_temperature != NULL) {cp= cp_temperature->Valeur(temperature);}
          if (compressibilite_temperature != NULL) {compressibilite= compressibilite_temperature->Valeur(temperature);}
          
          // choix pour les retours
          if (enuTQ == COEFF_DILATATION_LINEAIRE) {tyTQ=alphaT;}
          else if (enuTQ == CONDUCTIVITE) {tyTQ=lambda;}
          else if (enuTQ == CAPACITE_CALORIFIQUE) {tyTQ=cp;}
          else if (enuTQ == COEFF_COMPRESSIBILITE) {tyTQ=compressibilite;}
          else if ((enuTQ == CRISTALINITE)
                   && (crista != NULL))  
            {// !! a priori on sort les valeurs pour tdt, car sinon ça ne fonctionne pas pour l'instant
             // on considère que l'intervale = 0 
             tyTQ = crista->Cristalinite(save_resul.saveCrista,P,temperature);
             }
//          cout << "\n " << temp_trans <<" " << vol_spec << " " <<alphaT << " ";
         };
      };
     };
  };

// récupération et création de la liste de tous les grandeurs particulières
// ces grandeurs sont ajoutées à la liste passées en paramètres
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void Loi_iso_thermo::ListeGrandeurs_particulieres(bool absolue,List_io<TypeQuelconque>& liTQ)
 {Grandeur_scalaire_double grand_courant; // def d'une grandeur courante 
  // def d'un type quelconque représentatif à chaque grandeur
  // a priori ces grandeurs sont défini aux points d'intégration identique à la contrainte par exemple
  // enu_ddl_type_pt est définit dans la loi Abtraite générale
  // on n'ajoute que si sortie_post est vraie, sinon aucune grandeur n'est sauvegardé, donc on ne peut
  // plus y accèder
  if(sortie_post)
  {// a) $$$ cas de TEMPERATURE_LOI_THERMO_PHYSIQUE
   {TypeQuelconque typQ1(TEMPERATURE_LOI_THERMO_PHYSIQUE,enu_ddl_type_pt,grand_courant);
    liTQ.push_back(typQ1);
    };
   // b) $$$ cas de PRESSION_LOI_THERMO_PHYSIQUE
   {TypeQuelconque typQ2(PRESSION_LOI_THERMO_PHYSIQUE,enu_ddl_type_pt,grand_courant);
    liTQ.push_back(typQ2);
    };
   // e) $$$ cas de COEFF_DILATATION_LINEAIRE
   {TypeQuelconque typQ5(COEFF_DILATATION_LINEAIRE,enu_ddl_type_pt,grand_courant);
    liTQ.push_back(typQ5);
    };
   // f) $$$ cas de CONDUCTIVITE
   {TypeQuelconque typQ6(CONDUCTIVITE,enu_ddl_type_pt,grand_courant);
    liTQ.push_back(typQ6);
    };
   // g) $$$ cas de CAPACITE_CALORIFIQUE
   {TypeQuelconque typQ7(CAPACITE_CALORIFIQUE,enu_ddl_type_pt,grand_courant);
    liTQ.push_back(typQ7);
    };
   // h) $$$ cas de COEFF_COMPRESSIBILITE
   {TypeQuelconque typQ8(COEFF_COMPRESSIBILITE,enu_ddl_type_pt,grand_courant);
    liTQ.push_back(typQ8);
    };
   // i) $$$ cas de CRISTALINITE
   if (crista != NULL)
   {TypeQuelconque typQ8(CRISTALINITE,enu_ddl_type_pt,grand_courant);
    liTQ.push_back(typQ8);
    };
   }; //-- fin du cas sortie_post=true
  };
          
	   //----- lecture écriture de restart -----
	   // 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 Loi_iso_thermo::Lecture_base_info_loi(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
                                             ,LesFonctions_nD& lesFonctionsnD)
  { string nom; 
	if (cas == 1)
	  { ent >> nom; 
	    if (nom != "LOI_ISO_THERMO")
	     { cout << "\n erreur en lecture de la loi : LOI_ISO_THERMO, on attendait le mot cle : LOI_ISO_THERMO "
	            << "\n LOI_ISO_THERMO::Lecture_base_info_loi(...";
	       Sortie(1);
	      }
	    // ensuite normalement il n'y a pas de pb de lecture puisque c'est écrit automatiquement (sauf en debug)        
	    ent >> nom; // alphaT
	    bool test; ent >> test;
	    if (!test)
	     { ent >> alphaT;
	       if (alphaT_temperature != NULL) 
	           {if (alphaT_temperature->NomCourbe() == "_") delete alphaT_temperature; alphaT_temperature = NULL;};
	      }
	    else
	     { ent >> nom; alphaT_temperature = lesCourbes1D.Lecture_pour_base_info(ent,cas,alphaT_temperature); };
	    // lambda
	    ent >> nom >> test;
	    if (!test)
	     { ent >> lambda;
	       if (lambda_temperature != NULL) 
	          {if (lambda_temperature->NomCourbe() == "_") delete lambda_temperature; lambda_temperature = NULL;};
	      }
	    else
	     { ent >> nom; lambda_temperature = lesCourbes1D.Lecture_pour_base_info(ent,cas,lambda_temperature); };
	    // cp
	    ent >> nom >> test;
	    if (!test)
	     { ent >> cp;
	       if (cp_temperature != NULL) 
	          {if (cp_temperature->NomCourbe() == "_") delete cp_temperature; cp_temperature = NULL;};
	      }
	    else
	     { ent >> nom; cp_temperature = lesCourbes1D.Lecture_pour_base_info(ent,cas,cp_temperature); };
	    // compressibilite
	    ent >> nom >> test;
	    if (!test)
	     { ent >> compressibilite;
	       if (compressibilite_temperature != NULL) 
	          {if (compressibilite_temperature->NomCourbe() == "_") delete compressibilite_temperature; compressibilite_temperature = NULL;};
	      }
	    else
	     { ent >> nom; compressibilite_temperature = lesCourbes1D.Lecture_pour_base_info(ent,cas,compressibilite_temperature); };
        // cas du post-traitement
        ent >> nom >> sortie_post ; 
        // cas de la cristalinité
        ent >> nom >> type_de_calcul;
        if (type_de_calcul != 0)
     	{ Enum_crista enuCrista;
     	  ent >> nom >> enuCrista;
     	  // création s'il le faut de l'instance de calcul de la cristalinité
     	  if (crista != NULL)
     	  	{ // cas où une instance existe déjà
     	  	  if (crista->Type_Crista() != enuCrista)
     	  	  	{ // cas où l'instance n'est pas a doc
     	  	  	  delete crista; 
       	          // on crée une  loi conforme
       	          crista = CristaliniteAbstraite::New_Cristalinite(enuCrista);
     	  	  	};
     	  	}
     	  else // sinon l'instance n'existe pas, il faut donc la créer	
       	     { crista = CristaliniteAbstraite::New_Cristalinite(enuCrista);
     	  	  };
       	  // on lit les données spécifiques à la loi    
          crista->Lecture_don_base_info(ent,cas,lesCourbes1D,lesFonctionsnD);
     	};
	   } 
	 CompThermoPhysiqueAbstraite::Lecture_don_base_info(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
 };
       // cas donne le niveau de sauvegarde
       // = 1 : on sauvegarde tout
       // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Loi_iso_thermo::Ecriture_base_info_loi(ofstream& sort,const int cas)
{ if (cas == 1)
   { sort << " LOI_ISO_THERMO " ;
	 sort << "\n  alphaT= ";             
     if (alphaT_temperature == NULL)
      { sort << false << " " << alphaT << " ";}
     else 
      { sort << true << " fonction_alphaT_temperature ";
        LesCourbes1D::Ecriture_pour_base_info(sort,cas,alphaT_temperature);
       }; 
	 sort << "\n  lambda= ";             
     if (lambda_temperature == NULL)
      { sort << false << " " << lambda << " ";}
     else 
      { sort << true << " fonction_lambda_temperature ";
        LesCourbes1D::Ecriture_pour_base_info(sort,cas,lambda_temperature);
       }; 
	 sort << "\n  cp= ";             
     if (cp_temperature == NULL)
      { sort << false << " " << cp << " ";}
     else 
      { sort << true << " fonction_cp_temperature ";
        LesCourbes1D::Ecriture_pour_base_info(sort,cas,cp_temperature);
       }; 
	 sort << "\n  compressibilite= ";             
     if (compressibilite_temperature == NULL)
      { sort << false << " " << compressibilite << " ";}
     else 
      { sort << true << " fonction_compressibilite_temperature ";
        LesCourbes1D::Ecriture_pour_base_info(sort,cas,compressibilite_temperature);
       }; 
     // cas du post-traitement
     sort << "\n prepa_sortie_post= " << sortie_post << " "; 
     // cas de la cristalinité
     sort << "\n type_de_calcul= " << type_de_calcul;
     if (type_de_calcul != 0)
     	{ sort << " id_crista= " << crista->Type_Crista() << " ";
     	  crista->Ecriture_don_base_info(sort,cas);
     	};
     }  
  // appel de la classe mère
  CompThermoPhysiqueAbstraite::Ecriture_don_base_info(sort,cas);
  };

 // ========== codage des METHODES VIRTUELLES :================
// ramène les données thermiques défnies au point
// P: la pression à l'énuméré temps, et P_t la pression au temps t
void Loi_iso_thermo::Cal_donnees_thermiques
          (const double& P_t,CompThermoPhysiqueAbstraite::SaveResul * saveDon,const Deformation & def,const double& P
		  	                               ,Enum_dure temps, ThermoDonnee& donneeThermique)
  { saveResul = saveDon; // association pour les méthodes dérivées
    // calcul de la température
    temperature = def.DonneeInterpoleeScalaire(TEMP,temps);
    // calcul de alphaT
    if (alphaT_temperature != NULL) {alphaT= alphaT_temperature->Valeur(temperature);}
    if (lambda_temperature != NULL) {lambda= lambda_temperature->Valeur(temperature);}
    if (cp_temperature != NULL) {cp= cp_temperature->Valeur(temperature);}
    if (compressibilite_temperature != NULL) {compressibilite= compressibilite_temperature->Valeur(temperature);}
    // retour des données thermiques
    donneeThermique.ChangeAlphaTLambdaCp(alphaT,lambda,cp);  
    donneeThermique.ChangeCompressibilite(compressibilite);  
    // la cristalinité si nécessaire
    double taux_cris = 0;
    double temperature_t=0; 
    if (crista != NULL)
      { Loi_iso_thermo::SaveResul_Loi_iso_thermo* saveRes 
                = ((Loi_iso_thermo::SaveResul_Loi_iso_thermo*) saveResul);
        if (temps == TEMPS_tdt)
          { // dans ce cas on doit disposer des températures et pression à t
            temperature_t = def.DonneeInterpoleeScalaire(TEMP,TEMPS_t);
        	}
        else // on prend la température déjà calculée (car c'est o ou t)
          {	temperature_t = temperature;}
        taux_cris = crista->Cristalinite
                     (P_t,temperature_t,saveRes->saveCrista,P,temperature,temps);
        donneeThermique.ChangeTauxCrista(taux_cris);
        
      };
    // les données particulière a enregistrer si nécessaire
    if(sortie_post)
     { SaveResul_Loi_iso_thermo & save_resul = *((SaveResul_Loi_iso_thermo*) saveDon);
       save_resul.stockParaInt->pression=P;
       save_resul.stockParaInt->temperature=temperature;
      };
   };

// calcul du flux et ses variations  par rapport aux ddl a t+dt: stockage dans ptIntegThermi et dans d_flux
// calcul des énergies thermiques
// en entrée: température, gradient de temp, et grandeurs associées, métrique
void Loi_iso_thermo::Calcul_DfluxH_tdt
            (const double & P_t,PtIntegThermiInterne& ptIntegThermi, const double & P,DdlElement & tab_ddl
             ,const Deformation & def  // prévue pour servir pour l'interpolation
             , Tableau <CoordonneeB >& d_gradTB,Tableau <CoordonneeH >& d_flux,ThermoDonnee& dTP
             ,EnergieThermi & energ,const EnergieThermi & energ_t,const Met_abstraite::Impli& ex)
   {
     // on commence par calculer les paramètres de la loi thermique
     Cal_donnees_thermiques(P_t,saveResul,def,P,TEMPS_tdt,dTP);
     // calcul du flux en isotrope
     CoordonneeB fluxB = dTP.Conductivite() * ptIntegThermi.GradTB();
     // on le passe en coordonnées contravariantes
     ptIntegThermi.FluxH() = (*ex.gijHH_tdt) * fluxB;
     // calcul de la variation du flux par rapport aux ddl thermique
     int nb_ddl = d_gradTB.Taille();
     d_flux.Change_taille(nb_ddl); // mise à jour de la taille au cas ou
     if (lambda_temperature == NULL)
       // cas le plus simple où seule le gradient dépend de la température
       { for (int iddl=1;iddl<=nb_ddl;iddl++)
           d_flux(iddl) = (*ex.gijHH_tdt) * (lambda*d_gradTB(iddl));
       }
     else
       // cas où la conductivité dépend de la température
       { double der_lambda= lambda_temperature->Derivee(temperature);
         for (int iddl=1;iddl<=nb_ddl;iddl++)
           d_flux(iddl) = (*ex.gijHH_tdt)* (lambda*d_gradTB(iddl) + der_lambda * fluxB);
       };
     // pour les énergies je ne sais pas trop quoi faire actuellement
   };

