// 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 "Debug.h"
#include "ElemThermi.h"
#include <iomanip>
#include "ConstMath.h"
#include "Util.h"
#include "Coordonnee2.h"
#include "Coordonnee3.h"
#include "TypeQuelconqueParticulier.h"
#include "TypeConsTens.h"


	    
        
// affichage dans la sortie transmise, des variables duales "nom"
// aux differents points d'integration
// dans le cas ou nom est vide, affichage de "toute" les variables
void ElemThermi::VarDualSort(ostream& sort, Tableau<string>& nom,int ,int cas)
   {  if ((cas == 1) || (cas == 2))
       { // cas d'une premiere initialisation
         Tableau<Enum_variable_metrique> tab(5);
         tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt;
         tab(4) = igiH_0; tab(5) = igijHH_0;
         met->PlusInitVariables(tab) ;
        }
      // def de la dimension des Coordonnées
      int dim = ParaGlob::Dimension();
      // def de tenseurs pour la sortie
      Coordonnee  fluxD(dim);
      CoordonneeH  fluxDH(dim) ;
      Coordonnee  gradT(dim);
      CoordonneeB gradTB(dim);    
      CoordonneeB DgradTB(dim);
      Coordonnee  DgradT(dim);
      CoordonneeB DeltagradTB(dim) ;
      Coordonnee  DeltagradT(dim) ;
      Enum_dure temps;
    
      // a priori ici on travaille en absolue
      bool absolue = true;
      
      int ni; // compteur globale de point d'integration
      for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
    //  for (int ni=1;ni<= nbi;ni++)
       {// éléments de métrique et matrices de passage   
        TenseurHH* gijHH;TenseurBB* gijBB;
        Coordonnee* Mpt0;Coordonnee* Mptfin;
		      BaseB * giB_0; BaseB * giB_tdt;
		      BaseH * giH_0; BaseH * giH_tdt;
        Mat_pleine jB0(dim,dim),jBfin(dim,dim);
        if ((cas==1) || (cas==11))
        // calcul d'une  ortho interessance de visualisation des tenseurs
        // cas de tenseur 3D -> Ia, cas 1D on prend un vecteur norme collineaire
        // avec g1, dans le cas 2D
        // la nouvelle base jB est calculee dans def par projection de "Ia" sur Galpha
        // le resultat est une matrice de passage utilisable pour le changement de base
        // jB0 a t=0, B pour les tenseurs BB, jH0 idem pour les tenseurs HH
          // resultat a t+dt
          {const Met_abstraite::InfoImp& ex = def->RemontImp(absolue,jB0,jBfin);
           temps=TEMPS_tdt;
           Mpt0 = ex.M0; Mptfin = ex.Mtdt;
           giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
           giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
           gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
          }
        else if ((cas==2) || (cas==12)) 
          { // resultat a tdt
           const Met_abstraite::InfoExp_tdt& ex= def->RemontExp_tdt(absolue,jB0,jBfin);
           temps=TEMPS_tdt;
           Mpt0 = ex.M0; Mptfin = ex.Mtdt;
           giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
           giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
           gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
          }
        // calcul des grandeurs
        PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(ni);
        
        fluxDH = (ptIntegThermi.FluxH());
        CoordonneeB interB(dim); // variable inter
        for (int i=1;i<= dim; i++)
          interB += (*giB_tdt)(i) * fluxDH(i);
        fluxD = interB.Coor();
       
        gradTB = (ptIntegThermi.GradTB());
        CoordonneeH interH(dim); // variable inter
        for (int i=1;i<= dim; i++)
          interH += gradTB(i) * (*giH_tdt)(i);
        gradT = interH.Coor();
        
        DgradTB = (ptIntegThermi.DgradTB());
        interH.Zero(); // variable inter
        for (int i=1;i<= dim; i++)
          interH += DgradTB(i) * (*giH_tdt)(i);
        DgradT = interH.Coor();
        
        DeltagradTB = (ptIntegThermi.DeltaGradTB());
        interH.Zero(); // variable inter
        for (int i=1;i<= dim; i++)
          interH += DeltagradTB(i) * (*giH_tdt)(i);
        DeltagradT = interH.Coor();
        
        // donnees propre a la loi thermique au pt d'integ
        CompThermoPhysiqueAbstraite::SaveResul* sTP = tabSaveTP(ni);
        // donnees propre a la loi mécanique au pt d'integ
        Loi_comp_abstraite::SaveResul* sDon=NULL;  // les données spécifique mécanique
        if (sDon != NULL) {sDon = tabSaveDon(ni);};         // au pt d'integ si elles existes
        // données propre à la déformation au pt d'integ
        Deformation::SaveDefResul * sDefDon = tabSaveDefDon(ni);
        
        
        
        // affichage
        sort << "\n=================== Point d\'integration [[[ " << ni<<" ]]] ==================" ;
        sort << "\nCoordonnees avant deformation  " ; Mpt0->Affiche(sort,16);
        sort << "\nCoordonnees apres deformation  " ; Mptfin->Affiche(sort,16);
        sort <<" \n    et les variations          " ; ((*Mptfin) - (*Mpt0)).Affiche(sort,16);
        if (nom.Taille() == 0)
         { // cas d'une sortie complete
           for (int indic =1; indic<=11; indic++)
              AffDefCont
               (sort,sTP,gradTB,gradT,ptIntegThermi.Norme_gradT()
                ,DgradTB,DgradT,ptIntegThermi.Norme_DGradT()
                ,fluxDH,fluxD,ptIntegThermi.Norme_flux()
                ,ptIntegThermi.Temperature(),indic) ;
         }
        else 
         {
// pour mémoire je laisse le reste
//         for (int ij = 1;ij<= nom.Taille(); ij++)
//          if (nom(ij) == "Green-Lagrange")
//            AffDefCont(sort,sDon,gradT0B,gradTB,DgradTB,DeltagradTB,fluxDH,epsHB,sigHB,valPropreEps,valPropreDeps,valPropreSig,Mises
//                ,epsAlmBB,epslogBB,1);
         };
       };
      // liberation des tenseurs intermediaires
      LibereTenseur();   
    }; 
