// FICHIER : Maillage.cp // 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: . #include "Maillage.h" # include using namespace std; //introduces namespace std #include #include "Sortie.h" #include #include #include "List_io.h" #include "CharUtil.h" #ifndef SYSTEM_MAC_OS_X_unix #include "Frontier.h" #endif #include "ConstMath.h" #include "ReferenceNE.h" #include "ReferenceAF.h" #include "MvtSolide.h" #include "TypeQuelconqueParticulier.h" // 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_maill : est facultatif, s'il est différent de ".", il est pris en compte comme nom de maillage // Constructeur par defaut Maillage::Maillage (map < string, int , std::less > & lisNomMail,int nmail,int dim ,const string& nom_maill): listeNomMail(lisNomMail),nomDuMaillage(),idmail(nmail),dimension(dim) ,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front(),indice() , list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element() ,ddl_representatifs_des_physiques(),types_de_problemes() , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif ,detruire_les_noeuds_et_elements(true) { if (nom_maill == ".") {// tout d'abord on donne un nom par défaut au maillage nomDuMaillage = "pas_de_nom"; while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) { // on cherche un nom quelconque qui n'est pas déjà utilisé nomDuMaillage += '_'; }; } else // le paramètre de nom de maillage est valide { nomDuMaillage = nom_maill; }; // maintenant on associe le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; }; // Constructeur fonction d'une dimension, du nombre de noeuds // du nombre d'elements, et d'un numero d'identification (le nb de maillage) Maillage::Maillage (map < string, int , std::less > & lisNomMail ,int dim,int n_noeud,int n_elt,int nmail,const string& nom_maill): // Constructeur utile quand la dimension, le nombre de noeuds // et le nombre d'elements du maillage sont connus listeNomMail(lisNomMail),tab_noeud(n_noeud),tab_element(n_elt),listFrontiere(),tab_noeud_front() ,indice(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element() ,ddl_representatifs_des_physiques(),types_de_problemes() , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif ,detruire_les_noeuds_et_elements(true) {if (nmail <=0) { cout << "\nErreur : numero de maillage invalide !\n"; cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n"; Sortie(1); }; idmail = nmail; // traitement du nom de maillage if (nom_maill ==".") {// on donne un nom par défaut au maillage nomDuMaillage = "pas_de_nom"; while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) { // on cherche un nom quelconque qui n'est pas déjà utilisé nomDuMaillage += '_'; }; } else // le paramètre de nom de maillage est valide { nomDuMaillage = nom_maill; }; // maintenant on associe le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; if ( (dim<1) || (dim>3) ) { cout << "\nErreur : dimension invalide !\n"; cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n"; Sortie(1); }; if ( n_noeud<=0 ) { cout << "\nErreur : nombre de noeuds non valide !\n"; cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n"; Sortie(1); }; if ( n_elt<=0 ) { cout << "\nErreur : nombre d'elements invalide !\n"; cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n"; Sortie(1); }; dimension=dim; }; // 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::Maillage (map < string, int , std::less > & lisNomMail ,int dim,list & li_noeud, list li_element ,int nmail,const string& nom_maill ): listeNomMail(lisNomMail),tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front() ,indice(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element() ,ddl_representatifs_des_physiques(),types_de_problemes() , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif ,detruire_les_noeuds_et_elements(true) { if (ParaGlob::NiveauImpression() >= 5) cout << " \n creation du maillage: " << nom_maill << endl; if (nmail <=0) { cout << "\nErreur2 : numero de maillage invalide !\n"; cout << "MAILLAGE::MAILLAGE( ) \n"; Sortie(1); }; // si le numéro de maillage est déjà utilisé, on signale que la place est prise for (std::map< string, int , std::less >::iterator it=listeNomMail.begin(); it!=listeNomMail.end(); ++it) { if ((it->second) == nmail) { cout << "\n *** erreur: le numero de maillage "<first) << "\n constructeur: Maillage::Maillage (..."<< flush; Sortie(1); }; }; // sinon c'est ok idmail = nmail; // traitement du nom de maillage if (nom_maill ==".") {// on donne un nom par défaut au maillage nomDuMaillage = "pas_de_nom"; while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) { // on cherche un nom quelconque qui n'est pas déjà utilisé nomDuMaillage += '_'; }; } else // le paramètre de nom de maillage est valide { nomDuMaillage = nom_maill; }; // maintenant on associe le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; if ( (dim<1) || (dim>3) ) { cout << "\nErreur2 : dimension invalide !\n"; cout << "MAILLAGE::MAILLAGE(... \n"; Sortie(1); }; dimension=dim; // récupération des noeuds int nbN = li_noeud.size(); list ::iterator il,ilfin=li_noeud.end(); Change_nb_noeud(nbN); // tab_noeud.Change_taille(nbN,NULL); // on vérifie que la numérotation est correcte pour les noeuds // c'est-à-dire que tous les numéros peuvent être rangés à suivre bool numerotation_correcte = true; for (il=li_noeud.begin();il!=ilfin;il++) {int nb = (*il)->Num_noeud(); if (nb<1 || nb > nbN) {numerotation_correcte=false; break; }; }; if (numerotation_correcte) {// on peut y aller sans vérif for (il=li_noeud.begin();il!=ilfin;il++) tab_noeud((*il)->Num_noeud()) = *il; } else // on est obligé de changer la numérotation des noeuds {int nb=1; for (il=li_noeud.begin();il!=ilfin;il++,nb++) {tab_noeud(nb) = *il;int nbinit=(*il)->Num_noeud(); (*il)->Change_num_noeud(nb); if (ParaGlob::NiveauImpression() > 0) {cout << "\n warning : le numero initial du noeud " << nbinit << " est remplace par " << " le numero d'ordre attribue automatiquement par herezh " << nb << "\n seul ce dernier sera utilise par la suite ! " << endl; if (ParaGlob::NiveauImpression() > 5) cout << "\n Maillage::Maillage (map < string, int ,.... " << endl; }; }; }; // récupération des éléments int nbE = li_element.size(); list ::iterator ile,ilefin=li_element.end(); Change_nb_element(nbE); // on vérifie que la numérotation est correcte pour les éléments (comme pour les noeuds) // c'est-à-dire que tous les numéros peuvent être rangés à suivre numerotation_correcte = true; for (ile=li_element.begin();ile!=ilefin;ile++) {int nb = (*ile)->Num_elt(); if (nb<1 || nb > nbE) {numerotation_correcte=false; break; }; }; if (numerotation_correcte) {// on peut y aller sans vérif for (ile=li_element.begin();ile!=ilefin;ile++) tab_element((*ile)->Num_elt()) = *ile; } else // on est obligé de changer la numérotation des éléments {int nb=1; for (ile=li_element.begin();ile!=ilefin;ile++,nb++) {tab_element(nb) = *ile;int nbinit=(*ile)->Num_elt(); (*ile)->Change_num_elt(nb); if (ParaGlob::NiveauImpression() > 0) {cout << "\n warning : le numero initial de l'element " << nbinit << " est remplace par " << " le numero d'ordre attribue automatiquement par herezh " << nb << "\n seul ce dernier sera utilise par la suite ! " << endl; if (ParaGlob::NiveauImpression() > 5) cout << "\n Maillage::Maillage (map < string, int ,.... " << endl; }; }; }; // on modifie le numéro de maillage pour les noeuds et éléments int NBN_P1 = tab_noeud.Taille()+1; for (int nn=1;nn < NBN_P1;nn++) tab_noeud(nn)->Change_num_Mail(idmail); int NBE_P1 = tab_element.Taille()+1; for (int ne=1;ne < NBE_P1;ne++) tab_element(ne)->Change_num_maillage(idmail); if (ParaGlob::NiveauImpression() >= 5) cout << " \n fin creation du maillage: " << nom_maill << endl; }; // 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 // d'autre part le numéro de maillage et le nom de maillage n'est pas valide, il faut // ensuite les définir Maillage::Maillage (const Maillage& mail): listeNomMail(mail.listeNomMail),idmail(mail.idmail),nomDuMaillage(mail.nomDuMaillage),dimension(mail.dimension) ,tab_noeud(mail.tab_noeud),tab_element(mail.tab_element) ,listFrontiere(mail.listFrontiere),tab_noeud_front(mail.tab_noeud_front) ,indice(),list_refIn(),list_refOut(),lesRefin(NULL) ,mitoyen_de_chaque_element(mail.mitoyen_de_chaque_element) ,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques) ,types_de_problemes(mail.types_de_problemes) , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif ,detruire_les_noeuds_et_elements(true) { // tout d'abord on donne un nom par défaut au maillage nomDuMaillage = "pas_de_nom"; while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) { // on cherche un nom quelconque qui n'est pas déjà utilisé nomDuMaillage += '_'; }; // maintenant on associe le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; }; // 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 ! ni les normales, // ni les infos concernant les intégrales (qui sont propres aux maillages existants) Maillage::Maillage (map < string, int , std::less > & lisNomMail ,int nmail, const string& nomDu,const Maillage& mail): listeNomMail(lisNomMail),idmail(nmail),nomDuMaillage(nomDu),dimension(mail.dimension) ,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front() ,indice(),list_refIn(),list_refOut(),lesRefin(NULL) ,mitoyen_de_chaque_element() ,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques) ,types_de_problemes(mail.types_de_problemes) , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif ,detruire_les_noeuds_et_elements(true) { // on vérifie que le nom de maillage fourni n'existe pas if (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) { cout << "\n erreur, le nom de maillage demande existe deja : " << nomDuMaillage << "\n Maillage::Maillage (....."; Sortie(1); }; // on vérifie que le numéro de maillage proposé est valide if (idmail <=0) { cout << "\nErreur : numero de maillage invalide ! = "<< idmail <<"\n"; cout << "MAILLAGE::MAILLAGE(.... \n"; Sortie(1); }; // maintenant on associe le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; // on s'occupe tout d'abord des noeuds int nbn = mail.tab_noeud.Taille(); Change_nb_noeud(nbn); for (int ino=1;ino<= nbn;ino++) { tab_noeud(ino) = new Noeud(*(mail.tab_noeud(ino))); tab_noeud(ino)->Change_num_Mail(nmail); }; // maintenant les éléments int nbe = mail.tab_element.Taille(); Change_nb_element(nbe); for (int ie=1;ie<=nbe;ie++) { tab_element(ie) = mail.tab_element(ie)->Nevez_copie(); //debug //tab_element(ie)->Affiche(1); cout << endl; //fin debug // on réaffecte les noeuds du maillage Tableau& ttab = tab_element(ie)->Tab_noeud(); int ttabtaille=ttab.Taille(); for (int ine=1;ine<=ttabtaille;ine++) ttab(ine)=tab_noeud(ttab(ine)->Num_noeud()); // on change le numéro de maillage tab_element(ie)->Change_num_maillage(idmail); }; // dans le cas où mail.mitoyen_de_chaque_element n'est pas vide, // on construit le nouveau if (mail.mitoyen_de_chaque_element.Taille() != 0) Calcul_tous_les_front_et_leurs_mitoyens(); }; Maillage::~Maillage() // Destructeur { if ( detruire_les_noeuds_et_elements) // cas normal { for (int i=1;i<= tab_noeud.Taille();i++) delete tab_noeud(i); for (int i=1;i<= tab_element.Taille();i++) delete tab_element(i); }; // pas de destruction de tab_noeud_front car ce sont des noeuds de tab_noeud, ils sont déjà détruit }; void // lecture d'un maillage et def des references s'y rapportant Maillage::LectureMaillage(UtilLecture * entreePrinc,LesReferences& lesRef) { if (ParaGlob::NiveauImpression() >= 5) cout << " debut de lecture de maillage " << endl; if (ParaGlob::NiveauImpression() >= 6) cout << " lecture du nom de maillage " << endl; // cas où il y a un nom de maillage if (strstr(entreePrinc->tablcar,"nom_maillage")!=NULL) { // // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant // listeNomMail.erase(listeNomMail.find(nomDuMaillage)); // modif le 14 avril 2015 // non c'est une mauvaise idée, il faut au contraire arrêter le programme et dire qu'il y a // deux fois le même nom, par contre si le nom de maillage c'est "pas_de_nom" il faut le supprimer if ((nomDuMaillage == "pas_de_nom") && (listeNomMail.find(nomDuMaillage) != listeNomMail.end())) listeNomMail.erase(listeNomMail.find(nomDuMaillage)); string toto; *(entreePrinc->entree) >> toto >> nomDuMaillage; if (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) {cout << "\n erreur *** plusieurs maillages ont le meme nom : "<< nomDuMaillage << " \n revoir les noms de maillage !! " << endl; Sortie(1); }; // maintenant on associe le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; // ensuite lecture de l'entête des noeuds entreePrinc->NouvelleDonnee(); if (strstr(entreePrinc->tablcar,"noeuds")==NULL) { cout << " *** erreur dans la lecture des noeuds " << " \n LectureMaillage(... " << endl; entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; } else // on définit un nom apriori uniquement dans le cas d'un seul maillage // sinon c'est une erreur { if (idmail ==1) { // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant listeNomMail.erase(listeNomMail.find(nomDuMaillage)); nomDuMaillage = "premier_maillage"; // maintenant on associe le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; } else { cout << "\n Erreur dans la lecture du maillage " << idmail <<" ****** "; cout << "\n il n'y a pas de nom de maillage alors que c'est obligatoire !! " << " \n LectureMaillage(... " << endl; entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie (1); }; }; //------------- lecture des noeuds ------------- // lecture du nombre de noeud if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des noeuds " << endl; entreePrinc->NouvelleDonnee(); if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre de noeud " << endl ; int nbNoeud; // nombre de noeud *(entreePrinc->entree) >> nbNoeud; // lecture dans le flot memoire if (ParaGlob::NiveauImpression() >= 8) cout << nbNoeud << endl ; Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud #ifdef ETUDIANT_LIMITATION if (nbNoeud > nb_maxi_noeud) { cout << "\n nombre maxi de noeud autorisé atteind " << nb_maxi_noeud; Sortie(1); }; #endif // lecture des noeuds Noeud * ptr; for (int i=1; i<= nbNoeud; i++) { entreePrinc->NouvelleDonnee(); ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage if (ParaGlob::NiveauImpression() == 10) cout << "n:" << i << " " << flush ; // lecture du noeud ptr->Lecture(entreePrinc); Affectation_noeud(*ptr); }; // -------------- lecture des references se rapportant aux noeuds --------- entreePrinc->NouvelleDonnee(); if (strstr(entreePrinc->tablcar,"elements")==NULL) // cas où les références sont mises aprés les noeuds, dans ce cas c'est // des références de noeud { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references de noeuds " << endl; lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds lesRef.NbMaille(idmail); // indic le numéro de maillage aux références lesRef.Lecture(*entreePrinc); }; // ------------ lecture des elements ----------- // lecture du nombre d'element int nbElement=0; // nombre d'element null par défaut if (strstr(entreePrinc->tablcar,"elements")!=NULL) // cas avec element { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des elements du maillage " << endl ; entreePrinc->NouvelleDonnee(); if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre d'element " << endl ; *(entreePrinc->entree) >> nbElement; if (ParaGlob::NiveauImpression() >= 8) cout << nbElement << endl ; #ifdef ETUDIANT_LIMITATION if (nbElement > nb_maxi_element) { cout << "\n nombre maxi d'element autorise atteind " << nb_maxi_element; Sortie(1); }; #endif // dimensionnement dynamique du tableau d'elements Change_nb_element(nbElement); // Lecture des elements Element * ptr; for (int i=1; i<= nbElement; i++) { // lecture geometrie et interpolation entreePrinc->NouvelleDonnee(); if (ParaGlob::NiveauImpression() == 10) cout << "e:" << i << " " << flush ; // def des énumérations de travail int num_elt = i; // numéro interne de l'élément int num_elt_lue; // numéro lue Enum_geom id_geom; Enum_interpol id_interpol;EnumElemTypeProblem id_typeProb; // cas d'info annexe string str_precision(""); // stockage info annexe de choix, initié à rien par défaut // lectures des infos pour le choix d'un élément Lecture_info_1element(entreePrinc,num_elt_lue,id_geom,id_interpol,id_typeProb,str_precision); if (num_elt_lue != num_elt) { if (ParaGlob::NiveauImpression() > 0) {cout << "\n warning : le numero de l'element lue " << num_elt_lue << " est different du numero " << " d'ordre attribue automatiquement par herezh " << num_elt << "\n seul ce dernier sera utilise pour les resultats ! " << endl; }; }; // ======== choix de l'element ===================================== // et affectation du pointeur d'element en fonction de id_geom et id_interpol // le numero d'element : num_elt, est affecte a l'element pointe par ptr ptr = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision); if (ptr == NULL) { // l'operation a echouee cout << "\n Erreur dans le choix d'element ****** "; cout << "\n l\'element : " << Nom_interpol(id_interpol) << " " << Nom_geom(id_geom) << " n\'est pas present dans le programme ! " << endl; entreePrinc->MessageBuffer("** lecture d'un element **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie (1); }; // lecture des infos particulieres a l'element Tableau * pt = & tab_noeud; ptr->LectureDonneesParticulieres(entreePrinc,pt); Affectation_element(*ptr); // si c'est le premier élément du premier maillage on regarde s'il s'agit // d'un élément axisymétrique et on adapte l'espace de travail en conséquence if ((i==1) && (idmail==1)) { if (TestEnum_geom_axisymetrique(id_geom)) ParaGlob::Change_en_AxiSymetrie(); } else {// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie())) {cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail << " nom= " << nomDuMaillage; if (ParaGlob::AxiSymetrie()) cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)" << " et l'element lu est axisymetrique !! "; else cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)" << " et l'element lu n'est pas axisymetrique !! "; cout << endl; Sortie (1); }; }; } } else { if (ParaGlob::NiveauImpression() >= 6) cout << " cas de la lecture d'un maillage SANS elements " << endl; // cas sans element }; // -------------- lecture des references se rapportant aux elements --------- // ou aux arête ou aux faces et meme eventuellement à des noeuds if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references apres les elements " << endl ; entreePrinc->NouvelleDonnee(); lesRef.NbMaille(idmail); // indic le numéro de maillage aux références lesRef.Indic("rien_actuellement"); // indic que les prochaines references seront // a déterminer en fonction du nom de la référence lesRef.Lecture(*entreePrinc); // -------------- ajout de références globales --------------------- // ---- création de la référence de tous les éléments si elle n'existe pas déjà string etout("E_tout"); if (!lesRef.Existe(etout,idmail) && (nbElement != 0)) { // on construit le tableau des numéros des éléments Tableau tabE(nbElement); for (int i=1;i<=nbElement;i++) tabE(i)=i; ReferenceNE* retout = new ReferenceNE(tabE,idmail,2,etout);// construction de la référence lesRef.Ajout_reference(retout); // ajout de la ref, qui est maintenant géré par lesRef }; // ---- dans tous les cas on ajoute la référence de tous les noeuds dans le cas où elle n'existe pas string ntout("N_tout"); if (!lesRef.Existe(ntout,idmail)) { // on construit le tableau des numéros de noeuds Tableau tabN(nbNoeud); for (int i=1;i<=nbNoeud;i++) tabN(i)=i; ReferenceNE* rtout = new ReferenceNE(tabN,idmail,1,ntout);// construction de la référence lesRef.Ajout_reference(rtout); // ajout de la ref, qui est maintenant géré par lesRef }; if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture de maillage " << endl; // ----- on s'occupe maintenant de définir les types de pb gérés ------ Mise_a_jour_type_pb_type_associe_ddl(); }; // lecture et application des opérations d'affinages sur le maillage: ex:déplacement solide void Maillage::LectureEtApplicationAffinage(UtilLecture * entreePrinc,LesReferences& lesRef) { if (ParaGlob::NiveauImpression() >= 5) cout << " lecture affinage maillage " << endl; while ( (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL) || (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL) || (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL) || (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL) || (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL) || (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL) || (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL) || (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL) ) { // -------------- lecture éventuelle et application de mouvements rigides ------------------ Lecture_des_mouvements_solides(entreePrinc); // --------------- suppression éventuelle des noeuds, non référencés par les éléments ------ LectureEtSuppressionNoeudNonReferencer(entreePrinc,lesRef); // --------------- création éventuelle d'une référence sur les noeuds, non référencés par les éléments ------ LectureEtCreationRefNoeudNonReferencer(entreePrinc,lesRef); // --------------- éventuellement collapse de noeuds proches ------------------------ LectureEtCollapse_noeuds_proches(entreePrinc,&lesRef); // --------------- éventuellement collapse d'éléments supperposés ------------------- LectureEtCollapse_element_superpose(entreePrinc,&lesRef); // -------------- éventuellement suppression d'elements à 2 noeuds, de distances très proches LectureEtSup_Elem_noeudsConfondu(entreePrinc,&lesRef); //---------------- création automatique des références globales de frontière si demandé ---------- CreationRefFrontiere(entreePrinc,lesRef); //----- debug //{ // on écrit la connection de l'élément 55 // Element* el = tab_element(55); // const Tableau& tabi = el->Tab_noeud_const(); // cout << "\n *** connection de l'element 55: avant renumerotation "; // for (int i=1;i<=tabi.Taille();i++) cout << " "<Num_noeud(); // cout << " Maillage::LectureMaillage () " << endl; //} //---fin debug // --------------- renumérotation éventuelle des noeuds ------------------------------------ LectureEtRenumerotation(entreePrinc,lesRef); ////----- debug //{ // on écrit la connection de l'élément 55 // Element* el = tab_element(55); // const Tableau& tabi = el->Tab_noeud_const(); // cout << "\n *** connection de l'element 55: après renumerotation "; // for (int i=1;i<=tabi.Taille();i++) cout << " "<Num_noeud(); // cout << " Maillage::LectureMaillage () " << endl; // Sortie(1); //} ////---fin debug }; // ----------------- 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 VerifReference(lesRef); if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture affinage maillage " << endl; }; // affichage et definition interactive des commandes // cas = 1: interactif complet // cas = 2: entrée uniquement de noms de fichier // cas = 3: entrée uniquement de l'affinage void Maillage::Info_commande_Maillages(UtilLecture * entreePrinc,LesReferences& lesRef, int cas) { ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier string rep="o"; if (cas == 2) { cout << "\n# voulez-vous inclure un fichier ou continuer sur un exemple (rep o ou ? ou f) ? "; rep = lect_return_defaut(false,"f"); }; if (((rep == "o") || (rep == "O") ||(rep == "0")) && (cas != 3)) { cout << "\n non du fichier .her (sans l'extension .her) a inclure ? "; rep = lect_chaine(); sort << "\n\n # -- def maillage "; sort << "\n < " << (rep+".her") ; cout << "\n un fichier .lis a inclure ? (o ou n (defaut)) "; rep = lect_return_defaut(false,"n"); if (rep == "o") { cout << "\n non du fichier .lis (sans l'extension .lis) a inclure ? "; rep = lect_chaine(); sort << "\n < " << (rep+".lis") ; }; } else if ((rep == "?") && (cas != 3)) { // sinon on continue sur un exemple de maillage sort << "\n # -- defintion du nom du maillage (facultatif pour le premier maillage " << "\n # -- qui s'appel par defaut : premier_maillage)" << "\n" << "\n nom_maillage plaque_troue # exemple de nom de maillage" << "\n noeuds ------------ # definition des noeuds"; //------------- definition des noeuds ------------- int dimen = ParaGlob::Dimension(); #ifdef SYSTEM_MAC_OS_CARBON int nbNoeud = pow(3,dimen); // nombre de noeud de l'exemple #else int nbNoeud = ((int)pow((float)3,(int)dimen)); // nombre de noeud de l'exemple #endif sort << "\n "<< nbNoeud << " NOEUDS # definition du nombre de noeud" << "\n \n" << "\n#---------------------------------------------------------------" << "\n#|NO DU| X | Y | Z |" << "\n#|NOEUD| | | |" << "\n#---------------------------------------------------------------"; Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud // définition d'une grille générique de noeuds qui permettra de définir les éléments générique Tableau tab_coo(nbNoeud); switch (dimen) { case 1: { for (int i=1;i<=3;i++) tab_coo(i) = new Coordonnee((double) i); break;} case 2: { int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++,l++) tab_coo(l) = new Coordonnee((double) i,(double) j); break;} case 3: { int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++) for (int k=1;k<=3;k++,l++) tab_coo(l) = new Coordonnee((double) i,(double) j,(double) k); break;} }; // def des noeuds Noeud * ptr; for (int i=1; i<= nbNoeud; i++) { ptr = new Noeud(i,dimension,1); // et attribution du numero de maillage // def du noeud ptr->Info_commande_Noeud(entreePrinc,*tab_coo(i),i); Affectation_noeud(*ptr); }; // -------------- def d'exemples de references se rapportant aux noeuds --------- sort << "\n# --- reference de noeuds ce trouvant apres la definition des noeuds ---" << "\n# ( il est possible aussi de definir des references de noeud apres " << "\n# la definition des elements) " << "\n# NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres \n"; lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds lesRef.NbMaille(idmail); // indic le numéro de maillage aux références lesRef.Info_commande_lesRef(nbNoeud,0,entreePrinc,1); // def d'exemple des divers refs de noeuds // ------------ def d'exemple d'elements ----------- int nbElement = 0; // nombre d'element bool choix_valide=false; // affichage des types d'élément actuellement disponible selon la dimension // creation d'un tableau d'éléments Tableau tab_el = Element::Info_commande_Element(entreePrinc); int nbele = tab_el.Taille(); Tableau chooi(nbele,false); // tableau de travail cout << "\n Donner le type d'element que vous souhaitez utiliser: ? "; string rep;int num; while (!choix_valide) { try { // affichage des éléments possibles // on balaie le tableau des elements enregistre int undeux=0; cout << "\n (0) fin \n"; for (int i=1;i<=nbele;i++) { cout << " (" << i << ") " << tab_el(i)->Geometrie() <<" "<< tab_el(i)->Interpolation() <<" "; undeux++; if (undeux==2) {cout << "\n";undeux=0;} }; rep = lect_return_defaut(false,"0"); if (rep == "fin_prog") Sortie(1); num = ChangeEntier(rep); choix_valide=false; if (num == 0) { choix_valide=true;} else // sinon { if ((num > 0)&&(num<=nbele)) {if (chooi(num)) cout << "\n type d'element deja choisit, recommencer"; else chooi(num) = true; } else { cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, " << "\n redonnez une bonne valeur" << "\n ou taper fin_prog pour arreter le programme"; } } } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur { ErrSortieFinale toto; throw (toto); } catch (...)//(UtilLecture::ErrNouvelleDonnee erreur) { cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, " << "\n redonnez une bonne valeur" << "\n ou taper fin_prog pour arreter le programme"; choix_valide=false; } } //-- fin du while // on definit le maillage d'essai // 1- def du nombre d'élément int ielmax=0; for (int ie=1;ie<=nbele;ie++) if (chooi(ie)) ielmax++; Change_nb_element(ielmax); // 2- remplissage du tableau d'élément int iel=1; for (int ie=1;ie<=nbele;ie++) if (chooi(ie)) {tab_element(iel)=tab_el(ie); tab_element(iel)->Change_num_elt(iel); tab_el(ie)=NULL; iel++; } // on affiche les éléments sort << "\n # les elements \n" << "\n elements ----------"; sort << "\n " << ielmax << " ELEMENTS"; sort << "\n #----------------------------------------------------------------------"; sort << "\n #| NO | | |"; sort << "\n #|ELTS | type element | Noeuds |"; sort << "\n #----------------------------------------------------------------------"; string ord= "commande"; Tableau * pt = & tab_noeud; for (int i=1;i<=ielmax;i++) tab_element(i)->Info_com_Element(entreePrinc,ord,pt); sort << "\n \n" ; // -------------- def des references se rapportant aux elements --------- // ou aux arête ou aux faces et meme eventuellement à des noeuds sort << "\n# --- reference ce trouvant apres la definition des elements ---" << "\n# NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres " << "\n# une reference d'element commence par E suivi d'une chaine de caracteres " << "\n# une reference de face commence par F et une reference d'arrete commence par A \n"; lesRef.NbMaille(idmail); // indic le numéro de maillage aux références lesRef.Info_commande_lesRef(nbNoeud,ielmax,entreePrinc,2); // def d'exemple des divers refs de noeuds // effacement des éléments qui ne servent plus for (int i=1;i<=ielmax;i++) if (tab_el(i) != NULL) delete tab_el(i); }; // fin de l'exemple de maillage // ---------- définition des affinages éventuelles ---------- // while ( (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL) // || (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL) // || (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL) // || (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL) // || (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL) // || (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL) // || (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL) // || (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL) //On va proposer un menu while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { try { cout << "\n (0 ou f defaut) (fin) " << "\n (1) mouvement solide " << "\n (2) suppression des noeuds non reference " << "\n (3) collapse de noeuds proches " << "\n (4) collapse d'elements superposes " << "\n (5) creation de references frontieres " << "\n (6) renumerotation " << "\n (7) creation d'une ref sur les noeuds non references " << "\n (8) suppression des petits elements a 2 ou 3 noeuds 2D " << "\n (9 ou ? ) informations " << "\n "; rep = lect_return_defaut(false,"f"); if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe break; int num = ChangeEntier(rep); if (Minuscules(rep) == "?") num = 9; bool choix_valide=false; if ((num >= 0)&&(num<=9)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 9 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; } switch (num) { case 0: // sortie { break;} // normalement cela a déjà été filtré avant case 1: // mouvement solide { MvtSolide mvt; // un mouvement par défaut sort << "\n\n def_mouvement_solide_initiaux_ \n"; mvt.Info_commande_MvtSolide(sort); break;} case 2: // suppression des noeuds non reference { sort << "\n suppression_noeud_non_references_ "; break;} case 3: // collapse de noeuds proches { sort << "\n fusion_noeuds_proches_ "; cout << "\n donner la distance en dessous de laquelle on fusionne (un reel) ? "; double rayon=0.; rayon = lect_double(); cout << " valeur lue "<< rayon; sort << rayon << " "; break;} case 4: // collapse d'elements superposes { sort << "\n fusion_elements_superposes_ "; break;} case 5: // creation de references frontieres { sort << "\n def_auto_ref_frontiere_ "; break;} case 6: // creation de references frontieres { sort << "\n renumerotation_des_noeuds_ "; break;} case 7: // creation d'une ref sur les noeuds non reference { sort << "\n creation_ref_noeud_non_references_ "; break;} case 8: // suppression des petits elements a 2 ou 3 noeuds 2D { sort << "\n suppression_elements_2noeuds_tres_proches_ "; cout << "\n donner la distance entre deux noeuds de l'element en dessous de laquelle on supprime (un reel) ? "; double rayon=0.; rayon = lect_double(); cout << " valeur lue "<< rayon; sort << rayon << " "; break;} case 9: // informations { cout << "\n en dehors de la signification intuitive des differents ordres" << " pour des informations plus precise il est preferable de se rapporter a la documentation " << " d'Herezh++, car c'est differents ordres recouvrent des procedures difficiles a " << " decrire en quelques lignes. "; break;} default: cout << "\n le cas "<::const_iterator il,ilfin=types_de_problemes.end(); // cout <<"\n types_de_problemes: " << types_de_problemes.size() ; // for (il=types_de_problemes.begin();il != ilfin;il++) // NomElemTypeProblem(*il); // }; {int tail = types_de_problemes.Taille(); cout <<"\n types_de_problemes: " << tail ; for (int i=1;i<=tail;i++) cout << " "<< NomElemTypeProblem(types_de_problemes(i)); }; // // les ddl associés // {list ::const_iterator il,ilfin=ddl_representatifs_des_physiques.end(); // cout <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size(); // for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++) // Nom_ddl(*il); // }; {int tail = ddl_representatifs_des_physiques.Taille(); cout <<"\n type_de_ddl_associes: " << tail; for (int i=1;i<=tail;i++) cout << " "<< Nom_ddl(ddl_representatifs_des_physiques(i)); }; // cout << "Nombre de degres de liberte : " << Nombre_ddl() << "\n"; cout << "Nombre de noeuds : " << Nombre_noeud() << "\n"; cout << "Nombre d'elements : " << Nombre_element() << "\n\n"; for (int i=1;i<=Nombre_noeud();i++) // boucle sur les noeuds { cout << "\nNoeud " << i << " :\n"; tab_noeud(i)->Affiche(); }; cout << "\n"; for (int i=1;i<=Nombre_element();i++) // boucle sur les elements { cout << "\nElement " << i << " :\n"; tab_element(i)->Affiche(ParaGlob::NiveauImpression()); }; cout << "\n"; // renseignement concernant les frontières int nbmaxiElement = (int) listFrontiere.size(); cout << "nombre d'element frontiere : " << nbmaxiElement; cout << "liste : \n"; LaLIST ::const_iterator ip;int ne; for (ne=1,ip = listFrontiere.begin();ip != listFrontiere.end(); ip++,ne++) { // écriture de l'élément courant cout << ne << " " ; // le numéro const ElemGeomC0 & geom = (*ip).Eleme()->ElementGeometrique(); cout << Nom_geom(geom.TypeGeometrie()) << " " ; // la géométrie cout << Nom_interpol(geom.TypeInterpolation()) << " " ; // l'interpolation // les noeuds Tableau tabnoeud = (*ip).Eleme()->TabNoeud(); int taille = tabnoeud.Taille(); for (int ine = 1; ine<=taille; ine++) cout << tabnoeud(ine)->Num_noeud() << " "; cout << "\n"; }; // la liste des noeuds de la frontières, on ne sort que les numéros cout << " \n liste des numeros de noeud de la frontiere"; int taal = tab_noeud_front.Taille(); for (int i=1;i<= taal;i++) cout << tab_noeud_front(i)->Num_noeud() << " "; cout << "\n"; }; /*void Maillage::Affiche (char* nom_fichier) // Affiche les donnees du maillage dans le fichier nom_fichier // au format du fichier d'entree ".her" { FILE* fichier; // ouverture du fichier nom_fichier if ( (fichier=fopen(nom_fichier,"w"))==NULL ) { cout << "ERREUR D'OUVERTURE DU FICHIER :"; cout << nom_fichier << "\n"; Sortie(1); }; fprintf(fichier,"\n nom_maillage ",nomDuMaillage.c_str()); fprintf(fichier,"\n\nnoeuds --------\n\n"); fprintf(fichier,"\t\t%d NOEUDS\n\n",Nombre_noeud()); // affichage des noeuds : switch (dimension) { case 1 : // cas unidimensionnel for (int i=1;i<=Nombre_noeud();i++) { fprintf(fichier,"\t%d\t%lf\n",Noeud_mail(i).Num_noeud(), Noeud_mail(i).Coord0()(1)); }; break; case 2 : // cas bidimensionnel for (int i=1;i<=Nombre_noeud();i++) { fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud()); fprintf(fichier,"%lf\t%lf\n",Noeud_mail(i).Coord0()(1), Noeud_mail(i).Coord0()(2)); }; break; case 3 : // cas tridimensionnel for (int i=1;i<=Nombre_noeud();i++) { fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud()); fprintf(fichier,"%lf\t%lf\t%lf\n",Noeud_mail(i).Coord0()(1), Noeud_mail(i).Coord0()(2),Noeud_mail(i).Coord0()(3)); }; break; default : cout << "Erreur de dimension\n"; cout << "MAILLAGE::AFFICHE(char* ) \n"; Sortie(1); }; fprintf(fichier,"\n\nelements --------\n\n"); fprintf(fichier,"\t\t%d ELEMENTS\n\n",Nombre_element()); // affichage des elements for (int i=1;i<=Nombre_element();i++) { fprintf(fichier,"\t%d\t",Element_mail(i).Num_elt()); fprintf(fichier,"%s\t%s\t\t",Element_mail(i).Geometrie(), Element_mail(i).Interpolation()); for (int j=1;j<=Element_mail(i).Nombre_noeud();j++) fprintf(fichier,"%d\t",Element_mail(i).Num_noeud(j)); fprintf(fichier,"\n"); }; fprintf(fichier,"\n\n"); }; */ Maillage& Maillage::operator= (Maillage& mail) // Surcharge de l'operateur = : realise l'egalite entre deux maillages // cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut // ensuite les définir { dimension=mail.dimension; //nomDuMaillage = mail.nomDuMaillage; tab_noeud=mail.tab_noeud; tab_element=mail.tab_element; listFrontiere=mail.listFrontiere; tab_noeud_front = mail.tab_noeud_front; ddl_representatifs_des_physiques = mail.ddl_representatifs_des_physiques; types_de_problemes = mail.types_de_problemes; return (*this); }; // test si toutes les informations des maillages sont completes // = true -> complet // = false -> incomplet bool Maillage::Complet() { bool res = true; int tab_noeudTaille = tab_noeud.Taille(); for ( int i=1; i<= tab_noeudTaille;i++) { // res = res && tab_noeud(i)->TestComplet(); if(!(tab_noeud(i)->TestComplet())) { cout << " \n pb au niveau du test du noeud " << tab_noeud(i)->Num_noeud(); res = false; }; }; int tab_elemTaille = tab_element.Taille(); for ( int i=1; i<= tab_elemTaille;i++) {//res = res && tab_element(i)->TestComplet(); if(!(tab_element(i)->TestComplet())) {cout << "\n pb au niveau du test de l'element " << tab_element(i)->Num_elt(); res = false; }; }; // les parties frontières ne sont pas obligatoires return res; }; // ramene la demi largeur de bande en ddl et la largeur de bande void Maillage::Largeur_Bande(int& demi, int& total,const Nb_assemb& casAss) { demi = 0; int nb_ass = casAss.n; int tab_elemTaille = tab_element.Taille(); for (int ne=1;ne<=tab_elemTaille;ne++) {int tab_eleNbNoeud = tab_element(ne)->Nombre_noeud(); for (int noe=1; noe<= tab_eleNbNoeud;noe++) // bug, voic remarque qui suit for ( int no=noe+1; no<=tab_eleNbNoeud;no++) // l'idée est bonne de commencer à noe+1, mais en fait lorsque l'on a un seul noeud, cela conduit // a avoir une largeur de bande nulle, donc il faut commencer à noe, et dans ce cas c'est ok // mais pour les éléments avec plus d'un noeud, on a une boucle supp for ( int no=noe; no<=tab_eleNbNoeud;no++) { Noeud & nne = tab_element(ne)->Noeud_elt(noe); Noeud & nno = tab_element(ne)->Noeud_elt(no); int di; if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass)) di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass) + nne.NB_ddl_actif_casAssemb(nb_ass); else di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass) + nno.NB_ddl_actif_casAssemb(nb_ass); if ( di > demi) demi = di; }; }; total = demi * 2 -1; demi = demi; }; // 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 Maillage::Tous_Xi_fixes(const Nb_assemb& casAss) const { int retour = 1; int nb_ass = casAss.n; // on va parcourir les noeuds int tab_noeud_taille= tab_noeud.Taille(); int dim = ParaGlob::Dimension(); switch(dim) {case 3: {for (int i=1;i<=tab_noeud_taille;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (!( noe.Ddl_fixe(X3) && noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1))) {retour=0; break;}; }; break; } case 2: {for (int i=1;i<=tab_noeud_taille;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (!( noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1))) {retour=0; break;}; }; break; } case 1: {for (int i=1;i<=tab_noeud_taille;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (!( noe.Ddl_fixe(X1))) {retour=0; break;}; }; break; } }; // --- idem mais plus long a priori car contient un switch // for (int i=1;i<=tab_noeud_taille;i++) // { Noeud& noe = *tab_noeud(i); // pour simplifier // switch(dim) // {case 3: if (!(noe.Ddl_fixe(X3))) {retour=0; break;}; // case 2: if (!(noe.Ddl_fixe(X2))) {retour=0; break;}; // case 1: if (!(noe.Ddl_fixe(X1))) {retour=0; break;}; // }; // if (!retour) break; // }; return retour; }; // création pour chaque noeud de la liste des éléments qui contiennent le noeud void Maillage::Calcul_indice() { // création du tableau indice : pour chaque noeud on regarde quel élément contiend ce noeud /// les 3/ sont pour la version vector qui marche bien aussi /// vector > indice(tab_noeud.Taille()); int tab_noeud_taille= tab_noeud.Taille(); indice.Change_taille(tab_noeud_taille); // au cas où le tableau existait auparavant on initialise les éléments du tableau for (int i=1;i<= tab_noeud_taille;i++) indice(i).clear(); // maintenant on passe en revue les éléments int tabelTaille = tab_element.Taille(); // indice(i) contiend les numéros d'élément contenant le noeud i for (int i22 = 1; i22 <= tabelTaille; i22++) { Element * elem1 = tab_element(i22); // recup de l'element // récup de son tableau de noeud Tableau& tabn = elem1->Tab_noeud(); int tabntaille = tabn.Taille(); for (int ij=1;ij<= tabntaille;ij++) {// on balaie ses noeuds /// indice[(tabn(ij)->Num_noeud())-1].push_back(elem1); indice((tabn(ij)->Num_noeud())).push_back(elem1); }; }; // on supprime les doublons for (int i=1;i<=tab_noeud_taille;i++) { list& intertab = indice(i); // pour allèger l'écriture intertab.sort(); // on ordonne intertab.unique(); // on supprime les doublons /*//-- debug //{cout << "\n noeud " << i << " taille indice(i) " << intertab.size() ; // list::iterator ina,infin; // infin = intertab.end(); // for (ina = intertab.begin();ina!=infin;ina++) // {Element * elem2 = *ina; // recup de l'element // cout << " element " << elem2->Num_elt() << " "; // }; // cout << "\n"; // }; //-- debug //{cout << "\n debug ** Maillage::Calcul_indice() "; // int numnoeud = 104; // list& intertab = indice(numnoeud); // list::iterator ina,infin; // infin = intertab.end(); // for (ina = intertab.begin();ina!=infin;ina++) // {Element * elem2 = *ina; // recup de l'element // cout << " element-- " << elem2->Num_elt() << " "; // }; // cout << "\n"< calcul des normales à t=0 // et ajout conteneur aux noeuds des normales à t = 0 et t void Maillage::InitNormaleAuxNoeuds() { // on va parcourir les noeuds et on n'intervient que si le noeud // appartient à un élément 1D et/ou 2D int nbNoeud = tab_noeud.Taille(); int borne_max_nbNoeud = nbNoeud+1; Coordonnee coor_inter; // coordonnée de travail Coordonnee premiere_normale;// idem for (int ine =1; ine < borne_max_nbNoeud;ine++ ) {// on regarde si le conteneur de la normale existe au noeud // et création éventuelle Noeud & noe = *tab_noeud(ine); // pour simplifier if (!noe.Existe_ici(NN_SURF_t0)) { Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant TypeQuelconque typQ4(NN_SURF_t0,EPS11,grandCoordonnee); noe.AjoutUnTypeQuelconque(typQ4); }; // on fait la même chose à t ce qui évitera de tester à la mise à jour if (!noe.Existe_ici(NN_SURF_t)) { Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant TypeQuelconque typQ4(NN_SURF_t,EPS11,grandCoordonnee); noe.AjoutUnTypeQuelconque(typQ4); }; // et on le récupère après création éventuelle TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t0); Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee())); Coordonnee& normale = *gr.ConteneurCoordonnee(); normale.Zero(); // init // calcul éventuel du tableau Indice this->Indice(); List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud List_io < Element*>::iterator il,ilfin = li_elem.end(); // on balaie les éléments int nb_normale=0; // le nombre de normales trouvées for (il = li_elem.begin(); il != ilfin; il++) {Element& elem = *(*il); Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); // if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces {int cas = elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter); if (cas == 0) {cout << "\n *** erreur, le calcul de la normale n'est pas possible " << " pour le noeud "<Num_noeud() << " du maillage " << tab_noeud(ine)->Num_Mail() << " par rapport a l'element "<< elem.Num_elt() << " du maillage " << elem.Num_maillage() << "\n Maillage::MiseAjourNormaleAuxNoeuds() "; Sortie(1); } else if (cas == 2) {// le calcul n'est pas licite, mais ce n'est pas une erreur // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien } else // sinon c'est ok {// on peut avoir des directions très proches mais de sens inverse ... ce qui va // conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire // s'il est négatif on utilise l'inverse de la normale // donc en définitif on gardera globalement la direction précédente if ((normale * coor_inter) > 0.) {normale += coor_inter;} else {normale -= coor_inter;}; nb_normale++; }; }; }; if (nb_normale != 0) {normale /= nb_normale; // enfin on normalise la normale ////------ debug //if (normale.Norme() == 0.) // { // for (il = li_elem.begin(); il != ilfin; il++) // {Element& elem = *(*il); // Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); // // if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) // if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces // {elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter); // if (coor_inter.Dimension() == 0) // {cout << "\n *** erreur, le calcul de la normale n'est pas possible " // << " pour le noeud "<Num_noeud() // << " du maillage " << tab_noeud(ine)->Num_Mail() // << " par rapport a l'element "<< elem.Num_elt() // << " du maillage " << elem.Num_maillage() // << "\n Maillage::MiseAjourNormaleAuxNoeuds() "; // Sortie(1); // } // else // sinon c'est ok // {normale += coor_inter; // nb_normale++; // }; // }; // }; // // } // //// end debug normale.Normer(); // ce qui fini la mise à jour de la normale au noeud }; }; }; // 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. // mise à jour -> mise à jour des normales à t void Maillage::MiseAjourNormaleAuxNoeuds() { // on va parcourir les noeuds et on n'intervient que si le noeud // appartient à un élément 1D et/ou 2D int nbNoeud = tab_noeud.Taille(); int borne_max_nbNoeud = nbNoeud+1; Coordonnee coor_inter; // coordonnée de travail for (int ine =1; ine < borne_max_nbNoeud;ine++ ) {Noeud & noe = *tab_noeud(ine); // pour simplifier // on récupère la normale au noeud TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t); Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee())); Coordonnee& normale = *gr.ConteneurCoordonnee(); normale.Zero(); // init // calcul éventuel du tableau Indice this->Indice(); List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud List_io < Element*>::iterator il,ilfin = li_elem.end(); // on balaie les éléments int nb_normale=0; // le nombre de normales trouvées for (il = li_elem.begin(); il != ilfin; il++) {Element& elem = *(*il); Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); // if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces {int cas = elem.CalculNormale_noeud(TEMPS_t,*tab_noeud(ine),coor_inter); if (cas == 0) {cout << "\n *** erreur, le calcul de la normale n'est pas possible " << " pour le noeud "<Num_noeud() << " du maillage " << tab_noeud(ine)->Num_Mail() << " par rapport a l'element "<< elem.Num_elt() << " du maillage " << elem.Num_maillage() << "\n Maillage::MiseAjourNormaleAuxNoeuds() "; Sortie(1); } else if (cas == 2) {// le calcul n'est pas licite, mais ce n'est pas une erreur // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien } else // sinon c'est ok {normale += coor_inter; nb_normale++; }; }; }; if (nb_normale != 0) {normale /= nb_normale; // enfin on normalise la normale normale.Normer(); }; // ce qui fini la mise à jour de la normale au noeud }; }; // 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 Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T() { // on va parcourir les noeuds et on n'intervient que si le noeud // appartient à un élément 1D et/ou 2D int nbNoeud = tab_noeud.Taille(); int borne_max_nbNoeud = nbNoeud+1; Coordonnee coor_inter; // coordonnée de travail for (int ine =1; ine < borne_max_nbNoeud;ine++ ) {Noeud & noe = *tab_noeud(ine); // pour simplifier // on récupère la normale au noeud TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t); Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee())); Coordonnee& normale = *gr.ConteneurCoordonnee(); normale.Zero(); // init // calcul éventuel du tableau Indice this->Indice(); List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud List_io < Element*>::iterator il,ilfin = li_elem.end(); // on balaie les éléments int nb_normale=0; // le nombre de normales trouvées for (il = li_elem.begin(); il != ilfin; il++) {Element& elem = *(*il); Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); // if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces {// ici contrairement à la méthode: MiseAjourNormaleAuxNoeuds // on demande à l'élément de calculer la normale avec la géométrie à tdt int cas = elem.CalculNormale_noeud(TEMPS_tdt,*tab_noeud(ine),coor_inter); if (cas == 0) {cout << "\n *** erreur, le calcul de la normale n'est pas possible " << " pour le noeud "<Num_noeud() << " du maillage " << tab_noeud(ine)->Num_Mail() << " par rapport a l'element "<< elem.Num_elt() << " du maillage " << elem.Num_maillage() << "\n Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T() "; Sortie(1); } else if (cas == 2) {// le calcul n'est pas licite, mais ce n'est pas une erreur // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien } else // sinon c'est ok {normale += coor_inter; nb_normale++; }; }; }; if (nb_normale != 0) {normale /= nb_normale; // enfin on normalise la normale normale.Normer(); }; // ce qui fini la mise à jour de la normale au noeud }; }; // creation des elements frontiere void Maillage::CreeElemFront() { // 0- on supprime la liste existante listFrontiere.erase(listFrontiere.begin(),listFrontiere.end()); // 1- tout d'abord on crée les éléments frontière dans chaque élément int tabelTaille = tab_element.Taille(); // on boucle sur les elements for (int i2 = 1; i2 <= tabelTaille; i2++) // création des éléments frontières (on force) tab_element(i2)->Frontiere(true); // 2- maintenant on va créé des tableaux permettant d'accélérer l'algorithme final // pour chaque noeud on regarde quel élément contiend ce noeud Calcul_indice(); int tab_noeud_taille= tab_noeud.Taille(); // indice contiend les numéros d'élément succeptible d'avoir des frontières // communes // 3- maintenant on va de nouveau boucler sur les éléments en regardant // pour chaque frontière si elle est effectivement recevable c-a-d si // il n'y a pas deux frontières identiques Front lili; // un element de référence de frontière courant // for (int i1 = 1; i1 <= tabelTaille-1; ++i1) for (int i1 = 1; i1 <= tabelTaille; i1++) {Element * elem1 = tab_element(i1); // recup de l'element const Tableau & tab1 = elem1->Frontiere(); // et de ses frontières int tab1Taille = tab1.Taille(); // frontières //-- debug //cout << "\n elem1 " << elem1->Num_elt() << " "; //--fin debug // on boucle sur les frontière, qui doivent être repérée par un pointeur non nulle for (int j1=1;j1<= tab1Taille;j1++) // on essaie de voir si l'élément j1 est recevable, c-a-d pointeur non nulle // sinon cela veut dire que la frontière a été supprimer car en double {ElFrontiere * elfr = tab1(j1); // pour simplifier // on ne continu que si le pointeur est non nul if (elfr != NULL) { bool res = false; // si deux éléments frontières sont identiques alors tous leurs noeuds // sont identiques. En particulier le premier noeud de *elfr est commum // avec tous les éléments succeptibles de contenir un élément frontière // identique. On va donc utiliser la liste indice qui contiend cette liste int numnoeud = (elfr->TabNoeud())(1)->Num_noeud(); /// vector::iterator ina,infin; /// vector& intertab = indice[numnoeud-1]; // pour allèger l'écriture list::iterator ina,infin; list& intertab = indice(numnoeud); // pour allèger l'écriture infin = intertab.end(); // on balaie les élément succeptibles d'avoir des frontières communes for (ina = intertab.begin();ina!=infin;ina++) {Element * elem2 = *ina; // recup de l'element //-- debug //cout << " intertab.size() = " << intertab.size(); //cout << ", elem2 " << elem2->Num_elt() << " "; //--fin debug // on ne fait la recherche que pour les éléments différents de elem1 bool res_ina = false; // init d'un indicateur interne à la boucle j2 qui suit, if (elem2 != elem1) { //------- debug //cout << "\n debug ** Maillage::CreeElemFront() "; //elem2->Affiche(); cout << endl; //---- fin debug const Tableau & tab2 = elem2->Frontiere(); // et des éléments int tab2Taille = tab2.Taille(); // frontières for (int j2=1;j2<= tab2Taille;++j2) { // dans le cas où l'élément frontière existe, c'est-à-dire // qu'il n'a pas été supprimé par un précédent passage // on le compare ElFrontiere* tab2j2 = tab2(j2); // pour simplifier if (tab2j2 != NULL) {ElFrontiere* p = tab2j2->Oppose(); // variable transitoire if ((*elfr) == (*p)) // on a trouve un element qui annule { res = res_ina = true;// on met l'indicateur // suppression de l'élément dans la liste elem2->SupprimeFront(tab2j2); }; delete p; // suppression de l'element p transitoire } // si il y a eu suppression de l'élément frontière on sort de la boucle if (res_ina) break; // on sort de la boucle si pas élément de frontière }; // si l'on a détecté une égalité on arrète également cette boucle // après avoir supprimé l'élément frontière // non, car on pourrait avoir une frontière qui soit commune à plus de 2 éléments // pour l'instant ce n'est pas le cas, mais par exemple des arrêtes pour les volumes ?? // if (res) // { elem1->SupprimeFront(elfr); // elfr=NULL; // break; // } }; }; // en sortie on sauvegarde uniquement si c'est un élément frontière if (!res) {// lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1; int num_dans_le_type = elem1->Num_de_frontiere_dans_le_type(j1); listFrontiere.push_back(Front(*elfr,elem1,num_dans_le_type)); } else // sinon la frontière est commune avec au moins une autre, on l'a supprime { elem1->SupprimeFront(elfr); }; }; // fin du test if (elfr != NULL) }; // fin de la boucle sur les frontières de elem1 }// fin de la boucle externe des éléments /* // cas du dernier élément, ses éléments frontières non nuls sont forcément bons non finalement, cela semble poser des pb sur le dernier élément vu que l'on a mis une procédure d'accélération pour le calcul des frontières donc on met en stand by pour l'instant, si pas de pb qui apparaissent on supprime { Element * elem1 = tab_element(tabelTaille); // recup de l'element const Tableau & tab1 = elem1->Frontiere(); // et des éléments int tab1Taille = tab1.Taille(); // frontières for (int j1=1;j1<= tab1Taille;++j1) // on essaie de voir si l'élément j1 est recevable { ElFrontiere * elfr = tab1(j1); // pour simplifier if (elfr != NULL) {//lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1; listFrontiere.push_back(Front(elfr,elem1)); } } } */ //Sortie(1); // effacement du contenu du tableau indice indice.Libere (); //// ---- debug ----- // vérification que l'on a bien les frontières bien connectées // cout << " \n debug: Maillage::CreeElemFront()"; //{ LaLIST ::iterator iF; // LaLIST ::iterator iFfin = listFrontiere.end(); // cout << "\n liste des frontières: \n "; // for (iF = listFrontiere.begin();iF!=iFfin; iF++) // { Front* elfront = &(*iF); // Enum_type_geom type_front; // va être modifier par Num_frontiere // cout << " frontière: " << elfront->Num_frontiere() << " " << elfront->Eleme()->Type_geom_front() // << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage " // << elfront->PtEI()->Num_maillage() << " \n "; // }; //}; // // vérif particulière (a commenter !) //{ LaLIST ::iterator iF; // LaLIST ::iterator iFfin = listFrontiere.end(); // int nbf = 1; // for (iF = listFrontiere.begin();iF!=iFfin; iF++) // { Front* fro = &(*iF); // ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière // // récup de son tableau de noeud // Tableau& tabn = efem1->TabNoeud(); // int tabntaille = tabn.Taille(); // if (fro->PtEI()->Id_geometrie() == HEXAEDRE) // {cout << "nbf= " << nbf << ", ele= " << fro->PtEI()->Num_elt() << " : "; // for (int ij=1;ij<= tabntaille;ij++) // // on balaie ses noeuds // cout << tabn(ij)->Num_noeud() << " "; // cout << endl ; // nbf++; // }; // }; // //} // //// ---- fin debug ----- // definition des elements mitoyens aux elements de frontiere MitoyenFront(); // ==== définition du tableau des noeuds frontières ===== // 1) on définit un tableau de numéro de noeuds qui sont utilisés Tableau t_noe(tab_noeud_taille,0); // tous les éléments sont nul // 2) on balaie les éléments frontières LaLIST ::iterator li,li_end=listFrontiere.end(); for (li=listFrontiere.begin();li!=li_end;li++) { Tableau & tt = (*li).Eleme()->TabNoeud(); int tt_taille=tt.Taille(); for (int i=1;i<=tt_taille;i++) (t_noe(tt(i)->Num_noeud()))++; }; // 3) on récupère le nombre de noeud frontière int nb_n_f=0; for (int ii=1;ii<= tab_noeud_taille;ii++) if (t_noe(ii)!=0) nb_n_f++; // 4) def du tableau final tab_noeud_front.Change_taille(nb_n_f); nb_n_f=0; // on se ressert du numéro for (int ii=1;ii<= tab_noeud_taille;ii++) {if (t_noe(ii)!=0) {nb_n_f++;tab_noeud_front(nb_n_f)=tab_noeud(ii);};}; // dans le cas où les éléments frontières sont des lignes, on les ordonnes // de manière à former une ligne continue // OrdonancementDesLigne(); }; // change le nom et le numéro du maillage void Maillage::ChangeNomNumeroMaillage(const string & nom,int num) { // on vérifie que le nom de maillage fourni n'existe pas if (listeNomMail.find(nom) != listeNomMail.end()) { cout << "\n erreur, le nom de maillage demande existe deja : " << nom << "\n Maillage::ChangeNomNumeroMaillage(....."; Sortie(1); }; // on met à jour listeNomMail en supprimant le doublet nom <=> numéro existant listeNomMail.erase(listeNomMail.find(nomDuMaillage)); nomDuMaillage = nom; // on enregistre le nouveau nom // on vérifie que le numéro de maillage proposé est valide if (num <=0) { cout << "\nErreur : numero de maillage invalide ! = "<< num <<"\n"; cout << "Maillage::ChangeNomNumeroMaillage(.... \n"; Sortie(1); }; idmail=num; // on enregistre le nouveau numéro // maintenant on peut associer le nom au numéro dans la map listeNomMail[nomDuMaillage]=idmail; }; // ramène le numéro du noeud le plus proche du point donné à t=0 int Maillage::Noeud_le_plus_proche_0(const Coordonnee& M) { // tout d'abord si le maillage n'a pas de noeud on ramène 0 int tail_mail = tab_noeud.Taille(); if (tail_mail == 0) return 0; // sinon initialisation de la recherche int num_rech = 1; // choix du premier noeud // distance avec le noeud double dist = (tab_noeud(1)->Coord0() - M).Norme(); // on boucle sur les noeuds for (int i=2;i<=tail_mail;i++) { double dista = (tab_noeud(i)->Coord0() - M).Norme(); if (dista <= dist) { dist = dista; num_rech = i;}; }; // retour return num_rech; }; // ramène le numéro du noeud le plus proche du point donné à t=t int Maillage::Noeud_le_plus_proche_t(const Coordonnee& M) { // tout d'abord si le maillage n'a pas de noeud on ramène 0 int tail_mail = tab_noeud.Taille(); if (tail_mail == 0) return 0; // sinon initialisation de la recherche int num_rech = 1; // choix du premier noeud // distance avec le noeud double dist = (tab_noeud(1)->Coord1() - M).Norme(); // on boucle sur les noeuds for (int i=2;i<=tail_mail;i++) { double dista = (tab_noeud(i)->Coord1() - M).Norme(); if (dista <= dist) { dist = dista; num_rech = i;}; }; // retour return num_rech; }; // ramène le numéro du noeud le plus proche du point donné à t=tdt int Maillage::Noeud_le_plus_proche_tdt(const Coordonnee& M) { // tout d'abord si le maillage n'a pas de noeud on ramène 0 int tail_mail = tab_noeud.Taille(); if (tail_mail == 0) return 0; // sinon initialisation de la recherche int num_rech = 1; // choix du premier noeud // distance avec le noeud double dist = (tab_noeud(1)->Coord2() - M).Norme(); // on boucle sur les noeuds for (int i=2;i<=tail_mail;i++) { double dista = (tab_noeud(i)->Coord2() - M).Norme(); if (dista <= dist) { dist = dista; num_rech = i;}; }; // retour return num_rech; }; // 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 Maillage::NBelemEtptInteg Maillage::Element_le_plus_proche (Enum_dure enu_temps,const List_io & list_enu ,const Coordonnee& M) { Maillage::NBelemEtptInteg ret; // tout d'abord si le maillage n'a pas d'élément on ramène 0 int tail_mail = tab_element.Taille();ret.nbElem=0;ret.nbPtInteg=0; if (tail_mail == 0) { return ret;} // sinon initialisation de la recherche // on boucle sur les éléments pour trouver celui qui contiend M // M peut également être sur la surface de l'élément ce qui est ok également for (int i=1;i<=tail_mail;i++) { bool trouve = false; switch (enu_temps) { case TEMPS_0 : if(tab_element(i)->Interne_0(M)) trouve = true; break; case TEMPS_t : if(tab_element(i)->Interne_t(M)) trouve = true; break; case TEMPS_tdt : if(tab_element(i)->Interne_tdt(M)) trouve = true; break; }; if(trouve) {// on a trouvé un élément on recherche le point le plus près ou est exprimé la grandeur ret.nbElem = i; List_io ::const_iterator ii,iide= list_enu.begin(); List_io ::const_iterator iifin= list_enu.end(); ret.nbPtInteg = tab_element(i)->PointLePlusPres(enu_temps,(*iide).Enum(),M); // on vérifie que tous les ddl sont disponibles au pt d'integ for (ii = iide;ii != iifin; ii++) if (!(tab_element(i)->Existe_pt_integ (ret.nbPtInteg,(*ii).Enum()))) { ret.nbPtInteg = -1; return ret;} // retour normal return ret; /* ancienne vérif, pas bonne // on vérifie que tous les ddl sont de la même famille sinon erreur for (ii = iide;ii != iifin; ii++) if (!Meme_famille((*ii).Enum(),(*iide).Enum())) { ret.nbPtInteg = -1; return ret;} // retour normal return ret; */ }; }; // retour dans le cas où l'on n'a pas trouvé d'élément ret.nbElem = 0; ret.nbPtInteg = 0; return ret; }; // 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* Maillage::Centre_de_Gravite_Element_le_plus_proche(Enum_dure enu_temps,const Coordonnee& M) { Element * el_retour=NULL; double distance = ConstMath::tresgrand; int nbelem = tab_element.Taille(); Coordonnee G(ParaGlob::Dimension()); // on balaie les éléments for (int ine = 1; ine <= nbelem; ine++) {// on commence par calculer le centre de gravité G.Zero(); Tableau taN = tab_element(ine)->Tab_noeud(); int nbn = taN.Taille(); switch (enu_temps) { case TEMPS_0: for (int inn = 1;inn<=nbn;inn++) {Noeud* noe = taN(inn); G += noe->Coord0(); }; break; case TEMPS_t: for (int inn = 1;inn<=nbn;inn++) {Noeud* noe = taN(inn); G += noe->Coord1(); }; break; case TEMPS_tdt: for (int inn = 1;inn<=nbn;inn++) {Noeud* noe = taN(inn); G += noe->Coord2(); }; break; }; G /= nbn; double new_distance = (M-G).Norme(); if (new_distance < distance) {el_retour = tab_element(ine); distance = new_distance; }; }; // retour de l'élément return el_retour; }; // ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage double Maillage::Max_var_dep_t_a_tdt() const { int nbn = tab_noeud.Taille(); double ret=0.; for (int i=1;i<=nbn;i++) ret=MaX(tab_noeud(i)->Max_var_coor_t_a_tdt(),ret); return ret; }; // ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments double Maillage::Min_dist2Noeud_des_elements(Enum_dure temps) const { double retour=ConstMath::tresgrand; // init // on balaie les éléments int taille_elem = tab_element.Taille(); for (int i=1; i<=taille_elem;i++) { const Tableau& tab_N_el = tab_element(i)->Tab_noeud(); int nbn_loc = tab_N_el.Taille(); switch (temps) { case TEMPS_0 : { for (int in = 1;in<=nbn_loc;in++) {const Coordonnee& Ci = tab_N_el(in)->Coord0(); for (int jn = in+1;jn<=nbn_loc;jn++) {const Coordonnee& Cj = tab_N_el(jn)->Coord0(); retour = MiN(retour,(Ci-Cj).Max_val_abs()); }; }; break; } case TEMPS_t : { for (int in = 1;in<=nbn_loc;in++) {const Coordonnee& Ci = tab_N_el(in)->Coord1(); for (int jn = in+1;jn<=nbn_loc;jn++) {const Coordonnee& Cj = tab_N_el(jn)->Coord1(); retour = MiN(retour,(Ci-Cj).Max_val_abs()); }; }; break; } case TEMPS_tdt : { for (int in = 1;in<=nbn_loc;in++) {const Coordonnee& Ci = tab_N_el(in)->Coord2(); for (int jn = in+1;jn<=nbn_loc;jn++) {const Coordonnee& Cj = tab_N_el(jn)->Coord2(); retour = MiN(retour,(Ci-Cj).Max_val_abs()); }; }; break; } default : cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; cout << "Maillage::Min_dist2Noeud_des_elements(... \n"; Sortie(1); }; }; return retour; }; //----- lecture écriture de base info ----- // lecture base info // = 1 : on récupère tout // = 2 : on récupère uniquement les données variables (supposées comme telles) void Maillage::Lecture_base_info(ifstream& entr,const int cas) {switch (cas) { case 1 : // ------- on récupère tout ------------------------- {// l'id et le nom du maillage et la dimension int dime; string toto; int idmail_n; string nomDuMaillage_n; entr >> toto >> idmail_n >> nomDuMaillage_n >> toto >> dime ; // les types de problèmes associés // { types_de_problemes.clear(); int nb=0; // init // entr >> toto >> nb ; string type; // for (int i=1;i<=nb;i++) // {entr >> type;types_de_problemes.push_back(Id_nom_ElemTypeProblem(type));}; // }; { int nb=0; // init entr >> toto >> nb ; string type; types_de_problemes.Change_taille(nb); for (int i=1;i<=nb;i++) {entr >> type;types_de_problemes(i)=(Id_nom_ElemTypeProblem(type));}; }; // les ddl associés // { ddl_representatifs_des_physiques.clear(); int nb=0; // init // entr >> toto >> nb ; string ddl; // for (int i=1;i<=nb;i++) // {entr >> ddl;ddl_representatifs_des_physiques.push_back(Id_nom_ddl(ddl));}; // }; { int nb=0; // init entr >> toto >> nb ; string type; ddl_representatifs_des_physiques.Change_taille(nb); for (int i=1;i<=nb;i++) {entr >> type;ddl_representatifs_des_physiques(i)=(Id_nom_ddl(type));}; }; // si le nom de maillage lu est différent de celui existant, // on supprime le doublet dans la map de gestion et on met à jour if (nomDuMaillage != nomDuMaillage_n) { listeNomMail.erase(listeNomMail.find(nomDuMaillage)); nomDuMaillage = nomDuMaillage_n; listeNomMail[nomDuMaillage] = idmail_n; idmail = idmail_n; } else { // sinon on vérifie quand même que le numéro n'a pas changé if (idmail != idmail_n) { listeNomMail[nomDuMaillage] = idmail_n; idmail = idmail_n; }; }; if (dime != dimension) cout << "\nErreur : valeur de la dimension non coherente avec " << " l'espace de travail!\n" << "Maillage::Lecture_base_info(ofstream& sort,int cas)" << endl; cout << " === lecture du maillage " << nomDuMaillage << " nb " << idmail << "\n" ; //------------- lecture des noeuds ------------- cout << " lecture des noeuds " ; // le nombre de noeud int nbNoeud = tab_noeud.Taille(); entr >> nbNoeud >> toto; // normalement ici on ne doit pas avoir déjà de noeud Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud // lecture des noeuds Noeud * ptr; for (int i=1; i<= nbNoeud; i++) { ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage ptr->Lecture_base_info(entr,cas); Affectation_noeud(*ptr); }; // ------------ les elements finis ----------- cout << ", lecture des elements \n" ; entr >> toto; // lecture du nombre d'element int nbElement; entr >> toto >> nbElement; // dimensionnement dynamique du tableau d'elements Change_nb_element(nbElement); // Lecture des elements Element * pte; for (int i=1; i<= nbElement; i++) { // lecture geometrie et interpolation Enum_geom id_geom; Enum_interpol id_interpol; EnumElemTypeProblem id_typeProb;string str_precision; int num_elt; // donnee dont on ne se sert pas entr >> toto >> num_elt >> id_geom >> id_interpol >> id_typeProb; // on regarde le prochain caractère sans changer le flot /////int cr=entr.peek(); //--- début du remplacement du peek char car = Picococar(entr); // = flot.peek(); // on recupère l'entier correspondant au caractère int cr = int(car); //--- fin du remplacement du peek // on regarde s'il y a une chaine discriminante if (cr == int('_')) entr >> str_precision; // ======== choix de l'element ===================================== // et affectation du pointeur d'element en fonction de id_geom et id_interpol // le numero d'element : num_elt, est affecte a l'element pointe par ptr pte = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision); if (pte == NULL) { // l'operation a echouee cout << "\n Erreur dans le choix d'element ****** "; cout << "\n l\'element : " << Nom_interpol(id_interpol) << " " << Nom_geom(id_geom) << " n\'est pas present dans le programme ! " << "\n Maillage::Lecture_base_info(..." << endl; Sortie (1); }; // lecture des infos particulieres a l'element Tableau * pt = & tab_noeud; pte->Lecture_base_info(entr,pt,cas); Affectation_element(*pte); // si c'est le premier élément du premier maillage on regarde s'il s'agit // d'un élément axisymétrique et on adapte l'espace de travail en conséquence if ((i==1) && (idmail==1)) { if (TestEnum_geom_axisymetrique(id_geom)) ParaGlob::Change_en_AxiSymetrie(); } else {// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie())) {cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail << " nom= " << nomDuMaillage; if (ParaGlob::AxiSymetrie()) cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)" << " et l'element lu est axisymetrique !! "; else cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)" << " et l'element lu n'est pas axisymetrique !! "; cout << endl; Sortie (1); }; }; } // ------------ les elements frontières ----------- // il sont créé par ailleurs si il y en a besoin break; } case 2 : // ----------- lecture uniquement de se qui varie -------------------- {// le nom du maillage pour vérification // cout << "\n debug **** Maillage::Lecture_base_info\n" // << "\n entr.rdstate() " << entr.rdstate() << flush; //entr.clear(); string inter,nomDuMail; entr >> inter >> nomDuMail ; //string truc; entr >> truc; // cout << "\n debug **** Maillage::Lecture_base_info\n" // << " inter=" << inter << " nomDuMaillage= " << nomDuMail // << " titi= "<< titi << " titi1= "<< titi1 // << "\n entr.rdstate() " << entr.rdstate() << flush; if (nomDuMail != nomDuMaillage) { cout << "\nErreur : le nom du maillage lu (" << nomDuMail << ") n'est pas identique avec celui en cours (" << nomDuMaillage << ") !! " << "\n Maillage::Lecture_base_info(ofstream& sort,int cas)" << endl; Sortie (1); }; //------------- les noeuds ------------- // le tableau doit être déjà dimensionné int nbNoeud = tab_noeud.Taille(); for (int i=1; i<=nbNoeud;i++) tab_noeud(i)->Lecture_base_info(entr,cas); // ------------ les elements finis ----------- int nbElement = tab_element.Taille(); Tableau * pt = & tab_noeud; int nb;string toto; for (int j=1;j<=nbElement;j++) {entr >> toto >> nb; // le numéro de l'élément tab_element(j)->Lecture_base_info(entr,pt,cas); }; // ------------ les elements frontières ----------- // il sont créé par ailleurs si il y en a besoin break; } default : { cout << "\nErreur : valeur incorrecte du type de lecture !\n"; cout << "Maillage::Lecture_base_info(ofstream& sort,int cas)" << " cas= " << cas << endl; Sortie(1); }; }; }; // écriture base info // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void Maillage::Ecriture_base_info(ofstream& sort,const int cas) {switch (cas) { case 1 : // ------- on sauvegarde tout ------------------------- {// l'id et le nom du maillage et la dimension sort << "\n num= " << idmail <<" "<< nomDuMaillage <<" " << "dim= " << dimension; // les types de problèmes associés // {list ::iterator il,ilfin=types_de_problemes.end(); // sort <<"\n types_de_problemes: " << types_de_problemes.size() ; // for (il=types_de_problemes.begin();il != ilfin;il++) // sort << NomElemTypeProblem(*il); // }; {int tail = types_de_problemes.Taille(); sort <<"\n types_de_problemes: " << tail ; for (int i=1;i<=tail;i++) sort << " "<< NomElemTypeProblem(types_de_problemes(i)); }; // les ddl associés // {list ::iterator il,ilfin=ddl_representatifs_des_physiques.end(); // sort <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size(); // for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++) // Nom_ddl(*il); // }; {int tail = ddl_representatifs_des_physiques.Taille(); sort <<"\n type_de_ddl_associes: " << tail; for (int i=1;i<=tail;i++) sort << " "<< Nom_ddl(ddl_representatifs_des_physiques(i)); }; sort <<"\n"; //------------- les noeuds ------------- // le nombre de noeud int nbNoeud = tab_noeud.Taille(); sort << nbNoeud << " noeuds \n"; // sorti des noeuds for (int i=1; i<=nbNoeud;i++) tab_noeud(i)->Ecriture_base_info(sort,cas); // ------------ les elements finis ----------- sort << "\n --les_elements-- "; // le nombre d'élément int nbElement = tab_element.Taille(); sort <<"\n nombre_d'element " << nbElement ; // écriture des éléments for (int j=1;j<=nbElement;j++) { // tout d'abord les données de différentiation // numéro geometrie et interpolation sort << "\n\n element: " << tab_element(j)->Num_elt() << " " << tab_element(j)->Id_geometrie() << " " << tab_element(j)->Interpolation() << " " << tab_element(j)->TypeProblem() << " " << tab_element(j)->Infos_annexe() << "\n"; // puis les données de l'élément tab_element(j)->Ecriture_base_info(sort,cas); }; sort << "\n "; // ------------ les elements frontières ----------- // ne sont pas sauvegardé car reconstruit à la demande break; } case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- {// le nom du maillage pour vérification en lecture sort << "\nnomDuMail= " << nomDuMaillage << "\n"; //------------- les noeuds ------------- int nbNoeud = tab_noeud.Taille(); // sorti des noeuds for (int i=1; i<=nbNoeud;i++) tab_noeud(i)->Ecriture_base_info(sort,cas); // ------------ les elements finis ----------- int nbElement = tab_element.Taille(); for (int j=1;j<=nbElement;j++) {sort << "\n\n element_nb: " << tab_element(j)->Num_elt() << " "; tab_element(j)->Ecriture_base_info(sort,cas); }; // ------------ les elements frontières ----------- // ne sont pas sauvegardé car reconstruit à la demande break; } default : { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n"; cout << "Maillage::Ecriture_base_info(ofstream& sort,int cas)" << " cas= " << cas << endl; Sortie(1); }; }; }; // ------ 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 Maillage::Taille_boiteMail() { // définition du tableau de retour Tableau tabret(2); // cas particulier de maillage vide int nbNoeud = tab_noeud.Taille(); if (nbNoeud == 0) return tabret; // sinon le cas normal tabret(1).Change_taille(dimension); tabret(2).Change_taille(dimension); // on balaie tous les coordonnées des noeuds pour déterminer les tailles // maxi et mini // dans une première étape on regarde s'il existe les coordonnées à t=0 // t et t+dt, ceci à partir du premier noeud qui sert de test // on cherche les extrémas for (int i=1; i<=nbNoeud;i++) { Coordonnee a0=tab_noeud(i)->Coord0(); for (int k=1;k<= dimension;k++) { if (tabret(1)(k) > a0(k)) tabret(1)(k) = a0(k); if (tabret(2)(k) < a0(k)) tabret(2)(k) = a0(k); } // dans le cas de coordonnées à t idem if (tab_noeud(i)->ExisteCoord1()) {Coordonnee aat=tab_noeud(i)->Coord1(); for (int k=1;k<= dimension;k++) { if (tabret(1)(k) > aat(k)) tabret(1)(k) = aat(k); if (tabret(2)(k) < aat(k)) tabret(2)(k) = aat(k); } }; // dans le cas de coordonnées à t+dt idem if (tab_noeud(i)->ExisteCoord2()) {Coordonnee aatdt=tab_noeud(i)->Coord2(); for (int k=1;k<= dimension;k++) { if (tabret(1)(k) > aatdt(k)) tabret(1)(k) = aatdt(k); if (tabret(2)(k) < aatdt(k)) tabret(2)(k) = aatdt(k); } }; } return tabret; }; //========================== fonction protegee ============================= // definition des elements mitoyens aux elements de frontiere // à la fin du programme tous les éléments mitoyens sont stocké dant les éléments front // la manip est de créer des éléments frontières aux éléments frontières existant // ensuite deux éléments sont mitoyens s'il ont la même frontière // à la fin du programme tous les frontières des éléments frontières sont supprimé void Maillage::MitoyenFront() { // le tableau indice_NFr (indice des noeuds frontières) va permettre une recherche plus rapide // on le construit: int tab_noeud_taille= tab_noeud.Taille(); Tableau > indice_NFr(tab_noeud_taille); // indice_NFr contiend les front succeptible d'avoir des frontières géométriques communes LaLIST ::iterator iF; LaLIST ::iterator iFfin = listFrontiere.end(); for (iF = listFrontiere.begin();iF!=iFfin; iF++) { Front* fro = &(*iF); ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière // récup de son tableau de noeud Tableau& tabn = efem1->TabNoeud(); int tabntaille = tabn.Taille(); for (int ij=1;ij<= tabntaille;ij++) // on balaie ses noeuds indice_NFr((tabn(ij)->Num_noeud())).push_back(fro); }; // on supprime les doublons for (int i=1;i<=tab_noeud_taille;i++) { List_io & intertab = indice_NFr(i); // pour allèger l'écriture intertab.sort(); // on ordonne intertab.unique(); // on supprime les doublons }; //-- debug // cout << "\n maillage " << idmail << "\n"; // for (int ii=1;ii<= tab_noeud.Taille();ii++) // {cout << "\n noeud " << ii << "\n"; // list::iterator ina,infin; // list& intertab = indice_NFr(ii); // pour allèger l'écriture // infin = intertab.end(); // for (ina = intertab.begin();ina!=infin;ina++) // {Front* elem2 = (*ina); // recup de l'element // elem2->Affiche(); // }; // }; // cout << endl; // // Sortie(1); //--fin debug // on determine les elements front mitoyens a chaque element frontiere, s'ils existent LaLIST ::iterator iE,jE,iiE; LaLIST inters; // stockage intermediaire LaLIST ::iterator iEfin = listFrontiere.end(); for ( iE = listFrontiere.begin(); iE !=iEfin; iE++) // pour chaque element on recherche d'autre element ayant des frontieres communes { // création d'élément frontières secondaires des frontières primaires Tableau tabi = (*iE).Eleme()->Frontiere(); // frontieres géométriques de iE // pour le débug cout << "\n on cherche un mitoyen a "; (*iE).Affiche(); int tabitaille = tabi.Taille(); for (int i=1;i<= tabitaille;i++) { ElFrontiere* elfr = tabi(i); // pour le débug cout << " frontiere : " << i ; // si deux éléments frontières sont identiques alors tous leurs noeuds // sont identiques. En particulier le premier noeud de *elfr est commum // avec tous les éléments succeptibles de contenir un élément frontière // identique. On va donc utiliser le vector indice_NFr qui contiend cette liste int numnoeud = (elfr->TabNoeud())(1)->Num_noeud(); list::iterator ina,infin; list& intertab = indice_NFr(numnoeud); // pour allèger l'écriture infin = intertab.end(); // on balaie les élément succeptibles d'avoir des frontières communes for (ina = intertab.begin();ina!=infin;ina++) {Front* elem2 = (*ina); // recup de l'element frontière // on ne fait la recherche que pour les éléments différent de *iE if (*elem2!=*iE) {Tableau tabj = elem2->Eleme()->Frontiere(); // frontieres de ina int tabjtaille = tabj.Taille(); for (int j=1;j<= tabjtaille;j++) { // ElFrontiere * tabjjOppose=(tabj(j)->Oppose()); // element transitoire if ((*elfr) == *(tabj(j))) // || // (*(tabi(i)) == *tabjjOppose) ) // iE et ina ont une frontiere commune, sont donc mitoyen { //Front pj = &(*(*ina)); inters.push_back(&(*elem2)); //-- debug //{Tableau & toto = elfr->TabNoeud(); cout << "\n premiere frontiere NB: "<< i << ": "; //for (int ii=1;ii<=toto.Taille();ii++) cout <Num_noeud() << " ";} //{Tableau & toto = (tabj(j))->TabNoeud(); cout << "\n frontiere mitoyenne NB: "<< j << ": "; //for (int ii=1;ii<=toto.Taille();ii++) cout <Num_noeud() << " "; } //cout << "\n "; //if ((j1==3)&&(j2==6)) // cout << "on y est "; //--fin debug // pour le débug // cout << "\n on a trouve une frontiere commune "; // elem2->Affiche(); // cout << " frontiere commune: noeuds: "; // Tableau tabno = (tabj(j))->TabNoeud(); // int nb = tabno.Taille(); // for (int ijk=1;ijk<=nb; ijk++) // cout << tabno(ijk)->Num_noeud() << " "; // fin pour le débug }; // delete tabjjOppose; // suppression de l'element transitoire }; }; }; }; // fin de la recherche concernant elfr // on supprime les doublons inters.sort(); // on ordonne inters.unique(); // on supprime les doublons // creation d'un tableau a la place de la liste Tableau tabb((int) inters.size()); LaLIST ::iterator ip; int i2; LaLIST ::iterator ipfin=inters.end(); LaLIST ::iterator ipdebut=inters.begin(); for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++) tabb(i2) = &(*(*ip)); // def des elements mitoyen (*iE).DefMitoyen(tabb); // -- débug --- affichage //if (inters.size() > 6) // {cout << "\n nb frontière > 6 "; // (*iE).Affiche(); // cout << endl; // }; // -- fin débug --- affichage // on vide la liste inters.erase(ipdebut,ipfin); }; // -- débug --- affichage // for ( iE = listFrontiere.begin(); iE !=iEfin; iE++) // (*iE).Affiche(); // -- fin débug --- affichage //effacement de tous les éléments frontières secondaires des éléments frontières // primaires LaLIST ::iterator iEE; for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++) (*iEE).Eleme()->EffaceFrontiere(); // -- débug --- affichage // for ( iE = listFrontiere.begin(); iE !=iEfin; iE++) // { Tableau & tabi = (*iE).TabMitoyen(); // int tabitaille = tabi.Taille(); // for (int i=1;i<= tabitaille;i++) // { Front* elfr = tabi(i); // cout << "\n"; // elfr->Affiche(); // } // }; //// -- fin débug --- affichage // }; // dans le cas où les éléments frontières sont des lignes, on les ordonnes // de manière à former une ligne continue void Maillage::OrdonancementDesLigne() {// on définit une liste intermédiaire LaLIST interlist; // on commence par le premier élément de la liste et de proche en proche on // rempli la liste // on passe en revue les éléments frontières // LaLIST ::iterator iEE; // for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++) // (*iEE).elem->EffaceFrontiere(); }; // 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 Maillage::Calcul_tous_les_front_et_leurs_mitoyens() { // on crée les éléments frontières dans chaque élément int tabelTaille = tab_element.Taille(); mitoyen_de_chaque_element.Change_taille(tabelTaille); // dimensionnement // on boucle sur les elements for (int i2 = 1; i2 <= tabelTaille; i2++) { // création des éléments frontières Element * elem1 = tab_element(i2); elem1->Frontiere(true); // puis on crée tous les éléments Front, qui sont alors stockés dans mitoyen_de_chaque_element(i2) // par contre pour l'instant on n'a pas les mitoyens de calculés const Tableau & tab1 = elem1->Frontiere(); // et de ses frontières Tableau & tab_front = mitoyen_de_chaque_element(i2); // pour simplifier int tab1Taille = tab1.Taille(); // nb de frontières tab_front.Change_taille(tab1Taille); // dimensionne mitoyen_de_chaque_element(i2) for (int j=1;j<=tab1Taille;j++) tab_front(j) = Front(*tab1(j),elem1,j); //cout << "\n les front"; //for (int j=1;j<=tab1Taille;j++) // tab_front(j).Affiche(); }; // on crée des tableaux permettant d'accélérer l'algorithme final // pour chaque noeud on note quel élément contiend ce noeud // "indice" contiend les numéros d'élément succeptible d'avoir des frontières communes Calcul_indice(); // on va boucler sur les éléments en regardant // pour chaque frontière si il y a d'autres frontières mitoyennes c-a-d si // il y a d'autres frontières identiques for (int i1 = 1; i1 <= tabelTaille; i1++) {Tableau & tab_front = mitoyen_de_chaque_element(i1); // pour simplifier int tab1Taille = tab_front.Taille(); // nb de frontières (qui sont déjà stockées) for (int j1=1;j1<= tab1Taille;j1++) // on boucle sur les frontière de l'élément principale (nb=i1) // on essaie de voir si l'élément j1 est recevable {const ElFrontiere * elfr = tab_front(j1).Eleme_const(); // récup de la frontière // si deux éléments frontières sont identiques alors tous leurs noeuds // sont identiques. En particulier le premier noeud de *elfr est commum // avec tous les éléments succeptibles de contenir un élément frontière // identique. On va donc utiliser la liste indice qui contiend cette liste int numnoeud = (elfr->TabNoeud_const())(1)->Num_noeud(); list::iterator ina,infin; list& intertab = indice(numnoeud); // pour allèger l'écriture infin = intertab.end(); LaLIST inters; // stockage intermediaire // on balaie les élément succeptibles d'avoir des frontières communes for (ina = intertab.begin();ina!=infin;ina++) {Element * elem2 = *ina; // recup de l'element // on ne fait la recherche que pour les éléments différents de elem1 int num_elem2 = elem2->Num_elt(); if (num_elem2 != i1) {// récup des éléments front correspondant à elem2 Tableau & tab_fro = mitoyen_de_chaque_element(num_elem2); int tab_fro_taille = tab_fro.Taille(); for (int j2=1;j2<=tab_fro_taille;j2++) { // on compare if ((*tab_fro(j2).Eleme_const()) == (*elfr)) {// on récupère le Front de l'élément elem2, pour la frontière j2 Front* front_j2 = &tab_fro(j2); inters.push_back(front_j2); //--debug //tab_front(j1).Affiche(); //front_j2->Affiche(); //--fin_debug }; }; }; }; // on supprime les doublons inters.sort(); // on ordonne inters.unique(); // on supprime les doublons // creation d'un tableau a la place de la liste Tableau tabb((int) inters.size()); LaLIST ::iterator ip; int i2; LaLIST ::iterator ipfin=inters.end(); LaLIST ::iterator ipdebut=inters.begin(); for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++) tabb(i2) = &(*(*ip)); // def des elements mitoyen, stocké dans mitoyen_de_chaque_element(i1) tab_front(j1).DefMitoyen(tabb); }; // fin de la boucle sur les frontières de elem1 };// fin de la boucle externe des éléments //--debug //for (int i=1;i<=mitoyen_de_chaque_element.Taille();i++) // {cout <<"\n\n **** element: "<& tab_f = mitoyen_de_chaque_element(i); // for (int j=1;j<=tab_f.Taille();j++) // tab_f(j).Affiche(); // } //--fin debug // effacement du contenu du tableau indice indice.Libere (); }; // lectures des infos pour le choix d'un élément void Maillage::Lecture_info_1element(UtilLecture * entreePrinc,int& num_elt,Enum_geom& id_geom ,Enum_interpol& id_interpol,EnumElemTypeProblem& id_typeProb ,string& str_precision) { // mise en place des valeurs par défaut str_precision = ""; id_typeProb = MECA_SOLIDE_DEFORMABLE; // type par défaut // lecture des champs qui doivent être toujours présents *(entreePrinc->entree) >> num_elt >> id_geom >> id_interpol; // cas d'info annexe ou du type de problème // on regarde le prochain caractère sans changer le flot /// int cr=(entreePrinc->entree)->peek(); ne marche pas !!! //--- début du remplacement du peek char car = Picococar(*(entreePrinc->entree)); // = flot.peek(); // on recupère l'entier correspondant au caractère int cr = int(car); //--- fin du remplacement du peek // si c'est un chiffre c'est fini pour le choix de l'élément int zero = int('0'); int neuf = int('9'); // if ((cr >= int('0'))&&(cr <= int('9'))) return; if ((cr >= zero)&&(cr <= neuf)) return; // maintenant on a deux cas, soit des infos annexes ou soit // la définition du type de pb suivi ou non d'infos annexes if (cr == int('_')) // cas où on a des infos annexes de choix { *(entreePrinc->entree) >> str_precision; // ensuite il ne doit y avoir que des numéros donc fin return; } // ou on regarde s'il y a définition du type de problème // qui doit commencer par une lettre else if ( ((cr >= int('a'))&&(cr<=int('z'))) || ((cr >= int('A'))&&(cr<=int('Z'))) ) { *(entreePrinc->entree) >> id_typeProb; // on regarde s'il y a des infos annexes après le type de problem if (cr == int('_')) // cas où on a des infos annexes de choix { *(entreePrinc->entree) >> str_precision; // ensuite il ne doit y avoir que des numéros donc fin return; } }; // sinon c'est le cas qui ne doit pas arriver mais pour éviter des warnings return; }; // 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 Maillage::Affectation_noeud(Noeud& noeud) { int nbn = noeud.Num_noeud(); if (tab_noeud(nbn) == NULL) {tab_noeud(nbn)=&noeud;} else // on augmente la place {int tail_tab_noeud = tab_noeud.Taille()+1; tab_noeud.Change_taille(tail_tab_noeud); noeud.Change_num_noeud(tail_tab_noeud); tab_noeud(tail_tab_noeud)=&noeud; if (ParaGlob::NiveauImpression() > 0) {cout << "\n warning : le numero initial du noeud " << nbn << " est remplace par " << " le numero d'ordre attribue automatiquement par herezh " << tail_tab_noeud << "\n seul ce dernier sera utilise par la suite ! " << endl; if (ParaGlob::NiveauImpression() > 5) cout << "\n Maillage::Affectation_noeud (Noeud& noeud) " << endl; }; }; }; // 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 Maillage::Affectation_element(Element& element) { int nbe = element.Num_elt(); if (tab_element(nbe) == NULL) {tab_element(nbe)=&element;} else // on augmente la place {int tail_tab_element = tab_element.Taille()+1; tab_element.Change_taille(tail_tab_element); element.Change_num_elt(tail_tab_element); tab_element(tail_tab_element)=&element; if (ParaGlob::NiveauImpression() > 0) {cout << "\n warning : le numero initial de l'element " << nbe << " est remplace par " << " le numero d'ordre attribue automatiquement par herezh " << tail_tab_element << "\n seul ce dernier sera utilise par la suite ! " << endl; if (ParaGlob::NiveauImpression() > 5) cout << "\n Maillage::Affectation_element (Element& element) " << endl; }; }; // on met à jour éventuellement les types de problèmes gérés EnumElemTypeProblem enu = element.Id_TypeProblem(); if (!types_de_problemes.Contient(enu)) {int tail = types_de_problemes.Taille(); types_de_problemes.Change_taille(tail+1); types_de_problemes(tail+1) = enu; ddl_representatifs_des_physiques.Change_taille(tail+1); switch (enu) {case MECA_SOLIDE_DEFORMABLE : ddl_representatifs_des_physiques(tail+1)=X1;break; case THERMIQUE : ddl_representatifs_des_physiques(tail+1)=TEMP;break; default : cout << "\n***Erreur : pour l'instant le type de probleme: "<) // les éléments supplémentaires ont un pointeur mis à Null void Maillage::Change_nb_noeud (int nouveau_nb) { int vieille_taille = tab_noeud.Taille(); tab_noeud.Change_taille(nouveau_nb); for (int i=vieille_taille+1;i<=nouveau_nb;i++) tab_noeud(i)=NULL; }; // 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 Maillage::Change_nb_element (int nouveau_nb) { int vieille_taille = tab_element.Taille(); tab_element.Change_taille(nouveau_nb); for (int i=vieille_taille+1;i<=nouveau_nb;i++) tab_element(i)=NULL; };