396 lines
16 KiB
C++
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;
|
|
};
|