void ElemThermi::AffDefCont( ostream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
                         CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
                         CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_dGradT,
                         CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
                         double& temperature, int indic)
  { int dim = fluxDH.Dimension();
    switch (dim)
     { case 1:
          AffDefCont1D(sort,saveDon,gradTB,gradT,norme_gradT
                       ,DgradTB,DgradT,norme_dGradT
                       ,fluxDH,fluxD,norme_flux
                       ,temperature,indic);
          break;
       case 2:
          AffDefCont2D(sort,saveDon,gradTB,gradT,norme_gradT
                       ,DgradTB,DgradT,norme_dGradT
                       ,fluxDH,fluxD,norme_flux
                       ,temperature,indic);
          break;                
       case 3:
          AffDefCont3D(sort,saveDon,gradTB,gradT,norme_gradT
                       ,DgradTB,DgradT,norme_dGradT
                       ,fluxDH,fluxD,norme_flux
                       ,temperature,indic);
          break;
       default :
         {cout << "\nerreur seules les cas 1D 2D 3D sont pris considere  et non " << dim;
          cout << "\nElemThermi::AffDefCont( etc ..." << endl;
         }    
     }
   };    
void ElemThermi::AffDefCont1D( ostream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
                         CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
                         CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_DGradT,
                         CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
                         double& temperature, int indic)
{
 switch (indic)
  {case 1 :{ sort << "\nGradient de temperature dans repere global";
             sort << "\n        gradT     " ;
             sort << setw (16)  << gradT(1) ;
            }
            break;
   case 2 :{ sort << "\nGradient de temperature  dans repere global";
             sort << "\n       gradTB     " ;
             sort << setw (16)  << gradTB(1) ;
            }
            break;               
   case 3 :{ sort << "\nDensite de flux dans repere global";
             sort << "\n       fluxD     " ;
             sort << setw (16)  << fluxD(1) ;
            }
            break;               
   case 4 :{ sort << "\nDensite de flux dans repere local";
             sort << "\n     fluxDH     " ;
             sort << setw (16)  << fluxDH(1) ;
            }
            break;               
   case 5 :{ sort << "\nVitesse du gradient de temperature dans repere global";
             sort << "\n     DgradT     " ;
             sort << setw (16)  << DgradT(1) ;
            }
            break;               
   case 6 :{ sort << "\nVitesse du gradient de temperature dans repere local";
             sort << "\n     DgradTB        "  ;
             sort << setw (16)  << DgradTB(1) ;
           }
            break;               
   case 7 :{ sort << "\n norme gradT ";
             sort << "\n     norme_gradT   " ;
             sort << setw (16)  << norme_gradT ;
            }
            break;               
   case 8 :{ sort << "\n norme DgradT  ";
             sort << "\n     norme_DGradT     " ;
             sort << setw (16)   << norme_DGradT ;
            }
            break;
   case 9 :{ sort << "\n norme  fluxD ";
             sort << "\n     norme_flux    " ;
             sort << setw (16)   << norme_flux;
            }
            break;
   case 10 :{ sort << "\n Temperature ";
             sort << "\n       temperature     " ;
             sort << setw (16)  << temperature ;
            }
            break;               
   case 11 :{ if (saveDon != NULL)
              { sort << "\ngrandeurs attachees a la loi et au point ";
                loiTP->AfficheDataSpecif(sort,saveDon);
               } 
            }
            break;               
   default :
         {cout << "\nerreur seules les cas de 1 a 11 sont pris en consideration  et non " << indic;
          cout << "\nElemThermi::AffDefCont1D( etc ..." << endl;
         }    
 
   };
};    
    
      
void ElemThermi::AffDefCont2D( ostream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
                         CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
                         CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_DGradT,
                         CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
                         double& temperature, int indic)
{ 
  string type_repere=" repere global";
  int dim_glob = ParaGlob::Dimension();
  if (dim_glob == 3)
    // lorsque que l'on sort des vecteur de dim 2 en dimension 3, on utilise un repère particulier local orthonormé
    type_repere=" repere orthonorme local";
  int dim_loc = gradTB.Dimension();


 switch (indic)
  {case 1 :{ sort << "\nGradient de temperature dans repere global";
             sort << "\n        gradT     \n" ;
             for (int i=1;i<=dim_glob;i++) sort << setw (16)  << gradT(i) << " ";
            }
            break;
   case 2 :{ sort << "\nGradient de temperature  dans repere global";
             sort << "\n       gradTB     \n" ;
             for (int i=1;i<=dim_loc;i++) sort << setw (16)  << gradTB(i) << " ";
            }
            break;               
   case 3 :{ sort << "\nDensite de flux dans repere global";
             sort << "\n       fluxD     \n" ;
             for (int i=1;i<=dim_glob;i++) sort << setw (16)  << fluxD(i) << " ";
            }
            break;               
   case 4 :{ sort << "\nDensite de flux dans repere local";
             sort << "\n     fluxDH     \n" ;
             for (int i=1;i<=dim_loc;i++) sort << setw (16)  << fluxDH(i) << " ";
            }
            break;               
   case 5 :{ sort << "\nVitesse du gradient de temperature dans repere global";
             sort << "\n     DgradT     \n" ;
             for (int i=1;i<=dim_glob;i++) sort << setw (16)  << DgradT(i) << " ";
            }
            break;               
   case 6 :{ sort << "\nVitesse du gradient de temperature dans repere local";
             sort << "\n     DgradTB        \n"  ;
             for (int i=1;i<=dim_loc;i++) sort << setw (16)  << DgradTB(i) << " ";
           }
            break;               
   case 7 :{ sort << "\n norme gradT ";
             sort << "\n     norme_gradT   " ;
             sort << setw (16)  << norme_gradT ;
            }
            break;               
   case 8 :{ sort << "\n norme DgradT  ";
             sort << "\n     norme_DGradT     " ;
             sort << setw (16)   << norme_DGradT ;
            }
            break;
   case 9 :{ sort << "\n norme  fluxD ";
             sort << "\n     norme_flux    " ;
             sort << setw (16)   << norme_flux;
            }
            break;
   case 10 :{ sort << "\n Temperature ";
             sort << "\n       temperature     " ;
             sort << setw (16)  << temperature ;
            }
            break;               
   case 11 :{ if (saveDon != NULL)
              { sort << "\ngrandeurs attachees a la loi et au point ";
                loiTP->AfficheDataSpecif(sort,saveDon);
               } 
            }
   default :
         {cout << "\nerreur seules les cas de 1 a 11 sont pris en consideration  et non " << indic;
          cout << "\nElemThermi::AffDefCont2D( etc ..." << endl;
         }    
 
   }
};    
    
