

// 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 "TenseurQ.h"
#include "MathUtil.h"
#include "MathUtil2.h"

#ifndef  TenseurQ_H_deja_inclus


/*// produit contracte avec un vecteur
#ifndef MISE_AU_POINT
  inline 
#endif
 CoordonneeH operator * (const CoordonneeH & v ,const TenseurBH & t)
      { return (t.Transpose() * v) ; };*/

// ------------------tenseur HHHH ----------------------------------
//PtTenseurHHHH * LesMaillonsHHHH::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsHHHH::nbmailHHHH =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurHHHH 
   { public :
       PtTenseurHHHH * t1;     // adresse du maillon precedent
       TenseurHHHH * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurHHHH (const PtTenseurHHHH * x1,const TenseurHHHH * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurHHHH *) x1;sauvePtr = (TenseurHHHH *) x2;};
       ~PtTenseurHHHH () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHHHH::NouveauMaillon(const TenseurHHHH * ptr)
   { PtTenseurHHHH * poi = maille;
     maille = new PtTenseurHHHH ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailHHHH++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHHHH::Libere()
   { while (maille != NULL)
      { PtTenseurHHHH * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailHHHH = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurHHHH::Message(int dim, string mes) const 
  { cout << " \n erreur de calcul sur les tenseurs HHHH ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }  

     
// ------------------tenseur BBBB ----------------------------------
//PtTenseurBBBB * LesMaillonsBBBB::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsBBBB::nbmailBBBB =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurBBBB 
   { public :
       PtTenseurBBBB * t1;     // adresse du maillon precedent
       TenseurBBBB * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurBBBB (const PtTenseurBBBB * x1,const TenseurBBBB * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurBBBB *) x1;sauvePtr = (TenseurBBBB *) x2;};
       ~PtTenseurBBBB () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBBBB::NouveauMaillon(const TenseurBBBB * ptr)
   { PtTenseurBBBB * poi = maille;
     maille = new PtTenseurBBBB ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailBBBB++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBBBB::Libere()
   { while (maille != NULL)
      { PtTenseurBBBB * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailBBBB = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurBBBB::Message(int dim, string mes) const
  { cout << " \n erreur de calcul sur les tenseurs BBBB ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }  
    
    
// ------------------tenseur HHBB ----------------------------------
//PtTenseurHHBB * LesMaillonsHHBB::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsHHBB::nbmailHHBB =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurHHBB 
   { public :
       PtTenseurHHBB * t1;     // adresse du maillon precedent
       TenseurHHBB * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurHHBB (const PtTenseurHHBB * x1,const TenseurHHBB * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurHHBB *) x1;sauvePtr = (TenseurHHBB *) x2;};
       ~PtTenseurHHBB () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHHBB::NouveauMaillon(const TenseurHHBB * ptr)
   { PtTenseurHHBB * poi = maille;
     maille = new PtTenseurHHBB ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailHHBB++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHHBB::Libere()
   { while (maille != NULL)
      { PtTenseurHHBB * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailHHBB = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurHHBB::Message(int dim, string mes) const
  { cout << " \n erreur de calcul sur les tenseurs HHBB ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }  
      
// ------------------tenseur BBHH ----------------------------------
//PtTenseurBBHH * LesMaillonsBBHH::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsBBHH::nbmailBBHH =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurBBHH 
   { public :
       PtTenseurBBHH * t1;     // adresse du maillon precedent
       TenseurBBHH * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurBBHH (const PtTenseurBBHH * x1,const TenseurBBHH * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurBBHH *) x1;sauvePtr = (TenseurBBHH *) x2;};
       ~PtTenseurBBHH () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBBHH::NouveauMaillon(const TenseurBBHH * ptr)
   { PtTenseurBBHH * poi = maille;
     maille = new PtTenseurBBHH ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailBBHH++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBBHH::Libere()
   { while (maille != NULL)
      { PtTenseurBBHH * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailBBHH = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurBBHH::Message(int dim, string mes) const
  { cout << " \n erreur de calcul sur les tenseurs ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }
// ------------------tenseur HBHB ----------------------------------
//PtTenseurHBHB * LesMaillonsHBHB::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsHBHB::nbmailHBHB =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurHBHB 
   { public :
       PtTenseurHBHB * t1;     // adresse du maillon precedent
       TenseurHBHB * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurHBHB (const PtTenseurHBHB * x1,const TenseurHBHB * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurHBHB *) x1;sauvePtr = (TenseurHBHB *) x2;};
       ~PtTenseurHBHB () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHBHB::NouveauMaillon(const TenseurHBHB * ptr)
   { PtTenseurHBHB * poi = maille;
     maille = new PtTenseurHBHB ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailHBHB++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHBHB::Libere()
   { while (maille != NULL)
      { PtTenseurHBHB * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailHBHB = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurHBHB::Message(int dim, string mes) const
  { cout << " \n erreur de calcul sur les tenseurs ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }
    
// ------------------tenseur BHBH ----------------------------------
//PtTenseurBHBH * LesMaillonsBHBH::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsBHBH::nbmailBHBH =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurBHBH 
   { public :
       PtTenseurBHBH * t1;     // adresse du maillon precedent
       TenseurBHBH * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurBHBH (const PtTenseurBHBH * x1,const TenseurBHBH * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurBHBH *) x1;sauvePtr = (TenseurBHBH *) x2;};
       ~PtTenseurBHBH () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBHBH::NouveauMaillon(const TenseurBHBH * ptr)
   { PtTenseurBHBH * poi = maille;
     maille = new PtTenseurBHBH ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailBHBH++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBHBH::Libere()
   { while (maille != NULL)
      { PtTenseurBHBH * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailBHBH = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurBHBH::Message(int dim, string mes) const
  { cout << " \n erreur de calcul sur les tenseurs ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }  
    
// ------------------tenseur HBBH ----------------------------------
//PtTenseurHBBH * LesMaillonsHBBH::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsHBBH::nbmailHBBH =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurHBBH 
   { public :
       PtTenseurHBBH * t1;     // adresse du maillon precedent
       TenseurHBBH * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurHBBH (const PtTenseurHBBH * x1,const TenseurHBBH * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurHBBH *) x1;sauvePtr = (TenseurHBBH *) x2;};
       ~PtTenseurHBBH () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHBBH::NouveauMaillon(const TenseurHBBH * ptr)
   { PtTenseurHBBH * poi = maille;
     maille = new PtTenseurHBBH ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailHBBH++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsHBBH::Libere()
   { while (maille != NULL)
      { PtTenseurHBBH * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailHBBH = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurHBBH::Message(int dim, string mes) const
  { cout << " \n erreur de calcul sur les tenseurs ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }  
    
// ------------------tenseur BHHB ----------------------------------
//PtTenseurBHHB * LesMaillonsBHHB::maille = NULL; // initialisation de la première maille
 #ifdef MISE_AU_POINT
   int LesMaillonsBHHB::nbmailBHHB =0; // initialisation du nombre de tenseur intermediaire
 #endif

// def d'un maillon de liste chainee pour memoriser les differents tenseurs intermediaires
class PtTenseurBHHB 
   { public :
       PtTenseurBHHB * t1;     // adresse du maillon precedent
       TenseurBHHB * sauvePtr; // sauvegarde du pointeur de tenseur
       PtTenseurBHHB (const PtTenseurBHHB * x1,const TenseurBHHB * x2) 
               // ici on ruse pour endormir le compilateur avec un cast
               // par la suite on utilisera t1 et x2 pour effacer le tenseur !!
               // ce qui n'est pas possible avec const !! normalement
             { t1 = (PtTenseurBHHB *) x1;sauvePtr = (TenseurBHHB *) x2;};
       ~PtTenseurBHHB () 
         { delete sauvePtr;};
    }; 
// nouveau maillon
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBHHB::NouveauMaillon(const TenseurBHHB * ptr)
   { PtTenseurBHHB * poi = maille;
     maille = new PtTenseurBHHB ( poi,ptr);
     #ifdef MISE_AU_POINT
        nbmailBHHB++;
     #endif
   };
// liberation de l'espace
#ifndef MISE_AU_POINT
  inline 
#endif
void LesMaillonsBHHB::Libere()
   { while (maille != NULL)
      { PtTenseurBHHB * poi = maille->t1; // recup de l'adresse precedente
        delete maille; // liberation de l'espace de tenseur
        maille = poi;
      }; 
     #ifdef MISE_AU_POINT
           nbmailBHHB = 0;
     #endif
   };
	
// sortie d'un message standard
// dim = dimension du tenseur argument
#ifndef MISE_AU_POINT
  inline 
#endif
void TenseurBHHB::Message(int dim, string mes) const
  { cout << " \n erreur de calcul sur les tenseurs ***** ";
    cout << " dimension de l'argument = " << dim ;
    cout << '\n' << mes << endl;
    Sortie(1);
  }  
  
// ----------------- fonction externe globale -----------------------
   
// liberation des tenseurs intermediaires
#ifndef MISE_AU_POINT
  inline 
#endif
void LibereTenseurQ() 
   {  // appel du membre static  Libere des differents tenseurs
     LesMaillonsHHHH::Libere();
     LesMaillonsBBBB::Libere();
     LesMaillonsBBHH::Libere();
     LesMaillonsHHBB::Libere();
     LesMaillonsHBHB::Libere();
     LesMaillonsBHBH::Libere();
     LesMaillonsHBBH::Libere();
     LesMaillonsBHHB::Libere();
   };  
                
                
#endif  // fin pour l'insertion dans le .h
