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

371 lines
17 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 "Debug.h"
#include "GeomTetraQ.h"
#include <math.h>
#include "GeomSeg.h"
#include "GeomTriangle.h"
#include "MathUtil.h"
#include "Util.h"
// constructeur
// on a nbi pts d'integration, 10 noeuds , les coordonnées des points d'intégration
// sont définit dans GeomTetraCom, de même que les poids d'intégration
GeomTetraQ::GeomTetraQ(int nbi) :
GeomTetraCom(nbi,10,QUADRACOMPL)
,phi_M(),dphi_M()
{ // coordonnees dans l'élément de référence des noeuds
ptelem(1) = Coordonnee(0.,0.,0.); ptelem(2) = Coordonnee(1.,0.,0.);
ptelem(3) = Coordonnee(0.,1.,0.); ptelem(4) = Coordonnee(0.,0.,1.);
ptelem(5) = Coordonnee(0.5,0.,0.); ptelem(6) = Coordonnee(0.5,0.5,0.);
ptelem(7) = Coordonnee(0.,0.5,0.); ptelem(8) = Coordonnee(0,0.,0.5);
ptelem(9) = Coordonnee(0.5,0.,0.5); ptelem(10) = Coordonnee(0.,0.5,0.5);
// définition de la numérotation locale de l'élément de direction inverse
INVCONNEC(1) = 1; INVCONNEC(2) = 3; INVCONNEC(3) = 2;
INVCONNEC(4) = 4;
INVCONNEC(5) = 7; INVCONNEC(6) = 6; INVCONNEC(7) = 5;
INVCONNEC(8) = 8; INVCONNEC(9) = 10; INVCONNEC(10) = 9;
// le tableau des tranches
IND.Change_taille(3);
IND(1)=4; // les sommets
IND(2)=3; // les 3 noeuds quadratiques de la face du dessous
IND(3)=3; // les 3 noeuds quadratiques verticaux
//--------------------------------
//def des arretes
//--------------------------------
const int nbil =2; // nb de pt d'integ par ligne
const int nbnel =3; // nb de noeud du segment
seg(1) = new GeomSeg(nbil,nbnel);
for (int il=2;il<= NBSE; il++) // ici NBSE = 6
seg(il) = seg(1);
// def des tableaux de connection des noeuds des aretes
for (int i =1;i<=NBSE;i++) NONS(i).Change_taille(nbnel);
// la description est fait selon le fichier EIMail
NONS(1)(1) = 1;NONS(1)(2) = 5;NONS(1)(3) = 2;
NONS(2)(1) = 2;NONS(2)(2) = 6;NONS(2)(3) = 3;
NONS(3)(1) = 3;NONS(3)(2) = 7;NONS(3)(3) = 1;
NONS(4)(1) = 1;NONS(4)(2) = 8;NONS(4)(3) = 4;
NONS(5)(1) = 2;NONS(5)(2) = 9;NONS(5)(3) = 4;
NONS(6)(1) = 3;NONS(6)(2) = 10;NONS(6)(3) = 4;
//--------------------------------
//def des faces
//--------------------------------
const int nbis =3; // nb de pt d'integ par facee
const int nbnes =6; // nb de noeud de la face
face(1) = new GeomTriangle(nbis,nbnes);
for (int is=2;is<= NBFE; is++) // ici NBFE = 4
face(is) = face(1);
// def des tableaux de connection des noeuds des faces
for (int i =1;i<=NBFE;i++) NONF(i).Change_taille(nbnes);
// connection entre les noeuds des faces et les noeuds des elements
NONF(1)(1)= 7; NONF(1)(4)= 2;
NONF(1)(2)= 3; NONF(1)(5)= 5;
NONF(1)(3)= 6; NONF(1)(6)= 1;
NONF(2)(1)= 5; NONF(2)(4)= 4;
NONF(2)(2)= 2; NONF(2)(5)= 8;
NONF(2)(3)= 9; NONF(2)(6)= 1;
NONF(3)(1)= 7; NONF(3)(4)= 4;
NONF(3)(2)= 1; NONF(3)(5)= 10;
NONF(3)(3)= 8; NONF(3)(6)= 3;
NONF(4)(1)= 6; NONF(4)(4)= 4;
NONF(4)(2)= 3; NONF(4)(5)= 9;
NONF(4)(3)= 10; NONF(4)(6)= 2;
// triangulation des différentes faces
// on se sert d'une part de l'élément de référence de chaque face
// puis de la connection les faces par rapport à celle de l'élément
// ici c'est le même élément pour toutes les faces
// 1) récup du tableau de l'élément de référence de la face
const Tableau<Tableau<Tableau<int> > > & tabi = face(1)->Trian_lin();
int nbtria = tabi(1).Taille(); // nombre de triangle par face
// on est obligé de boucler sur tous les indices et de faire
// de l'adressage indirecte
for (int isf=1;isf<= NBFE; isf++) // boucle sur les faces
{ NONFt(isf).Change_taille(nbtria);
for (int if1=1;if1<= nbtria; if1++) // boucle sur les triangles de la face
{ NONFt(isf)(if1).Change_taille(3);
for (int in1=1;in1<= 3; in1++) // boucle sur les noeuds du triangle
NONFt(isf)(if1)(in1) = NONF(isf)(tabi(1)(if1)(in1));
}
}
// calcul des fonctions d'interpolations aux points d'intégration
for (int i =1;i<=Nbi();i++)
tabPhi(i)= Phi_point(ptInteg(i));
////---debug
//// for (int i =1;i<=10;i++)
//// { Vecteur inter = Phi(ptelem(i));
//// inter.Affiche();
//// };
// for (int i =1;i<=4;i++)
// { Mat_pleine dpho = Dphi(ptInteg(i));
// Coordonnee g1(3),g2(3),g3(3);
// for (int a=1;a<=3;a++)
// for (int j=1;j<=3;j++)
// for (int r=1;r<=10;r++)
// {switch(j)
// { case 1: g1(a) += ptelem(r)(a) * dpho(j)(r);break;
// case 2: g2(a) += ptelem(r)(a) * dpho(j)(r);break;
// case 3: g3(a) += ptelem(r)(a) * dpho(j)(r);break;
// }
// };
// double jaco = Util::Determinant(g1,g2,g3);
// cout << "\n pti: "<< i << " jacobien= " << jaco << endl;
//
// };
// Sortie(1);
////--fin debug
// calcul des dérivées des fonctions d'interpolations aux points d'intégration
for (int i =1;i<=Nbi();i++)
tabDPhi(i)= Dphi_point(ptInteg(i));
// ---- constitution du tableau Extrapol -----
Calcul_extrapol(nbi);
};
// destructeur
GeomTetraQ::~GeomTetraQ()
{ delete seg(1);
delete face(1);
};
// constructeur de copie
GeomTetraQ::GeomTetraQ(const GeomTetraQ& a) :
GeomTetraCom(a),phi_M(a.phi_M),dphi_M(a.dphi_M)
{ // la copie des parties pointées est à la charge de la classe spécifique
// definition des faces
face(1) = new GeomTriangle(*((GeomTriangle*)(a.face(1))));
// def des segments
seg(1) = new GeomSeg(*((GeomSeg*)(a.seg(1)))) ;
for (int il=2;il<= NBSE; il++)
seg(il) = seg(1);
};
// création d'élément identiques : cette fonction est analogue à la fonction new
// elle y fait d'ailleurs appel. l'implantation est spécifique dans chaque classe
// dérivée
// pt est le pointeur qui est affecté par la fonction
ElemGeomC0 * GeomTetraQ::newElemGeomC0(ElemGeomC0 * pt)
{ pt = new GeomTetraQ(*this);
return pt;
};
//--------- cas de coordonnees locales quelconques ----------------
// retourne les fonctions d'interpolation au point M (en coordonnees locales)
const Vecteur& GeomTetraQ::Phi_point(const Coordonnee& M)
{
#ifdef MISE_AU_POINT
// verification de la dimension des coordonnees locales
if (M.Dimension() != 3)
{ cout << "\n erreur la dimension des coordonnees locales :" << M.Dimension()
<<"n\'est pas egale a 3 "
<< "\nGeomTetraQ::Phi(Coordonnee& M)";
Sortie(1);
}
#endif
// Vecteur phi(NBNE); // tableau des fonctions d'interpolation
// dimentionnement éventuelle du tableau des fonctions d'interpolation
phi_M.Change_taille(NBNE); // si la taille est identique -> aucune action
//------------------------------------------------------
// cas d'un tétrahèdre trilquadratique
// page 140, Dhatt et Touzot et Lefrançois hermés ed 2005, ISBN 2-7462-0979-9
//------------------------------------------------------
// les chiffre bi correspondent au i ième numéro du bouquin
int b1=1; int b2=5; int b3=2; int b4=6; int b5=3;
int b6=7; int b7=8; int b8=9; int b9=10; int b10=4;
// interpolation
const double lambda = 1. - M(1) - M(2) - M(3);
phi_M(b1) = - lambda * (1.-2.*lambda);
phi_M(b2) = 4.* M(1) * lambda ;
phi_M(b3) = - M(1) * (1.-2.*M(1));
phi_M(b4) = 4.* M(1) * M(2) ;
phi_M(b5) = - M(2) * (1.-2.*M(2));
phi_M(b6) = 4.* M(2) * lambda ;
phi_M(b7) = 4.* M(3) * lambda ;
phi_M(b8) = 4.* M(1) * M(3) ;
phi_M(b9) = 4.* M(2) * M(3) ;
phi_M(b10) = - M(3) * (1.-2.*M(3));
// retour de phi_M
return phi_M;
};
// retourne les derivees des fonctions d'interpolation au point M (en coordonnees locales)
const Mat_pleine& GeomTetraQ::Dphi_point(const Coordonnee& M)
{
#ifdef MISE_AU_POINT
// verification de la dimension des coordonnees locales
if (M.Dimension() != 3)
{ cout << "\n erreur la dimension des coordonnees locales :" << M.Dimension()
<<"n\'est pas egale a 3 "
<< "\nGeomTetraQ::Dphi(Coordonnee& M)";
Sortie(1);
}
#endif
// Mat_pleine dphi(3,NBNE); // le tableau des derivees
// le tableau des derivees: redimentionnement si nécessaire
if ((dphi_M.Nb_ligne() != 3)&&(dphi_M.Nb_colonne() != NBNE))
dphi_M.Initialise (3,NBNE,0.);
//------------------------------------------------------
// cas d'un tétrahèdre trilquadratique
// page 140, Dhatt et Touzot et Lefrançois hermés ed 2005, ISBN 2-7462-0979-9
//------------------------------------------------------
// les chiffre bi correspondent au i ième numéro du bouquin
int b1=1; int b2=5; int b3=2; int b4=6; int b5=3;
int b6=7; int b7=8; int b8=9; int b9=10; int b10=4;
// dérivées
const double lambda = 1. - M(1) - M(2) - M(3);
dphi_M(1,b1) = 1.- 4*lambda; dphi_M(2,b1) = 1.- 4*lambda; dphi_M(3,b1) =1.- 4*lambda;
dphi_M(1,b2) = 4.*(lambda-M(1)) ; dphi_M(2,b2) = -4.*M(1); dphi_M(3,b2) = -4.*M(1);
dphi_M(1,b3) = -1.+4.*M(1); dphi_M(2,b3) = 0; dphi_M(3,b3) = 0.;
dphi_M(1,b4) = 4.*M(2) ; dphi_M(2,b4) = 4.*M(1); dphi_M(3,b4) = 0;
dphi_M(1,b5) = 0.; dphi_M(2,b5) = -1.+ 4.* M(2); dphi_M(3,b5) = 0;
dphi_M(1,b6) = -4.* M(2) ; dphi_M(2,b6) = 4.* (lambda - M(2)); dphi_M(3,b6) = -4.* M(2);
dphi_M(1,b7) = -4.* M(3) ; dphi_M(2,b7) = -4.* M(3); dphi_M(3,b7) = 4.* (lambda - M(3));
dphi_M(1,b8) = 4. * M(3) ; dphi_M(2,b8) = 0.; dphi_M(3,b8) = 4. * M(1);
dphi_M(1,b9) = 0 ; dphi_M(2,b9) = 4. * M(3) ; dphi_M(3,b9) = 4. * M(2);
dphi_M(1,b10) = 0 ; dphi_M(2,b10) = 0; dphi_M(3,b10) = -1. + 4. * M(3);
// retour des derivees
return dphi_M;
};
// en fonction de coordonnees locales, retourne true si le point est a l'interieur
// de l'element, false sinon
bool GeomTetraQ::Interieur(const Coordonnee& M)
{ if ((M(1) >= 0.) && (M(1) <= 1.) )
if ((M(2) >= 0.) && (M(2) <= 1.-M(1)) )
if ((M(3) >= 0.) && (M(3) <= 1.-M(1) - M(2)) )
return true;
return false;
};
// constitution du tableau Extrapol
void GeomTetraQ::Calcul_extrapol(int nbi)
{ // cas de l'extrapolation de grandeur des points d'intégrations aux noeuds
// def du tableau de pondération tab(i)(j) qu'il faut appliquer
// aux noeuds pour avoir la valeur aux noeuds
// val_au_noeud(i) = somme_(de j=indir(i)(1) à indir(i)(taille(indir(i)) )) {tab(i)(j) * val_pt_integ(j) }
// cas = 1: la valeur au noeud = la valeur au pt d'integ le plus près ou une moyenne des
// pt les plus près (si le nb de pt d'integ < nb noeud)
// --- pour l'instant seul le cas 1 est implanté ---
Tableau<Tableau<int> > & indir = extrapol(1).indir; // pour simplifier
Tableau<Tableau<double > > & tab = extrapol(1).tab; // pour simplifier
switch (nbi)
{ case 1:
{ // cas avec un point d'intégration, on reporte la valeur au pt d'integ, telle quelle au noeud
for (int ne=1;ne<=NBNE;ne++)
{tab(ne)(1)=1.;
indir(ne).Change_taille(1); indir(ne)(1)=1;
};
break;
}
case 4:
{ // cas avec 4 points d'intégration , on exporte directement la valeur du
// pt d'integ le plus proche ou d'une moyenne
int ne = 1; tab(ne)(1) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=1;
ne = 2; tab(ne)(4) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=4;
ne = 3; tab(ne)(3) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=3;
ne = 4; tab(ne)(2) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=2;
// pour les noeuds intermédiaires on moyenne les pt d'integ de part et autre
ne = 5; tab(ne)(1) = 0.5;tab(ne)(4) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=1;indir(ne)(2)=4;
ne = 6; tab(ne)(3) = 0.5;tab(ne)(4) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=3;indir(ne)(2)=4;
ne = 7; tab(ne)(1) = 0.5;tab(ne)(3) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=1;indir(ne)(2)=3;
ne = 8; tab(ne)(1) = 0.5;tab(ne)(2) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=1;indir(ne)(2)=2;
ne = 9; tab(ne)(2) = 0.5;tab(ne)(4) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=2;indir(ne)(2)=4;
ne = 10; tab(ne)(2) = 0.5;tab(ne)(3) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=2;indir(ne)(2)=3;
break;
} // fin du cas avec 4 pt d'intégration
case 5:
{ // cas avec 5 points d'intégration , on exporte directement la valeur du
// pt d'integ le plus proche ou d'une moyenne
int ne = 1; tab(ne)(2) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=2;
ne = 2; tab(ne)(5) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=5;
ne = 3; tab(ne)(4) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=4;
ne = 4; tab(ne)(3) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=3;
// pour les noeuds intermédiaires on moyenne les pt d'integ de part et autre
ne = 5; tab(ne)(2) = 0.5;tab(ne)(5) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=2;indir(ne)(2)=5;
ne = 6; tab(ne)(5) = 0.5;tab(ne)(4) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=5;indir(ne)(2)=4;
ne = 7; tab(ne)(2) = 0.5;tab(ne)(4) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=2;indir(ne)(2)=4;
ne = 8; tab(ne)(2) = 0.5;tab(ne)(3) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=2;indir(ne)(2)=3;
ne = 9; tab(ne)(5) = 0.5;tab(ne)(3) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=5;indir(ne)(2)=3;
ne = 10; tab(ne)(4) = 0.5;tab(ne)(3) = 0.5;
indir(ne).Change_taille(2); indir(ne)(1)=4;indir(ne)(2)=3;
break;
} // fin du cas avec 4 pt d'intégration
case 15:
{ // cas avec 15 points d'intégration , on exporte directement la valeur du
// pt d'integ le plus proche ou d'une moyenne
int ne = 1; tab(ne)(2) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=2;
ne = 2; tab(ne)(3) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=3;
ne = 3; tab(ne)(4) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=4;
ne = 4; tab(ne)(5) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=5;
ne = 5; tab(ne)(12) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=12;
ne = 6; tab(ne)(15) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=15;
ne = 7; tab(ne)(11) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=11;
ne = 8; tab(ne)(10) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=10;
ne = 9; tab(ne)(8) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=8;
ne = 10; tab(ne)(7) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=7;
break;
}
default:
{ cout << "\n erreur le nombre de point d'integration demande :" << nbi <<"n\'est pas implante "
<< "\nGeomTriangle::Calcul_extrapol(..";
Sortie(1);
};
};
};