void ElemThermi::AffDefCont3D( ostream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
                         CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
                         CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_DGradT,
                         CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
                         double& temperature, int indic)
{int dim_glob = 3; int dim_loc = 3;
 switch (indic)
  {case 1 :{ sort << "\nGradient de temperature dans repere global";
             sort << "\n        gradT     \n" ;
             for (int i=1;i<=dim_glob;i++) sort << setw (16)  << gradT(i) << " ";
            }
            break;
   case 2 :{ sort << "\nGradient de temperature  dans repere global";
             sort << "\n       gradTB     \n" ;
             for (int i=1;i<=dim_loc;i++) sort << setw (16)  << gradTB(i) << " ";
            }
            break;               
   case 3 :{ sort << "\nDensite de flux dans repere global";
             sort << "\n       fluxD     \n" ;
             for (int i=1;i<=dim_glob;i++) sort << setw (16)  << fluxD(i) << " ";
            }
            break;               
   case 4 :{ sort << "\nDensite de flux dans repere local";
             sort << "\n     fluxDH     \n" ;
             for (int i=1;i<=dim_loc;i++) sort << setw (16)  << fluxDH(i) << " ";
            }
            break;               
   case 5 :{ sort << "\nVitesse du gradient de temperature dans repere global";
             sort << "\n     DgradT     \n" ;
             for (int i=1;i<=dim_glob;i++) sort << setw (16)  << DgradT(i) << " ";
            }
            break;               
   case 6 :{ sort << "\nVitesse du gradient de temperature dans repere local";
             sort << "\n     DgradTB        \n"  ;
             for (int i=1;i<=dim_loc;i++) sort << setw (16)  << DgradTB(i) << " ";
           }
            break;               
   case 7 :{ sort << "\n norme gradT ";
             sort << "\n     norme_gradT   " ;
             sort << setw (16)  << norme_gradT ;
            }
            break;               
   case 8 :{ sort << "\n norme DgradT  ";
             sort << "\n     norme_DGradT     " ;
             sort << setw (16)   << norme_DGradT ;
            }
            break;
   case 9 :{ sort << "\n norme  fluxD ";
             sort << "\n     norme_flux    " ;
             sort << setw (16)   << norme_flux;
            }
            break;
   case 10 :{ sort << "\n Temperature ";
             sort << "\n       temperature     " ;
             sort << setw (16)  << temperature ;
            }
            break;               
   case 11 :{ if (saveDon != NULL)
              { sort << "\ngrandeurs attachees a la loi et au point ";
                loiTP->AfficheDataSpecif(sort,saveDon);
               } 
            }
   default :
         {cout << "\nerreur seules les cas de 1 a 11 sont pris en consideration  et non " << indic;
          cout << "\nElemThermi::AffDefCont2D( etc ..." << endl;
         }    
 
   }
};
    
        
// récupération des  valeurs au numéro d'ordre  = iteg pour
// les grandeur enu
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
Tableau <double> ElemThermi::Valeur_multi
                  (bool absolue,Enum_dure temps,const List_io<Ddl_enum_etendu>& enu,int iteg,int cas )
                  
   { // ----- def de grandeurs de travail 
     // def de la dimension des tenseurs  
     int dim = ParaGlob::Dimension();
     PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(iteg);
     // recup de l'incrément de temps
     double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
     double unSurDeltat=0;    
     if (Abs(deltat) >= ConstMath::trespetit)
       {unSurDeltat = 1./deltat;}
     else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
       { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
     if (unSurDeltat < 0)
       { cout << "\n le pas de temps est négatif !! "; };
         unSurDeltat = ConstMath::tresgrand;
       };

     // def de grandeurs pour la sortie
     Coordonnee  fluxD(dim);
     CoordonneeH  fluxDH(dim) ;
     Coordonnee  gradT(dim);
     CoordonneeB gradTB(dim);    
     CoordonneeB DgradTB(dim);
     Coordonnee  DgradT(dim);
     CoordonneeB DeltagradTB(dim) ;
     Coordonnee  DeltagradT(dim) ;
    
     Coordonnee Mtdt(ParaGlob::Dimension()); // coordonnées éventuelles du point d'intégration considéré
        
     Tableau <double> tab_ret (enu.size()); 
     // définition des grandeurs qui sont indépendante de la boucle sur les ddl_enum_etendue
           
     def->ChangeNumInteg(iteg);  // on change le numéro de point d'intégration courant
     if (((cas == 1) || (cas == 2)))
       { // cas d'une premiere initialisation
         Tableau<Enum_variable_metrique> tab(5);
         tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt;
         tab(4) = igiH_0; tab(5) = igijHH_0;
         met->PlusInitVariables(tab) ;
        }
     // éléments de métrique et matrices de passage   
     TenseurHH* gijHH;TenseurBB* gijBB;
     Coordonnee* Mpt0;Coordonnee* Mptfin;
		   BaseB * giB_0; BaseB * giB_tdt;
		   BaseH * giH_0; BaseH * giH_tdt;
     Mat_pleine jB0(dim,dim),jBfin(dim,dim);
     if ((cas==1) || (cas==11))
              // calcul d'une  ortho interessance de visualisation des tenseurs
              // cas de tenseur 3D -> Ia, cas 1D on prend un vecteur norme collineaire
              // avec g1, dans le cas 2D
              // la nouvelle base jB est calculee dans def par projection de "Ia" sur Galpha
              // le resultat est une matrice de passage utilisable pour le changement de base
              // jB0 a t=0, B pour les tenseurs BB, jH0 idem pour les tenseurs HH
              // resultat a t+dt
          {const Met_abstraite::InfoImp& ex = def->RemontImp(absolue,jB0,jBfin);
           Mpt0 = ex.M0; Mptfin = ex.Mtdt;
           gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
           giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
           giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
           }
     else if ((cas==2) || (cas==12)) 
              // resultat a t
          {const Met_abstraite::InfoExp_tdt& ex= def->RemontExp_tdt(absolue,jB0,jBfin);
           Mpt0 = ex.M0; Mptfin = ex.Mtdt;
           giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
           giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
           gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
           };
      
     // on définie des indicateurs pour ne pas faire plusieurs fois le même calcul
     List_io<Ddl_enum_etendu>::const_iterator ie,iefin=enu.end();
     bool besoin_coordonnees = false;
     for (ie=enu.begin(); ie!=iefin;ie++)
       { if (Meme_famille((*ie).Enum(),X1)) besoin_coordonnees=true;
       };
          
     // ----- maintenant on calcule les grandeurs nécessaires -----
        
     fluxDH = (ptIntegThermi.FluxH());
     CoordonneeB interB(dim); // variable inter
     for (int i=1;i<= dim; i++)
       interB += (*giB_tdt)(i) * fluxDH(i);
     fluxD = interB.Coor();
     
     gradTB = (ptIntegThermi.GradTB());
     CoordonneeH interH(dim); // variable inter
     for (int i=1;i<= dim; i++)
       interH += gradTB(i) * (*giH_tdt)(i);
     gradT = interH.Coor();
     
     DgradTB = (ptIntegThermi.DgradTB());
     interH.Zero(); // variable inter
     for (int i=1;i<= dim; i++)
       interH += DgradTB(i) * (*giH_tdt)(i);
     DgradT = interH.Coor();
     
     DeltagradTB = (ptIntegThermi.DeltaGradTB());
     interH.Zero(); // variable inter
     for (int i=1;i<= dim; i++)
       interH += DeltagradTB(i) * (*giH_tdt)(i);
     DeltagradT = interH.Coor();
 
     if (besoin_coordonnees)
       Mtdt = def->Position_tdt();               

     // donnees propre a la loi thermique au pt d'integ
     CompThermoPhysiqueAbstraite::SaveResul* sTP = tabSaveTP(iteg);
     // donnees propre a la loi mécanique au pt d'integ
     Loi_comp_abstraite::SaveResul* sDon=NULL;  // les données spécifique mécanique
     if (sDon != NULL) {sDon = tabSaveDon(iteg);};         // au pt d'integ si elles existes
     // données propre à la déformation au pt d'integ
     Deformation::SaveDefResul * sDefDon = tabSaveDefDon(iteg);

     //----- fin du calcul des grandeurs nécessaires  -----        
           
     // on balaie maintenant la liste des grandeurs à sortir
     int it; // it est l'indice dans le tableau de retour
     for (it=1,ie=enu.begin(); ie!=iefin;ie++,it++)
      {
        switch ((*ie).Enum())
          { case FLUXD1 : tab_ret(it)= fluxD(1); break;
            case FLUXD2 : tab_ret(it)= fluxD(2); break;
            case FLUXD3 : tab_ret(it)= fluxD(3); break;
            case GRADT1  : tab_ret(it)= gradT(1); break;
            case GRADT2  : tab_ret(it)= gradT(2); break;
            case GRADT3  : tab_ret(it)= gradT(3); break;
            case DGRADT1  : tab_ret(it)= DgradT(1); break;
            case DGRADT2  : tab_ret(it)= DgradT(2); break;
            case DGRADT3  : tab_ret(it)= DgradT(3); break;
            case TEMP  : tab_ret(it)= ptIntegThermi.Temperature(); break;
            case X1  : tab_ret(it)= Mtdt(1); break;
            case X2  : tab_ret(it)= Mtdt(2); break;
            case X3  : tab_ret(it)= Mtdt(3); break;
            default :
             {int posi = (*ie).Position()-NbEnum_ddl();
              switch (posi)
              { case 107: /*norme_gradT*/ tab_ret(it)=ptIntegThermi.Norme_gradT()  ;break;
                case 108: /*norme_DgradT*/ tab_ret(it)=ptIntegThermi.Norme_DGradT_const() ;break;
                case 109: /*norme_dens_flux*/ tab_ret(it)=ptIntegThermi.Norme_flux_const() ;break;
                case 111: /*DeltagradT1*/ tab_ret(it)=DeltagradT(1) ;break;
                case 112: /*DeltagradT2*/ tab_ret(it)=DeltagradT(2) ;break;
                case 113: /*DeltagradT3*/ tab_ret(it)=DeltagradT(3) ;break;
                default :
                  {cout << "\n cas de ddl actuellement non traite "
                        << "\n pas de ddl " << (*ie).Nom() << "  dans l'element "
                        << "\n ou cas non implante pour l'instant"
                        << "\n ElemThermi::Valeur_multi(....";
                   };
              };  // fin cas **** 2 >>>>>
             };
          };

      };// -- fin de la boucle sur la liste de Ddl_enum_etendu
                                 
      // liberation des tenseurs intermediaires
      LibereTenseur();   
     return tab_ret;
    };                             	
	 
        
