// FICHIER : Noeud2.cp // CLASSE : Noeud // 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 "Noeud.h" #include "Util.h" #include #include "TypeQuelconqueParticulier.h" // ajout d'un type quelconque au noeud (il s'agit ici de définir le conteneur) // dans le cas où les types existent déjà, on ne fait rien // cas d'un tableau void Noeud::AjoutTabTypeQuelconque(const Tableau & tab_t_quel) {// on passe en revue le tableau transmis int tailt = tab_t_quel.Taille(); int tailtab = tab_type_quel.Taille(); // pour ne faire qu'une passe on crée un tableau d'existence Tableau tab_ex(tailt); int a_ajouter=0; // le nombre de grandeur à ajouter for (int i=1;i<=tailt;i++) { bool trouver = false; for (int j=1;j<=tailtab;j++) if (tab_type_quel(j).EnuTypeQuelconque()==tab_t_quel(i).EnuTypeQuelconque()) {trouver = true;break;}; if (!trouver) {a_ajouter++; tab_ex(i)=1;}; }; // dans le cas où il n'y a rien n'a ajouter on retourne if (a_ajouter == 0) return; // maintenant on ajoute vraiment tab_type_quel.Change_taille(tailtab+a_ajouter); update_type_quel.Change_taille(tailtab+a_ajouter); // =0 par défaut int compteur=1; for (int ii=1;ii<=tailt;ii++) {if (tab_ex(ii)==1) {tab_type_quel(tailtab+compteur).ChangeGrandeur(tab_t_quel(ii));compteur++;} }; // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour MiseAjourTypeQuelconque(); // mise en place de l'adressage directe }; // cas d'une seule grandeur quelconque void Noeud::AjoutUnTypeQuelconque(const TypeQuelconque & t_quel) {int tailtab = tab_type_quel.Taille(); // on n'ajoute que si la grandeur n'existe pas déjà bool existe=false; for (int j=1;j<=tailtab;j++) if (tab_type_quel(j).EnuTypeQuelconque()==t_quel.EnuTypeQuelconque()) {existe = true;break;}; if (!existe) { tab_type_quel.Change_taille(tailtab+1); update_type_quel.Change_taille(tailtab+1,0); // =0 par défaut tab_type_quel(tailtab+1).ChangeGrandeur(t_quel); // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour MiseAjourTypeQuelconque(); // mise en place de l'adressage directe }; }; // supprime une grandeur quelconque (si elle est présente) void Noeud::SupprimeUnTypeQuelconque(const TypeQuelconque & t_quel) { // récup du type TypeQuelconque_enum_etendu en = t_quel.EnuTypeQuelconque(); int nb=Existe(en); if ( nb != 0) {// dans le cas où la grandeur existe on la supprime int tai=tab_type_quel.Taille(); if ( update_type_quel(nb) != 0) nbTypeQ_update--; for (int i= nb;i & tab_t_quel) {// on passe en revue le tableau transmis int tailt = tab_t_quel.Taille(); int tailtab = tab_type_quel.Taille(); // pour ne faire qu'une passe on crée un tableau d'existence Tableau tab_in(tailtab); bool on_supprime=false; for (int i=1;i<=tailt;i++) { // on passe en revue le tableau fourni int num = Existe(tab_t_quel(i).EnuTypeQuelconque()); if (num != 0) {tab_in(num)=1; if ( update_type_quel(num) != 0) nbTypeQ_update--; on_supprime=true;}; }; // retour s'il n'y a rien à supprimer if (!on_supprime) return; // maintenant on supprime vraiment int i=1; // pointeur des grandeurs restantes for (int j=1;i<=tailtab;i++,j++) { // on passe en revue if (tab_in(j)!=1) { // grandeur à garder tab_type_quel(i).ChangeGrandeur(tab_type_quel(j)); update_type_quel(i)=update_type_quel(j); i++; }; }; // la valeur de i-1 = la taille à conserver tab_type_quel.Change_taille(i-1); // on met à jour le tableau de gestion d'indiçage indirecte MiseAjourTypeQuelconque(); }; // récupération d'une grandeur quelconque pour modification // après l'appel de cette méthode, la grandeur quelconque est réputée updaté TypeQuelconque& Noeud::ModifGrandeur_quelconque(TypeQuelconque_enum_etendu enu) { // récup de l'indice de la grandeur int indice = (*pos_Quelconque)(enu.Position()); // si le type n'était pas updaté on met à jour les 2 indicateurs if (update_type_quel(indice) == 0) {update_type_quel(indice)=1; nbTypeQ_update++;} else {update_type_quel(indice)++; }; return (tab_type_quel(indice)); }; // signale que toutes les grandeurs quelconques sont non-updatées void Noeud::Mise_non_update_grandeurs_quelconques() { int tailupdate = update_type_quel.Taille(); for (int i=1;i<=tailupdate;i++) update_type_quel(i)=0; nbTypeQ_update=0; // reset du nombre total }; // signale qu'une grandeur quelconque est non-updatées // en particulier la grandeur en question ne sera pas sauvegarder dans base_info void Noeud::Mise_non_update_grandeurs_quelconques(TypeQuelconque_enum_etendu enu) { // récup de l'indice int nb=Existe(enu); update_type_quel(nb)=0; nbTypeQ_update--; // met à jour du nombre total }; // ajout d'un ddl étendu (il s'agit ici de définir le conteneur) // dans le cas où les types existent déjà, on ne fait rien // cas d'un tableau void Noeud::AjoutTabDdl_etendu(const Tableau & t_ddletendu) {// on passe en revue le tableau transmis int tailt = t_ddletendu.Taille(); int tailtab = tab_ddletendu.Taille(); // pour ne faire qu'une passe on crée un tableau d'existence Tableau tab_ex(tailt,0); int a_ajouter=0; // le nombre de grandeur à ajouter int ttaill = tab_ddletendu.Taille(); for (int i=1;i<=tailt;i++) { bool trouver = false; // on passe en revue le tableau actuel for (int j=1;j<=tailtab;j++) if (tab_ddletendu(j).DdlEnumEtendu()==t_ddletendu(i)) {trouver = true;break;}; if (!trouver) {a_ajouter++; tab_ex(i)=1;}; }; // dans le cas où il n'y a rien n'a ajouter on retourne if (a_ajouter == 0) return; // maintenant on ajoute vraiment tab_ddletendu.Change_taille(tailtab+a_ajouter); update_ddletendu.Change_taille(tailtab+a_ajouter,0); // =0 par défaut int compteur=1; for (int ii=1;ii<=tailt;ii++) {if (tab_ex(ii)==1) {tab_ddletendu(tailtab+compteur)=t_ddletendu(ii); compteur++;}; }; // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour MiseAjourDdl_etendu(); // mise en place de l'adressage directe }; // cas d'un seul ddl étendu void Noeud::AjoutUnDdl_etendu(const Ddl_enum_etendu & ddlenumetendu) {int tailtab = tab_ddletendu.Taille(); // on n'ajoute que si la grandeur n'existe pas déjà bool existe=false; for (int j=1;j<=tailtab;j++) if (tab_ddletendu(j).DdlEnumEtendu()==ddlenumetendu) {existe = true;break;}; if (!existe) { tab_ddletendu.Change_taille(tailtab+1); update_ddletendu.Change_taille(tailtab+1,0); // =0 par défaut tab_ddletendu(tailtab+1)=Ddl_etendu(ddlenumetendu); // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour MiseAjourDdl_etendu(); // mise en place de l'adressage directe }; }; // supprime un ddl étendu (si il est présent) void Noeud::SupprimeUnDdl_etendu(const Ddl_enum_etendu & ddletendu) { // récup du type int nb=Existe_ddlEtendu(ddletendu); if ( nb != 0) {// dans le cas où la grandeur existe on la supprime int tai=tab_ddletendu.Taille(); if ( update_ddletendu(nb) != 0) nbddletendu_update--; for (int i= nb;i & t_ddletendu) {// on passe en revue le tableau transmis int tailt = t_ddletendu.Taille(); int tailtab = tab_ddletendu.Taille(); // pour ne faire qu'une passe on crée un tableau d'existence Tableau tab_in(tailtab); bool on_supprime=false; for (int i=1;i<=tailt;i++) { // on passe en revue le tableau fourni int num = Existe_ddlEtendu(t_ddletendu(i)); if (num != 0) {tab_in(num)=1; if ( update_type_quel(num) == 1) nbTypeQ_update--; on_supprime=true;}; }; // retour s'il n'y a rien à supprimer if (!on_supprime) return; // maintenant on supprime vraiment int i=1; // pointeur des grandeurs restantes for (int j=1;i<=tailtab;i++,j++) { // on passe en revue if (tab_in(j)!=1) { // grandeur à garder tab_ddletendu(i)=tab_ddletendu(j); update_ddletendu(i)=update_ddletendu(j); i++; }; }; // la taille à conserver update_ddletendu.Change_taille(i-1); tab_ddletendu.Change_taille(i-1); // on met à jour le tableau de gestion d'indiçage indirecte MiseAjourDdl_etendu(); }; // récupération d'un ddl étendu pour modification // après l'appel de cette méthode, le ddl étendu est réputée updaté Ddl_etendu& Noeud::ModifDdl_etendu(const Ddl_enum_etendu& ddletendu) { // récup de l'indice de la grandeur int indice = Existe_ddlEtendu(ddletendu); // si le type n'était pas updaté on met à jour les 2 indicateurs if (update_ddletendu(indice) == 0) {update_ddletendu(indice)=1; nbddletendu_update++;} else {update_ddletendu(indice)++;}; return (tab_ddletendu(indice)); }; // signale que toutes les ddl étendus sont non-updatées void Noeud::Mise_non_update_Ddl_etendu() { int tailupdate = update_ddletendu.Taille(); for (int i=1;i<=tailupdate;i++) update_ddletendu(i)=0; nbddletendu_update=0; // reset du nombre total }; // signale qu'un Ddl_etendu est non-updatées // en particulier le Ddl_etendu en question ne sera pas sauvegarder dans base_info void Noeud::Mise_non_update_Ddl_etendu(Ddl_enum_etendu ddlenumetendu) { // récup de l'indice de la grandeur int indice = Existe_ddlEtendu(ddlenumetendu); update_ddletendu(indice)=0; nbddletendu_update--; // met à jour du nombre total }; // ------------------------ procedures protegees ------------------------ // liaison des ddl et des deplacement a t et 0 // nb = le numero correspondant aux début des coordonnees dans les tableaux // de ddl void Noeud::Liaison_t(int nb) { // cas ou l'on est en coordonnees entrainees // 1) cas des coord0 // positionnement a l'adresse des coordonnees double * pt = &(tab_0(nb)); if (coord0 != NULL) // si les coordonnees existent deja on les sauvegarde // et on remplace les valeurs des ddl par les coor { Coordonnee truc(*coord0); delete coord0; // on passe un pointeur donc il n'y a pas de creation de memoire // dans le new coord0 = new Coordonnee(ParaGlob::Dimension(),pt); *coord0 = truc; } else // sinon on cree coord0 a la meme place que les ddl a t = 0 {coord0 = new Coordonnee(ParaGlob::Dimension(),pt); } // 2) cas des coord1 int dim = ParaGlob::Dimension(); if (coord1.Taille() == 0) { // il faut construire le tableau coord1.Change_taille(dim); for (int ii=1;ii<=dim;ii++) coord1(ii) = &(tab_ddl(nb+ii-1).Valeur()); } else if (coord1(1) == NULL) // tableau existant mais non affecte for (int ii=1;ii<=dim;ii++) coord1(ii) = &(tab_ddl(nb+ii-1).Valeur()); else // tableau existant et affecte, donc ici pas de pb a priori car lorsque les coordonnées à t // sont affectées elles le sont obligatoirement sur le tableau de ddl //les valeurs du tableau // de coordonnées vont etre misent a la place des valeurs de ddl for (int ii=1;ii<=dim;ii++) { double sa = *(coord1(ii)); // on ne supprime pas la valeur pointée car il n'y a jamais eu de new avec // l'allocation de coord1 // on réaffecte coord1(ii) = &(tab_ddl(nb+ii-1).Valeur()); // récup de la valeur *(coord1(ii)) = sa; } }; // liaison des ddl et des deplacement a tdt seulement // nb = le nb du début des deplacement dans les ddl void Noeud::LiaiSeuletdt(int nb) { // positionnement a l'adresse des coordonnees double * pt = &(tab_tdt(nb)); if (coord2 != NULL) // si les coordonnees existent deja on les sauvegarde // et on remplace les valeurs des ddl par les coor { Coordonnee truc(*coord2); delete coord2; coord2 = new Coordonnee(ParaGlob::Dimension(),pt); *coord2 = truc; } else // sinon on cree coord2 a la meme place que les ddl a tdt {coord2 = new Coordonnee(ParaGlob::Dimension(),pt); } }; // liaison des ddl et des deplacement a t,tdt et 0 // nb = le nb du début des deplacement dans les ddl void Noeud::Liaison_tdt(int nb) { // cas ou l'on est en coordonnees entrainees // 1) cas des coord0 et des coord1 Liaison_t(nb); // 2) cas des coord2 LiaiSeuletdt(nb); }; // mise a jour des tableaux et des liaisons void Noeud::MiseAjour() { // tout d'abord on regarde si tab_0 est correctement dimensionne int t1 = tab_0.Taille(); int t2 = tab_ddl.Taille(); if (t1 != t2) // cas ou le tableau de ddl a ete agrandi // on change la taille des tableaux. // on sauvegarde les coordonnées à 0 si elles sont liées if (Existe(X1)) { Coordonnee truc(*coord0); delete coord0; coord0 = new Coordonnee(truc); }; // maintenant on peut changer les tableaux { tab_0.Change_taille(t2); for (int i=t1+1;i<=t2;i++) tab_0(i) = tab_ddl(i).Valeur(); if ( tab_tdt.Taille() != 0) // cas ou le tableau tdt est en service tab_tdt.Change_taille(t2); } // on regarde ensuite s'il y a des liaisons entre ddl et deplacements int nb = Existe(X1); if (nb != 0) // cas ou il y a une liaison ddl coordonnées {double * pt0 = &((*coord0)(1)); if (pt0 != &(tab_0(nb))) // cas d'une mauvaise liaison, on remet à jour if (tab_tdt.Taille() == 0) // choix t ou t et tdt Liaison_t(nb); else Liaison_tdt(nb); else if (tab_tdt.Taille() != 0) // cas d'une bonne liaison pour t=0, reste le cas à tdt { if (coord2 != NULL) // cas ou les coord2 sont deja affectees { double * pt2 = &((*coord2)(1)); if (pt2 != &(tab_tdt(nb))) LiaiSeuletdt(nb); // cas pas affectees au bonne endroit } else // cas où il n'y avait pas encore de liaison LiaiSeuletdt(nb); // on affecte les coordonnees } } }; // mise a jour de l'adressage via l'identificateur d'énumération // c'est-à-dire la gestion via list_tab_enum et pos_enum // ne doit être appelé que si l'on a introduit un nouveau ddl !! // ou changé l'ordre etc.. void Noeud::MiseAjourEnum() { // tout d'abord on regarde si le dernier tableau construit dans la liste // convient, car ce sera le cas pour le cas courant // le dernier tableau est positionné en début de liste. list >::iterator ideb = list_tab_enum.begin(); list >::iterator iancien = pos_enum; int taille = tab_ddl.Taille(); // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position int ttail = (*ideb).Taille(); bool okk = true; // le test n'est effectué que si la liste n'est pas vide if (list_tab_enum.size() != 0) { // d'abort la taille, on compte le nombre d'élément non nul dans int ttaile = (*ideb)(ttail); if (taille != ttaile) okk = false; else // maintenant le contenu for (int i = 1; i<= taille;i++) if( (*ideb)(tab_ddl(i).Id_nom()) != i) { okk = false; break;} } else okk = false; // si le tableau convient on met à jour le pointeur et c'est fini // sinon on passe en revu toute la liste if (okk) pos_enum = ideb; else // ---- cas où on passe en revue la liste ----- // ici la procédure est plus longue, mais normalement elle ne sera // utilisé que peut souvent { // on reconstruit un tableau d'adressage indirect des ddl // la taille du tableau d'adressage est celui du nombre maxi // de type de ddl différent (donc certain ne serviron pas) // les données du tableau sont initialisées à 0, ainsi si l'on // cherche à utiliser un ddl indice 0, l'erreur sera détecté au // niveau de Tableau_T // l'avant dernier élément du tableau sert à stocker le nombre de noeud // qui utilise le tableau // le dernier élément indique le nombre d'élément non nul Tableau tab_indi_enum(NbEnum_ddl()+2,0); for (int i=1;i<=taille;i++) tab_indi_enum(tab_ddl(i).Id_nom())=i; // on enregistre la taille tab_indi_enum(NbEnum_ddl()+2) = taille; // maintenant on va regarder si ce tableau existe dans la liste list >::iterator ifin = list_tab_enum.end(); list >::iterator iter; bool trouver = false; for (iter = ideb;ideb!= ifin;ideb++) if ((*iter) == tab_indi_enum) { trouver = true; break;} // si pas trouver on ajoute sinon on utilise la position déjà existante if (!trouver) // cas où on n'a pas trouvé de tableau { list_tab_enum.push_front(tab_indi_enum); // allocation // on attribue le nouveau pointage pos_enum = list_tab_enum.begin(); // sauvegarde de la position } else // cas où on a trouvé un tableau dans la liste pos_enum = iter; } // --- gestions des tableaux ---- // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau // (permet de supprimer les tableaux qui ne servent plus) // on regarde si pos_enum était déjà attribué if (iancien != list_tab_enum.end()) // cas où ce n'est pas la première initialisation {if ((*iancien)(NbEnum_ddl()+1) == 1) // cas où c'est le dernier noeud qui pointe sur ce tableau // on supprime le tableau list_tab_enum.erase(iancien); else // sinon on décrémente le compteur ((*iancien)(NbEnum_ddl()+1))--; // maintenant on s'occupe du nouveau pointage ((*pos_enum)(NbEnum_ddl()+1))++; } else // c'est la première initialisation // on incrémente le compteur du tableau ((*pos_enum)(NbEnum_ddl()+1))++; }; // mise a jour du tableau des ddl de variable actives // et du tableau de ddl actives (variables et données) void Noeud::MiseAjourActif() { // ------- cas des variables uniquement -------- // tout d'abord on regarde le nombre de ddl actif int nbddlactif = 0; int tab_ddlTaille = tab_ddl.Taille(); for (int i = 1; i<=tab_ddlTaille; i++) if ((tab_ddl(i).Service())&&(tab_ddl(i).UneVariable())) nbddlactif++; // dimensionnement du tableau de pointeur if (tab_var_actives.Taille() != nbddlactif) { ////----- debug //if (num_noeud == 120) // {cout << "\n debug Noeud::MiseAjourActif()"; // for (int j = 1; j <= tab_var_actives.Taille(); j++) // cout << "\n tab_var_actives(" << j <<")= " // << tab_var_actives(j) << " "; // cout << endl; // }; ////----- fin debug tab_var_actives.Change_taille(nbddlactif); } // remplissage du tableau int indice = 1; for (short int i = 1; i<=tab_ddlTaille; i++) if ((tab_ddl(i).Service())&&(tab_ddl(i).UneVariable())) {tab_var_actives(indice) = i; indice++; } // -------- cas des données et des variables ---------- nbddlactif = 0; for (int i = 1; i<=tab_ddlTaille; i++) if (tab_ddl(i).Service()) nbddlactif++; // dimensionnement du tableau de pointeur if (tab_actif.Taille() != nbddlactif) tab_actif.Change_taille(nbddlactif); // remplissage du tableau indice = 1; for (short int i = 1; i<=tab_ddlTaille; i++) if (tab_ddl(i).Service()) {tab_actif(indice) = i; indice++; } }; // lecture des grandeurs quelconques sur flot void Noeud::Lecture_grandeurs_quelconque(istream & ent) { // la lecture est longue, ne sert que pour la visualisation en faite string nom; ent >> nom >> nbTypeQ_update; if (nbTypeQ_update != 0) // lecture que s'il y a des types updatées enregistrées { // tout d'abord on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); // lecture de l'entête et récup d'enu EnuTypeQuelParticulier enu = pour_lire.Lecture_un(ent); // on regarde si ce type quelconque existe déjà int indice = Indice_grandeur_quelconque(pour_lire.EnuTypeQuelconque()); if (indice == 0) { // cas d'une grandeur qui n'existe pas déjà, on la crée int tailtab = tab_type_quel.Taille();tailtab++; tab_type_quel.Change_taille(tailtab); update_type_quel.Change_taille(tailtab); // =0 par défaut // création d'une grandeur associée et lecture des information sur le flot TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); // création d'un type quelconque TypeQuelconque tq(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); delete grandeur; // car il ne sert plus à rien // affectation tab_type_quel(tailtab)=tq;update_type_quel(tailtab)=1; //normalement update } else { // cas d'une grandeur qui existe déjà ent >> tab_type_quel(indice);update_type_quel(indice)=1; //normalement update }; }; }; // écriture des grandeurs quelconques sur flot void Noeud::Ecriture_grandeurs_quelconque(ostream & sort) const { // on ne sauvegarde que les grandeurs updatées et qui sont prévu pour une sauvegarde sort << " G_quel " << nbTypeQ_update << " "; // en tête et nombre de grandeurs updatées int tailupdate = update_type_quel.Taille(); for (int i=1;i<=tailupdate;i++) { if (update_type_quel(i) != 0) sort << tab_type_quel(i) << " ";}; }; // récupe de l'indice d'une grandeur quelconque // si la grandeur n'existe pas -> ramène 0 int Noeud::Indice_grandeur_quelconque(const TypeQuelconque_enum_etendu& a) { int tailtab = tab_type_quel.Taille(); for (int i=posi_type_quel;i<=tailtab;i++) { if ( tab_type_quel(i).EnuTypeQuelconque() == a) { posi_type_quel=i; return i;} }; // cas on la grandeur a chercher est peut-être au début du tableau for (int j=1;j< posi_type_quel;j++) { if ( tab_type_quel(j).EnuTypeQuelconque() == a) { posi_type_quel=j; return j;} }; // cas où l'on n'a pas trouvé la grandeur return 0; }; // mise a jour de l'adressage via l'identificateur d'énumération // c'est-à-dire la gestion via list_tab_typeQuelconque et pos_Quelconque // ne doit être appelé que si l'on a introduit un nouveau type quelconque !! // ou changé l'ordre etc.. void Noeud::MiseAjourTypeQuelconque() { // la méthode sert à mettre à jour les différents indicateurs d'adressage rapides // 1-- s'il n'y a pas de type quelconque, on regarde si le pointeur de tableau a changé // utilisé par exemple par le destructeur, ou les constructeurs // on récupère le nombre maxi de type de grandeurs quelconques existantes actuellement // (ce nombre n'est pas forcément fixe pendant le calcul, on peut avoir de nouvelle grandeur qui // sont définit pendant le calcul : typiquement associée à de nouvelles grandeurs globales créées par // l'utilisateur: ex: le calcul d'une intégrale) int nbmaxTypeQ = TypeQuelconque_enum_etendu::NBmax_TypeQuelconque_enum_etendue(); if (tab_type_quel.Taille() == 0) // -> pas de type quelconque stocké { if (pos_Quelconque == list_tab_typeQuelconque.end()) // cela signifie qu'il n'y a jamais eu de type quelconque pour tous les noeuds // et qu'il n'y a rien à faire, retour directe {return;} else // sinon c'est le cas d'une destruction de types quelconques // on met à jour les indicateurs ad hoc { // l'avant dernier élément du tableau contient le nombre de noeud qui utilise ce type int taille_pos_quelconque = (*pos_Quelconque).Taille(); // on n'utilise pas nbmaxTypeQ car il peut varier pendant le calcul if ((*pos_Quelconque)(nbmaxTypeQ+1) == 1) if ((*pos_Quelconque)(taille_pos_quelconque-1) == 1) // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau list_tab_typeQuelconque.erase(pos_Quelconque); else // sinon on décrémente le compteur ((*pos_Quelconque)(taille_pos_quelconque-1))--; // puis on met à jour le pointeur pos_Quelconque = list_tab_typeQuelconque.end(); // -> veut dire pas de tableau associé // et retour return; }; }; // 2-- la suite concerne le cas où des types quelconque existent // tout d'abord on regarde si le dernier tableau construit dans la liste // convient, car ce sera le cas pour le cas courant // le dernier tableau est positionné en début de liste. list >::iterator ideb = list_tab_typeQuelconque.begin(); list >::iterator iancien = pos_Quelconque; int taille = tab_type_quel.Taille(); // nombre d'éléments quelconques actuellement stocké // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position bool okk = true; // le test n'est effectué que si la liste n'est pas vide if (list_tab_typeQuelconque.size() != 0) { // d'abort la taille, on compte le nombre d'élément non nul int ttail = (*ideb).Taille();// les deux dernières valeurs = le nombre de noeuds associés, le nombre de quelconque à considérer int ttaile = (*ideb)(ttail); // == le nombre de quelconque qui sont considérer if (taille != ttaile) // -> là c'est sûr que cela ne convient pas car déjà le nombre est différent okk = false; else // sinon on test les contenues // maintenant le contenu for (int i = 1; i<= taille;i++) if( (*ideb)(tab_type_quel(i).EnuTypeQuelconque().Position()) != i) { okk = false; break;} } else // si n'existe pas encore, il faut le créer {okk = false;}; // si le tableau convient on met à jour le pointeur et c'est fini // sinon on passe en revu toute la liste if (okk) {pos_Quelconque = ideb;} // cas ou on n'a pas à faire de création else // ---- cas où on passe en revue la liste : cas d'une création ----- // ici la procédure est plus longue, mais normalement elle ne sera // utilisé que peut souvent { // on reconstruit un tableau d'adressage indirect des types quelconques // la taille du tableau d'adressage est celui du nombre maxi // de type quelconques différent (donc certain ne serviront pas) // les données du tableau sont initialisées à 0, ainsi si l'on // cherche à utiliser un type quelconque indice 0, l'erreur sera détecté au // niveau de Tableau_T // l'avant dernier élément du tableau sert à stocker le nombre de noeud // qui utilise le tableau // le dernier élément indique le nombre d'élément non nul Tableau tab_indi_TypeQ(nbmaxTypeQ+2,0); for (int i=1;i<=taille;i++) tab_indi_TypeQ(tab_type_quel(i).EnuTypeQuelconque().Position())=i; // on enregistre la taille tab_indi_TypeQ(nbmaxTypeQ+2) = taille; // maintenant on va regarder si ce tableau existe dans la liste list >::iterator ifin = list_tab_typeQuelconque.end(); list >::iterator iter; bool trouver = false; for (iter = ideb;iter!= ifin;iter++) // if ((*iter) == tab_indi_TypeQ) if (tab_indi_TypeQ.Egalite_tranche(1,(*iter),nbmaxTypeQ)) { trouver = true; break;} // si pas trouver on ajoute sinon on utilise la position déjà existante if (!trouver) // cas où on n'a pas trouvé de tableau { list_tab_typeQuelconque.push_front(tab_indi_TypeQ); // allocation // on attribue le nouveau pointage pos_Quelconque = list_tab_typeQuelconque.begin(); // sauvegarde de la position } else // cas où on a trouvé un tableau dans la liste pos_Quelconque = iter; }; // --- gestions des tableaux ---- // l'idée est ici la suivante: si le pointeur de tableau: pos_Quelconque a changé par rapport à iancien // et que iancien était associé à un seul noeud, alors il faut le supprimer car il n'est plus associé à aucun noeud // évidemment ceci n'est a considérer que si iancien pointait sur quelque chose de valide int taille_pos_quelconque = (*pos_Quelconque).Taille(); // récup de la taille actuelle // on regarde si pos_Quelconque était déjà attribué // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau // (permet de supprimer les tableaux qui ne servent plus) if (iancien != pos_Quelconque) { // cas où on a changé de pointeur de tableau if (iancien != list_tab_typeQuelconque.end()) // cas où ce n'est pas la première initialisation {int taille_pos_ancien = (*iancien).Taille(); if ((*iancien)(taille_pos_ancien-1) == 1) // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau list_tab_typeQuelconque.erase(iancien); else // sinon on décrémente le compteur ((*iancien)(taille_pos_ancien-1))--; // maintenant on s'occupe du nouveau pointage ((*pos_Quelconque)(taille_pos_quelconque-1))++; } else // c'est la première initialisation // on incrémente le compteur du tableau: -> on ajoute 1 noeud ((*pos_Quelconque)(taille_pos_quelconque-1))++; }; // si iancien == pos_Quelconque, il n'y a pas eu de nouveau noeud ajouté, donc rien à faire }; // --- cas des Ddl_enum_etendu ---- // lecture des Ddl_enum_etendu sur flot void Noeud::Lecture_Ddl_etendu(istream & ent) { string nom; ent >> nom >> nbddletendu_update; tab_ddletendu.Change_taille(nbddletendu_update); ent >> nom >> update_ddletendu; int tailupdate = update_ddletendu.Taille(); for (int i=1;i<=tailupdate;i++) { if (update_ddletendu(i) != 0) ent >> tab_ddletendu(i) ;}; }; // écriture des Ddl_enum_etendu sur flot void Noeud::Ecriture_Ddl_etendu(ostream & sort) const { // on ne sauvegarde que les grandeurs updatées et qui sont prévu pour une sauvegarde sort << "\n G_ddletendu " << nbddletendu_update << " "; // en tête et nombre de grandeurs updatées // écriture du tableau d'update sort << "\n update_ddletendu: "<< update_ddletendu << " "; // sortie conditionnelle de tab_ddletendu int tailupdate = update_ddletendu.Taille(); for (int i=1;i<=tailupdate;i++) { if (update_ddletendu(i) != 0) sort << tab_ddletendu(i) << " ";}; }; // récupe de l'indice d'un Ddl_enum_etendu // si la grandeur n'existe pas -> ramène 0 int Noeud::Indice_Ddl_etendu(const Ddl_enum_etendu& a) { int tailtab = tab_ddletendu.Taille(); for (int i=posi_ddletendu;i<=tailtab;i++) { if ( tab_ddletendu(i).Const_DdlEnumEtendu() == a) { posi_ddletendu=i; return i;} }; // cas ou la grandeur a chercher est peut-être au début du tableau for (int j=1;j< posi_ddletendu;j++) { if ( tab_ddletendu(j).Const_DdlEnumEtendu() == a) { posi_ddletendu=j; return j;} }; // cas où l'on n'a pas trouvé la grandeur return 0; }; // mise a jour de l'adressage via l'identificateur d'énumération // c'est-à-dire la gestion via list_tab_ddletendu et pos_ddletendu // ne doit être appelé que si l'on a introduit un nouveau Ddl_enum_etendu !! // ou changé l'ordre etc.. void Noeud::MiseAjourDdl_etendu() { // la méthode sert à mettre à jour les différents indicateurs d'adressage rapides // 1-- s'il n'y a pas de ddl étendue, on regarde si le pointeur de tableau a changé // utilisé par exemple par le destructeur, ou les constructeurs int nbmaxddleten = Ddl_enum_etendu::NBmax_ddl_enum_etendue(); if (tab_ddletendu.Taille() == 0) { if (pos_ddletendu == list_tab_ddletendu.end()) // cela signifie qu'il n'y a jamais eu de ddl étendue et qu'il n'y a rien à faire, retour directe {return;} else // sinon c'est le cas d'une destruction des ddl étendue // on met à jour les indicateurs ad hoc { if ((*pos_ddletendu)(nbmaxddleten+1) == 1) // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau list_tab_ddletendu.erase(pos_ddletendu); else // sinon on décrémente le compteur ((*pos_ddletendu)(nbmaxddleten+1))--; // puis on met à jour le pointeur pos_ddletendu = list_tab_ddletendu.end(); // -> veut dire pas de tableau associé // et retour return; }; }; // 2-- la suite concerne le cas où il y a des ddl étendue // tout d'abord on regarde si le dernier tableau construit dans la liste // convient, car ce sera le cas courant // le dernier tableau est positionné en début de liste. list >::iterator ideb = list_tab_ddletendu.begin(); list >::iterator iancien = pos_ddletendu; int taille = tab_ddletendu.Taille(); // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position bool okk = true; // init // le test n'est effectué que si la liste n'est pas vide if (list_tab_ddletendu.size() != 0) { // d'abort la taille, on compte le nombre d'élément non nul int ttail = (*ideb).Taille(); // les deux dernières valeurs = le nombre de noeuds associés, le nombre de ddl enum étendu à considérer int ttaile = (*ideb)(ttail); if (taille != ttaile) okk = false; else // maintenant le contenu for (int i = 1; i<= taille;i++) if( (*ideb)(tab_ddletendu(i).Const_DdlEnumEtendu().Position()) != i) { okk = false; break;} } else {okk = false;}; // si le tableau convient on met à jour le pointeur et c'est fini // sinon on passe en revu toute la liste if (okk) pos_ddletendu = ideb; else // ---- cas où on passe en revue la liste ----- // ici la procédure est plus longue, mais normalement elle ne sera // utilisé que peu souvent { // on reconstruit un tableau d'adressage indirect des ddl étendu // la taille du tableau d'adressage est celui du nombre maxi // de ddl étendu différents (donc certain ne serviron pas) // les données du tableau sont initialisées à 0, ainsi si l'on // cherche à utiliser un ddl étendu indice 0, l'erreur sera détecté au // niveau de Tableau_T // l'avant dernier élément du tableau sert à stocker le nombre de noeud // qui utilise le tableau // le dernier élément indique le nombre d'élément non nul Tableau tab_indi_ddletendu(nbmaxddleten+2,0); for (int i=1;i<=taille;i++) tab_indi_ddletendu(tab_ddletendu(i).Const_DdlEnumEtendu().Position())=i; // on enregistre la taille tab_indi_ddletendu(nbmaxddleten+2) = taille; // maintenant on va regarder si ce tableau existe dans la liste list >::iterator ifin = list_tab_ddletendu.end(); list >::iterator iter; bool trouver = false; for (iter = ideb;ideb!= ifin;ideb++) if ((*iter) == tab_indi_ddletendu) { trouver = true; break;} // si pas trouver on ajoute sinon on utilise la position déjà existante if (!trouver) // cas où on n'a pas trouvé de tableau { list_tab_ddletendu.push_front(tab_indi_ddletendu); // allocation // on attribue le nouveau pointage pos_ddletendu = list_tab_ddletendu.begin(); // sauvegarde de la position } else // cas où on a trouvé un tableau dans la liste pos_ddletendu = iter; }; // --- gestions des tableaux ---- // l'idée est ici la suivante: si le pointeur de tableau: pos_ddletendu a changé par rapport à iancien // et que iancien était associé à un seul noeud, alors il faut le supprimer car il n'est plus associé à aucun noeud // évidemment ceci n'est a considérer que si iancien pointait sur quelque chose de valide // on regarde si pos_ddletendu était déjà attribué // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau // (permet de supprimer les tableaux qui ne servent plus) if (iancien != pos_ddletendu) { // cas où on a changé de pointeur de tableau if (iancien != list_tab_ddletendu.end()) // cas où ce n'est pas la première initialisation {if ((*iancien)(nbmaxddleten+1) == 1) // cas où c'est le dernier noeud qui pointe sur ce tableau // on supprime le tableau list_tab_ddletendu.erase(iancien); else // sinon on décrémente le compteur ((*iancien)(nbmaxddleten+1))--; // maintenant on s'occupe du nouveau pointage ((*pos_ddletendu)(nbmaxddleten+1))++; } else // c'est la première initialisation // on incrémente le compteur du tableau ((*pos_ddletendu)(nbmaxddleten+1))++; }; // si iancien == pos_ddletendu, il n'y a pas eu de nouveau noeud ajouté, donc rien à faire }; // ordonne et on met a suivre les ddl d'une même famille suivant un ordre croissant // ceci pour des ddl que l'on vient d'ajouter, QUE L'ON CONSIDÈRE ÊTRE À LA FIN DE TAB_DDL ! // en paramètre le ou les ddl /*void Noeud::OrdonneDdlMemeFamille(const Ddl& a) { // on ne traite que si la dimension est supérieur à 1 ou que le ddl fait partie d'une famille if ((ParaGlob::Dimension()>1)&&FoncDim(a.Id_nom())) {Enum_ddl enu=a.Id_nom(); int dim = ParaGlob::Dimension();// pour simplifier // On parcourt le tableau pour trouver les autres ddl de la même famille // et on en profite pour ordonner les ddl Tableau ptin(dim); int irecup=0; int taille=tab_ddl.Taille(); for (int i=0; i<= taille-1;i++) if (Meme_famille(tab_ddl(i).Id_nom(),enu)) {if (tab_ddl(i).Id_nom() > enu) Permutation_2ddl(i,taille); irecup++; ptin(irecup)=i; }; // -- maintenant les ddl de la même famille sont dans un ordre croissant, il reste // -- à les mettre à suivre // on continu que si effectivement il y a des autre ddl de la même famille if (irecup == 0) return; // retour car aucun ddl de la meme famille // on traite en fonction de irecup if (irecup == 1) {// cas sympathique ou l'on a simplement à permutter deux positions du tableau Enum_ddl enu1=tab_ddl(ptin(irecup)).Id_nom(); if (ptin(irecup)==taille-1) {return;}// cas déjà à suivre else // sinon on permutte le suivant de enu1 et enu {Permutation_2ddl(ptin(irecup)+1,taille);} } else // cas }; void Noeud::OrdonneDdlMemeFamille(const Tableau& ta) { }; // permutation de deux ddl (sert pour OrdonneDdlMemeFamille) void Noeud::Permutation_2ddl(const int& ipo1,cont int& ipo2) { // tout d'abord le ddl Ddl intir=tab_ddl(ipo1); tab_ddl(ipo1)=tab_ddl(ipo2); tab_ddl(ipo2)=intir; // maintenant les valeurs à 0 double xnia0=tab_0(ipo1); tab_0(ipo1)=tab_0(ipo2); tab_0(ipo2)=xnia0; // éventuellement les valeurs à tdt if (tab_tdt.Taille()!=0) { double xniatdt=tab_tdt(ipo1); tab_tdt(ipo1)=tab_tdt(ipo2); tab_tdt(ipo2)=xniatdt; }; }; */ // ordonner un tableau de ddl suivant un ordre croissant et avec des ddl à suivre void Noeud::OrdonnerTableauDdl(Tableau& ta) { int tataille = ta.Taille(); for (int i1=1;i1<=tataille;i1++) {for (int j1=i1+1;j1<=tataille;j1++) if (ta(i1).Id_nom() > ta(j1).Id_nom()) {// il ne sont pas dans le bonne ordre on permutte Ddl intir = ta(i1); ta(i1)=ta(j1); ta(j1)=intir; } } }; // liste des ddl (en famille) à ajouter // (la liste est initialisée au début) // recopie des ddl existant déjà // change_donn_var indique si les ddl existant on été modifiée void Noeud::ListeDdlAajouter(list& liDdl,Tableau& ta,bool& change_donn_var) { // dans la liste existante tous les ddl des familles existantes, sont présents // et ordonné dans chaque famille mais par forcément globalement, // par contre dans ta on peut avoir que certains représentants de famille // mais ta est également ordonnée // on regarde combien de Ddl existe deja list ::iterator il; liDdl.clear(); // init au début list li_travail; // une liste de travaille int j=1; int taille=tab_ddl.Taille(); int tataille=ta.Taille(); if (j>tataille) return; // cas d'un tableau vide do { bool rel = false;Enum_ddl enu=ta(j).Id_nom(); // on cherche si le ddl existe déjà for (int i=1;i<= taille; i++) {if (tab_ddl(i).Id_nom() == enu) { rel = true; tab_ddl(i) = ta(j); change_donn_var=true; j++; // on passe au suivant break; }; }; // cas où il n'y a pas de ddl existant if (!rel) {// dans le cas d'une famille: // on regarde si tous les ddl de la famille font partie de la liste if (FoncDim(enu) && (ParaGlob::Dimension()!=1)) {// on récupère tous les ddl de la famille Tableau t_enu =TableauTypeDdl(enu); int ttlle = t_enu.Taille(); // on regarde tout d'abord si les premiers ddl sont présents // sachant que enu est le plus petit de la famille ! (car ta est ordonné) int iy=0; for (iy=1;iy<=ttlle;iy++) {if (t_enu(iy)!=enu) { // on regarde également s'il est déjà dans la liste, si oui, on passe if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) {li_travail.push_back(t_enu(iy)); // on ajoute le ddl pour l'instant hors service et a priori libre Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE); liDdl.push_back(addl); }; } else { // on regarde également s'il est déjà dans la liste, si oui, on passe if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) {li_travail.push_back(t_enu(iy)); // il n'existe pas , on ajoute le bon ddl liDdl.push_back(ta(j)); } else // il exite, on met la bonne valeur { list ::iterator ith,ithfin=liDdl.end(); for (ith = liDdl.begin();ith!=ithfin;ith++) { if ((*ith).Id_nom() == t_enu(iy)) {(*ith)=ta(j);break;} }; }; break; }; }; iy++; // on passe à l'enu suivant des ddl de la famille // maintenant on balaie les enu restants si nécessaire j++; //on incrémente car on regarde l'élément suivant du tableau for (;iy<=ttlle;iy++) { if(j <= tataille) // donc j est valide { if ((t_enu(iy)!=ta(j).Id_nom())) { // on regarde également s'il est déjà dans la liste, si oui, on passe if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) {li_travail.push_back(t_enu(iy)); // on ajoute le ddl pour l'instant hors service et a priori libre Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE); liDdl.push_back(addl); }; } else { // on regarde également s'il est déjà dans la liste, si oui, on passe if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) {li_travail.push_back(t_enu(iy)); // il n'existe pas , on ajoute le bon ddl liDdl.push_back(ta(j)); } else // il exite, on met la bonne valeur { list ::iterator ith,ithfin=liDdl.end(); for (ith = liDdl.begin();ith!=ithfin;ith++) { if ((*ith).Id_nom() == t_enu(iy)) {(*ith)=ta(j);break;} }; }; break; }; } else // cas ou le j n'est plus valide on rajoute les ddl manquants { // on regarde également s'il est déjà dans la liste, si oui, on passe if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) {li_travail.push_back(t_enu(iy)); // on ajoute le ddl pour l'instant hors service et a priori libre Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE); liDdl.push_back(addl); }; }; }; } else // cas d'un ddl qui n'appartient pas à une famille // on l'ajoute tout simplement { liDdl.push_back(ta(j)); j++; }; }//-- fin du cas on on ajoute des ddl à la liste } while (j<=tataille) ; }; // modification du type de laison entre noeud éventuel avec init des tableaux de liaison // pour le cas d'assemblage nb_assemb void Noeud::Change_Enu_liason(int nb_assemb, Enum_liaison_noeud enu_liai ,const Tableau & tab_N_lier) { // on fait tout d'abord une petite vérification if (enu_liai && ((tab_N_lier.Taille() == 0))) { cout << "\n inchoerence !! on veut une liaison entre noeud mais le tableau de liaison est vide ! " << "\n nb_assemb= "<< nb_assemb << " Enum_liaison_noeud= "<< Nom_liaison_noeud(enu_liai) << " taille de tab_N_lier= " << tab_N_lier.Taille() << "\n Noeud::Change_Enu_liason(... "<; tab_ddl_lier = new Tableau < Tableau > ; }; // cas où il faut augmenter les tailles if (nb_assemb > tab_enu_liaison->Taille()) {tab_enu_liaison->Change_taille(nb_assemb); tab_ddl_lier->Change_taille(nb_assemb); }; // maintenant on renseigne les valeurs (*tab_enu_liaison)(nb_assemb) = enu_liai; (*tab_ddl_lier)(nb_assemb) = tab_N_lier; }; // suppression de tous les liaisons noeuds void Noeud::Suppression_tous_liaisons_noeuds() { if (tab_enu_liaison != NULL) delete tab_enu_liaison; if (tab_ddl_lier != NULL) delete tab_ddl_lier; }; // sortie du schemaXML: en fonction de enu void Noeud::SchemaXML_Noeud(ostream& sort,const Enum_IO_XML enu) { switch (enu) {case XML_TYPE_GLOBAUX: {// on définit des types pour un maillage sort << "\n " << "\n" << "\n " << "\n un numero et 3 coordonnees " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n"; break; } case XML_IO_POINT_INFO: { // définition d'une liste de noeuds // sort << "\n "; break; } }; };