// 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 "GeomHexalin.h" #include #include "GeomSeg.h" #include "GeomQuadrangle.h" #include "MathUtil.h" #include "Coordonnee1.h" // constructeur // la dimension est 3, on a 8 pt d'integration par défaut, 8 noeuds et 6 faces, 12 aretes GeomHexalin::GeomHexalin(int nbi ) : GeomHexaCom(nbi,8,LINEAIRE),phi_M(),dphi_M() { // coordonnees dans l'élément de référence des noeuds ptelem(1) = Coordonnee(-1.,-1.,-1.); ptelem(2) = Coordonnee(1.,-1.,-1.); ptelem(3) = Coordonnee(1.,1.,-1.); ptelem(4) = Coordonnee(-1.,1.,-1.); ptelem(5) = Coordonnee(-1.,-1.,1.); ptelem(6) = Coordonnee(1.,-1.,1.); ptelem(7) = Coordonnee(1.,1.,1.); ptelem(8) = Coordonnee(-1.,1.,1.); // définition de la numérotation locale de l'élément de direction inverse INVCONNEC(1) = 1;INVCONNEC(2) = 4; INVCONNEC(3) = 3;INVCONNEC(4) = 2; INVCONNEC(5) = 5;INVCONNEC(6) = 8; INVCONNEC(7) = 7;INVCONNEC(8) = 6; // le tableau des tranches IND.Change_taille(1); IND(1)=8; //-------------------------------- //def des arretes //-------------------------------- int nbil =1; // nb de pt d'integ par ligne int nbnel =2; // nb de noeud du segment seg(1) = new GeomSeg(nbil,nbnel); for (int il=2;il<= NBSE; il++) // ici NBSE = 12 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) = 4;NONS(4)(1) = 4;NONS(4)(2) = 1; NONS(5)(1) = 1;NONS(5)(2) = 5;NONS(6)(1) = 2;NONS(6)(2) = 6; NONS(7)(1) = 3;NONS(7)(2) = 7;NONS(8)(1) = 4;NONS(8)(2) = 8; NONS(9)(1) = 5;NONS(9)(2) = 6;NONS(10)(1) = 6;NONS(10)(2) = 7; NONS(11)(1) = 7;NONS(11)(2) = 8;NONS(12)(1) = 8;NONS(12)(2) = 5; //-------------------------------- //def des faces //-------------------------------- int nbis =4; // nb de pt d'integ par facee int nbnes =4; // nb de noeud de la face face(1) = new GeomQuadrangle(nbis,nbnes); for (int is=2;is<= NBFE; is++) // ici NBFE = 6 face(is) = face(1); // def des tableaux de connection des noeuds des faces for (int i =1;i<=NBFE;i++) NONF(i).Change_taille(4); // connection entre les noeuds des faces et les noeuds des elements NONF(1)(1)= 1; NONF(1)(2)= 4; NONF(1)(3)= 3; NONF(1)(4)= 2; NONF(2)(1)= 1; NONF(2)(2)= 5; NONF(2)(3)= 8; NONF(2)(4)= 4; NONF(3)(1)= 1; NONF(3)(2)= 2; NONF(3)(3)= 6; NONF(3)(4)= 5; NONF(4)(1)= 5; NONF(4)(2)= 6; NONF(4)(3)= 7; NONF(4)(4)= 8; NONF(5)(1)= 2; NONF(5)(2)= 3; NONF(5)(3)= 7; NONF(5)(4)= 6; NONF(6)(1)= 3; NONF(6)(2)= 4; NONF(6)(3)= 8; NONF(6)(4)= 7; // 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)); } } // définition des fonctions d'interpolation et de leurs dérivées if (nbi == 8) // cas classique // on utilise des valeurs prédéfinies via deux methodes internes // fonctions d'interpolation globales { Phiphi(); // derivees des fonctions d'interpolations DphiDphi(); } else if ((nbi==1) || (nbi==27) || (nbi == 64)) { // on utilise les méthodes internes pour calculer les fonctions // d'interpolation aux points d'intégrations for (int ptint=1;ptint<= Nbi(); ptint++) tabPhi(ptint) = Phi_point( ptInteg(ptint)); for (int ptint=1;ptint<= Nbi(); ptint++) tabDPhi(ptint) = Dphi_point( ptInteg(ptint)); }; // ---- constitution du tableau Extrapol ----- Calcul_extrapol(nbi); }; // destructeur GeomHexalin::~GeomHexalin() { delete seg(1); delete face(1); }; // constructeur de copie GeomHexalin::GeomHexalin(const GeomHexalin& a) : GeomHexaCom(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 GeomQuadrangle(*((GeomQuadrangle*)(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 * GeomHexalin::newElemGeomC0(ElemGeomC0 * pt) { pt = new GeomHexalin(*this); return pt; }; //--------- cas de coordonnees locales quelconques ---------------- // retourne les fonctions d'interpolation au point M (en coordonnees locales) const Vecteur& GeomHexalin::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 " << "\nGeomHexalin::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 Hexaedre trilineaire //------------------------------------------------------ if (NBNE == 8) { int nbnes = 2; // nombre de noeud par cote Coordonnee X(1),Y(1),Z(1); X(1) = M(1); Y(1) = M(2);Z(1) = M(3); // coordonnees pour le segment // fonctions d'interpolation int ne = 1; Vecteur tabPhiT(NBNE); for (int iz = 1;iz<= nbnes; iz++) for (int iy = 1;iy<= nbnes; iy++) for (int ix =1;ix<=nbnes;ix++) { tabPhiT(ne) = seg(1)->Phi_point(X)(ix) * seg(1)->Phi_point(Y)(iy) * seg(1)->Phi_point(Z)(iz); ne++; } // numerotation suivant le standard habituel Tableau ind(8); // ind(1) = 5; ind(2) = 6; ind(3) = 8; ind(4) = 7; // ind(5) = 1; ind(6) = 2; ind(7) = 4; ind(8) = 3; ind(1) = 1; ind(2) = 2; ind(3) = 4; ind(4) = 3; ind(5) = 5; ind(6) = 6; ind(7) = 8; ind(8) = 7; for (int ne = 1; ne<= 8; ne++) phi_M(ne) = tabPhiT(ind(ne)); } else {cout << "\n erreur l'hexaedre de nombre de noeud NBNE = " << NBNE << "\n n\'est pas implante !! "; cout << "\nGeomHexalin::Phi(Coordonnee& M) " << endl; Sortie(1); } // retour de phi_M return phi_M; }; // retourne les derivees des fonctions d'interpolation au point M (en coordonnees locales) const Mat_pleine& GeomHexalin::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 " << "\nGeomHexalin::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 Hexaedre trilineaire //------------------------------------------------------ if (NBNE == 8) { int nbnes = 2; // nombre de noeud par cote Coordonnee X(1),Y(1),Z(1); X(1) = M(1); Y(1) = M(2);Z(1) = M(3); // coordonnees pour le segment // derivee des fonctions d'interpolation int ne = 1; Mat_pleine tabDPhiT(3,NBNE); for (int iz = 1;iz<= nbnes; iz++) for (int iy = 1;iy<= nbnes; iy++) for (int ix = 1;ix<= nbnes; ix++) { //tabDPhiT(1,ne) = seg(1)->Dphi(X)(1,ix) * seg(1)->Phi(Y)(iy) * seg(1)->Phi(Z)(iz); //tabDPhiT(2,ne) = seg(1)->Phi(X)(ix) * seg(1)->Dphi(Y)(1,iy) * seg(1)->Phi(Z)(iz); //tabDPhiT(3,ne) = seg(1)->Phi(X)(ix) * seg(1)->Phi(Y)(iy) * seg(1)->Dphi(Z)(1,iz); double phi_X_ix = seg(1)->Phi_point(X)(ix); double phi_Y_iy = seg(1)->Phi_point(Y)(iy); double phi_Z_iz = seg(1)->Phi_point(Z)(iz); tabDPhiT(1,ne) = seg(1)->Dphi_point(X)(1,ix) * phi_Y_iy * phi_Z_iz; tabDPhiT(2,ne) = phi_X_ix * seg(1)->Dphi_point(Y)(1,iy) * phi_Z_iz; tabDPhiT(3,ne) = phi_X_ix * phi_Y_iy * seg(1)->Dphi_point(Z)(1,iz); ne++; } // numerotation suivant le standard habituel Tableau ind(8); // ind(1) = 5; ind(2) = 6; ind(3) = 8; ind(4) = 7; // ind(5) = 1; ind(6) = 2; ind(7) = 4; ind(8) = 3; ind(1) = 1; ind(2) = 2; ind(3) = 4; ind(4) = 3; ind(5) = 5; ind(6) = 6; ind(7) = 8; ind(8) = 7; for (int ne = 1; ne<= 8; ne++) { dphi_M(1,ne) = tabDPhiT(1,ind(ne)); dphi_M(2,ne) = tabDPhiT(2,ind(ne)); dphi_M(3,ne) = tabDPhiT(3,ind(ne)); } } else { cout << "\n erreur le nombre de noeud demande :" << NBNE <<"n\'est pas implante " << "\nGeomHexalin::Dphi(Coordonnee& M)"; Sortie(1); } // retour des derivees return dphi_M; }; // constitution du tableau Extrapol void GeomHexalin::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) //--- changement: 26 oct 2020: on fait une extrapolation tri-linéaire via les pti les plus proches switch (nbi) { case 1: { // cas avec un point d'intégration, quelque soit le nombre de noeuds, // on reporte la valeur au pt d'integ, telle quelle au noeud Tableau > & indir = extrapol(1).indir; // pour simplifier Tableau > & tab = extrapol(1).tab; // pour simplifier for (int ne=1;ne<=NBNE;ne++) {tab(ne).Change_taille(nbi); tab(ne)(1)=1.; indir(ne).Change_taille(1); indir(ne)(1)=1; }; break; } case 8: { // cas avec 8 points d'intégration , // on a deux méthodes extrapol.Change_taille(2); // tab est supposé être initialisé à 0. Tableau gi_B,gi_H; // bases naturelle et duale // --- méthode 1 (par défaut), on utilise une extrapolation via un hexaèdre bi-linéaire {Tableau > & indir = extrapol(1).indir; // pour simplifier Tableau > & tab = extrapol(1).tab; // pour simplifier Tableau indirect(nbi); // tableau de travail: on a 8 pondérations tab.Change_taille(NBNE);indir.Change_taille(NBNE); // on extrapole bi-linéairement vers les noeuds en considérant // les 8 pti dans l'ordre actuel: il faut utiliser une indirection // car la numérotation des pti ne correspond pas à celle des noeuds d'un hexa bi-linéaire indirect(1) = 8; indirect(2) = 4; indirect(3) = 2; indirect(4) = 6; indirect(5) = 7; indirect(6) = 3; indirect(7) = 1; indirect(8) = 5; for (int ne=1; ne <= NBNE; ne++) { // il nous faut calculer les coordonnées locales. // sachant que les pti ici considérés, sont aux sommets d'un hexa linéaire orthogonal // on peut traiter séparément chaque composante Coordonnee theta(3); // les coordonnées que l'on cherche Vecteur phi_x(2); // le conteneur pour les fonctions d'interpolation Vecteur phi_y(2); // le conteneur pour les fonctions d'interpolation Vecteur phi_z(2); // le conteneur pour les fonctions d'interpolation {Tableau indirect_local(2); // tableau de travail Coordonnee theta_loc(1); // le conteneur pour les coordonnées locales Tableau gi_loc_B,gi_loc_H; // bases naturelle et duale Vecteur phi_loc(2); // le conteneur pour les fonctions d'interpolation // suivant x {indirect_local(1) = indirect(1);indirect_local(2) = indirect(2); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // def de l'origine ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_x,theta_loc); theta(1)=theta_loc(1); // on enregistre } // suivant y {indirect_local(1) = indirect(1);indirect_local(2) = indirect(4); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_y,theta_loc); theta(2)=theta_loc(1); // on enregistre } // suivant z {indirect_local(1) = indirect(1);indirect_local(2) = indirect(8); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_z,theta_loc); theta(3)=theta_loc(1); // on enregistre } }; // maintenant on calcule les fct d'interpolation au noeud ne // via ses coordonnées locales theta const Vecteur& phiphi = this->Phi_point(theta); // et on enregistre indir(ne).Change_taille(nbi); tab(ne).Change_taille(nbi); // on boucle sur les pti de l'hexa linéaire d'interpolation for (int i=1;i<9;i++) {tab(ne)(indirect(i))=phiphi(i); indir(ne)(i)=indirect(i); }; } }; // fin méthode 1 // --- deuxième méthode en utilisant un tétraèdre linéaire // le pb est que le choix du tétraèdre est vraiment arbitraire {// on extrapole linéairement vers les noeuds en considérant à chaque fois les 4 pt d'intégration les plus près qui ne doivent pas être coplanaires Tableau > & indir = extrapol(2).indir; // pour simplifier Tableau > & tab = extrapol(2).tab; // pour simplifier tab.Change_taille(NBNE);indir.Change_taille(NBNE); // // -- le premier noeud {int ne = 1; indir(ne).Change_taille(4); indir(ne)(1)=8;indir(ne)(2)=4;indir(ne)(3)=6;indir(ne)(4)=7; } // -- le deuxième noeud { int ne = 2; indir(ne).Change_taille(4); indir(ne)(1)=4;indir(ne)(2)=2;indir(ne)(3)=6;indir(ne)(4)=3; } // -- le troisième noeud {int ne = 3; indir(ne).Change_taille(4); indir(ne)(1)=2;indir(ne)(2)=6;indir(ne)(3)=4;indir(ne)(4)=1; } // -- le quatrième noeud {int ne = 4; indir(ne).Change_taille(4); indir(ne)(1)=6;indir(ne)(2)=8;indir(ne)(3)=2;indir(ne)(4)=5; } // -- le cinquième noeud {int ne = 5; indir(ne).Change_taille(4); indir(ne)(1)=7;indir(ne)(2)=5;indir(ne)(3)=3;indir(ne)(4)=8; } // -- le sixième noeud {int ne = 6; indir(ne).Change_taille(4); indir(ne)(1)=3;indir(ne)(2)=7;indir(ne)(3)=1;indir(ne)(4)=4; } // -- le septième noeud {int ne = 7; indir(ne).Change_taille(4); indir(ne)(1)=1;indir(ne)(2)=3;indir(ne)(3)=5;indir(ne)(4)=2; } // -- le huitième noeud {int ne = 8; indir(ne).Change_taille(4); indir(ne)(1)=5;indir(ne)(2)=1;indir(ne)(3)=7;indir(ne)(4)=6; } // 2) --- on calcule l'interpolation Coordonnee theta(3); // les coordonnées que l'on cherche Tableau gi_B,gi_H; // bases naturelle et duale Vecteur phi_(4); // le conteneur pour les fonctions d'interpolation for (int ne = 1;ne<=NBNE; ne++) { tab(ne).Change_taille(nbi);// 8 pti Tableau & indirect= indir(ne) ; // tableau de travail: on a 4 pondérations Bases_naturel_duales(indirect,gi_B,gi_H); Coordonnee O(ptInteg(indirect(1))); // def de l'origine ElemGeomC0::Coor_phi(O,gi_H,ptelem(ne),phi_,theta); tab(ne)(indirect(1)) = phi_(1);tab(ne)(indirect(2)) = phi_(2); tab(ne)(indirect(3)) = phi_(3);tab(ne)(indirect(4)) = phi_(4); }; }; // fin méthode 2 // --- ancienne méthode // // cas avec 8 points d'intégration = le nombre de noeud, on exporte directement la valeur du // // pt d'integ le plus proche // int ne = 1; tab(ne)(8) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=8; // ne = 2; tab(ne)(4) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=4; // ne = 3; tab(ne)(2) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=2; // ne = 4; tab(ne)(6) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=6; // ne = 5; tab(ne)(7) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=7; // ne = 6; tab(ne)(3) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=3; // ne = 7; tab(ne)(1) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=1; // ne = 8; tab(ne)(5) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=5; break; } // fin du cas avec 8 pt d'intégration case 27: { // cas avec 27 points d'intégration // on a une seules méthode Tableau gi_B,gi_H; // bases naturelle et duale // --- méthode 1 (par défaut), on utilise une extrapolation via un hexaèdre bi-linéaire {Tableau > & indir = extrapol(1).indir; // pour simplifier Tableau > & tab = extrapol(1).tab; // pour simplifier Tableau indirect(8); // tableau de travail: on a 8 pondérations tab.Change_taille(NBNE);indir.Change_taille(NBNE); // on essaie de faire une boucle mais il y a des exceptions ... // -- le noeud 1 { int ne = 1; indir(ne).Change_taille(8); indir(ne)(1)= 1;indir(ne)(2)= 2;indir(ne)(3)= 5;indir(ne)(4)= 4; indir(ne)(5)=10;indir(ne)(6)=11;indir(ne)(7)=14;indir(ne)(8)=13; } // -- le deuxième noeud { int ne = 2; indir(ne).Change_taille(8); indir(ne)(1)= 2;indir(ne)(2)= 3;indir(ne)(3)= 6;indir(ne)(4)= 5; indir(ne)(5)=11;indir(ne)(6)=12;indir(ne)(7)=15;indir(ne)(8)=14; } // -- le troisième noeud {int ne = 3; indir(ne).Change_taille(8); indir(ne)(1)= 5;indir(ne)(2)= 6;indir(ne)(3)= 9;indir(ne)(4)= 8; indir(ne)(5)=14;indir(ne)(6)=15;indir(ne)(7)=18;indir(ne)(8)=17; } // -- le quatrième noeud {int ne = 4; indir(ne).Change_taille(8); indir(ne)(1)= 4;indir(ne)(2)= 5;indir(ne)(3)= 8;indir(ne)(4)= 7; indir(ne)(5)=13;indir(ne)(6)=14;indir(ne)(7)=17;indir(ne)(8)=16; } // -- le cinquième noeud {int ne = 5; indir(ne).Change_taille(8); indir(ne)(1)= 10;indir(ne)(2)= 11;indir(ne)(3)=14;indir(ne)(4)=13; indir(ne)(5)=19;indir(ne)(6)=20;indir(ne)(7)=23;indir(ne)(8)=22; } // -- le sixième noeud {int ne = 6; indir(ne).Change_taille(8); indir(ne)(1)= 11;indir(ne)(2)= 12;indir(ne)(3)= 15;indir(ne)(4)= 14; indir(ne)(5)=20;indir(ne)(6)=21;indir(ne)(7)=24;indir(ne)(8)=23; } // -- le septième noeud {int ne = 7; indir(ne).Change_taille(8); indir(ne)(1)=14;indir(ne)(2)=15;indir(ne)(3)=18;indir(ne)(4)=17; indir(ne)(5)=23;indir(ne)(6)=24;indir(ne)(7)=27;indir(ne)(8)=26; } // -- le huitième noeud {int ne = 8; indir(ne).Change_taille(8); indir(ne)(1)=13;indir(ne)(2)=14;indir(ne)(3)=17;indir(ne)(4)=16; indir(ne)(5)=22;indir(ne)(6)=23;indir(ne)(7)=26;indir(ne)(8)=25; } // 2) --- on calcule l'interpolation Coordonnee theta(3); // les coordonnées que l'on cherche for (int ne = 1;ne<28; ne++) { indir(ne).Change_taille(8); // il nous faut calculer les coordonnées locales. // sachant que les pti ici considérés, sont aux sommets d'un hexa linéaire orthogonal // on peut traiter séparément chaque composante Coordonnee theta(3); // les coordonnées que l'on cherche Vecteur phi_x(2); // le conteneur pour les fonctions d'interpolation Vecteur phi_y(2); // le conteneur pour les fonctions d'interpolation Vecteur phi_z(2); // le conteneur pour les fonctions d'interpolation Tableau indirect_local(2); // tableau de travail Coordonnee theta_loc(1); // le conteneur pour les coordonnées locales Tableau gi_loc_B,gi_loc_H; // bases naturelle et duale Vecteur phi_loc(2); // le conteneur pour les fonctions d'interpolation // suivant x {indirect_local(1) = indirect(1);indirect_local(2) = indirect(2); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // def de l'origine ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_x,theta_loc); theta(1)=theta_loc(1); // on enregistre } // suivant y {indirect_local(1) = indirect(1);indirect_local(2) = indirect(4); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // def de ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_y,theta_loc); theta(2)=theta_loc(1); // on enregistre } // suivant z {indirect_local(1) = indirect(1);indirect_local(2) = indirect(8); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_z,theta_loc); theta(3)=theta_loc(1); // on enregistre } // maintenant on calcule les fct d'interpolation au noeud ne // via ses coordonnées locales theta const Vecteur& phiphi = this->Phi_point(theta); // et on enregistre tab(ne).Change_taille(nbi); // on boucle sur les pti de l'hexa linéaire d'interpolation for (int i=1;i<9;i++) tab(ne)(indir(ne)(i))=phiphi(i); }; }; // fin de la méthode 1 // // --- ancienne méthode // // on exporte directement la valeur du pt d'integ le plus proche // int ne = 1; tab(ne)(1) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=1; // ne = 2; tab(ne)(3) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=3; // ne = 3; tab(ne)(9) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=9; // ne = 4; tab(ne)(7) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=7; // ne = 5; tab(ne)(19) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=19; // ne = 6; tab(ne)(21) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=21; // ne = 7; tab(ne)(27) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=27; // ne = 8; tab(ne)(25) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=25; break; } // fin du cas avec 27 pt d'intégration case 64: { // cas avec 64 points d'intégration // on considère une seule méthode Tableau gi_B,gi_H; // bases naturelle et duale // --- méthode 1 (par défaut), on utilise une extrapolation via un hexaèdre bi-linéaire { Tableau > & indir = extrapol(1).indir; // pour simplifier Tableau > & tab = extrapol(1).tab; // pour simplifier tab.Change_taille(NBNE);indir.Change_taille(NBNE); // 1) --- on commence par remplir les tableaux d'indirection // on utilise une numérotation de base issue des éléments 1D // -> c'est le numéro nee : on balaie x puis y puis z // et ne est le véritable numéro de noeud Tableau jnd; jnd.Change_taille(NBNE); jnd(1) = 1; jnd(3) = 2; jnd(9) = 3; jnd(7) = 4;jnd(19) = 5; jnd(21) = 6; jnd(27) = 7; jnd(25) = 8; jnd(2) = 9;jnd(6) = 10; jnd(8) = 11; jnd(4) = 12; jnd(10) = 13; jnd(12) = 14;jnd(18) = 15; jnd(16) = 16; jnd(20) = 17; jnd(24) = 18; jnd(26) = 19;jnd(22) = 20; jnd(5) = 21; jnd(11) = 22; jnd(15) = 23; jnd(17) = 24;jnd(13) = 25; jnd(23) = 26; jnd(14) = 27; // -- le noeud 1 { int ne = 1; indir(ne).Change_taille(8); indir(ne)(1)= 1;indir(ne)(2)= 2;indir(ne)(3)= 6;indir(ne)(4)= 5; indir(ne)(5)=17;indir(ne)(6)=18;indir(ne)(7)=22;indir(ne)(8)=21; } // -- le deuxième noeud {int ne = 2; indir(ne).Change_taille(8); indir(ne)(1)= 3;indir(ne)(2)= 4;indir(ne)(3)= 8;indir(ne)(4)= 7; indir(ne)(5)=19;indir(ne)(6)=20;indir(ne)(7)=24;indir(ne)(8)=23; } // -- le troisième noeud {int ne = 3; indir(ne).Change_taille(8); indir(ne)(1)=11;indir(ne)(2)=12;indir(ne)(3)=16;indir(ne)(4)=15; indir(ne)(5)=27;indir(ne)(6)=28;indir(ne)(7)=32;indir(ne)(8)=31; } // -- le quatrième noeud {int ne = 4; indir(ne).Change_taille(8); indir(ne)(1)= 9;indir(ne)(2)=10;indir(ne)(3)=14;indir(ne)(4)=13; indir(ne)(5)=25;indir(ne)(6)=26;indir(ne)(7)=30;indir(ne)(8)=29; } // pour les autres noeuds, on décale suivant z: de 32 // noeuds 5 à 9 for (int ne = 5; ne < 9; ne++) {int nbase= ne-4; indir(ne).Change_taille(8); for (int i=1;i<5;i++ ) {indir(ne)(i)= indir(nbase)(i) + 32; indir(ne)(i+4)= indir(nbase)(i+4) + 32; } }; // 2) --- on calcule l'interpolation Coordonnee theta(3); // les coordonnées que l'on cherche for (int ne = 1;ne<28; ne++) { // il nous faut calculer les coordonnées locales. // sachant que les pti ici considérés, sont aux sommets d'un hexa linéaire orthogonal // on peut traiter séparément chaque composante Vecteur phi_x(2); // le conteneur pour les fonctions d'interpolation Vecteur phi_y(2); // le conteneur pour les fonctions d'interpolation Vecteur phi_z(2); // le conteneur pour les fonctions d'interpolation Tableau indirect_local(2); // tableau de travail Coordonnee theta_loc(1); // le conteneur pour les coordonnées locales Tableau gi_loc_B,gi_loc_H; // bases naturelle et duale Vecteur phi_loc(2); // le conteneur pour les fonctions d'interpolation // suivant x {indirect_local(1) = indir(ne)(1);indirect_local(2) = indir(ne)(2); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // def de l'origine ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_x,theta_loc); theta(1)=theta_loc(1); // on enregistre } // suivant y {indirect_local(1) = indir(ne)(1);indirect_local(2) = indir(ne)(4); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // def de ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_y,theta_loc); theta(2)=theta_loc(1); // on enregistre } // suivant z {indirect_local(1) = indir(ne)(1);indirect_local(2) = indir(ne)(8); Bases_naturel_duales(indirect_local,gi_loc_B,gi_loc_H); Coordonnee O(0.5*(ptInteg(indirect_local(1))+ptInteg(indirect_local(2)))); // def de ElemGeomC0::Coor_phi(O,gi_loc_H,ptelem(ne),phi_z,theta_loc); theta(3)=theta_loc(1); // on enregistre } // maintenant on calcule les fct d'interpolation au noeud ne // via ses coordonnées locales theta const Vecteur& phiphi = this->Phi_point(theta); // et on enregistre tab(ne).Change_taille(nbi); // on boucle sur les pti de l'hexa linéaire d'interpolation for (int i=1;i<9;i++) tab(ne)(indir(ne)(i))=phiphi(i); }; }; // fin de la méthode 1 // // --- ancienne méthode // // on exporte directement la valeur du pt d'integ le plus proche // 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)(16) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=16; // ne = 4; tab(ne)(13) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=13; // ne = 5; tab(ne)(49) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=49; // ne = 6; tab(ne)(52) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=52; // ne = 7; tab(ne)(64) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=64; // ne = 8; tab(ne)(61) = 1.;indir(ne).Change_taille(1); indir(ne)(1)=61; break; } // fin du cas avec 64 pt d'intégration default: { cout << "\n erreur le nombre de point d'integration demande :" << nbi <<"n\'est pas implante " << "\nGeomTriangle::Calcul_extrapol(.."; Sortie(1); }; }; };