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

/************************************************************************
 
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:   Fonctions utilitaires.                                    *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *                                                                $     *
 ************************************************************************/
#ifndef UTIL_H
#define UTIL_H

#include "Vecteur.h"
#include "Tableau_T.h"
#include "Enum_ddl.h"
#include "Ddl.h"
#include "Base.h"
#include "PtTabRel.h"


/// @addtogroup Classes_utilitaires_sur_vecteurs_et_matrices
///  @{
///

/// Util: divers utilitaires sur vecteurs, coordonnées, matrices ...
class Util

{ public :
  /// PRODUIT VECTORIEL DE DEUX VECTEURS EN COORDONNEES ASBOLUS
/// on supprime la fonction relative aux vecteurs, car elle "doit" être remplacée par celle sur les coordonnées
///  static Vecteur ProdVec( const Vecteur & v1, const Vecteur & v2);
  /// idem en coordonnées absolues avec le type Coordonnee
  static Coordonnee ProdVec_coor( const Coordonnee & v1, const Coordonnee & v2);
  /// idem en coordonnées contravariantes avec le type CoordonneeH
  static CoordonneeH ProdVec_coorH( const CoordonneeH & v1, const CoordonneeH & v2);
  /// idem en coordonnées covariantes avec le type CoordonneeB
  static CoordonneeB ProdVec_coorB( const CoordonneeB & v1, const CoordonneeB & v2);
  /// idem en coordonnées covariantes avec le type CoordonneeB, et en retour un coordonnee normal
  static Coordonnee ProdVec_coorBN( const CoordonneeB & v1, const CoordonneeB & v2);
  /// CALCUL DU DETERMINANT DE TROIS VECTEURS
/// on supprime la fonction relative aux vecteurs, car elle "doit" être remplacée par celle sur les coordonnées
///  static double Determinant( const Vecteur & v1, const Vecteur & v2, const Vecteur & v3);
  /// idem en coordonnées covariantes
  static double DeterminantB( const CoordonneeB & v1, const CoordonneeB & v2, const CoordonneeB & v3);
  /// idem en coordonnées absolues avec le type Coordonnee
  static double Determinant( const Coordonnee & v1, const Coordonnee & v2, const Coordonnee & v3);
  /// CALCUL DU DETERMINANT DE DEUX VECTEURS
/// on supprime la fonction relative aux vecteurs, car elle "doit" être remplacée par celle sur les coordonnées
///  static double Determinant( const Vecteur & v1, const Vecteur & v2);
  /// idem en coordonnées covariantes
  static double DeterminantB( const CoordonneeB & v1, const CoordonneeB & v2);
  /// idem en coordonnées absolues avec le type Coordonnee
  static double Determinant( const Coordonnee & v1, const Coordonnee & v2);
  /// CALCUL DU DETERMINANT DE UN VECTEUR
/// on supprime la fonction relative aux vecteurs, car elle "doit" être remplacée par celle sur les coordonnées
///  static double Determinant( const Vecteur & v1);
  /// idem en coordonnées covariantes
  static double DeterminantB( const CoordonneeB & v1);
  /// idem en coordonnées absolues avec le type Coordonnee
  static double Determinant( const Coordonnee & v1);
  /// calcul de la variation d'un vecteur unitaire connaissant la variation du
  /// vecteur non norme
  /// v : le vecteur non norme, Dv : la variation de v, nor : la norme de v
  /// en retour : la variation de vecteur : le vecteur peut-être de dimension > 3
  ///!!!!!!!!!!!!! très important: il doit s'agir de vecteur exprimé dans un repère orthonormé
  /// ceci est vrai quelque soit la variance affichée: car ici on ne prend pas en compte la variation
  ///  d'une métrique associée à un repère non orthonormé
  /// ex: les variations des gi sont ok car en fait les gi représentent les coorddonées dans un repère absolu
  static Vecteur VarUnVect( const Vecteur & v,  const Vecteur & Dv, double  nor);
  /// idem avec des coordonnées, donc dim <= 3
  static Coordonnee VarUnVect_coor( const Coordonnee & v,  const Coordonnee & Dv, double  nor);  
  /// idem avec des coordonnéesB, donc dim <= 3
  static CoordonneeB VarUnVect_coorB( const CoordonneeB & v,  const CoordonneeB & Dv, double  nor);
  /// idem avec des coordonnéesH, donc dim <= 3
  static CoordonneeH VarUnVect_coorH( const CoordonneeH & v,  const CoordonneeH & Dv, double  nor);
  /// calcul du tableau de variation d'un vecteur unitaire connaissant le tableau de variation du
  /// vecteur non norme
  /// v : le vecteur non norme, Dv : la variation de v, nor : la norme de v
  /// en retour : le tableau de variation
  static Tableau <Vecteur> VarUnVect( const Vecteur & v,  const Tableau <Vecteur >& Dv, double  nor);
  static Tableau <Coordonnee> VarUnVect_coor( const Coordonnee & v,  const Tableau <Coordonnee >& Dv, double  nor);
  static Tableau <CoordonneeB> VarUnVect_coorB( const CoordonneeB & v,  const Tableau <CoordonneeB >& Dv, double  nor);
  /// idem  et le tableau de retour passé en paramètre
  static Tableau <Vecteur>& VarUnVect( const Vecteur & v,  const Tableau <Vecteur >& Dv, double  nor, Tableau <Vecteur>& retour);
  static Tableau <Coordonnee>& VarUnVect_coor( const Coordonnee & v,  const Tableau <Coordonnee >& Dv, double  nor, Tableau <Coordonnee>& retour );
  static Tableau <CoordonneeB>& VarUnVect_coorB( const CoordonneeB & v,  const Tableau <CoordonneeB >& Dv, double  nor,Tableau <CoordonneeB>& retour);
  /// la variation du vecteur est supposé se trouver dans le premier vecteur de la base
  static Tableau <Coordonnee>& VarUnVect_coorBN( const CoordonneeB & v,  const Tableau <BaseB>& Dv, double  nor,Tableau <Coordonnee>& retour);

