// 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) . // // 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 . // // For more information, please consult: . //#include "Debug.h" #include "GeomTetraL.h" #include #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 > > & 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 > & indir = extrapol(1).indir; // pour simplifier Tableau > & 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); }; }; };