277 lines
11 KiB
C++
277 lines
11 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 "GeomTetraL.h"
|
|
#include <math.h>
|
|
#include "GeomSeg.h"
|
|
#include "GeomTriangle.h"
|
|
#include "MathUtil.h"
|
|
|
|
// constructeur
|
|
// on a nbi pts d'integration, 4 noeuds , les coordonnées des points d'intégration
|
|
// sont définit dans GeomTetraCom, de même que les poids d'intégration
|
|
GeomTetraL::GeomTetraL(int nbi) :
|
|
GeomTetraCom(nbi,4,LINEAIRE)
|
|
,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(1.,1.,0.); ptelem(4) = Coordonnee(0.,0.,1.);
|
|
// 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;
|
|
// le tableau des tranches
|
|
IND.Change_taille(1);
|
|
IND(1)=4; // les sommets
|
|
//--------------------------------
|
|
//def des arretes
|
|
//--------------------------------
|
|
const int nbil =1; // nb de pt d'integ par ligne
|
|
const int nbnel =2; // 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(2);
|
|
// la description est fait selon le fichier EIMail
|
|
NONS(1)(1) = 1;NONS(1)(2) = 2;NONS(2)(1) = 2;NONS(2)(2) = 3;
|
|
NONS(3)(1) = 3;NONS(3)(2) = 1;NONS(4)(1) = 1;NONS(4)(2) = 4;
|
|
NONS(5)(1) = 2;NONS(5)(2) = 4;NONS(6)(1) = 3;NONS(6)(2) = 4;
|
|
//--------------------------------
|
|
//def des faces
|
|
//--------------------------------
|
|
const int nbis =1; // nb de pt d'integ par facee
|
|
const int nbnes =3; // 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)= 1;
|
|
NONF(1)(2)= 3;
|
|
NONF(1)(3)= 2;
|
|
NONF(2)(1)= 1;
|
|
NONF(2)(2)= 4;
|
|
NONF(2)(3)= 3;
|
|
NONF(3)(1)= 1;
|
|
NONF(3)(2)= 2;
|
|
NONF(3)(3)= 4;
|
|
NONF(4)(1)= 2;
|
|
NONF(4)(2)= 3;
|
|
NONF(4)(3)= 4;
|
|
// 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));
|
|
// 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
|
|
GeomTetraL::~GeomTetraL()
|
|
{ delete seg(1);
|
|
delete face(1);
|
|
};
|
|
// constructeur de copie
|
|
GeomTetraL::GeomTetraL(const GeomTetraL& 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 * GeomTetraL::newElemGeomC0(ElemGeomC0 * pt)
|
|
{ pt = new GeomTetraL(*this);
|
|
return pt;
|
|
};
|
|
|
|
//--------- cas de coordonnees locales quelconques ----------------
|
|
|
|
// retourne les fonctions d'interpolation au point M (en coordonnees locales)
|
|
const Vecteur& GeomTetraL::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 "
|
|
<< "\nGeomTetraL::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 trilineaire
|
|
//------------------------------------------------------
|
|
// interpolation
|
|
phi_M(1) = 1. - M(1) - M(2) - M(3);
|
|
phi_M(2) = M(1); phi_M(3) = M(2); phi_M(4) = 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& GeomTetraL::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 "
|
|
<< "\nGeomTetraL::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 trilineaire
|
|
//------------------------------------------------------
|
|
// dérivées
|
|
dphi_M(1,1) = -1.;dphi_M(2,1) = -1.;dphi_M(3,1) = -1.;
|
|
dphi_M(1,2) = 1. ;dphi_M(2,2) = 0; dphi_M(3,2) = 0;
|
|
dphi_M(1,3) = 0; dphi_M(2,3) = 1.; dphi_M(3,3) = 0.;
|
|
dphi_M(1,4) = 0 ;dphi_M(2,4) = 0.; dphi_M(3,4) = 1.;
|
|
// 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 GeomTetraL::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 GeomTetraL::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;
|
|
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;
|
|
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;
|
|
break;
|
|
}
|
|
default:
|
|
{ cout << "\n erreur le nombre de point d'integration demande :" << nbi <<"n\'est pas implante "
|
|
<< "\nGeomTriangle::Calcul_extrapol(..";
|
|
Sortie(1);
|
|
};
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|