// récupération des  valeurs Tensorielles (et non scalaire comme avec Valeur_multi)
// au numéro d'ordre  = iteg pour les grandeur enu
// enu contiend les grandeurs de retour
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void ElemThermi::Valeurs_Tensorielles(bool absolue,Enum_dure temps,List_io<TypeQuelconque>& enu
                                    ,int iteg,int cas )
                  
   { // ----- def de grandeurs de travail 
     // def de la dimension des tenseurs  
     int dim = ParaGlob::Dimension();
     PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(iteg);
    
    
     // def de conteneur pour la sortie
     Coordonnee*  fluxD=NULL; bool besoin_fluxD = false;
     Coordonnee*  gradT=NULL; bool besoin_gradT = false;
     Coordonnee*  DgradT=NULL; bool besoin_DgradT = false;
     Coordonnee*  DeltagradT=NULL; bool besoin_deltagradT = false;

     Coordonnee* Mtdt=NULL; // coordonnées éventuelles du point d'intégration considéré
     bool besoin_coordonnees = false;
     
     double* erreur = NULL; bool besoin_erreur = false;

     // --- dev d'un ensemble de variable booléenne pour gérer les sorties en une passe -----
     // on se réfère au informations définit dans la méthode: Les_type_evolues_internes()
    
     // on initialise ces variables booléennes
     List_io<TypeQuelconque>::iterator ipq,ipqfin=enu.end();
     for (ipq=enu.begin();ipq!=ipqfin;ipq++)
      {switch ((*ipq).EnuTypeQuelconque().EnumTQ()) //,FLUXD, GRADT, DGRADT
	      {case FLUXD : {besoin_fluxD=true;
	        Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
	        fluxD = gr.ConteneurCoordonnee();  break;}
		      case GRADT : {besoin_gradT=true;
	        Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
	        gradT = gr.ConteneurCoordonnee();  break;}

		      case DGRADT : {besoin_DgradT=true;
	        Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
	        DgradT = gr.ConteneurCoordonnee();  break;}
		      case DELTAGRADT : {besoin_deltagradT=true;
	        Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
	        DeltagradT = gr.ConteneurCoordonnee();  break;}

		      default :
         {// on initialise la grandeur pour éviter d'avoir des valeurs aléatoires
          ((*ipq).Grandeur_pointee())->InitParDefaut();
          if (ParaGlob::NiveauImpression() > 0)
           {cout << "\nWarning : attention cas non traite: "
			               <<  ((*ipq).EnuTypeQuelconque().NomPlein()) << "!\n";
            if (ParaGlob::NiveauImpression() > 5)
	             cout << "\n ElemThermi::Valeurs_Tensorielles(....";
           };
         };
	      };
      };

     // definition générale
     def->ChangeNumInteg(iteg);  // on change le numéro de point d'intégration courant
     if (((cas == 1) || (cas == 2)))
       { // cas d'une premiere initialisation
         Tableau<Enum_variable_metrique> tab(5);
         tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt;
         tab(4) = igiH_0; tab(5) = igijHH_0;
         met->PlusInitVariables(tab) ;
        }
     // éléments de métrique et matrices de passage   
     TenseurHH* gijHH;TenseurBB* gijBB;
     Coordonnee* Mpt0;Coordonnee* Mptfin;
		   BaseB * giB_0; BaseB * giB_tdt;
		   BaseH * giH_0; BaseH * giH_tdt;
     Mat_pleine jB0(dim,dim),jBfin(dim,dim);
     if ((cas==1) || (cas==11))
              // calcul d'une  ortho interessance de visualisation des tenseurs
              // cas de tenseur 3D -> Ia, cas 1D on prend un vecteur norme collineaire
              // avec g1, dans le cas 2D
              // la nouvelle base jB est calculee dans def par projection de "Ia" sur Galpha
              // le resultat est une matrice de passage utilisable pour le changement de base
              // jB0 a t=0, B pour les tenseurs BB, jH0 idem pour les tenseurs HH
              // resultat a t+dt
          {const Met_abstraite::InfoImp& ex = def->RemontImp(absolue,jB0,jBfin);
           Mpt0 = ex.M0; Mptfin = ex.Mtdt;
           gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
           giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
           giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
           }
     else if ((cas==2) || (cas==12)) 
              // resultat a t
          {const Met_abstraite::InfoExp_tdt& ex= def->RemontExp_tdt(absolue,jB0,jBfin);
           Mpt0 = ex.M0; Mptfin = ex.Mtdt;
           gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
           giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
           giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
           }
     else
      { cout << "\n erreur, cas non prevu! " << "\n ElemThermi::Valeurs_Tensorielles(..."; Sortie(1);};
     
     // ----- calcul des grandeurs à sortir
    
     // ----- maintenant on calcule les grandeurs nécessaires -----
        
     if (besoin_fluxD)
      {CoordonneeH & fluxDH = (ptIntegThermi.FluxH());
       CoordonneeB interB(dim); // variable inter
       for (int i=1;i<= dim; i++)
         interB += (*giB_tdt)(i) * fluxDH(i);
       (*fluxD) = interB.Coor();
      };
     
     if (besoin_gradT)
      {CoordonneeB & gradTB = (ptIntegThermi.GradTB());
       CoordonneeH interH(dim); // variable inter
       for (int i=1;i<= dim; i++)
         interH += gradTB(i) * (*giH_tdt)(i);
       (*gradT) = interH.Coor();
      };
     
     if (besoin_DgradT)
      {CoordonneeB & DgradTB = (ptIntegThermi.DgradTB());
       CoordonneeH interH(dim); // variable inter
       for (int i=1;i<= dim; i++)
         interH += DgradTB(i) * (*giH_tdt)(i);
       (*DgradT) = interH.Coor();
      };
     
     if (besoin_deltagradT)
      {CoordonneeB & DeltagradTB = (ptIntegThermi.DeltaGradTB());
       CoordonneeH interH(dim); // variable inter
       for (int i=1;i<= dim; i++)
         interH += DeltagradTB(i) * (*giH_tdt)(i);
       (*DeltagradT) = interH.Coor();
      };
 
     if (besoin_coordonnees)
       (*Mtdt) = def->Position_tdt();
    

     // donnees propre a la loi thermique au pt d'integ
     CompThermoPhysiqueAbstraite::SaveResul* sTP = tabSaveTP(iteg);
     // donnees propre a la loi mécanique au pt d'integ
     Loi_comp_abstraite::SaveResul* sDon=NULL;  // les données spécifique mécanique
     if (sDon != NULL) {sDon = tabSaveDon(iteg);};         // au pt d'integ si elles existes
     // données propre à la déformation au pt d'integ
     Deformation::SaveDefResul * sDefDon = tabSaveDefDon(iteg);
    
      // liberation des tenseurs intermediaires
      LibereTenseur();   
    };