#include "debug.h"

#include "Triangleg.h"
#include "Segment.h"
#include "MathUtil.h"

// constructeur
// dimension 2, nbi pt integ, nbne noeuds, 1 face, 3 aretes

Triangleg::Triangleg( int nbi, int nbne) :
   ElemGeom(2,nbi,nbne,1,3)
  { // definition de la face
     face(1) = this;
     NONF(1).Change_taille(NBNE);
     for (int i=1;i<=NBNE;i++)
        NONF(1)(i) = i;// def du pointeur de ligne
    double LAMBDA; // variable de calcul intermediaire

   //      ------------------------------
   //      choix des points d'integration
   //      ------------------------------
      if (Nbi()==1) 
       {
        KSI(1)= 1./3.;
        ETA(1)= KSI(1);
        WI(1)= 0.5 ;
        }
      else  if (Nbi() == 3)
       {
        KSI(1)= 0.5; 
        ETA(1)= 0.5; 
        WI(1)= 1. /6.; 
        KSI(2)= 0.;
        ETA(2)= 0.5 ;
        WI(2)= 1. /6.; 
        KSI(3)= 0.5 ;
        ETA(3)= 0. ;
        WI(3)= 1. /6. ;
        }
      else  if (Nbi()==4) 
       {
        KSI(1)= 1. /3.; 
        ETA(1)= 1. /3. ;
        WI(1)= -27. /96.; 
        KSI(2)= 1. /5.; 
        ETA(2)= 1. /5. ;
        WI(2)= 25. /96. ;
        KSI(3)= 3. /5.;  
        ETA(3)= 1. /5.; 
        WI(3)= 25. /96.; 
        KSI(4)= 1. /5.;  
        ETA(4)= 3. /5.; 
        WI(4)= 25. /96.;
        } 
       else 
        {
         cout << "\n erreur, le nombre de point d\'integration demande n\'est pas implante ";
         cout << " nbi = " << Nbi();
         cout << "\n Triangleg::Triangleg( int nbi, int nbne) " << endl;
         Sortie (1);
         } 
      //--------------------------------
      //def des arretes
      //--------------------------------
      //def des aretes
      int nbil;  // nb de pt d'integ par ligne
      if (Nbi() == 1) 
            nbil = 1;
      else
            nbil = 2; 
      int nbnel;   // nb de noeud du segment
      if (NBNE == 3) nbnel = 2; else nbnel = 3;        
      seg(1) = new Segment(nbil,nbnel);
      for (int il=2;il<= NBSE; il++)  // ici NBSE = 3
           seg(il) = seg(1);
      // def des tableaux de connection des noeuds  des cotes
      if (NBNE == 3)
           { for (int i =1;i<=NBSE;i++) NONS(i).Change_taille(2);
             NONS(1)(1) = 1;NONS(1)(2) = 2;NONS(2)(1) = 2;NONS(2)(2) = 3;
             NONS(3)(1) = 3;NONS(3)(2) = 1;
            }   
      else 
           { for (int i =1;i<=NBSE;i++) NONS(i).Change_taille(3);
             NONS(1)(1) = 1;NONS(1)(2) = 4;NONS(1)(3) = 2;
             NONS(2)(1) = 2;NONS(2)(2) = 5;NONS(2)(3) = 3;
             NONS(3)(1) = 3;NONS(3)(2) = 6;NONS(3)(3) = 1;
            }   
      
      //--------------------------------
      //valeurs aux points d'integration
      //--------------------------------
      //-----------------------------------------------------
      //------------------- cas lineaire --------------------
      //-----------------------------------------------------
      if (NBNE== 3) 
        for (int NI = 1; NI<= Nbi(); NI++)
         {
          //------------------------------
          //des fonctions d'interpolations
          //------------------------------
          tabPhi(NI)(1) = 1.  - KSI(NI) - ETA(NI);
          tabPhi(NI)(2) = KSI(NI);
          tabPhi(NI)(3) = ETA(NI);
          //-----------------
          //de leurs derivees
          //-----------------
          tabDPhi(NI)(1,1) = -1.; 
          tabDPhi(NI)(2,1) = -1.; 
          tabDPhi(NI)(1,2) = 1.; 
          tabDPhi(NI)(2,2) = 0.; 
          tabDPhi(NI)(1,3) = 0.; 
          tabDPhi(NI)(2,3) = 1.;
         }  

      //---------------------------------------------------------
      //--------------------- cas quadratique -------------------
      //---------------------------------------------------------
      else if (NBNE== 6)
        for (int NI = 1; NI<= Nbi(); NI++)
         {
          LAMBDA= 1.  - KSI(NI) - ETA(NI);
         //------------------------------
         //des fonctions d'interpolations
         //------------------------------
          tabPhi(NI)(1) = -LAMBDA * (1. -2. * LAMBDA);
          tabPhi(NI)(2) = -KSI(NI) * (1. -2. * KSI(NI));
          tabPhi(NI)(3) = -ETA(NI) * (1. -2. * ETA(NI));
          tabPhi(NI)(4) = 4. * KSI(NI) * LAMBDA;
          tabPhi(NI)(5) = 4. * KSI(NI) * ETA(NI);
          tabPhi(NI)(6) = 4. * ETA(NI) * LAMBDA;
         //-----------------
         //de leurs derivees
         //-----------------
          tabDPhi(NI)(1,1) = 1. -4. * LAMBDA;
          tabDPhi(NI)(2,1) = 1. -4. * LAMBDA;
          tabDPhi(NI)(1,2) = -1. +4. * KSI(NI);
          tabDPhi(NI)(2,2) = 0.; 
          tabDPhi(NI)(1,3) = 0.; 
          tabDPhi(NI)(2,3) = -1. +4. * ETA(NI);
          tabDPhi(NI)(1,4) = 4. * (LAMBDA-KSI(NI));
          tabDPhi(NI)(2,4) = -4. * KSI(NI);
          tabDPhi(NI)(1,5) = 4. * ETA(NI);
          tabDPhi(NI)(2,5) = 4. * KSI(NI);
          tabDPhi(NI)(1,6) = -4. * ETA(NI);
          tabDPhi(NI)(2,6) = 4. * (LAMBDA-ETA(NI));
         } 
    else 
        {
         cout << "\n erreur, le nombre de noeud demande n\'est pas implante ";
         cout << " nbne = " << NBNE;
         cout << "\n Triangleg::Triangleg( int nbi, int nbne) " << endl;
         Sortie (1);
         } 
  };
