// 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 "GeomHexaCom.h"
#include <math.h>
#include "GeomSeg.h"
#include "GeomQuadrangle.h"
#include "MathUtil.h"

// constructeur
    // le constructeur par défaut ne doit pas être utilisé
GeomHexaCom::GeomHexaCom()
  {   cout << "\n erreur le constructeur par défaut ne doit pas être utilisé " ;
        cout << "\nGeomHexaCom::GeomHexaCom()  " << endl;     
        Sortie(1);
   };
    
//  la dimension est 3, on a nbi pt d'integration et nbe noeuds 6 faces, 12 aretes
GeomHexaCom::GeomHexaCom(int nbi, int nbe, Enum_interpol interpol) :
    ElemGeomC0(3,nbi,nbe,6,12,HEXAEDRE,interpol)
   {  // coordonnees des points d'integration
      if (nbi == 8) // cas classique
        { double a = 1./sqrt(3.);
          ptInteg(1) = Coordonnee(a,a,a);
          ptInteg(2) = Coordonnee(a,a,-a);
          ptInteg(3) = Coordonnee(a,-a,a);
          ptInteg(4) = Coordonnee(a,-a,-a);
          ptInteg(5) = Coordonnee(-a,a,a);
          ptInteg(6) = Coordonnee(-a,a,-a);
          ptInteg(7) = Coordonnee(-a,-a,a);
          ptInteg(8) = Coordonnee(-a,-a,-a);
          // poids d'integration
          for (int i =1;i<=Nbi();i++)
            WI(i)= 1.;
         }
      else if ((nbi==1) || (nbi==27) || (nbi == 64))
        // on définit les points et poids d'intégration à partir 
        // d'un produit de ceux du segment      
       {  // definition des cotes
         int nbil = 0;
	        switch (nbi)
	         { case 1 :
			           nbil = 1;
              break;
            case  27 :
              nbil = 3;
              break;
            case  64 :
              nbil = 4;
              break;
	         };
         // on choisit 2 noeuds par défaut au lieu de la racine cubique de
         // nbne mais cela n'a pas d'importance pour la détermination des
         // points et poids d'intégration
         GeomSeg b(nbil,2);
         // definition des points et des poids
         int ni = 1;
         for (int niz = 1; niz<= nbil; niz++)
          for (int niy = 1; niy<= nbil; niy++)
            for (int nix = 1; nix<= nbil; nix++)
              { WI(ni) = b.Wi(nix) * b.Wi(niy) * b.Wi(niz);
                ptInteg(ni) =
                     Coordonnee(b.CoorPtInteg(nix)(1),b.CoorPtInteg(niy)(1)
                                ,b.CoorPtInteg(niz)(1));
                ni++;
               }
       }
      else
       {cout << "\n erreur l'hexaèdre de nombre de  point d\'integration " << Nbi() 
             << " n\'est pas implante !! ";
        cout << "\nGeomHexaCom::GeomHexaCom(int nbi)  " << endl;     
        Sortie(1);
        }
        
};


// destructeur
GeomHexaCom::~GeomHexaCom() 
  { 
   };
// constructeur de copie
GeomHexaCom::GeomHexaCom(const GeomHexaCom& a) :
  ElemGeomC0(a)
   {
   };    
   
// en fonction de coordonnees locales, retourne true si le point est a l'interieur
// de l'element, false sinon
bool GeomHexaCom::Interieur(const Coordonnee& M)
  { if ((Dabs(M(1)) <= 1.) &&
        (Dabs(M(2)) <= 1.) &&
        (Dabs(M(3)) <= 1.) )
        
        return true;
    else
        return false;    
   };
       
// en fonction de coordonnees locales, retourne le point local P, maximum intérieur à l'élément, donc sur la frontière
// dont les coordonnées sont sur la droite GM: c-a-d GP = alpha GM, avec apha maxi et P appartenant à la frontière
// de l'élément, G étant le centre de gravité, sauf si GM est nul, dans ce cas retour de M
Coordonnee GeomHexaCom::Maxi_Coor_dans_directionGM(const Coordonnee& M)
  { // on recherche du maxi des 3 composantes en valeur absolu
    double xmax = MaX(MaX(Dabs(M(1)),Dabs(M(2))),Dabs(M(3)));
    if (xmax <= ConstMath::petit) return M;
    // sinon on fait la règle de 3
    Coordonnee P= M/xmax;
    return P;
   };