Herezh_dev/Elements/Geometrie/ElemGeom/ElemGeomC0.cc
2023-05-03 17:23:49 +02:00

396 lines
16 KiB
C++

// 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"ElemGeomC0.h"
#include "MathUtil.h"
// CONSTRUCTEURS :
// pardefaut
ElemGeomC0::ElemGeomC0() :
ptelem(),ptInteg() ,tabPhi() , tabDPhi () , WI()
,NONF(),NONS(),face(), seg(),NONFt(),NONSs(),INVCONNEC(),extrapol(1), IND(0)
,id_type_pt_integ(PTI_GAUSS)
{ NBNE = 0; // pas de noeud
dimension = 0; // pas de dimension
NBFE = 0; // pas de face
NBSE = 0; // pas de segment
id_interpol=RIEN_INTERPOL;
id_geom=RIEN_GEOM;
};
// cas ou l'on connait nbi et nbne
ElemGeomC0::ElemGeomC0(int dim,int nbi,int nbne,int nbfe,int nbse
,Enum_geom geom, Enum_interpol interpol
,Enum_type_pt_integ type_pti ) :
dimension(dim),NBNE(nbne),NBFE(nbfe), NBSE(nbse),NONFt(nbfe),NONSs(nbse)
,ptelem(nbne),ptInteg(nbi) ,tabPhi(nbi) , tabDPhi (nbi) , WI(nbi)
,NONF(nbfe),NONS(nbse),face(nbfe), seg(nbse),id_interpol(interpol),id_geom(geom)
,INVCONNEC(nbne),extrapol(1),IND(0),id_type_pt_integ(type_pti)
{ for (int i= 1; i<=nbi; i++)
{ tabPhi(i).Change_taille(NBNE);
tabDPhi(i).Initialise (dimension,NBNE,0.);
ptInteg(i).Change_dim(dimension);
};
for (int i1 =1; i1<= NBFE; i1++)
face(i1) = NULL;
for (int i2 =1; i2<= NBSE; i2++)
seg(i2) = NULL;
extrapol(1).tab.Change_taille(NBNE);
extrapol(1).indir.Change_taille(NBNE);
for (int ne=1;ne<=NBNE;ne++)
{extrapol(1).tab(ne).Change_taille(nbi);
};
};
// de copie
ElemGeomC0::ElemGeomC0(const ElemGeomC0& a) :
dimension(a.dimension),NBNE(a.NBNE),NBFE(a.NBFE),NBSE(a.NBSE)
,ptelem(a.ptelem) ,ptInteg(a.ptInteg) ,tabPhi(a.tabPhi)
, tabDPhi (a.tabDPhi) , WI(a.WI)
,NONF(a.NONF),NONS(a.NONS),face((a.face).Taille()),seg((a.seg).Taille())
,id_interpol(a.id_interpol),id_geom(a.id_geom),NONFt(a.NONFt),NONSs(a.NONSs)
,INVCONNEC(a.INVCONNEC),extrapol(a.extrapol),IND(a.IND),id_type_pt_integ(a.id_type_pt_integ)
{ // concernant les faces et les segments éventuelles il faut créer ces éléments
// int facetaille= face.Taille();
// for (int i=1;i<=facetaille;i++)
// if (a.face(i) != NULL) face(i)= (a.face(i))->newElemGeomC0(face(i));
// int segtaille= seg.Taille();
// for (int i=1;i<=segtaille;i++)
// if (a.seg(i) != NULL) seg(i)=(a.seg(i))->newElemGeomC0(seg(i));
};
// DESTRUCTEUR :
ElemGeomC0::~ElemGeomC0()
{ // il faut supprimer les faces ou segments pointés, eventuelle
// --- en fait due au type de construction des faces et segments, ---
// ceux-ci sont construit dans l'élément dérivé spécifique et donc supprimé dans
// également dans les éléments spécifiques
// int facetaille= face.Taille();
// for (int i=1;i<=facetaille;i++)
// if (face(i) != NULL) delete face(i);
// int segtaille= seg.Taille();
// for (int i=1;i<=segtaille;i++)
// if (seg(i) != NULL) delete seg(i);
};
// fonctions utilitaires spécifiques à l'interpolation linéaire:
// méthode utilisée pour extrapoler une grandeur à partir:
// soit de 2 points -> ex: pour une extrapolation linéaire (métrique en 1D)
// soit de 3 points -> ex: pour une extrapolation linéaire (métrique en 2D )
// soit de 4 points (non coplanaires) -> ex: pour une extrapolation linéaire (métrique en 3D )
// ces nipt points sont définit par le tableau tab_M,
//et en sortie on récupère les dim vecteurs de la base naturelle et les dim vecteurs de la base duale
// dans le cas où le calcul n'est pas possible (points trop près) on ramène false, sinon true
bool ElemGeomC0::Bases_naturelles_duales(const Tableau <Coordonnee >& tab_M
,Tableau <Coordonnee> & gi_B,Tableau <Coordonnee> & gi_H )
{// on récupère la dimension de la métrique
int dime = tab_M.Taille();
// traitement suivant la taille
switch (dime)
{ case 1:
{// calcul de la base naturelle
gi_B.Change_taille(1);
// gi_B(1)= tab_M(2)-tab_M(1); // modif 29 oct 2020
gi_B(1)= 0.5*(tab_M(2)-tab_M(1));
// calcul de la métrique
double g11BB=gi_B(1)*gi_B(1);
// inverse de la métrique
double det = g11BB;
if (Dabs(det) <= ConstMath::trespetit)
{ cout << "\nAttention : le determinant du systeme est nulle !"
<< " il n'est pas possible de calculer la base duale ";
cout << "\n ElemGeomC0::Bases_naturelles_duales(..";
return false;
};
double unsurdet = 1./det;
double g11HH = unsurdet * g11BB;
// base duale
gi_H(1)= g11HH * gi_B(1);
}
break;
case 2:
{// calcul de la base naturelle
gi_B.Change_taille(2);
gi_B(1)= tab_M(2)-tab_M(1);
gi_B(2)= tab_M(3)-tab_M(1);
// calcul de la métrique
double g11BB=gi_B(1)*gi_B(1);
double g12BB=gi_B(1)*gi_B(2);
double g22BB=gi_B(2)*gi_B(2);
// inverse de la métrique
double det = g11BB*g22BB - g12BB*g12BB;
if (Dabs(det) <= ConstMath::trespetit)
{ cout << "\nAttention : le determinant du systeme est nulle !"
<< " il n'est pas possible de calculer la base duale ";
cout << "\n ElemGeomC0::Bases_naturelles_duales(..";
return false;
};
double unsurdet = 1./det;
double g11HH = unsurdet * g22BB;
double g22HH = unsurdet * g11BB;
double g12HH = - unsurdet * g12BB;
// base duale
gi_H(1)= g11HH * gi_B(1) + g12HH * gi_B(2);
gi_H(2)= g12HH * gi_B(1) + g22HH * gi_B(2);
}
break;
case 3:
{// calcul de la base naturelle
gi_B.Change_taille(3);
gi_B(1)= tab_M(2)-tab_M(1);
gi_B(2)= tab_M(3)-tab_M(1);
gi_B(3)= tab_M(4)-tab_M(1);
// calcul de la métrique
Mat_pleine gijBB(3,3);
for (int i=1;i<=3;i++)
for (int j=1;j<=i;j++)
gijBB(i,j)=gijBB(j,i)=gi_B(i)*gi_B(j);
// inverse de la métrique
Mat_pleine gijHH(3,3); // def
try
{gijHH = gijBB.Inverse();}
catch (ErrResolve_system_lineaire excep)
// cas d'une erreur pendant l'inversion
{ cout << "\nAttention : l'extrapolation via un tetraedre lineaire !"
<< " n'est pas possible ";
cout << "\n ElemGeomC0::Bases_naturelles_duales(..";
return false;
};
// base duale
gi_H(1)= gijHH(1,1) * gi_B(1) + gijHH(1,2) * gi_B(2) + gijHH(1,3) * gi_B(3);
gi_H(2)= gijHH(2,1) * gi_B(1) + gijHH(2,2) * gi_B(2) + gijHH(2,3) * gi_B(3);
gi_H(3)= gijHH(3,1) * gi_B(1) + gijHH(3,2) * gi_B(2) + gijHH(3,3) * gi_B(3);
}
break;
default:
cout << "\n erreur !!! cas dime = " << dime << " non prevu "
<< "\n ElemGeomC0::Bases_naturel_duales(...";
Sortie(1);
};
// retour ok
return true;
};
// on donne les vecteurs de la base naturelle, et les vecteurs de la base duale
// l'origine de la base O,
// et un point A,
// en sortie: les coordonnées locale de A dans la base naturelle, et les fonctions d'interpolation
// linéaire (1,2 ou 3D ce qui correspond à ligne, triangle, tetraedre) au point A
void ElemGeomC0::Coor_phi(const Coordonnee& O
,const Tableau <Coordonnee> & giH_, const Coordonnee& A
,Vecteur& phi_, Coordonnee& theta)
{// on récupère la dimension de la métrique
int dime = giH_.Taille();
// vecteur local
Coordonnee OA = A - O;
// traitement suivant la taille
switch (dime)
{ case 1:
{ // calcul des coordonnées locales
theta.Change_dim(1);
theta(1) = OA * giH_(1);
// les fonctions d'interpolation
phi_.Change_taille(2);
phi_(1)=0.5*(1.-theta(1));
phi_(2)=0.5*(1.+theta(1));;
}
break;
case 2:
{ // calcul des coordonnées locales
theta.Change_dim(2);
theta(1) = OA * giH_(1); theta(2) = OA * giH_(2);
// les fonctions d'interpolation
phi_.Change_taille(3);
phi_(1)=1.-theta(1)-theta(2);
phi_(2)=theta(1);
phi_(3)=theta(2);
}
break;
case 3:
{ // calcul des coordonnées locales
theta.Change_dim(3);
theta(1) = OA * giH_(1); theta(2) = OA * giH_(2);theta(3) = OA * giH_(3);
// les fonctions d'interpolation
phi_.Change_taille(4);
phi_(1)=1.-theta(1)-theta(2)-theta(3);
phi_(2)=theta(1);
phi_(3)=theta(2);
phi_(4)=theta(3);
}
break;
default:
cout << "\n erreur !!! cas dime = " << dime << " non prevu "
<< "\n ElemGeomC0::Bases_naturel_duales(...";
Sortie(1);
};
};
// -- méthode identique à Bases_naturelles_duales sauf que l'on utilise une numérotation
// indirecte ce qui permet d'éviter de contruire le tableau de coordonnées lorsque celui-ci
// existe globalement
// ---
// méthode utilisée pour extrapoler une grandeur à partir:
// soit de 2 points -> ex: pour une extrapolation linéaire (métrique en 1D)
// soit de 3 points -> ex: pour une extrapolation linéaire (métrique en 2D )
// soit de 4 points cas = 2 : extrapolation bi-linéaire (métrique en 2D)
// soit de 4 points (non coplanaires) cas = 1 -> ex: pour une extrapolation linéaire (métrique en 3D )
// soit de 8 points cas = 1 : pour une extrapolation bi-linéaire (métrique en 3D)
// ces nipt points d'intégration, dont les numéros dans ptInteg sont défini par le tableau indirec(i),
// i=1 à nipt, avec ptInteg(indirec(i)) le point à considérer, et en sortie on récupère les dim vecteurs
// de la base naturelle et les dim vecteurs de la base duale
// dans le cas où le calcul n'est pas possible (points trop près) on ramène false, sinon true
bool ElemGeomC0::Bases_naturel_duales(const Tableau <int>& indirec
,Tableau <Coordonnee> & gi_B,Tableau <Coordonnee> & gi_H
,int cas) const
{// on récupère la dimension de la métrique
int dime = indirec.Taille();
// traitement suivant la taille
switch (dime)
{ case 2: // on interpole linéairement entre deux points définissant une droite
{// calcul de la base naturelle
gi_B.Change_taille(1);
// gi_B(1)= ptInteg(indirec(2))-ptInteg(indirec(1)); // modif 29 oct 2020
gi_B(1)= 0.5*(ptInteg(indirec(2))-ptInteg(indirec(1)));
// calcul de la métrique
double g11BB=gi_B(1)*gi_B(1);
// inverse de la métrique
double det = g11BB;
if (Dabs(det) <= ConstMath::trespetit)
{ cout << "\nAttention : le determinant du systeme est nulle !"
<< " il n'est pas possible de calculer la base duale ";
cout << "\n ElemGeomC0::Bases_naturelles_duales(..";
return false;
};
// double unsurdet = 1./det;
double g11HH = 1./ g11BB;
// base duale
gi_H.Change_taille(1);
gi_H(1)= g11HH * gi_B(1);
}
break;
case 3: // on interpole linéairement entre 3 points définissant un triangle
{// calcul de la base naturelle
gi_B.Change_taille(2);
gi_B(1)= ptInteg(indirec(2))-ptInteg(indirec(1));
gi_B(2)= ptInteg(indirec(3))-ptInteg(indirec(1));
// calcul de la métrique
double g11BB=gi_B(1)*gi_B(1);
double g12BB=gi_B(1)*gi_B(2);
double g22BB=gi_B(2)*gi_B(2);
// inverse de la métrique
double det = g11BB*g22BB - g12BB*g12BB;
if (Dabs(det) <= ConstMath::trespetit)
{ cout << "\nAttention : le determinant du systeme est nulle !"
<< " il n'est pas possible de calculer la base duale ";
cout << "\n ElemGeomC0::Bases_naturelles_duales(..";
return false;
};
double unsurdet = 1./det;
double g11HH = unsurdet * g22BB;
double g22HH = unsurdet * g11BB;
double g12HH = - unsurdet * g12BB;
// base duale
gi_H.Change_taille(2);
gi_H(1)= g11HH * gi_B(1) + g12HH * gi_B(2);
gi_H(2)= g12HH * gi_B(1) + g22HH * gi_B(2);
}
break;
case 4:
if (cas == 1 )// on interpole linéairement entre 4 points définissant un tétraèdre
{// calcul de la base naturelle
gi_B.Change_taille(3);
gi_B(1)= ptInteg(indirec(2))-ptInteg(indirec(1));
gi_B(2)= ptInteg(indirec(3))-ptInteg(indirec(1));
gi_B(3)= ptInteg(indirec(4))-ptInteg(indirec(1));
// calcul de la métrique
Mat_pleine gijBB(3,3);
for (int i=1;i<=3;i++)
for (int j=1;j<=i;j++)
gijBB(i,j)=gijBB(j,i)=gi_B(i)*gi_B(j);
// inverse de la métrique
Mat_pleine gijHH(3,3); // def
{try
{gijHH = gijBB.Inverse();
}
catch (ErrResolve_system_lineaire excep)
// cas d'une erreur pendant l'inversion
{ cout << "\nAttention : l'extrapolation via un tetraedre lineaire !"
<< " n'est pas possible ";
cout << "\n ElemGeomC0::Bases_naturelles_duales(..";
return false;
};
}
// base duale
gi_H.Change_taille(3);
gi_H(1)= gijHH(1,1) * gi_B(1) + gijHH(1,2) * gi_B(2) + gijHH(1,3) * gi_B(3);
gi_H(2)= gijHH(2,1) * gi_B(1) + gijHH(2,2) * gi_B(2) + gijHH(2,3) * gi_B(3);
gi_H(3)= gijHH(3,1) * gi_B(1) + gijHH(3,2) * gi_B(2) + gijHH(3,3) * gi_B(3);
}
else // on interpole bi-linéairement en métrique 2D
{// calcul de la base naturelle
gi_B.Change_taille(2);
gi_B(1)= ptInteg(indirec(2))-ptInteg(indirec(1));
gi_B(2)= ptInteg(indirec(3))-ptInteg(indirec(1));
// calcul de la métrique
double g11BB=gi_B(1)*gi_B(1);
double g12BB=gi_B(1)*gi_B(2);
double g22BB=gi_B(2)*gi_B(2);
// inverse de la métrique
double det = g11BB*g22BB - g12BB*g12BB;
if (Dabs(det) <= ConstMath::trespetit)
{ cout << "\nAttention : le determinant du systeme est nulle !"
<< " il n'est pas possible de calculer la base duale ";
cout << "\n ElemGeomC0::Bases_naturelles_duales(..";
return false;
};
double unsurdet = 1./det;
double g11HH = unsurdet * g22BB;
double g22HH = unsurdet * g11BB;
double g12HH = - unsurdet * g12BB;
// base duale
gi_H.Change_taille(2);
gi_H(1)= g11HH * gi_B(1) + g12HH * gi_B(2);
gi_H(2)= g12HH * gi_B(1) + g22HH * gi_B(2);
}
break;
default:
cout << "\n erreur !!! cas dime = " << dime << " non prevu "
<< "\n ElemGeomC0::Bases_naturel_duales(...";
Sortie(1);
};
// retour ok
return true;
};