// This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-2022 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . #include "LesReferences.h" #include "PtTabRel.h" #include "ReferenceAF.h" #include "ReferenceNE.h" #include "ReferencePtiAF.h" #include "ParaGlob.h" //-------- une méthode permettant d'utiliser des tableaux de map de références ----- // surcharge de l'operator d'ecriture ostream & operator << (ostream & sort, const map < string, Reference*, std::less > & ) { // tout d'abord un indicateur donnant le type if (ParaGlob::Francais()) {sort << " \n erreur (de developpement) a une fonction d'ecriture << d'une map de reference " << " voir LesReference.h "; } else {sort << " \n error (for developper) for the writing method << concerning a map of references " << " see LesReference.h "; } Sortie(1); return sort; }; //----------- fin de la méthode permettant d'utiliser des tableaux de map de références ----- // --------------- variables statiques --------- MotCle LesReferences::motCle; // liste des mots clés LesReferences::LesReferences () : // par defaut t_mapDeRef(),ref(NULL),num_mail_presuivant(0),listeNomMail(NULL) { nbMaille =1; indic = 0; }; // DESTRUCTEUR : LesReferences::~LesReferences () { // effacement des grandeurs pointées par la liste de référence int taille = t_mapDeRef.Taille(); for (int i=1;i<=taille;i++) { map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i); map < string, Reference*, std::less >::iterator il,ilfin = mapDeRef.end(); for (il=mapDeRef.begin() ; il != ilfin; il++) if ((*il).second != NULL) {delete (*il).second;(*il).second=NULL;}; mapDeRef.erase(mapDeRef.begin(),mapDeRef.end()); }; }; // def du numero de maillage courant, utilise avant la lecture void LesReferences::NbMaille(int nb) { nbMaille = nb; }; // def du type de reference a lire, utilise avant la lecture void LesReferences::Indic(string type) { if (type == "noeud") indic = 1; else if (type == "element") indic =2; else if(type == "surface") indic = 3; else if(type == "arete")indic = 4; else if(type == "noeud_element")indic = 5; else if(type == "pt_integ_element")indic = 6; else if(type == "pt_integ_face_element")indic = 7; else if(type == "pt_integ_arete_element")indic = 8; else if(type == "rien_actuellement") indic = 0; else { if (ParaGlob::Francais()) {cout << " \n **** erreur de type de reference, type donne = " << type;} else {cout << " \n **** error of type of reference, type = " << type;} cout << "LesReferences::Indic(string type)" << endl; Affiche(); Sortie(1); }; }; // lecture des references void LesReferences::Lecture(UtilLecture & entreePrinc) { // on lit des references temps qu'il n'y a pas de pb if (indic < 0) { if (ParaGlob::Francais()) {cout << " \n erreur en lecture de reference, le type de reference n\'st pas defini " ;} else {cout << " \n error in reading a reference, the reference type is not defined " ;}; cout << "\n LesReferences::LectureLesReferences(etc ... " << endl; Affiche(); Sortie(1); } while ( LectureReference(entreePrinc)) // la methode LectureReference cree une référence pointée par ref { // verification que l'on n'a pas deux references identiques if (Existe(ref->Nom(),ref->Nbmaille())) { if (ParaGlob::Francais()) { cout <<" \n Erreur de lecture de reference, deux refs ont le meme nom \n"; cout <<" nom = " << ref->Nom() << " pour le meme maillage nb: " << ref->Nbmaille() << '\n';} else { cout <<" \n Error in reading a reference, two refs have the same name \n"; cout <<" name = " << ref->Nom() << " for the same mesh nb: " << ref->Nbmaille() << '\n';} cout <<"LesReferences::LectureLesReferences(UtilLecture & entreePrinc)" << endl; entreePrinc.MessageBuffer("lecture des references"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie (1); } else {int num_mail = ref->Nbmaille(); if (num_mail < 1 ) // on vérifie que le numéro de maillage est licite { if (ParaGlob::Francais()) { cout << "\n erreur, on veut ajouter une reference sur le maillage numero nul ou negatif : " << num_mail << " ";} else { cout << "\n error, we cannot add a reference on the mesh, number : " << num_mail << " ";} ref->Affiche(); cout << "\n LesReferences::LectureLesReferences(... "; Sortie(1); } else if (num_mail > t_mapDeRef.Taille()) // maintenant on regarde si l'on a déjà enregistré dans ce maillage { t_mapDeRef.Change_taille(num_mail); }; // puis on enregistre t_mapDeRef(num_mail)[ref->Nom()]=ref; // t_mapDeRef(nbMaille)[ref->Nom()]= ref; }; } }; // ajout d'une référence déjà construite par ailleurs void LesReferences::Ajout_reference(Reference * refi) { int num_mail = refi->Nbmaille(); if (num_mail < 1 ) // on vérifie que le numéro de maillage est licite { if (ParaGlob::Francais()) { cout << "\n erreur, on veut ajouter une reference sur le maillage numero nul ou negatif : " << num_mail << " "; } else { cout << "\n error, we cannot add a reference on the mesh, number : " << num_mail << " ";} refi->Affiche(); cout << "\n LesReferences::Ajout_reference(Reference * refi) "; Sortie(1); } else if (num_mail > t_mapDeRef.Taille()) // maintenant on regarde si l'on a déjà enregistré dans ce maillage { t_mapDeRef.Change_taille(num_mail); }; // supprime les doublons internes éventuels dans la référence refi->Supprime_doublons_internes(); // puis on enregistre t_mapDeRef(num_mail)[refi->Nom()]=refi; return; }; // affichage et definition interactive des commandes // nbMaxiNoeud: nombre maxi de noeud pour les exemples void LesReferences::Info_commande_lesRef(int nbMaxiNoeud,int nbMaxiElem,UtilLecture * entreePrinc,int cas) { // on dimensionne la taille de t_mapDeRef if ( nbMaille > t_mapDeRef.Taille()) // maintenant on regarde si l'on a déjà enregistré dans ce maillage { t_mapDeRef.Change_taille(nbMaille); }; switch (cas) { case 1: {// en fait on s'occupe ici uniquement des références de noeuds ref = new ReferenceNE("N_exemple_ref_NE", nbMaille,1); ref-> Info_commande_Ref(nbMaxiNoeud,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; break; } case 2: {// cas de toutes les références ref = new ReferenceNE(nbMaille,1); // cas d'une ref de noeuds ref-> Info_commande_Ref(nbMaxiNoeud,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; ref = new ReferenceNE(nbMaille,2); // cas d'une ref d'elements ref-> Info_commande_Ref(nbMaxiElem,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; ref = new ReferenceAF(nbMaille,3); // cas d'une ref de surfaces ref-> Info_commande_Ref(nbMaxiElem,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; ref = new ReferenceAF(nbMaille,4); // cas d'une ref d'arrete ref-> Info_commande_Ref(nbMaxiElem,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; ref = new ReferenceAF(nbMaille,5); // cas d'une ref de noeud associé à un élément ref-> Info_commande_Ref(nbMaxiElem,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; ref = new ReferenceAF(nbMaille,6); // cas d'une ref de point d'intégration associé à un élément ref-> Info_commande_Ref(nbMaxiElem,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; ref = new ReferencePtiAF(nbMaille,7); // cas d'une ref de point d'intégration associé à une face d'élément ref-> Info_commande_Ref(nbMaxiElem,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; ref = new ReferencePtiAF(nbMaille,8); // cas d'une ref de point d'intégration associé à une arete d'élément ref-> Info_commande_Ref(nbMaxiElem,entreePrinc,cas); t_mapDeRef(nbMaille)[ref->Nom()]= ref; break; } default : { if (ParaGlob::Francais()) {cout << "\nErreur : valeur incorrecte du cas = " << cas << "\n";} else {cout << "\nError : incorrect value for the case = " << cas << "\n";} cout << "LesReferences::Info_commande_lesRef..." ; Sortie(1); }; } }; // affichage des informations contenu dans les references // par défaut affiche toutes les infos // si niveau = 1 : affiche que les noms des ref void LesReferences::Affiche(int niveau) const { int taille = t_mapDeRef.Taille(); for (int i=1;i<=taille;i++) { map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i); map < string, Reference*, std::less >::const_iterator i_map; if (ParaGlob::Francais()) {cout << " \n ------- affichage des listes de references ------- \n ";} else {cout << " \n ------- display of the lists of references ------- \n ";}; for (i_map=mapDeRef.begin() ; i_map != mapDeRef.end(); i_map++) if (!niveau) (*i_map).second->Affiche(); else cout << " " << (*i_map).first ; cout << endl; }; }; // affichage des informations contenu dans les references d'un certain type // défini par indic : // indic = 1 -> noeud, =2 -> element // =3 -> surface associée à un élément , =4 -> arete associée à un élément // =5 -> noeud associée à un élément // =6 -> point d'intégration associée à un élément // =7 -> de points d'intégrations relatifs à des surfaces d'éléments // =8 -> de points d'intégrations relatifs à des arrete d'éléments // =0 -> rien_actuellement // par défaut affiche toutes les infos // si niveau = 1 : affiche que les noms des ref void LesReferences::Affiche(int indic, int niveau) const { int taille = t_mapDeRef.Taille(); for (int i=1;i<=taille;i++) { map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i); map < string, Reference*, std::less >::const_iterator i_map; if (ParaGlob::Francais()) {cout << " \n ------- affichage references ------- \n ";} else {cout << " \n ------- display references ------- \n ";}; for (i_map=mapDeRef.begin() ; i_map != mapDeRef.end(); i_map++) if ((*i_map).second->Indic() == indic) {if (niveau==1) cout << " " << (*i_map).first ; else (*i_map).second->Affiche(); }; cout << endl; }; }; // Affiche les donnees des références pour le maillage imail dans un fichier // dont le nom est construit à partir du nom du maillage au format ".lis" void LesReferences::Affiche_dans_lis(const string& nom_maillage,int imail) { // tout d'abord on vérifie qu'il existe des références pour ce maillage // ce qui peut-être fait de manière très simple en testant t_mapDeRef.Taille() // si l'élément de tableau n'existe pas, ce n'est pas la peine de continuer, il n'y a pas de ref // s'il existe, il y a peut-être des ref ... donc on continue if (imail > t_mapDeRef.Taille()) return; // ouverture du fichier pour les noeuds char namm[132]; char*fileNoome = namm; strcpy(fileNoome, nom_maillage.c_str()); ofstream * sur_sort = new ofstream (strcat(fileNoome,".lis")); ofstream & sort = * sur_sort; if(!(sort.is_open())) // le fichier ne peut être ouvert, message d'erreur { if (ParaGlob::Francais()) {cout << "\n erreur en ouverture pour l'ecriture du fichier " << fileNoome << "\n";} else {cout << "\n error, when trying to open for writing, the file " << fileNoome << "\n";}; cout << " Maillage::Affiche_dans_her_lis(.... " << endl; Sortie(1); }; // écriture de l'entete if (ParaGlob::Francais()) {sort << "\n ###########################################################################" << "\n # ecriture automatique d'un maillage au format .lis, par Herezh++ #" << "\n ###########################################################################";} else {sort << "\n ###########################################################################" << "\n # automatic writing by Herezh++, of a mesh with format .lis #" << "\n ###########################################################################";}; sort << "\n # version: " << ParaGlob::NbVersion() << "\n \n \n "; // --- écriture des références de noeuds if (ParaGlob::Francais()) {sort << "\n # -- reference de noeud ";} else {sort << "\n # -- reference of nodes ";}; // on passe en revue les différentes références pour trouver la bonne map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(imail); map < string, Reference*, std::less >::const_iterator il,ilfin=mapDeRef.end(); for (il=mapDeRef.begin();il!=ilfin;il++) if ((*il).second->Indic()==1) {// on a trouvé une référence de noeud pour le maillage considéré (*il).second->Affiche_dans_lis(sort); // affichage }; // --- écriture des références des éléments if (ParaGlob::Francais()) {sort << "\n # -- reference des elements ";} else {sort << "\n # -- reference of elements ";}; // on passe en revue les différentes références pour trouver la bonne for (il=mapDeRef.begin();il!=ilfin;il++) if ((*il).second->Indic()==2) {// on a trouvé une référence d'element pour le maillage considéré (*il).second->Affiche_dans_lis(sort); // affichage } // --- écriture des références de pt d'integ, noeuds, faces et arretes if (ParaGlob::Francais()) {sort << "\n # -- references de pt d'integ, noeuds, faces et arretes associes a des elements ";} else {sort << "\n # -- references of Gauss points, nodes, facets, segments, associated with elements ";}; // on passe en revue les différentes références pour trouver la bonne for (il=mapDeRef.begin();il!=ilfin;il++) if (((*il).second->Indic()==3)||((*il).second->Indic()==4) ||((*il).second->Indic()==5)||((*il).second->Indic()==6) ||((*il).second->Indic()==7)||((*il).second->Indic()==8)) {// on a trouvé une référence de pt d'integ, noeuds, faces et arretes pour le maillage considéré (*il).second->Affiche_dans_lis(sort); // affichage }; // quelques lignes blanches à la fin du fichier sort << "\n \n \n"; // fermeture du fichier delete sur_sort; }; // initialise le questionnement de la récupération de référence et // retourne la première référence si elle existe sinon un pointeur nul const Reference* LesReferences::Init_et_Premiere() { num_mail_presuivant=0; Reference * refret = NULL; int t_taille = t_mapDeRef.Taille(); if ( t_taille == 0) return NULL; // sinon on boucle sur les éléments du tableaux // et on cherche la première ref valide qui existe for (int i=1;i<=t_taille;i++) { iref = t_mapDeRef(i).begin(); if (iref != t_mapDeRef(i).end()) { num_mail_presuivant=i; refret = (*iref).second; break; }; }; // retour return refret; }; // retourne la référence suivante ou, s'il n'y en n'a plus, retourne // un pointeur nul const Reference* LesReferences::Reference_suivante() { Reference * refret = NULL; if (num_mail_presuivant != 0) {iref++; if (iref != t_mapDeRef(num_mail_presuivant).end()) { return (*iref).second; } // donc arrivé ici cela veut dire qu'on est sur une fin else { // sinon on boucle sur les éléments du tableaux qui restent // et on cherche la première ref valide qui existe int t_taille = t_mapDeRef.Taille(); for (int i=num_mail_presuivant+1;i<=t_taille;i++) { iref = t_mapDeRef(i).begin(); if (iref != t_mapDeRef(i).end()) { num_mail_presuivant=i; refret = (*iref).second; break; }; }; }; }; // retour return refret; }; // test si la reference existe reellement // retourne false si n'existe pas , true sinon bool LesReferences::Existe(const string & st1,int num_mail) const { // tout d'abord on regarde si le tableau de map n'est pas vide if (t_mapDeRef.Taille() == 0) return false; // sinon on peut continuer bool existe=true; if (num_mail > t_mapDeRef.Taille()) { existe = false; } else if (t_mapDeRef(num_mail).find(st1) == t_mapDeRef(num_mail).end()) { existe = false; }; // sinon c'est ok return existe; }; // idem mais avec un nom de maillage bool LesReferences::Existe(const string & st1,const string* nom_mail) const { // tout d'abord on regarde si le tableau de map n'est pas vide if (t_mapDeRef.Taille() == 0) return false; // sinon on peut continuer // on regarde si le nom de maillage est licite if (nom_mail == NULL) { // acceptable que si l'on a un seul maillage #ifdef MISE_AU_POINT if (listeNomMail != NULL) if (listeNomMail->size() != 1) if (ParaGlob::NiveauImpression() >2) { if (ParaGlob::Francais()) {cout << "\n warning: la reference demandee= " << st1 << " , n'a pas de nom de maillage associe" << " alors qu'il y a plusieurs maillage defini !! : on considere que c'est une ref du premier maillage";} else {cout << "\n warning: the wanted reference " << st1 << " , has no associated mesh " << " but several meshes exist !! : we consider that it is a ref for the first mesh ";} if (ParaGlob::NiveauImpression() >5) { if (ParaGlob::Francais()) {cout << "\n nom_de_maillages= ";} else {cout << "\n names of the meshes = ";} map < string, int , std::less >::const_iterator ili,ilifin=listeNomMail->end(); for (ili = listeNomMail->begin();ili != ilifin; ili++) cout << (*ili).first << ", " ; cout << "\n LesReferences::Existe(const string & st1,const string* nom_mail) "; }; } // Sortie(1); #endif // on ramène le cas du premier maillage qui doit exister return Existe(st1,1); } else { #ifdef MISE_AU_POINT // on regarde si le nom de maillage existe dans la liste if (listeNomMail->find(*nom_mail) == listeNomMail->end()) { if (ParaGlob::Francais()) {cout << "\nErreur : le nom de maillage : " << *nom_mail << " n'existe pas \n";} else {cout << "\nError : the name of the mesh : " << *nom_mail << " does not exist \n";} if (ParaGlob::NiveauImpression() >5) cout << "LesReferences::Existe(const string & st1,const string& nom_mail) \n"; Sortie(1); } #endif return Existe(st1,(*(listeNomMail->find(*nom_mail))).second); }; }; // retourne la reference correspondant a une cle const Reference& LesReferences::Trouve(const string & st1,int num_mail) const { if (num_mail > t_mapDeRef.Taille()) { if (ParaGlob::Francais()) {cout << " \n pb la reference de nom " << st1 << " pour le maillage nb= "<< num_mail << " n'existe pas \n";} else {cout << "\nError : the reference with the name " << st1 << " for the mesh nb= " << num_mail << " does not exist \n";} if (ParaGlob::NiveauImpression() >5) { cout << " \n LesReferences::Trouve(const string & st1,int num_mail) " << endl;}; Sortie (1); } else if (t_mapDeRef(num_mail).find(st1) == t_mapDeRef(num_mail).end()) { if (ParaGlob::Francais()) {cout << " \n pb la reference de nom " << st1 << " pour le maillage nb= "<< num_mail << " n'existe pas \n";} else {cout << "\nError : the reference with the name " << st1 << " for the mesh nb= " << num_mail << " does not exist \n";} if (ParaGlob::NiveauImpression() >5) { cout << " \n LesReferences::Trouve(const string & st1,int num_mail) " << endl;}; Sortie (1); }; // sinon c'est ok return *(t_mapDeRef(num_mail)[st1]); }; // idem mais avec un nom de maillage const Reference& LesReferences::Trouve(const string & st1,const string* nom_mail) const { // on regarde si le nom de maillage est licite if (nom_mail == NULL) { // acceptable que si l'on a un seul maillage #ifdef MISE_AU_POINT if (listeNomMail->size() != 1) if (ParaGlob::NiveauImpression() >2) { if (ParaGlob::Francais()) {cout << "\n warning: la reference demandee= " << st1 << " , n'a pas de nom de maillage associe" << " alors qu'il y a plusieurs maillage defini !! : on considere que c'est une ref du premier maillage";} else {cout << "\n warning: the wanted reference " << st1 << " , has no associated mesh " << " but several meshes exist !! : we consider that it is a ref for the first mesh ";} if (ParaGlob::NiveauImpression() >5) { if (ParaGlob::Francais()) {cout << "\n nom_de_maillages= ";} else {cout << "\n names of the meshes = ";} map < string, int , std::less >::const_iterator ili,ilifin=listeNomMail->end(); for (ili = listeNomMail->begin();ili != ilifin; ili++) cout << (*ili).first << ", " ; cout << "\n LesReferences::Trouve(const string & st1,const string& nom_mail) "; }; // Sortie(1); }; #endif // on ramène le cas du premier maillage qui doit exister return Trouve(st1,1); } else { #ifdef MISE_AU_POINT // on regarde si le nom de maillage existe dans la liste if (listeNomMail->find(*nom_mail) == listeNomMail->end()) { if (ParaGlob::Francais()) {cout << "\nErreur : le nom de maillage : " << *nom_mail << " n'existe pas \n";} else {cout << "\nError : the name of the mesh : " << *nom_mail << " does not exist \n";} if (ParaGlob::NiveauImpression() >5) cout << "LesReferences::Trouve(const string & st1,const string& nom_mail) \n"; Sortie(1); }; #endif return Trouve(st1,(*(listeNomMail->find(*nom_mail))).second); }; }; // mise à jour des références de noeud, dans le cas où les numéros de noeuds ont changés //1) cas où l'on supprime éventuellement des noeuds de la référence, qui ne sont plus référencé // nv_tab est tel que : nv_tab(i) est le nouveau numéro qui avait auparavant le numéro "i" // non_referencer(i) : = true signifie qu'il ne faut plus tenir compte de ce noeud // = false indique qu'il continue d'être actif void LesReferences::Mise_a_jour_ref_noeud(Tableau & nv_tab,int num_mail,Tableau & non_referencer) { bool fr = ParaGlob::Francais(); // pour simplifier // on vérifie le numéro de maillage if ((num_mail < 0) || (num_mail > t_mapDeRef.Taille())) { if (fr) {cout << "\n **** bizarre on demande de changer la numerotation de noeuds de reference pour le" << " maillage numero: " << num_mail << " qui soit n'existe pas ou soit n'a pas de reference !! ";} else {cout << "\n **** strange, we try to change the numerotation of nodes belonging to a reference of a " << " mesh number : " << num_mail << " which does not exist or does not contain any reference !! ";}; }; // on balaie la map map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(num_mail); map < string, Reference*, std::less >::iterator il,ilfin = mapDeRef.end(); // list ::const_iterator il,ilfin=listeDeRef.end(); int nb_noeud = nv_tab.Taille(); for (il=mapDeRef.begin() ; il != ilfin; il++) { if ((*il).second->Indic() == 1) { // cas où il s'agit d'une référence de noeud ReferenceNE* refe = ((ReferenceNE*) (*il).second); // on récupère la référence int nb_el = refe->Taille(); // premier passage on change les numéros int nb_noeud_supprime = 0; // nombre de noeuds supprimés for (int i=1; i<= nb_el; i++) { int num_ancien = refe->Numero(i); // on vérifie que le noeud continue d'être valide if (non_referencer(num_ancien)) { if (ParaGlob::NiveauImpression() > 3) {if (fr) {cout << "\n suppression du noeud " << num_ancien << " dans la reference " << refe->Nom() << " maillage:" << num_mail ;} else {cout << "\n erasure of the node " << num_ancien << " in the reference " << refe->Nom() << " mesh :" << num_mail ;}; }; // on commence par mettre -100 dans le tableau de num et ensuite on retassera le tableau à la fin refe->Change_num_dans_ref(i,-100); nb_noeud_supprime++; } else // sinon il faut le garder { // on vérifie que le numéro de la référence est licite (normalement il doit l'être) if ((num_ancien > 0) && (num_ancien <= nb_noeud)) {refe->Change_num_dans_ref(i,nv_tab(num_ancien));} else {if (fr) {cout << "\n erreur dans la mise a jour d'une reference , le numero " << num_ancien << " de la liste " << " n'appartient pas a l'intervalle des noeuds disponibles [1," << nb_noeud << "] ";} else {cout << "\n error during the update of a reference, the number " << num_ancien << " in the list " << " does not belong to the range of existing nodes [1," << nb_noeud << "] ";}; // debug cout << " \n non_referencer(num_ancien) " << non_referencer(num_ancien) << endl; refe->Affiche(); Sortie(1); }; }; }; // second passage dans le cas où l'on a supprimé des noeuds if (nb_noeud_supprime) {// a) on fait un décalage dans le tableau initial int indice_new = 1; for (int i=1; i<= nb_el; i++) { if (refe->Numero(i) != -100) {refe->Change_num_dans_ref(indice_new,refe->Numero(i)); indice_new++; } }; // b) on retasse le tableau Tableau tab_inter = refe->Tab_num(); tab_inter.Change_taille(nb_el-nb_noeud_supprime); refe->Change_tab_num(tab_inter); }; // on supprime les doublons éventuels refe->Supprime_doublons_internes(); }; }; }; // mise à jour des références de noeud, dans le cas où les numéros de noeuds ont changés //2) cas où on considère tous les noeuds // nv_tab est tel que : nv_tab(i) est le nouveau numéro qui avait auparavant le numéro "i" void LesReferences::Mise_a_jour_ref_noeud(Tableau & nv_tab,int num_mail) { bool fr = ParaGlob::Francais(); // pour simplifier // on vérifie le numéro de maillage if ((num_mail < 0) || (num_mail > t_mapDeRef.Taille())) { if (fr) {cout << "\n **** bizarre on demande de changer la numerotation de noeuds de reference pour le" << " maillage numero: " << num_mail << " qui soit n'existe pas ou soit n'a pas de reference !! ";} else {cout << "\n **** strange, we try to change the numerotation of nodes belonging to a reference of a " << " mesh number : " << num_mail << " which does not exist or does not contain any reference !! ";}; }; // on balaie la map map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(num_mail); map < string, Reference*, std::less >::iterator il,ilfin = mapDeRef.end(); // list ::const_iterator il,ilfin=listeDeRef.end(); int nb_noeud = nv_tab.Taille(); for (il=mapDeRef.begin() ; il != ilfin; il++) { if ((*il).second->Indic() == 1) { // cas où il s'agit d'une référence de noeud ReferenceNE* refe = ((ReferenceNE*) (*il).second); // on récupère la référence int nb_el = refe->Taille(); for (int i=1; i<= nb_el; i++) { int num_ancien = refe->Numero(i); // on vérifie que le numéro de la référence est licite (normalement il doit l'être) if ((num_ancien > 0) && (num_ancien <= nb_noeud)) {refe->Change_num_dans_ref(i,nv_tab(num_ancien));} else {if (fr) {cout << "\n erreur dans la mise a jour d'une reference , le numero " << num_ancien << " de la liste " << " n'appartient pas a l'intervalle des noeuds disponibles [1," << nb_noeud << "] ";} else {cout << "\n error during the update of a reference, the number " << num_ancien << " in the list " << " does not belong to the range of existing nodes [1," << nb_noeud << "] ";}; refe->Affiche(); Sortie(1); }; }; // on supprime les doublons éventuels refe->Supprime_doublons_internes(); }; }; }; // mise à jour des références d'élément, dans le cas où les numéros d'élément ont changés //1) cas où l'on supprime éventuellement des éléments de la référence, qui ne sont plus référencé // nv_tab est tel que : nv_tab(i) est le nouveau numéro qui avait auparavant le numéro "i" // non_referencer(i) : = true signifie qu'il ne faut plus tenir compte de cet élément // = false indique qu'il continue d'être actif void LesReferences::Mise_a_jour_ref_element(Tableau & nv_tab,int num_mail,Tableau & non_referencer) { bool fr = ParaGlob::Francais(); // pour simplifier // on vérifie le numéro de maillage if ((num_mail < 0) || (num_mail > t_mapDeRef.Taille())) { if (fr) {cout << "\n **** bizarre on demande de changer la numerotation d'element de reference pour le" << " maillage numero: " << num_mail << " qui soit n'existe pas ou soit n'a pas de reference !! ";} else {cout << "\n **** strange, we try to change the numerotation of elements belonging to a reference of a " << " mesh number : " << num_mail << " which does not exist or does not contain any reference !! ";}; }; // on balaie la map map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(num_mail); map < string, Reference*, std::less >::iterator il,ilfin = mapDeRef.end(); // { int i = num_mail; // map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i); // map < string, Reference*, std::less >::const_iterator i_map; // if (ParaGlob::Francais()) {cout << " \n ------- affichage des listes de references ------- \n ";} // else {cout << " \n ------- display of the lists of references ------- \n ";}; // for (i_map=mapDeRef.begin() ; i_map != mapDeRef.end(); i_map++) // (*i_map).second->Affiche(); // cout << endl; // }; // list ::const_iterator il,ilfin=listeDeRef.end(); int nb_element = nv_tab.Taille(); for (il=mapDeRef.begin() ; il != mapDeRef.end(); il++) { switch((*il).second->Indic()) {case 2: // cas où il s'agit d'une référence d'élément { ReferenceNE* refe = ((ReferenceNE*) (*il).second); // on récupère la référence int nb_el = refe->Taille(); // premier passage on change les numéros int nb_element_supprime = 0; // nombre de elements supprimés for (int i=1; i<= nb_el; i++) { int num_ancien = refe->Numero(i); // on vérifie que l'élement continue d'être valide if (non_referencer(num_ancien)) { if (ParaGlob::NiveauImpression() > 3) {if (fr) {cout << "\n suppression de l'element " << num_ancien << " dans la reference " << refe->Nom() << " maillage:" << num_mail << endl;} else {cout << "\n erasure of the element " << num_ancien << " in the reference " << refe->Nom() << " mesh :" << num_mail << endl;}; }; // on commence par mettre -100 dans le tableau de num et ensuite on retassera le tableau à la fin refe->Change_num_dans_ref(i,-100); nb_element_supprime++; } else // sinon il faut le garder { // on vérifie que le numéro de la référence est licite (normalement il doit l'être) if ((num_ancien > 0) && (num_ancien <= nb_element)) {refe->Change_num_dans_ref(i,nv_tab(num_ancien));} else {if (fr) {cout << "\n erreur dans la mise a jour d'une reference , le numero " << num_ancien << " de la liste " << " n'appartient pas a l'intervalle des elements disponibles [1," << nb_element << "] ";} else {cout << "\n error during the update of a reference, the number " << num_ancien << " in the list " << " does not belong to the range of existing elements [1," << nb_element << "] ";}; // debug cout << " \n non_referencer(num_ancien) " << non_referencer(num_ancien) << endl; refe->Affiche(); Sortie(1); }; }; }; // second passage dans le cas où l'on a supprimé des elements if (nb_element_supprime) { // a) on fait un décalage dans le tableau initial int indice_new = 1; for (int i=1; i<= nb_el; i++) { if (refe->Numero(i) != -100) {refe->Change_num_dans_ref(indice_new,refe->Numero(i)); indice_new++; }; }; // b) on retasse le tableau Tableau tab_inter = refe->Tab_num(); tab_inter.Change_taille(nb_el-nb_element_supprime); refe->Change_tab_num(tab_inter); }; // on supprime les doublons éventuels refe->Supprime_doublons_internes(); break; } case 3: case 4: case 6: // cas où il s'agit d'une face ou arête ou ptint d'élément {ReferenceAF* refe = ((ReferenceAF*) (*il).second); // on récupère la référence // on récupère les deux tableaux de la référence const Tableau& tab_elem = refe->Tab_Elem(); // le tableau des numeros d'éléments //puis le tableau des numeros de faces, ou d'arêtes, ou de noeud d'element, ou de points d'integ const Tableau& tab_entite = refe->Tab_FA(); // on va travailler avec ces tableaux et ensuite on recréra une nouvelle référence avec de nouveaux tableaux int nb_el = tab_elem.Taille(); // premier passage on change les numéros int nb_element_supprime = 0; // nombre de elements supprimés for (int i=1; i<= nb_el; i++) { int num_ancien = refe->NumeroElem(i); // on vérifie que le element continue d'être valide if (non_referencer(num_ancien)) { if (ParaGlob::NiveauImpression() > 3) {if (fr) {cout << "\n suppression de l'element " << num_ancien << " dans la reference " << refe->Nom() << " maillage:" << num_mail ;} else {cout << "\n erasure of the element " << num_ancien << " in the reference " << refe->Nom() << " mesh :" << num_mail ;}; }; // on commence par mettre -100 dans le tableau de num et ensuite on retassera le tableau à la fin tab_elem(i) = -100; nb_element_supprime++; } else // sinon il faut le garder { // on vérifie que le numéro de la référence est licite (normalement il doit l'être) if ((num_ancien > 0) && (num_ancien <= nb_element)) {tab_elem(i) = nv_tab(num_ancien);} // {refe->Change_num_dans_ref(i,nv_tab(num_ancien));} else {if (fr) {cout << "\n erreur dans la mise a jour d'une reference , le numero " << num_ancien << " de la liste " << " n'appartient pas a l'intervalle des elements disponibles [1," << nb_element << "] ";} else {cout << "\n error during the update of a reference, the number " << num_ancien << " in the list " << " does not belong to the range of existing elements [1," << nb_element << "] ";}; // debug cout << " \n non_referencer(num_ancien) " << non_referencer(num_ancien) << endl; refe->Affiche(); Sortie(1); }; }; }; // on crée deux nouveaux tableaux Tableau tab_elem_new(nb_el-nb_element_supprime); // le nouveau tableau des numeros d'éléments //puis le tableau des numeros de faces, ou d'arêtes, ou de noeud d'element, ou de points d'integ Tableau tab_entite_new(nb_el-nb_element_supprime); // on va travailler avec ces tableaux et ensuite on mettra à jour la référence // second passage dans le cas où l'on a supprimé des elements if (nb_element_supprime) {// on recopie les grandeurs correctes int indice_new = 1; for (int i=1; i<= nb_el; i++) { if (tab_elem(i) != -100) {tab_elem_new(indice_new)=tab_elem(i); tab_entite_new(indice_new) = tab_entite(i); indice_new++; }; }; // on change les deux tableaux dans la référence refe->Change_tab_num(tab_elem_new,tab_entite_new); // on supprime les doublons éventuels refe->Supprime_doublons_internes(); } else // sinon on ne fait que supprimer les doublons éventuels {refe->Supprime_doublons_internes();}; break; } case 7: case 8: // cas où il s'agit de pti d'une face ou arête d'élément {ReferencePtiAF* refe = ((ReferencePtiAF*) (*il).second); // on récupère la référence // on récupère les trois tableaux de la référence const Tableau& tab_elem = refe->Tab_Elem(); // le tableau des numeros d'éléments //puis le tableau des numeros de faces, ou d'arêtes const Tableau& tab_entite = refe->Tab_FA(); // puis le tableau des pti const Tableau& tab_entite_pti = refe->Tab_Pti(); // on va travailler avec ces tableaux et ensuite on recréra une nouvelle référence avec de nouveaux tableaux int nb_el = tab_elem.Taille(); // premier passage on change les numéros int nb_element_supprime = 0; // nombre de elements supprimés for (int i=1; i<= nb_el; i++) { int num_ancien = refe->NumeroElem(i); // on vérifie que le element continue d'être valide if (non_referencer(num_ancien)) { if (ParaGlob::NiveauImpression() > 3) {if (fr) {cout << "\n suppression de l'element " << num_ancien << " dans la reference " << refe->Nom() << " maillage:" << num_mail ;} else {cout << "\n erasure of the element " << num_ancien << " in the reference " << refe->Nom() << " mesh :" << num_mail ;}; }; // on commence par mettre -100 dans le tableau de num et ensuite on retassera le tableau à la fin tab_elem(i) = -100; nb_element_supprime++; } else // sinon il faut le garder { // on vérifie que le numéro de la référence est licite (normalement il doit l'être) if ((num_ancien > 0) && (num_ancien <= nb_element)) {tab_elem(i) = nv_tab(num_ancien);} else {if (fr) {cout << "\n erreur dans la mise a jour d'une reference , le numero " << num_ancien << " de la liste " << " n'appartient pas a l'intervalle des elements disponibles [1," << nb_element << "] ";} else {cout << "\n error during the update of a reference, the number " << num_ancien << " in the list " << " does not belong to the range of existing elements [1," << nb_element << "] ";}; // debug cout << " \n non_referencer(num_ancien) " << non_referencer(num_ancien) << endl; refe->Affiche(); Sortie(1); }; }; }; // on crée 3 nouveaux tableaux Tableau tab_elem_new(nb_el-nb_element_supprime); // le nouveau tableau des numeros d'éléments //puis le tableau des numeros de faces, ou d'arêtes, Tableau tab_entite_new(nb_el-nb_element_supprime); //puis le tableau de points d'integ Tableau tab_entite_pti_new(nb_el-nb_element_supprime); // on va travailler avec ces tableaux et ensuite on mettra à jour la référence // second passage dans le cas où l'on a supprimé des elements if (nb_element_supprime) {// on recopie les grandeurs correctes int indice_new = 1; for (int i=1; i<= nb_el; i++) { if (tab_elem(i) != -100) {tab_elem_new(indice_new)=tab_elem(i); tab_entite_new(indice_new) = tab_entite(i); tab_entite_pti_new(indice_new) = tab_entite_pti(i); indice_new++; }; }; // on change les deux tableaux dans la référence refe->Change_tab_num(tab_elem_new,tab_entite_new,tab_entite_pti_new); // on supprime les doublons éventuels refe->Supprime_doublons_internes(); } else // sinon on ne fait que supprimer les doublons éventuels {refe->Supprime_doublons_internes();}; break; } }; }; }; // suppression d'une référence void LesReferences::SupprimeReference(const string & st1,int num_mail) { bool fr = ParaGlob::Francais(); // pour simplifier // tout d'abord on cherche la référence if (num_mail > t_mapDeRef.Taille()) { if (fr) {cout << " \n pb1 la reference de nom " << st1 << " pour le maillage nb= "<< num_mail << " n\'existe pas !! , on ne peut pas la supprimer " << endl;} else {cout << " \n pb1 the reference with name " << st1 << " for the mesh number= "<< num_mail << " does not exist !! , we cannot erase it " << endl;}; if (ParaGlob::NiveauImpression() >= 5) cout << "\n LesReferences::SupprimeReference(..."; Sortie (1); }; map < string, Reference*, std::less >::iterator il = t_mapDeRef(num_mail).find(st1); if (il == t_mapDeRef(num_mail).end()) { if (fr) {cout << " \n pb2 la reference de nom " << st1 << " pour le maillage nb= "<< num_mail << " n\'existe pas !! , on ne peut pas la supprimer " << endl;} else {cout << " \n pb2 the reference with name " << st1 << " for the mesh number= "<< num_mail << " does not exist !! , we cannot erase it " << endl;}; if (ParaGlob::NiveauImpression() >= 5) cout << "\n LesReferences::SupprimeReference(..."; Sortie (1); } else // sinon c'est ok { // on commence par effacer la référence if ((*il).second != NULL) {delete (*il).second;(*il).second=NULL;}; // puis on le suprime du tableau de map t_mapDeRef(num_mail).erase(il); }; }; // suppression de tous les référence d'un maillage donné // si avec_diminution_num_maillage = true: // tous les numéros de maillage, > num_mail, associé aux maillages qui restent // sont diminués de un, pour tenir compte de la disparition du maillage et donc // d'une nouvelle numérotation des maillages // si avec_diminution_num_maillage = false, le conteneur des ref de maillage num_mail // est vidé, mais il continu à exister: on considère qu'il y a toujours un maillage num_mail potentiel void LesReferences::Supprime_tour_lesRef_un_maillage(int num_mail, bool avec_diminution_num_maillage) {// bien que nbMaille ne serve pas a priori sans être initialisé // , pour éviter qu'il soit inchoérent, on le modifie éventuellement if (nbMaille > num_mail) {nbMaille = 1; // par défaut indic = 1; // toujours par défaut }; // on met à jour la t_mapDeRef map < string, Reference*, std::less >::iterator il,ilfin; map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(num_mail); // vérif int tai=t_mapDeRef.Taille(); if (num_mail <1) { cout << "\n erreur, impossible de supprimer les ref du maillage "< tai) // pas de référence enregistrées pour ce maillage // on ne fait rien et on revient return; // on supprime les ref ilfin = mapDeRef.end(); for (il = mapDeRef.begin();il != ilfin; il++) delete (*il).second; // suppression ou non du conteneur if (avec_diminution_num_maillage) { // on retasse le tableau for (int i=num_mail;i<=tai-1;i++) {t_mapDeRef(i)=t_mapDeRef(i+1); // on change les numéros de maillages map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i ); ilfin = mapDeRef.end(); for (il = mapDeRef.begin();il != ilfin; il++) (*il).second->Change_Nbmaille(i); }; // le fait de changer de taille supprime l'élément tai t_mapDeRef.Change_taille(tai-1); nbMaille--; // on diminue le nombre de maillage en service pour les ref }; }; //----- 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 LesReferences::Lecture_base_info(ifstream& entr,const int cas) {bool fr = ParaGlob::Francais(); // pour simplifier // pour l'instant nous n'avons que des références fixes if (cas == 1) {if (fr) {cout << " == lecture des references \n";} else {cout << " == reading of the references \n";}; // on commence par effacer les références existantes int taille = t_mapDeRef.Taille(); for (int i=1;i<=taille;i++) { map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i); map < string, Reference*, std::less >::iterator il,ilfin = mapDeRef.end(); for (il=mapDeRef.begin() ; il != ilfin; il++) if ((*il).second != NULL) {delete (*il).second;(*il).second=NULL;}; mapDeRef.erase(mapDeRef.begin(),mapDeRef.end()); }; // on lit et dimensionne le tableau string toto;int t_taille; entr >> toto >> t_taille ; t_mapDeRef.Change_taille(t_taille); for (int i=1;i<=t_taille;i++) { map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i); int nb_ref=0; entr >> toto >> nb_ref; // on boucle sur le nombre de référence à lire int indic; for (int i=1;i<= nb_ref; i++) { // lecture du type de référence entr >> toto >> indic; // création d'une référence ad hoc int nbMaille = -10; switch (indic) {// le numéro de maillage est mis en négatif pour indiquer qu'il est faux // il est ensuite lue à la bonne valeur par la référence case 1 : ref = new ReferenceNE(nbMaille,indic); break; case 2 : ref = new ReferenceNE(nbMaille,indic); break; case 3 : ref = new ReferenceAF(nbMaille,indic); break; case 4 : ref = new ReferenceAF(nbMaille,indic); break; case 5 : ref = new ReferenceAF(nbMaille,indic); break; case 6 : ref = new ReferenceAF(nbMaille,indic); break; case 7 : ref = new ReferencePtiAF(nbMaille,indic); break; case 8 : ref = new ReferencePtiAF(nbMaille,indic); break; default : if (fr) {cout << "\nErreur : valeur incorrecte du type de reference indic = " << indic << "\n";} else {cout << "\nError : incorrect value of the type of reference indic = " << indic << "\n";}; cout << "LesReferences::Lecture_base_info(..." ; Sortie(1); }; // lecture de la référence en question ref->Lecture_base_info(entr,cas); // intégration dans la map mapDeRef[ref->Nom()]=ref; }; }; }; }; // écriture base info // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void LesReferences::Ecriture_base_info(ofstream& sort,const int cas) {bool fr = ParaGlob::Francais(); // pour simplifier // pour l'instant nous n'avons que des références fixes if (cas == 1) {int t_taille = t_mapDeRef.Taille(); if (fr) {sort << "\n ****taille_tableau_references= " << t_taille << " ";} else {sort << "\n ****size_tab_references= " << t_taille << " ";}; for (int i=1;i<=t_taille;i++) { map < string, Reference*, std::less >& mapDeRef = t_mapDeRef(i); map < string, Reference*, std::less >::iterator il,ilfin=mapDeRef.end(); if (fr) {sort << "\n ****les_references_du_maillage"<LectureReference(entreePrinc)); // on supprime les doublons éventuels ref->Supprime_doublons_internes(); return retour; }; // retourne la reference correspondant a une cle Reference& LesReferences::Trouve_interne(const string & st1,int num_mail) const { if (num_mail > t_mapDeRef.Taille()) { if (ParaGlob::Francais()) {cout << " \n pb la reference de nom " << st1 << " pour le maillage nb= "<< num_mail << " n'existe pas \n";} else {cout << "\nError : the reference with the name " << st1 << " for the mesh nb= " << num_mail << " does not exist \n";} if (ParaGlob::NiveauImpression() >5) { cout << " \n LesReferences::Trouve(const string & st1,int num_mail) " << endl;}; Sortie (1); } else if (t_mapDeRef(num_mail).find(st1) == t_mapDeRef(num_mail).end()) { if (ParaGlob::Francais()) {cout << " \n pb la reference de nom " << st1 << " pour le maillage nb= "<< num_mail << " n'existe pas \n";} else {cout << "\nError : the reference with the name " << st1 << " for the mesh nb= " << num_mail << " does not exist \n";} if (ParaGlob::NiveauImpression() >5) { cout << " \n LesReferences::Trouve(const string & st1,int num_mail) " << endl;}; Sortie (1); }; // sinon c'est ok return *(t_mapDeRef(num_mail)[st1]); }; // idem mais avec un nom de maillage Reference& LesReferences::Trouve_interne(const string & st1,const string* nom_mail) const { // on regarde si le nom de maillage est licite if (nom_mail == NULL) { // acceptable que si l'on a un seul maillage #ifdef MISE_AU_POINT if (listeNomMail->size() != 1) if (ParaGlob::NiveauImpression() >2) { if (ParaGlob::Francais()) {cout << "\n warning: la reference demandee= " << st1 << " , n'a pas de nom de maillage associe" << " alors qu'il y a plusieurs maillage defini !! : on considere que c'est une ref du premier maillage";} else {cout << "\n warning: the wanted reference " << st1 << " , has no associated mesh " << " but several meshes exist !! : we consider that it is a ref for the first mesh ";} if (ParaGlob::NiveauImpression() >5) { if (ParaGlob::Francais()) {cout << "\n nom_de_maillages= ";} else {cout << "\n names of the meshes = ";} map < string, int , std::less >::const_iterator ili,ilifin=listeNomMail->end(); for (ili = listeNomMail->begin();ili != ilifin; ili++) cout << (*ili).first << ", " ; cout << "\n LesReferences::Trouve_interne(const string & st1,const string& nom_mail) "; }; // Sortie(1); }; #endif // on ramène le cas du premier maillage qui doit exister return Trouve_interne(st1,1); } else { #ifdef MISE_AU_POINT // on regarde si le nom de maillage existe dans la liste if (listeNomMail->find(*nom_mail) == listeNomMail->end()) { if (ParaGlob::Francais()) {cout << "\nErreur : le nom de maillage : " << *nom_mail << " n'existe pas \n";} else {cout << "\nError : the name of the mesh : " << *nom_mail << " does not exist \n";} if (ParaGlob::NiveauImpression() >5) cout << "LesReferences::Trouve_interne(const string & st1,const string& nom_mail) \n"; Sortie(1); } #endif return Trouve_interne(st1,(*(listeNomMail->find(*nom_mail))).second); }; };