// FICHIER : Maillage.h // CLASSE : Maillage // 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-2021 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: . /************************************************************************ * DATE: 23/01/97 * * $ * * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * * $ * * PROJET: Herezh++ * * $ * ************************************************************************ * BUT: def de la classe Maillage, * * Une instance de la classe Maillage est identifiee a partir * * de la dimension, des tableaux des noeuds et des elements. * * $ * * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * * VERIFICATION: * * * * ! date ! auteur ! but ! * * ------------------------------------------------------------ * * ! ! ! ! * * $ * * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * MODIFICATIONS: * * ! date ! auteur ! but ! * * ------------------------------------------------------------ * * $ * ************************************************************************/ #ifndef MAILLAGE_H #define MAILLAGE_H #include #include #include "Noeud.h" #include "Element.h" #include "Tableau_T.h" #include "UtilLecture.h" #include "Enum_geom.h" #include "Enum_interpol.h" #include "LesReferences.h" #include "Front.h" #include "LaList.h" #include "Nb_assemb.h" #include "Ddl_enum_etendu.h" #include "Droite.h" #include "Plan.h" #include "Sphere.h" #include "Cylindre.h" #include "Cercle.h" #include "Condilineaire.h" #include "DiversStockage.h" /// @addtogroup Les_Maillages /// @{ /// //------------------------------------------------------------------ //! Maillage: un maillage particulier //------------------------------------------------------------------ /// \author Gérard Rio /// \version 1.0 /// \date 23/01/97 class Maillage { public : friend class LesMaillages; // CONSTRUCTEURS : // pour tous les constructeurs: map < string, int , std::less >* lisNomMail, // est un tableau associatif nom <=> numéro de maillage, qui est utilisé par // les maillages, mais mis à jour par chaque maillage. // nom_maillage : est facultatif, s'il est différent de ".", il est pris en compte // Constructeur par defaut Maillage (map < string, int , std::less > & lisNomMail,int nmail=1,int dim=3 ,const string& nom_maillage = "."); // Constructeur fonction d'une dimension, du nombre de noeuds // du nombre d'elements, et d'un numero d'identification (le nb de maillage) Maillage (map < string, int , std::less > & lisNomMail ,int dim,int n_noeud,int n_elt,int nmail ,const string& nom_maillage = "."); // Constructeur fonction de la plupart des informations (qui peuvent être vide // mais doivent être cohérentes) // *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments, // ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé Maillage (map < string, int , std::less > & lisNomMail ,int dim,list & li_noeud, list li_element ,int nmail ,const string& nom_maillage = "."); // Constructeur de copie, cependant ici il n'y a pas de création de noeud ni d'élément // c'est seulement une création de nouveaux conteneurs de pointeurs // cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut // ensuite les définir Maillage (const Maillage& mail); // Constructeur de copie, avec création de nouveaux noeuds et éléments identiques à ceux passées // en argument, nmail: donne le numéro du nouveau maillage créée, qui est donc a priori différent // de celui de mail, idem pour le nom du maillage // les frontières ne sont pas transmises ni calculées ! Maillage (map < string, int , std::less > & lisNomMail ,int nmail, const string& nomDuMaillage, const Maillage& mail); // DESTRUCTEUR : ~Maillage (); // METHODES : // lecture de maillages au travers des outils de la classe // UtilLecture et def des references s'y rapportant void LectureMaillage(UtilLecture * entreePrinc,LesReferences& lesRef); // lecture et application des opérations d'affinages sur le maillage: ex:déplacement solide void LectureEtApplicationAffinage(UtilLecture * entreePrinc,LesReferences& lesRef); // ajout d'une liste de noeud à un maillage // si le numéro de maillage associé au noeud est nul, il est remplacé par celui du maillage // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a // création d'un nouveau noeud identique, avec le numéro this // ajout éventuel d'une liste de référence de noeuds, si celle-ci est non-nulle // il y a création de nouvelles ref correspondantes au numéro de maillage de this // et ces références sont rajoutées à lesRef void Ajout_de_Noeuds(const list & taN,list * lref=NULL,LesReferences* lesRef=NULL ); // ajout d'une liste d'éléments et de noeud à un maillage // si le numéro de maillage associé à l'élément ou noeud est nul, il est remplacé par celui du maillage // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a // création d'un nouvel item identique, avec le numéro this // ajout éventuel d'une liste de références associées , si celle-ci est non-nulle // il y a création de nouvelles ref correspondantes au numéro de maillage de this // et ces références sont rajoutées à lesRef // les noeuds qui sont associés aux éléments de taE, doivent faire partie : soit de taN, soit du maillage this void Ajout_elements_et_noeuds(const list & taN, const list & taE,list * lref,LesReferences* lesRef ); // affichage et definition interactive des commandes // cas = 1: interactif complet // cas = 2: entrée uniquement de noms de fichier void Info_commande_Maillages(UtilLecture * entreePrinc,LesReferences& lesRef, int cas); // Affiche les donnees du maillage void Affiche () const ; // Affiche les donnees du maillage dans un fichier // dont le nom est construit à partir du nom du maillage // au format ".her" et ".lis" void Affiche_dans_her_lis(LesReferences &lesRef,Enum_dure temps); //modification du maillage pour le restreindre aux seuls éléments de la référence passée en paramètre // toutes les infos relatives à des éléments supprimés, sont également supprimés void Restreint_sous_maillage(LesReferences* lesRef, string nom_ref); // Surcharge de l'operateur = : realise l'egalite de deux maillages // cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut // ensuite les définir Maillage& operator= (Maillage& mail); inline int Dimension () const // Retourne la dimension { return dimension; }; // ramène la liste des problèmes physiques gérés par les éléments du maillage inline const Tableau & Ddl_representatifs_des_physiques()const {return ddl_representatifs_des_physiques;}; // ramene la liste des degrés de liberté inconnus, associés aux pb // physiques gérés par les éléments qui existent dans le maillage // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i // Si éléments thermiques -> ddl de température // Si éléments méca + éléments thermiques -> ddl Xi et température // etc. en fonction des éléments qui existent dans le maillage inline const Tableau & Types_de_problemes() const {return types_de_problemes;}; inline int Nombre_noeud_elt(int i) const // Retourne le nombre de noeuds lies au ieme element { return tab_element(i)->Nombre_noeud(); }; inline int Nombre_noeud() const // Retourne le nombre de noeuds du maillage { return tab_noeud.Taille(); }; inline int Nombre_element() const // Retourne le nombre d'elements du maillage { return tab_element.Taille(); }; inline Tableau& Tab_noeud() // Retourne le tableau des noeuds { return tab_noeud; }; inline Tableau& Tab_element() // Retourne le tableau des elements { return tab_element; }; inline Noeud& Noeud_mail(int i) // Retourne le ieme noeud Noeud du tableau tab_noeud { return *tab_noeud(i); }; inline Element& Element_mail(int i) // Retourne le ieme element Element du tableau tab_element { return *tab_element(i); }; // idem mais en version constant inline const Element& Element_mail_const(int i) { return *tab_element(i); }; // test si toutes les informations des maillages sont completes // = true -> complet // = false -> incomplet bool Complet(); // ramene la demi largeur de bande en ddl et la largeur de bande void Largeur_Bande(int& demi, int& total,const Nb_assemb& nb_casAssemb); // test pour savoir si tous les coordonnées des noeuds d'un maillage sont imposé // ramène 1 si tout est fixé, 0 sinon int Tous_Xi_fixes(const Nb_assemb& casAss) const; // calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement // a priori le calcul s'effectue par une moyenne des normales des éléments qui // entourent le noeud. // init -> calcul des normales à t=0 // et ajout conteneur aux noeuds des normales à t = 0 et t void InitNormaleAuxNoeuds(); // mise à jour -> mise à jour des normales à t void MiseAjourNormaleAuxNoeuds(); // mise à jour -> mise à jour des normales à t // mais ici, on calcule les normales à tdt, et on transfert à t // cette méthode est utile si on veut utiliser des normales à t pour une valeur // particulière (transitoire) de la géométrie à tdt // cf: l'algo non dyna par exempel void MiseAjourNormaleAuxNoeuds_de_tdt_vers_T(); // creation des elements frontiere void CreeElemFront(); // ramene un pointeur sur la liste des elements frontieres inline LaLIST * ListFront() { return &listFrontiere;}; // ramene le tableau des noeuds de la frontière Tableau& Tab_noeud_front() {return tab_noeud_front; }; // ramene le nom du maillage string NomDuMaillage() {return nomDuMaillage;}; // change le nom et le numéro du maillage void ChangeNomNumeroMaillage(const string & nom,int num); // ramène le numéro du noeud le plus proche du point donné à t=0, int Noeud_le_plus_proche_0(const Coordonnee& M); // idem à t int Noeud_le_plus_proche_t(const Coordonnee& M); // idem à tdt int Noeud_le_plus_proche_tdt(const Coordonnee& M); // ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage double Max_var_dep_t_a_tdt() const; // ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments double Min_dist2Noeud_des_elements(Enum_dure temps) const; // transfert de grandeurs des points d'intégration aux noeuds // 1- en entrée les type de ddl internes que l'on veut transférer // idem pour les type évoluées et les types particuliers // 2- en entrée: cas qui indique la méthode de transfert à utiliser // =1 : les valeurs aux noeuds sont obtenue par moyennage des valeurs des pts d'integ les plus près // des éléments qui entourent le noeud // on décompose le processus en trois étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois // le même transfert // A) première étape def des conteneurs et c'est tout, la méthode peut donc être utilisée // pour autre chose. tabQ: permet d'avoir plusieurs listes de TypeQuelconque // en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur // est nulle on n'en tient pas compte void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu ,const Tableau * >& tabQ); // B) initialisation des updates sur les noeuds void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu ,const Tableau * >& tabQ,int cas); // C) exécution du transfert // transfert incrémental (pour un élément et tous les pt d'integ): // transfert de ddl de tous les pt d'integ aux noeuds d'un éléments (on ajoute aux noeuds, on ne remplace pas) // les ddl doivent déjà exister aux noeuds sinon erreur // il doit s'agir du même type de répartition de pt d'integ pour toutes les grandeurs void TransfertPtIntegAuNoeud(Element& ele,const List_io < Ddl_enum_etendu >& lietendu ,const Tableau > & tab_val,int cas) {ele.TransfertAjoutAuNoeuds(lietendu,tab_val,cas);}; // idem pour des grandeurs quelconques, transfert de "tous" les points d'intégration en même temps // ceci pour optimiser, les informations sont ici contenues dans les types quelconques // liQ_travail: est une liste de travail qui sera utilisée dans le transfert // - transfert de type quelconque des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds, // - on ne remplace pas). Les types quelconques doivent déjà exister. // - un tableau tab_liQ correspondent aux grandeurs quelconque pour tous les pt integ. tab_liQ(i) est associé au pt d'integ i // - Toutes les listes sont identiques au niveau des descripteurs (types...) ce sont uniquement les valeurs numériques // - c-a-dire les valeurs associées à TypeQuelconque::Grandeur qui sont différentes (elles sont associées à chaque pt d'integ) // - liQ_travail: est une liste de travail qui sera utilisée dans le transfert void TransfertPtIntegAuNoeud(Element& ele,const Tableau >& tab_liQ ,List_io < TypeQuelconque > & liQ_travail,int cas) {ele.TransfertAjoutAuNoeuds(tab_liQ,liQ_travail,cas);}; // D) dernière étape: (par exemple calcul des moyennes en chaque noeuds) // les résultats sont stockés aux noeuds void FinTransfertPtIntegAuNoeud(const List_io < Ddl_enum_etendu >& lienu ,const Tableau * >& tabQ,int cas); // ..... cumul et moyenne de grandeurs venant des éléments vers les noeuds (exemple la pression appliquée) ..... // on décompose le processus en 4 étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois // la même opération (typiquement à chaque incrément) // on peut utiliser: // A) AjoutConteneurAuNoeud : pour ajouter des conteneurs ad hoc aux noeuds // B) InitUpdateAuNoeud: avant le cumul, initialise les conteneurs // C) Accumul_aux_noeuds : balaie les éléments avec cumul aux noeuds // D) MoyenneCompteurAuNoeud : effectue les moyennes aux noeuds // accumulation aux noeuds de grandeurs venant des éléments vers leurs noeuds (exemple la pression appliquée) // autres que celles aux pti classiques, mais directements disponibles // le contenu du conteneur stockées dans liQ est utilisé en variable intermédiaire void Accumul_aux_noeuds(const List_io < Ddl_enum_etendu >& lietendu ,List_io < TypeQuelconque > & liQ,int cas) {int NBE=tab_element.Taille(); for (int i=1;i<=NBE;i++) tab_element(i)->Accumul_aux_noeuds(lietendu,liQ,cas); }; // fonctions utilitaires du même genre // ajout sur le maillage d'un conteneur particulier quelconque void AjoutConteneurAuNoeud(TypeQuelconque& tQ); // ajout sur le maillage d'un ou plusieur ddl_enum_etendu comme conteneur void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu); // initialisation des updates de ddl_étendu uniquement sur les noeuds: on met à 0 les ddl_etendu correspondant, // les compteurs, comptant le nombre de fois où les noeuds sont modifiés, sont mis à 0 void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu); // idem pour un seul ddl_etendu void InitUpdateAuNoeud(const Ddl_enum_etendu & enu); // moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié) void MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu); // initialisation des coordonnées à t et tdt aux mêmes valeurs qu'à 0 // utile quand on veut utiliser les métriques pour un pb non couplés void Init_Xi_t_et_tdt_de_0(); // def d'un conteneur pour deux numéros: elem et pti class NBelemEtptInteg {public: int nbElem; int nbPtInteg; // surcharge de l'operator de lecture friend istream & operator >> (istream & ent, NBelemEtptInteg & de) { ent >> de.nbElem >> de.nbPtInteg; return ent;}; // surcharge de l'operator d'ecriture friend ostream & operator << (ostream & sort , const NBelemEtptInteg & de) { sort << de.nbElem <<" " << de.nbPtInteg << " "; return sort;}; bool operator < (const NBelemEtptInteg& c) const; bool operator > (const NBelemEtptInteg& c) const; bool operator == (const NBelemEtptInteg& c) const {return ((nbElem==c.nbElem)&&(nbPtInteg==c.nbPtInteg));}; bool operator != (const NBelemEtptInteg& c) const {return !((nbElem==c.nbElem)&&(nbPtInteg==c.nbPtInteg));}; }; // def d'un conteneur pour 3 numéros: elem, num face ou arete, et pti class NBelemFAEtptInteg {public: int nbElem; int nbFA; int nbPtInteg; // surcharge de l'operator de lecture friend istream & operator >> (istream & ent, NBelemFAEtptInteg & de) { ent >> de.nbElem >> de.nbFA >> de.nbPtInteg; return ent;}; // surcharge de l'operator d'ecriture friend ostream & operator << (ostream & sort , const NBelemFAEtptInteg & de) { sort << de.nbElem <<" "<< de.nbFA <<" " << de.nbPtInteg << " "; return sort;}; bool operator < (const NBelemFAEtptInteg& c) const; bool operator > (const NBelemFAEtptInteg& c) const; bool operator == (const NBelemFAEtptInteg& c) const {return ((nbElem==c.nbElem)&&(nbFA==c.nbFA)&&(nbPtInteg==c.nbPtInteg));}; bool operator != (const NBelemFAEtptInteg& c) const {return !((nbElem==c.nbElem)&&(nbFA==c.nbFA)&&(nbPtInteg==c.nbPtInteg));}; }; // ramène le numéro de l'élément qui contiend un point donné et le numéro du point // d'intégration le plus proche pour les ddl de la liste, (ddl spécifique à l'élément c'est-a-dire // hors des ddl des noeuds de l'éléments) // si pas de numéro d'élément ramène un numéro d'élément nulle // si les numéros de point d'intégration ne sont pas identique pour l'ensemble // des ddl, pb !!, le numéro du pt integ de retour est alors négatif // enu_temps: dit si les coordonnées du point M sont à 0 ou t ou tdt NBelemEtptInteg Element_le_plus_proche (Enum_dure enu_temps,const List_io & list_enu,const Coordonnee& M); // ramène le numéro de l'élément dont le centre de gravité à t = enu_temps est le plus proche d'un point donné // Le point peut être n'importe où, en particulier à l'extérieur de la matière // si pb retour de null const Element* Centre_de_Gravite_Element_le_plus_proche(Enum_dure enu_temps,const Coordonnee& M); // ramène pour chaque noeud, la liste des éléments qui contiennent le noeud // si le tableau n'existe pas, il est construit, sinon uniquement un retour // et la miss à jour est uniquement faite lors de la création des frontières const Tableau >& Indice() {if (indice.Taille() == 0) Calcul_indice(); return indice; }; //----- lecture écriture dans base info ----- // cas donne le niveau de la récupération // = 1 : on récupère tout // = 2 : on récupère uniquement les données variables (supposées comme telles) void Lecture_base_info(ifstream& ent,const int cas); // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void Ecriture_base_info(ofstream& sort,const int cas); // sortie du schemaXML: en fonction de enu static void SchemaXML_Maillages(ofstream& sort,const Enum_IO_XML enu) ; // ------ informations utiles par exemples pour la visualisation // retourne les dimensions minis et maxi suivant les axes du repère // absolu du maillage (en faite le calcul est fondé // uniquement sur la position des noeuds du maillage // le premier vecteur contient les minimums // le deuxième vecteur contient les maximums Tableau Taille_boiteMail(); // --------- utilitaires de manipulation de maillage // test pour savoir si le maillage contiend des éléments à interpolation linéaire bool Contient_lineaire(); // test pour savoir si le maillage contiend des éléments à interpolation quadratique incomplète bool Contient_quadratique_incomplet(); // transformation des éléments linéaires du maillage en quadratiques. // les éléments linéaires sont supprimés, // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage void Transfo_lin_quadraIncomp(LesReferences &lesRef); // transformation des éléments quadratiques incomplet du maillage en quadratiques complets. // les éléments incomplets sont supprimée, // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage void Transfo_quadraIncomp_quadraComp(LesReferences &lesRef); // relocalisation des points milieux des arrêtes des éléments quadratiques void RelocPtMilieuMailleQuadra(); // définition interactive de listes de références void CreationInteractiveListesRef(LesReferences* lesRef); // modification de l'orientation d'éléments void Modif_orientation_element(int cas_orientation,LesReferences* lesRef); // Lecture et Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe void LectureEtCollapse_element_superpose(UtilLecture * entreePrinc,LesReferences* lesRef); // Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe void Collapse_element_superpose(LesReferences* lesRef); // Lecture et collapse de noeuds très proche: appartenant à des éléments différents void LectureEtCollapse_noeuds_proches(UtilLecture * entreePrinc, LesReferences* lesRef); // collapse de noeuds très proche: appartenant à des éléments différents // rayon : donne la distance maxi entre les noeuds qui doivent être collapsé void Collapse_noeuds_proches(double rayon, LesReferences* lesRef); // Lecture et suppression d'elements à 2 noeuds, de distances très proches void LectureEtSup_Elem_noeudsConfondu(UtilLecture * entreePrinc, LesReferences* lesRef); // suppression d'elements à 2 noeuds, de distances très proches // rayon : donne la distance maxi entre les noeuds void Sup_Elem_noeudsConfondu(double rayon, LesReferences* lesRef); // création d'éléments SFE en fonction d'éléments classiques void CreationMaillageSFE(); // test pour savoir si le maillage est ok pour être transformée en sfe bool OKPourTransSfe(); // lecture et suppression éventuelle des noeuds, non référencés par les éléments et les références void LectureEtSuppressionNoeudNonReferencer(UtilLecture * entreePrinc,LesReferences& lesRef); // uniquement suppression éventuelle des noeuds, non référencés par les éléments et les références void SuppressionNoeudNonReferencer(LesReferences& lesRef); // Affichage des noeuds, non référencés par les éléments void AffichageNoeudNonReferencer(); // lecture et création éventuelle d'une ref sur les noeuds, non référencés par les éléments void LectureEtCreationRefNoeudNonReferencer(UtilLecture * entreePrinc,LesReferences& lesRef); // création éventuelle d'une référence sur les noeuds, non référencés par les éléments void CreationRefNoeudNonReferencer(LesReferences& lesRef); // vérification que toutes les références de noeuds, d'éléments, d'arêtes et de faces sont valides // c-a-d se réfèrent à des éléments existants void VerifReference(LesReferences& lesRef); // lecture et renumérotation éventuelle des noeuds void LectureEtRenumerotation(UtilLecture * entreePrinc,LesReferences& lesRef); // renumérotation des noeuds du maillage, en fonction de conditions linéaires éventuelles // ramène false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure), vrai sinon bool Renumerotation(LesReferences& lesRef,const Tableau >& condCLL); // création automatique des références globales de frontière si demandé dans le .info void CreationRefFrontiere(UtilLecture * entreePrinc,LesReferences& lesRef); // demande de création automatique des références globales de frontière void CreationRefFrontiere(LesReferences& lesRef); // force la mise à une valeur d'un ddl (ou de la liste de ddl fonction de la dimention) particulier, quelques soit son activité // si fonction_de_la_dimension = true : c'est toute les ddl fct de la dimension qui sont mis à la valeur void Force_Ddl_aux_noeuds_a_une_valeur(Enum_ddl enu, const double& val,Enum_dure temps, bool fonction_de_la_dimension); // mise à zéro de dd_enum_etendu aux noeuds : force la mise à une valeur à 0 void Force_Ddl_etendu_aux_noeuds_a_zero(const Tableau& tab_enu); protected : int idmail ; // numero de maillage string nomDuMaillage; // liste communes de tous les noms de maillages associée à un numéro // sous forme d'un arbre pour faciliter la recherche // cette liste n'est modifiée que par chaque maillage map < string, int , std::less >& listeNomMail; int dimension; // dimension du maillage Tableau tab_noeud; // tableau des noeuds du maillage Tableau tab_element; // tableau des elements du maillage // list des elements frontieres du maillage, c-a-d des frontières uniques LaLIST listFrontiere; // tableau des noeuds des éléments frontières Tableau tab_noeud_front; // tableau utilitaire: // indice(i) contient la liste des éléments qui contiennent le noeud i Tableau > indice; // pour chaque élément "i" , mitoyen_de_chaque_element(i)(j) contient l'élément Front // qui décrit la frontière "j" de l'élément et dedans, les éléments mitoyens de cette frontière // appartenant à d'autres éléments (ce tableau est construit par la méthode : Mitoyen()) Tableau < Tableau > mitoyen_de_chaque_element; // définie la liste des types de degrés de liberté inconnus, qui vont être calculés par la résolution des problèmes // physiques gérés par les éléments qui existent dans le maillages // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i // Si éléments thermiques -> ddl de température // Si éléments méca + éléments thermiques -> ddl Xi et température // etc. en fonction des éléments qui existent dans les maillages // (généré à la lecture du maillage, ce qui permet d'optimiser la consultation par la suite) Tableau ddl_representatifs_des_physiques; // idem au niveau des types de problèmes gérés par les éléments Tableau types_de_problemes; //indicateur uniquement utilisé pour la destruction, par défaut est toujours vrai // via la méthode Preparation_destruction_avec_conservation_noeuds_elements(), on peut le modifier bool detruire_les_noeuds_et_elements; // -- variables internes utilisées par Orientation_elements_mitoyens_recursif // tab_sens_element(i) : = 1 au début, puis vaut -1 si le sens de l'élément i à été changé Tableau tab_sens_element; // pendant les différents appels de Orientation_elements_mitoyens_recursif // - on définit un tableau d'indicateur, permettant de savoir si un élément a été traité ou pas // une fois qu'un élément a été traité: a) on ne permet plus son changement de sens // b) de plus dans le cas d'une suite d'appels récursif, il n'est plus retenue pour les nouvelles listes Tableau ind_elem; // def et init à 0, c-à-d non traité // -- fin variables internes utilisées par Orientation_elements_mitoyens_recursif // METHODES PROTEGEES : // cas particulier de destruction, sans suppression des noeuds et éléments // l'utilisation de la méthode suivante, permet ensuite de supprimer le maillage // tout en évitant la destruction des noeuds internes et éléments internes // à utiliser avec précaution, intéressant si l'on veut créer un nouveau maillage // avec les noeuds et éléments de ce maillage void Preparation_destruction_avec_conservation_noeuds_elements() { detruire_les_noeuds_et_elements = false; }; // change le numéro de maillage void Change_numero_maillage(int new_num); // definition des elements mitoyens aux elements de frontiere // à la fin du programme tous les éléments mitoyens sont stocké dant les éléments // Front et non les éléments frontières qui eux sont supprimés void MitoyenFront(); // création pour chaque noeud de la liste des éléments qui contiennent le noeud void Calcul_indice(); // definition d'un stockage contenant tous les Front associés à toutes les frontières de tous les éléments // puis définition des elements mitoyens à ces Front : deux éléments Front sont mitoyens // s'ils correspondent à des Element différents, et si les frontières associées possèdent les mêmes noeuds // toutes ces informations sont stockées dans : mitoyen_de_chaque_element (cf. sa description) void Calcul_tous_les_front_et_leurs_mitoyens(); // dans le cas où les éléments frontières sont des lignes, on les ordonnes // de manière à former une ligne continue void OrdonancementDesLigne(); // lectures des infos pour le choix d'un élément void Lecture_info_1element(UtilLecture * entreePrinc,int& num_elt,Enum_geom& id_geom ,Enum_interpol& id_interpol,EnumElemTypeProblem& id_typeProb ,string& discriminant); // lecture des mouvements solides si nécessaire void Lecture_des_mouvements_solides(UtilLecture * entreePrinc); // une classe de travail qui sert pour pouvoir classer les noeuds par leur position géométrique initiale // deux élément sont identiques si leur position initiale sont identique // a >= b si : soit a.x >= b.x, ou a.x==b.x et a.y >= b.y, ou a.x==b.x et a.y == b.y et a.z >= b.z class PosiEtNoeud { public: Noeud * noe; // le noeud Element * el; // l'élément auquel il est rattaché // -------- constructeur ------------ PosiEtNoeud() : noe(NULL),el(NULL) {}; // constructeur par défaut PosiEtNoeud(Noeud * no,Element * e) : noe(no),el(e) {}; // constructeur normal PosiEtNoeud(const PosiEtNoeud& po) : noe(po.noe),el(po.el) {}; // constructeur de copie //------ surcharges qui ne travaillent que sur la position -------- PosiEtNoeud& operator= (const PosiEtNoeud& po); // affectation bool operator == (const PosiEtNoeud& po) const ; // test d'égalité bool operator != (const PosiEtNoeud& po) const ; // test d'inégalité bool operator < (const PosiEtNoeud& po) const ; // relation d'ordre bool operator <= (const PosiEtNoeud& po) const ; // relation d'ordre bool operator > (const PosiEtNoeud& po) const ; // relation d'ordre bool operator >= (const PosiEtNoeud& po) const ; // relation d'ordre }; // fonctions simples ayant pour but de bien repérer des opérations dangereuses // affectation d'un noeud au maillage c-a-d au tableau de pointeur de noeud, // a condition que la place ne soit pas déjà occupée sinon on change le numéro // de noeud et on augmente le tableau void Affectation_noeud (Noeud& noeud); // affectation d'un element au maillage c-a-d au tableau de pointeur d'element, // a condition que la place ne soit pas déjà occupée sinon on change le numéro // de l'élément et on augmente le tableau void Affectation_element (Element& element); // Modifie le nombre de noeuds du maillage (N.B.: Fait appel // a la methode Change_taille de la classe Tableau) // les éléments supplémentaires ont un pointeur mis à Null void Change_nb_noeud (int nouveau_nb); // Modifie le nombre d'elements du maillage (N.B.: Fait appel // a la methode Change_taille de la classe Tableau) // les éléments supplémentaires ont un pointeur mis à Null void Change_nb_element (int nouveau_nb); // ** pour l'instant ne fonctionne que pour les éléments surfaces // orientation automatique des éléments mitoyens, à l'élément num_elem, et ensuite // récursivement à tous les éléments mitoyens des mitoyens jusqu'à ce que la chaine s'arrête // L'ensemble des éléments est alors groupé dans une référence qui est construit à partir du numéro num_elem // et qui est ajouté aux refs déjà existantes // ensuite, le programme passe en revue les éléments restants, et regarde s'ils font parti // d'un ensemble homogène orienté, si non, ramène la liste des éléments hors ensemble orienté // *** ne concerne que les éléments surfaces, les autres sont ignorés // ind_elem(i) : (tableau interne) indique si l'élément i a été traité (=true) ou non (=false) // ind_elem: est pris en compte puis mis à jour par le programme, c-a-d que les nouveaux éléments orienté // passe de false à true, par contre tous les éléments déjà à true, ne sont pas pris en compte dans le traitement // angle_maxi : angle maximum entre deux éléments, au dessus duquel on considère qu'il y a une rupture de la mitoyenneté // nom_ref : s'il est différent de "_", donne le nom de base voulu à la série de référence qui va être construite // inverse : indique si l'on souhaite partir d'une orientation inverse de celle existante avant application de l'algo // ceci pour l'élément de départ: au premier appel, l'opération est toujours possible, ensuite cela dépend // si l'élément trouvé a déjà été traité ou pas // recursiv : indique si l'on se situe dans une suite récursive d'appel de la méthode // si oui, seule les éléments non déjà pris en compte dans les appels précédents, sont examiné // c'est ind_elem qui permet de s'en assurer // si non: cas par exemple d'un angle_maxi qui change, on réexamine tous les éléments, cependant // la ré_orientation éventuelle n'est faite qu'une seule fois (toujours via ind_elem) list Orientation_elements_mitoyens_recursif(bool recursif,string& nom_ref,int num_elem , LesReferences& lesRef,double& angle_maxi,bool inverse); // méthode pour initialiser les différents tableaux utilisés par Orientation_elements_mitoyens_recursif void Init_Orientation_elements_mitoyens_recursif(); // méthode pour orienter des éléments en fonction d'un rayon: AG, A étant un point donné, G étant le centre de // gravité d'une facette // A : coordonnée d'un point, si indic_G(i) est true, alors A(i) est remplacé par la coordonnée G(i) du centre // de gravité de la facette // zone_a_traiter: le nom de la référence des éléments a traiter // inverse : si true, l'orientation des normales des facettes est identique à celles de AG, sinon c'est l'inverse void Orientation_via_rayon(const Tableau & indic_G,const Coordonnee & A ,const string& zone_a_traiter, LesReferences& lesRef, bool inverse); // ------- pour la définition interactive de liste de ref ------------- // def d'un conteneur pour deux numéros: nb element nb face class NBelemEtFace {public: int nbElem; int nbFace; bool operator < (const NBelemEtFace& c) const; bool operator > (const NBelemEtFace& c) const; bool operator == (const NBelemEtFace& c) const {return ((nbElem==c.nbElem)&&(nbFace==c.nbFace));}; bool operator != (const NBelemEtFace& c) const {return !((nbElem==c.nbElem)&&(nbFace==c.nbFace));}; }; // def d'un conteneur pour deux numéros: nb element nb arête class NBelemEtArete {public: int nbElem; int nbArete; bool operator < (const NBelemEtArete& c) const; bool operator > (const NBelemEtArete& c) const; bool operator == (const NBelemEtArete& c) const {return ((nbElem==c.nbElem)&&(nbArete==c.nbArete));}; bool operator != (const NBelemEtArete& c) const {return !((nbElem==c.nbElem)&&(nbArete==c.nbArete));}; }; // calcul des listes de références en fonction de la demande: // list_nomReference: contient les types de refs que l'on veut // list_methode: contient la ou les méthodes que l'on veut utiliser // cas 1D void CalculListRef_1D(list& list_nomReference,LesReferences* lesRef,list& list_methode ,const Enum_ddl & enu_ddl); // cas 2D void CalculListRef_2D(list& list_nomReference,LesReferences* lesRef,list& list_methode ,const Enum_ddl & enu_ddl); // cas 3D void CalculListRef_3D(list& list_nomReference,LesReferences* lesRef,list& list_methode ,const Enum_ddl & enu_ddl); // les méthodes de bases // fonction générique pour des condition PresDe void PresDe(const list& list_nomReference, list & list_noeud_restant ,list & list_element_restant,const Enum_ddl& enu_ddl ,list & list_elemPtin_restant,bool& premLpti ,list & list_elemFace_restant,bool& premLface ,list & list_elemArrete_restant,bool& premLarrete); // fonction générique pour des condition "tout dedans" void ToutDedans(const list& list_nomReference, list & list_noeud_restant ,list & list_element_restant,const Enum_ddl& enu_ddl ,list & list_elemPtin_restant,bool& premLpti ,list & list_elemFace_restant,bool& premLface ,list & list_elemArrete_restant,bool& premLarrete); // constitution des références void EnregRef(const list& list_nomReference,list & list_noeud_restant ,list & list_elemPtin_restant,list & list_element_restant ,list & list_elemFace_restant,list & list_elemArrete_restant ,LesReferences* lesRef); // définition des fonctions conditions // def de data internes qui servent pour les fonctions init et exe: dimensionnées dans init, utilisé dans exe // donc: init et exe doivent être utilisé absolument à suivre Tableau t_poi; Tableau t_droit; Tableau t_para; Tableau t_plan; Tableau t_sphere; Tableau t_cylindre; Tableau t_cercle; // cas de croisement avec des références existantes: def de variables de passage pour InRef et OutRef // les pointeurs qui suivent ne servent pas à créer des refs, mais uniquement a récupérer les adresses list list_refIn; list list_refOut; LesReferences* lesRefin; // variable utilisée uniquement pour le passage d'info à // ,InitInRef(), ExeInRef (), InitOutRef(), ExeOutRef() // tout d'abord les pointeurs de fonctions en cours // - pour les conditions Presde // acquisition interactive des paramètres de la condition void (Maillage::*initConditionPresDe) (double& dist); // exécution de la condition : ramène true si ok, false sinon bool (Maillage::*ExeConditionPresDe) (const double& dist,const Coordonnee& M)const; // - pour les condition ToutDedans // acquisition interactive des paramètres de la condition void (Maillage::*initConditionToutDedans) (); // exécution de la condition : ramène true si ok, false sinon bool (Maillage::*ExeConditionToutDedans) (const Tableau & tab_M)const; // recherche près d'un point // def interactive du point et de la distance void InitPresPoint(double& dist); // exécution de la condition bool ExePresPoint(const double& dist,const Coordonnee& M) const; // recherche d'un coté d'un point (en 1D) void InitCotePoint(); // ramène true si tous les points sont du même coté que t_poi(1) bool ExeCotePoint(const Tableau & t_M)const; // recherche entre deux points (1D) void InitEntrePoint(); // ramène true si tous les points sont entre t_poi(1) et t_poi(2) bool ExeEntrePoint(const Tableau & t_M)const; // recherche entre deux points (1D) _avec_distance void InitEntrePoint_avec_distance(); // ramène true si tous les points sont entre t_poi(1) et t_poi(2) bool ExeEntrePoint_avec_distance(const Tableau & t_M)const; // recherche près d'une ligne void InitPresLigne(double& dist); bool ExePresLigne(const double& dist,const Coordonnee& M)const; // dans le cas particulier d'une ligne, on peut ordonner certaines listes résultantes / à la lignes // il s'agit des noeuds et des pt d'integ: on les ordonnes par rapport à leurs projections sur la lignes void InitOrdonneLigne(); void OrdonneLigne(list & list_noeud_restant,list & list_elemPtin_restant ,const Enum_ddl& enu_ddl); // recherche près d'un cercle void InitPresCercle(double& dist); bool ExePresCercle(const double& dist,const Coordonnee& M)const; // recherche près d'un plan void InitPresPlan(double& dist); bool ExePresPlan(const double& dist,const Coordonnee& M)const; // recherche près d'un cylindre void InitPresCylindre(double& dist); bool ExePresCylindre(const double& dist,const Coordonnee& M)const; // recherche près d'une sphere void InitPresSphere(double& dist); bool ExePresSphere(const double& dist,const Coordonnee& M)const; // recherche d'un coté d'un plan void InitCotePlan(); // ramène true si tous les points sont du même coté que t_poi(1) du plan bool ExeCotePlan(const Tableau & t_M)const; // condition entre plans // void InitEntrePlan(); // ramène true si tous les points sont entre les deux plans bool ExeEntrePlan(const Tableau & t_M)const; // condition entre plans _avec_distance // void InitEntrePlan_avec_distance(); // ramène true si tous les points sont entre les deux plans bool ExeEntrePlan_avec_distance(const Tableau & t_M)const; // condition dans ou dehors un cylindre void InitDansCylindre(); // ramène true si tous les points sont dans le cylindre bool ExeDansCylindre(const Tableau & t_M)const; // ramène true si tous les points sont à l'extérieur du cylindre bool ExeOutCylindre(const Tableau & t_M)const; // condition entre deux cylindre void InitEntreCylindre(); // ramène true si tous les points sont entre les deux cylindres bool ExeEntreCylindre(const Tableau & t_M)const; // condition dans ou dehors d'une sphére void InitDansSphere(); // ramène true si tous les points sont dans la sphère bool ExeDansSphere(const Tableau & t_M)const; // ramène true si tous les points sont à l'extérieur de la sphère bool ExeOutSpheres(const Tableau & t_M)const; // condition entre deux spheres concentriques void InitEntreSpheres(); // ramène true si tous les points sont entre les deux sphères bool ExeEntreSpheres(const Tableau & t_M)const; // condition du même coté d'une droite (en 2D seulement) void InitCoteDroite(); // ramène true si tous les points sont du même coté que t_poi(1) de la droite (en 2D uniquement) bool ExeCoteDroite(const Tableau & t_M)const; // condition entre 2 droites (en 2D seulement) void InitEntreDroite(); // ramène true si tous les points sont entre les 2 droites (en 2D uniquement) bool ExeEntreDroite(const Tableau & t_M)const; // condition entre 2 droites (en 2D seulement) _avec_distance void InitEntreDroite_avec_distance(); // ramène true si tous les points sont entre les 2 droites (en 2D uniquement) bool ExeEntreDroite_avec_distance(const Tableau & t_M)const; // condition dans ou dehors un cercle (en 2D seulement) void InitDansCercle(); // ramène true si tous les points sont dans le cercle bool ExeDansCercle(const Tableau & t_M)const; // ramène true si tous les points sont à l'extérieur du cercle bool ExeOutCercle(const Tableau & t_M)const; // condition entre cercles concentriques (en 2D seulement) void InitEntreCercles(); // ramène true si tous les points sont entre les deux cercles concentriques bool ExeEntreCercles (const Tableau & t_M)const; // acquisition d'un plan Plan Acquisition_interactive_plan(); // acquisition d'un point Coordonnee Acquisition_interactive_point(); // acquisition d'une droite Droite Acquisition_interactive_droite(); // acquisition d'un vecteur=direction Coordonnee Acquisition_interactive_vecteur(); // condition d'appartenance à une référence existante void InitInRef(); // condition d'exclusion à une référence existante void InitOutRef(); // ---- mise en place de la condition d'appartenance ou d'exclusion à des références existantes // contrairement aux autres conditions, cette condition est prise en compte au moment de la création finale // de la référence dans la méthode : EnregRef, via les méthodes du 2) // 1) une fonction qui ne fait rien, mais est là pour que le tout fonctionne normalement bool Exe_In_out_avecRefExistantes(const Tableau & t_M)const; // ne fait rien // 2) fonctions qui réellement font quelque chose: utilisées dans la méthode EnregRef void Exe_In_out_avecRefExistantes_N(list & list_noeud_restant); void Exe_In_out_avecRefExistantes_E(list & list_element_restant); void Exe_In_out_avecRefExistantes_G(list & list_elemPtin_restant); void Exe_In_out_avecRefExistantes_F(list & list_elemFace_restant); void Exe_In_out_avecRefExistantes_A(list & list_elemArrete_restant); // void InterOuDiff_avecRefExistantes(const Tableau & t_M)const; //-------------------- méthodes particulières pour l'optimisation de largeur de bande ------------------------ // une classe intermédiaire pour pouvoir classer les noeuds en fonction du degré class Noeud_degre { public: Noeud* noe; int degre; Noeud_degre (): noe(NULL), degre(0) {}; Noeud_degre (Noeud* no,int deg): noe(no),degre(deg) {}; Noeud_degre (const Noeud_degre& no ): noe(no.noe), degre(no.degre) {}; ~Noeud_degre() {}; bool operator > (const Noeud_degre& a) const { return (this->degre > a.degre);}; bool operator >= (const Noeud_degre& a) const { return (this->degre >= a.degre);}; bool operator < (const Noeud_degre& a) const { return (this->degre < a.degre);}; bool operator <= (const Noeud_degre& a) const { return (this->degre <= a.degre);}; Noeud_degre& operator= (const Noeud_degre& de) { degre = de.degre; noe = de.noe; return (*this);}; }; // méthode static: c-a-d indépendante des données du maillage (elle est générale) // calcul du point de départ, en fonction de conditions linéaires éventuelles // il y a également calcul des voisins et de la descendance du noeud de retour // s'il y a un pb, calcul_ok en retour est false static Noeud* Point_de_depart(const Tableau& tab_elem ,const Tableau& tab_noe ,const Tableau *> tt_noeud_front ,Tableau < LaLIST_io >& t_voisin , list < list < Noeud_degre > > & lis_descent ,const Tableau >& condCLL,bool& calcul_ok); // méthode static: c-a-d indépendante des données du maillage (elle est générale) // calcul des voisins de tous les noeuds du maillage en fonction des éléments et de conditions // linéaires éventuelles, // en entrée/sortie t_voisin // restriction: il faut que tab_noe contienne tous les noeuds référencés dans tab_elem et tt_t_condCLL // s'il y a un pb, calcul_ok en retour est false static Tableau < LaLIST_io >& Voisins(const Tableau& tab_elem ,const Tableau& tab_noe ,Tableau < LaLIST_io >& t_voisin ,const Tableau >& t_t_condCLL,bool& calcul_ok); // méthode static: c-a-d indépendante des données du maillage (elle est générale) // calcul de la descendance d'un noeud noeu, // on considère que les voisins sont dèjà correctement définis // en entrée la liste qui est modifiée en interne et retournée en sortie // le premier élément de la liste c'est la dernière descendance // s'il y a un pb, calcul_ok en retour est false static list < list < Noeud_degre > > & Descendance (const int& taille_tabnoeud ,Noeud * noeu, Tableau < LaLIST_io >& t_voisin , list < list < Noeud_degre > > & lient,bool& calcul_ok); // méthode static: c-a-d indépendante des données du maillage (elle est générale) // algorithme de Cuthill Mac Kee directe // noeu : le noeud de départ // lis_descent : les descendants de noeu, qui va être modifié dans le processus // ramène une nouvelle numérotation (mais les numéros internes des noeuds ne sont pas changé static Tableau Cuthill_Mac_Kee(const int& taille_tabnoeud,Noeud * noeu ,Tableau < LaLIST_io >& t_voisin , list < list < Noeud_degre > >& lis_descent); // méthode static: c-a-d indépendante des données du maillage (elle est générale) // calcul de la largeur de bande en noeuds static int LargeurBandeEnNoeuds(const Tableau& tab_elem); // on s'occupe de mettre à jour les types de pb et les ddl types associés void Mise_a_jour_type_pb_type_associe_ddl(); }; /// @} // end of group #endif