// destructeur
Triangleg::~Triangleg() 
  {   delete seg(1);
   };

// constructeur de copie
Triangleg::Triangleg(Triangleg& a) :
  ElemGeom(a)
   {
   };    
    
//--------- cas de coordonnees locales quelconques ---------------- 

    // retourne les fonctions d'interpolation au point M (en coordonnees locales)
Vecteur Triangleg::Phi(Coordonnee& M)
  {
    #ifdef MISE_AU_POINT	 	   
     // verification de la dimension des coordonnees locales
     if (M.Dimension() != 2)
       { cout << "\n erreur la dimension des coordonnees locales :" << M.Dimension()
              <<"n\'est pas egale a 2 "
             << "\nTriangleg::Phi(Coordonnee& M)";
        Sortie(1);
      }
    #endif
    Vecteur phi(NBNE); // tableau des fonctions d'interpolation
    // fonction  des fonctions d'interpolation
    if (NBNE== 3) 
         {
          //------------------------------
          //des fonctions d'interpolations
          //------------------------------
          phi(1) = 1.  - M(1) - M(2);
          phi(2) = M(1);
          phi(3) = M(2);
         }  
    else if (NBNE== 6)
       {
          double LAMBDA= 1.  - M(1) - M(2);
         //------------------------------
         //des fonctions d'interpolations
         //------------------------------
          phi(1) = -LAMBDA * (1. -2. * LAMBDA);
          phi(2) = -M(1) * (1. -2. * M(1));
          phi(3) = -M(2) * (1. -2. * M(2));
          phi(4) = 4. * M(1) * LAMBDA;
          phi(5) = 4. * M(1) * M(2);
          phi(6) = 4. * M(2) * LAMBDA;
         } 
    else 
       {
         cout << "\n erreur, le nombre de noeud demande :" << NBNE <<"n\'est pas implante ";
         cout << "\n Triangleg::Phi(Coordonnee& M) " << endl;
         Sortie (1);
        }
    // retour de phi    
    return phi;    
   };
    // retourne les derivees des fonctions d'interpolation au point M (en coordonnees locales)
Mat_pleine Triangleg::Dphi(Coordonnee& M)
  {  
   #ifdef MISE_AU_POINT	 	   
     // verification de la dimension des coordonnees locales
     if (M.Dimension() != 2)
       { cout << "\n erreur la dimension des coordonnees locales :" << M.Dimension()
              <<"n\'est pas egale a 2 "
             << "\nTriangleg::Dphi(Coordonnee& M)";
        Sortie(1);
      }
    #endif
   Mat_pleine dphi(2,NBNE); // le tableau des derivees 
   // fonction et derivees des fonctions d'interpolation
    if (NBNE== 3) 
         {
          //-----------------
          //de leurs derivees
          //-----------------
          dphi(1,1) = -1.; 
          dphi(2,1) = -1.; 
          dphi(1,2) = 1.; 
          dphi(2,2) = 0.; 
          dphi(1,3) = 0.; 
          dphi(2,3) = 1.;
         }  
    else if (NBNE== 6)
       {
          double LAMBDA= 1.  - M(1) - M(2);
         //-----------------
         //de leurs derivees
         //-----------------
          dphi(1,1) = 1. -4. * LAMBDA;
          dphi(2,1) = 1. -4. * LAMBDA;
          dphi(1,2) = -1. +4. * M(1);
          dphi(2,2) = 0.; 
          dphi(1,3) = 0.; 
          dphi(2,3) = -1. +4. * M(2);
          dphi(1,4) = 4. * (LAMBDA-M(1));
          dphi(2,4) = -4. * M(1);
          dphi(1,5) = 4. * M(2);
          dphi(2,5) = 4. * M(1);
          dphi(1,6) = -4. * M(2);
          dphi(2,6) = 4. * (LAMBDA-M(2));
         } 
    else 
      { cout << "\n erreur le nombre de noeud demande :" << NBNE <<"n\'est pas implante "
             << "\nTriangleg::Dphi(Coordonnee& M)";
        Sortie(1);
      }
    return dphi;
   };
       
   
// en fonction de coordonnees locales, retourne true si le point est a l'interieur
// de l'element, false sinon
bool Triangleg::Interieur(Coordonnee& M)
  { if ((M(1) >= 0.) && (M(1) <= 1.) )
      if ((M(2) >= 0.) && (M(2) <= 1.-M(1)) )                
        return true;
      else 
        return false;  
    else
        return false;    
   };
        
  
  
  
  
  