  /// calcul de la variation d'un produit vectoriel
  /// vi et Dvi les vecteurs du produit vectoriel et leurs variations
/// on supprime la fonction relative aux vecteurs, car elle "doit" être remplacée par celle sur les coordonnées
///  static Tableau <Vecteur> VarProdVect( const Vecteur & v1, const Vecteur & v2,
///                  const Tableau <Vecteur >& Dv1, const Tableau <Vecteur >& Dv2);
  static Tableau <Coordonnee> VarProdVect_coor( const Coordonnee & v1, const Coordonnee & v2,
                  const Tableau <Coordonnee >& Dv1, const Tableau <Coordonnee >& Dv2);
/// on supprime la fonction relative aux vecteurs, car elle "doit" être remplacée par celle sur les coordonnées
///  // idem que le précédent module mais avec Dv qui est la référence des vecteurs Dv1 et Dv2
///  static Tableau <Vecteur> VarProdVect( const Vecteur & v1, const Vecteur & v2,
///                  const Tableau <BaseB >& Dv);
  /// idem que le précédent module mais avec un retour en coordonnée, et un tableau de BaseB
  static Tableau <Coordonnee> VarProdVect_coor(const Coordonnee & v1, const Coordonnee & v2,
                  const Tableau <BaseB >& Dv);
  /// idem que le précédent module mais avec in-out en coordonnéeB, et un tableau de BaseB
  static Tableau <CoordonneeB> VarProdVect_coorB(const CoordonneeB & v1, const CoordonneeB & v2,
                  const Tableau <BaseB >& Dv);

  /// idem  avec le tableau de retour passé en paramètre
  static  Tableau <Coordonnee>& VarProdVect_coor( const Coordonnee & v1, const Coordonnee & v2,
                  const Tableau <Coordonnee >& Dv1, const Tableau <Coordonnee >& Dv2
						,Tableau <Coordonnee>& retour);
  static Tableau <Coordonnee>& VarProdVect_coor(const Coordonnee & v1, const Coordonnee & v2,
                  const Tableau <BaseB >& Dv,Tableau <Coordonnee>& retour);
  static Tableau <CoordonneeB>&  VarProdVect_coorB(const CoordonneeB & v1, const CoordonneeB & v2,
                  const Tableau <BaseB >& Dv,Tableau <CoordonneeB>& retour);
  static Tableau <Coordonnee>& VarProdVect_coorBN(const CoordonneeB & v1, const CoordonneeB & v2,
                  const Tableau <BaseB >& Dv,Tableau <Coordonnee>& retour);
						
  /// calcul de la variation de la norme d'un vecteur, connaissant la variation du vecteur,
  /// le vecteur, et sa norme, si la norme est trop petite on met à 0 la variation
  static Tableau <double> VarNorme( const Tableau <Coordonnee >& Dv,const Coordonnee& V,const double& norme);
  /// ici le vecteur peut-être de dimension quelconque > 3 par exemple
  static Tableau <double> VarNorme( const Tableau <Vecteur >& Dv,const Vecteur& V,const double& norme);               
  /// retourne le numero du ddl recherche identifie par en, dans le tableau passé en paramètre
  /// s'il existe sinon 0
  static int Existe(const Tableau<Ddl >& tab_ddl,Enum_ddl en);
  /// calcul du produit mixte des  vecteurs d'une base  en coordonnées covariantes
  static double ProduitMixte(const BaseB & tab_v );
  /// calcul de l'inverse d'une matrice 3x3 donnée par ces coordonnées, en retour la matrice
  /// d'entrée est remplacée par la matrice inverse
  ///  1) cas d'une matrice non symétrique (quelconque), rangement des valeurs:
  /// (1,1) ; (1,2) ; (1,3) ; (2,1) ; (2,2) ; (2,3) ; (3,1) ; (3,2) ; (3,3)
  static void Inverse_mat3x3(listdouble9Iter & i9Iter); 
  ///  2) cas d'une matrice symétrique , rangement des valeurs:
  /// (1,1) ; (2,2) ; (3,3) ; (2,1) = (1,2) ; (3,2) = (2,3) ; (3,1) = (1,3) ;
  static void Inverse_mat3x3(listdouble6Iter & i6Iter); 
  /// calcul de l'inverse d'une matrice 2x2 donnée par ces coordonnées, en retour la matrice
  /// d'entrée est remplacée par la matrice inverse
  ///  1) cas d'une matrice non symétrique (quelconque), rangement des valeurs:
  /// (1,1) ; (2,2) ; (2,1) ; (1,2) ;
  static void Inverse_mat2x2(listdouble4Iter & i4Iter); 
  ///  2) cas d'une matrice symétrique , rangement des valeurs:
  /// (1,1) ; (2,2) ; (2,1) = (1,2) ;  
  static void Inverse_mat2x2(listdouble3Iter & i3Iter); 
  
  
  };
  /// @}  // end of group

#ifndef MISE_AU_POINT
  #include "Util.cc"
  #define  Util_H_deja_inclus
#endif

#endif  
