// FICHIER : Noeud.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-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 "Noeud.h" #include "Util.h" #include #include "TypeQuelconqueParticulier.h" // variable globale à la classe short int Noeud::posi_type_quel = 1; short int Noeud::posi_ddletendu = 1; list > Noeud::list_tab_enum; List_io > Noeud::list_tab_posi_actif; List_io > Noeud::list_tab_typeQuelconque; // au début il n'y a rien dans la liste List_io > Noeud::list_tab_ddletendu; // au début il n'y a rien dans la liste // ------ méthode concernant laclass Posi_ddl_noeud ---------------- // surcharge de l'operateur de lecture istream & operator >> ( istream & ent, Posi_ddl_noeud & a) { // lecture du type et vérification string nomtype; ent >> nomtype; if (nomtype != "Posi_ddl_noeud") { Sortie(1); return ent; } // lecture des data ent >> a.nb_maillage >> a.nb_noeud >> a.enu ; return ent; }; // surcharge de l'operateur d'ecriture ostream & operator << ( ostream & sort,const Posi_ddl_noeud & a) { // écriture du type sort << " Posi_ddl_noeud " ; // les data sort << a.nb_maillage << " "<< a.nb_noeud << " "<< a.enu << " "; return sort; }; // Affiche les donnees liees au noeud void Posi_ddl_noeud::Affiche (ofstream& sort) const { // les data sort << " Posi_ddl_noeud " ; sort << nb_maillage << " "<< nb_noeud << " "<< enu << " "; }; // ------ fin des méthodes concernant la sous_class Posi_ddl_noeud ---------------- //========================================================================= // Fait appel au constructeur par defaut de Coordonnee et de Tableau // Constructeur se servant eventuellement d'un numero d'identification Noeud::Noeud (int num_id,int num_M): tab_0(),tab_ddl(),tab_tdt(),coord1() ,tab_var_actives(),tab_actif(),pos_enum(list_tab_enum.end()) ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) ,t_enum_s(),tab_type_quel(),update_type_quel(),nbTypeQ_update(0) ,tab_nb_Elem(),pos_Quelconque(list_tab_typeQuelconque.end()) ,pos_ddletendu(list_tab_ddletendu.end()) ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) { num_noeud=num_id; coord0 = NULL; coord2 = NULL; num_Mail = num_M; posi_type_quel = 1; MiseAjourEnum(); // mise en place de l'adressage directe MiseAjourDdl_etendu(); // cas des ddl étendue MiseAjourTypeQuelconque(); // cas des grandeurs quelconques }; // Constructeur utile quand seuls le numero d'identification et la // dimension de l'espace sont connus Noeud::Noeud (int num_id,int dimension,int num_M): tab_0(),tab_ddl(),tab_tdt(),coord1(),tab_var_actives(),tab_actif() ,pos_enum(list_tab_enum.end()) ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) ,t_enum_s(),tab_type_quel() ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() ,pos_Quelconque(list_tab_typeQuelconque.end()) ,pos_ddletendu(list_tab_ddletendu.end()) ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) { num_noeud=num_id; coord0 = new Coordonnee(dimension); coord2 = NULL; num_Mail = num_M; posi_type_quel = 1; MiseAjourEnum(); // mise en place de l'adressage directe MiseAjourDdl_etendu(); // cas des ddl étendue MiseAjourTypeQuelconque(); // cas des grandeurs quelconques }; // Constructeur pour un noeud dont le numero et les coordonnees initiales // sont connus Noeud::Noeud (int num_id,const Coordonnee& c0,int num_M): tab_0(),tab_ddl(),tab_tdt(),coord1(),tab_var_actives(),tab_actif() ,pos_enum(list_tab_enum.end()) ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) ,t_enum_s(),tab_type_quel() ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() ,pos_Quelconque(list_tab_typeQuelconque.end()) ,pos_ddletendu(list_tab_ddletendu.end()) ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) { num_noeud=num_id; coord0 = new Coordonnee(c0); coord2 = NULL; num_Mail = num_M; posi_type_quel = 1; MiseAjourEnum(); // mise en place de l'adressage directe MiseAjourDdl_etendu(); // cas des ddl étendue MiseAjourTypeQuelconque(); // cas des grandeurs quelconques }; // Constructeur fonction d'un numero d'identification, des coordonnees // initiales et du tableau des degres de liberte // les ddl t=0 sont initialises avec les valeurs du tableaux // sauf coord0 qui est initialise avec c0 // par defaut les tableaux de ddl a 0 et t sont initialises mais pas // a t+dt Noeud::Noeud (int num_id,const Coordonnee& c0,const Tableau& tab,int num_M): tab_ddl(tab),tab_0(tab_ddl.Taille()),tab_tdt(),coord1() ,tab_var_actives(),tab_actif() ,pos_enum(list_tab_enum.end()) ,baseB(NULL),baseB_t(NULL),baseB_0(NULL) ,posiAssemb(),t_enum_s(),tab_type_quel() ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() ,pos_Quelconque(list_tab_typeQuelconque.end()) ,pos_ddletendu(list_tab_ddletendu.end()) ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) { num_noeud=num_id; coord0 = NULL; coord2 = NULL; num_Mail = num_M; // init de tab_0 for (int i=1;i<=tab_0.Taille();i++) tab_0(i) = tab_ddl(i).Valeur(); // cas ou l'on est en coordonnees entrainees if ( Existe(X1) != 0) { Liaison_t(Existe(X1)); *coord0 = c0; } // cas ou les ddl sont separes des coordonnees else { coord0 = new Coordonnee(c0); }; posi_type_quel = 1; // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); MiseAjourEnum(); // mise en place de l'adressage directe MiseAjourDdl_etendu(); // cas des ddl étendue MiseAjourTypeQuelconque(); // cas des grandeurs quelconques }; // Constructeur fonction d'un numero d'identification, des coordonnees // initiales, a un instant t, et du tableau des degres de liberte // les ddl t=0 sont initialises avec les valeurs du tableaux // par defaut les tableaux de ddl a 0 et t sont initialises mais pas // a t+dt // les ddl corespondant a Xi sont ajoute s'ils n'existaient pas // et il y a automatiquement liaison entre ddl et coordonnées Noeud::Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Tableau& tab,int num_M): tab_ddl(tab),tab_0(tab_ddl.Taille()),tab_tdt(),coord1(c1.Dimension()) ,tab_var_actives(),tab_actif() ,pos_enum(list_tab_enum.end()) ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) ,t_enum_s(),tab_type_quel() ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() ,pos_Quelconque(list_tab_typeQuelconque.end()) ,pos_ddletendu(list_tab_ddletendu.end()) ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) { num_noeud=num_id; coord0 = NULL; coord2 = NULL; num_Mail = num_M; // init de tab_0 #ifdef MISE_AU_POINT // vérification de la dimension de tab_ddl if (tab.Taille() < c1.Dimension()) { cout << "\nErreur : dans le constructeur de noeud : "; cout << " Noeud (int num_id,Coordonnee& c0,Coordonnee& c1," << "const Tableau& tab,int num_M)\n"; Sortie(1); }; #endif for (int i=1;i<=tab_0.Taille();i++) tab_0(i) = tab_ddl(i).Valeur(); // cas ou l'on est en coordonnees entrainees int posi_X1=0; // init if ( Existe(X1) == 0) { // le ddl X1 n'existe pas on le rajoute int an = tab_ddl.Taille(); tab_ddl.Change_taille(an+Dimension()); tab_0.Change_taille(an+Dimension()); for (int jj=1;jj<=Dimension();jj++) tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); posi_X1 = an+1; // c'est la position du ddl X1 } else // sinon il existe on récupère sa position posi_X1 = Existe(X1) ; // on effectue la liaison ddl/ deplacement Liaison_t(posi_X1); // (Existe(X1)); *coord0 = c0; for (int j=1;j<= Dimension();j++) *(coord1(j)) = c1(j); posi_type_quel = 1; // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); MiseAjourEnum(); // mise en place de l'adressage directe MiseAjourDdl_etendu(); // cas des ddl étendue MiseAjourTypeQuelconque(); // cas des grandeurs quelconques }; // Constructeur pour un noeud dont le numero, les coordonnees initiales, aux // instant t et t+dt ainsi que le tableau des degres de liberte sont connus // comme les coordonnées à t+dt sont données cela signifie qu'ils sont des // degrés de liberté // les ddl corespondant a Xi sont ajoute s'ils n'existaient pas // et il y a automatiquement liaison entre ddl et coordonnées Noeud::Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Coordonnee& c2, const Tableau& tab,int num_M): tab_ddl(tab),tab_0(tab.Taille()),tab_tdt(tab.Taille()),coord1(c1.Dimension()) ,tab_var_actives(),tab_actif() ,pos_enum(list_tab_enum.end()) ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) ,t_enum_s(),tab_type_quel() ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() ,pos_Quelconque(list_tab_typeQuelconque.end()) ,pos_ddletendu(list_tab_ddletendu.end()) ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) { num_noeud=num_id; coord0 = NULL; coord2 = NULL; num_Mail = num_M; // init de tab_0 #ifdef MISE_AU_POINT // vérification de la dimension de tab_ddl if (tab.Taille() < c1.Dimension()) { cout << "\nErreur : dans le constructeur de noeud : "; cout << " Noeud (int num_id,Coordonnee& c0,Coordonnee& c1,Coordonnee& c2," << "const Tableau& tab,int num_M)\n"; Sortie(1); }; #endif int tab0Taille = tab_0.Taille(); for (int i=1;i<=tab0Taille;i++) tab_0(i) = tab_ddl(i).Valeur(); // on est en coordonnees entrainees, on vérifie que les ddl XI // sont présent sinon on rajoute int posi_X1=0; // init if ( Existe(X1) == 0) { // le ddl X1 n'existe pas on rajoute les XI int an = tab_ddl.Taille(); tab_ddl.Change_taille(an+Dimension()); tab_0.Change_taille(an+Dimension()); tab_tdt.Change_taille(an+Dimension()); for (int jj=1;jj<=Dimension();jj++) tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); posi_X1 = an+1; // c'est la position du ddl X1 } else // sinon il existe on récupère sa position posi_X1 = Existe(X1) ; // on effectue la liaison ddl/ deplacement, donc la mémoire // des coordonnées est positionnée dans le tableau de ddl Liaison_tdt(posi_X1); // (Existe(X1)); // Liaison_tdt(Existe(X1)); *coord0 = c0; // recopie des valeurs *coord2 = c2; // """" for (int j=1;j<= Dimension();j++) *(coord1(j)) = c1(j); posi_type_quel = 1; // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); MiseAjourEnum(); // mise en place de l'adressage directe MiseAjourDdl_etendu(); // cas des ddl étendue MiseAjourTypeQuelconque(); // cas des grandeurs quelconques }; // Constructeur de copie Noeud::Noeud (const Noeud& nd): tab_0(nd.tab_0),tab_ddl(nd.tab_ddl),tab_tdt(nd.tab_tdt),coord1() ,tab_var_actives(nd.tab_var_actives),tab_actif(nd.tab_actif) ,pos_enum(nd.pos_enum) ,posiAssemb(nd.posiAssemb),baseB(NULL),baseB_t(NULL) // on définit ensuite la base ,baseB_0(NULL) ,t_enum_s(nd.t_enum_s) ,tab_type_quel(nd.tab_type_quel),update_type_quel(nd.update_type_quel) ,nbTypeQ_update(0),tab_nb_Elem(nd.tab_nb_Elem) ,pos_Quelconque(list_tab_typeQuelconque.end()) // idem ddl étendues ,pos_ddletendu(list_tab_ddletendu.end()) // c'est dans la méthode MiseAjourDdl_etendu, que le pointeur sera mis à jour ,nbddletendu_update(nd.nbddletendu_update) ,tab_ddletendu(nd.tab_ddletendu),update_ddletendu(nd.update_ddletendu) // pour les liaisons cinématiques: pas de recopie, il s'agit d'un stockage uniquement: // l'utilisation et la manipulation est à la charge des classes appelantes ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) { num_noeud=nd.num_noeud; coord2 = NULL; // initialisation num_Mail = nd.num_Mail; if ( Existe(X1) != 0) { coord0 = NULL; // traitement des liaisons et avec du cas de coord1 if ( tab_tdt.Taille() != 0) // cas avec les coordonnees a t+dt //on effectue la liaison ddl/ deplacement Liaison_tdt(Existe(X1)); else // sinon uniquement à t Liaison_t(Existe(X1)); } else {if (nd.coord0 != NULL) {coord0 = new Coordonnee(*(nd.coord0)); } else {coord0 = NULL; }; }; // cas d'une base locale éventuelle if (nd.baseB != NULL) {baseB = new BaseB(*nd.baseB);}; if (nd.baseB_t != NULL) {baseB_t = new BaseB(*nd.baseB_t);}; if (nd.baseB_0 != NULL) {baseB_0 = new BaseB(*nd.baseB_0);}; posi_type_quel = nd.posi_type_quel; // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); // pour les grandeurs quelconques, a priori on les met "non a jour" // la mise à jour nécessite l'appel explicite à l'ordre de mise à jour if (update_type_quel.Taille() != 0) { int t_typTaille = update_type_quel.Taille(); for (int titq=1;titq<= t_typTaille;titq++) update_type_quel(titq)=0; }; MiseAjourDdl_etendu(); // cas des ddl étendue MiseAjourTypeQuelconque(); // cas des grandeurs quelconques }; Noeud::~Noeud() // Destructeur de Noeud utilisant les destructeurs // de Coordonnee et de Tableau { delete coord0; // le choix de la destruction ou pas de la zone //mémoire est fait dans coord0 if (coord2 != NULL) delete coord2; // on n'efface pas le tableau coord2 car s'il existe (c-a-d différent de null) il représente aussi // des degrés de liberté, donc il se situe au même endroit que les éléments de tab_tdt // qui lui sera de toute façon détruit par le destructeur automatique // pour les enum étendus, on utilise la méthode MiseAjourDdl_etendu(), pour que tout soit cohérent // on commence par supprimer les tableaux ad hoc et ensuite on met à jour tab_ddletendu.Libere();update_ddletendu.Libere();nbddletendu_update=0; MiseAjourDdl_etendu(); // idem pour les grandeurs quelconques tab_type_quel.Libere(); update_type_quel.Libere(); nbTypeQ_update=0; MiseAjourTypeQuelconque(); // cas des grandeurs quelconques // dans le cas ou il existe des liaisons cinématiques on supprime les conteneurs Suppression_tous_liaisons_noeuds(); // cas où il existe une base locale if (baseB_0 != NULL) delete baseB_0; if (baseB_t != NULL) delete baseB_t; if (baseB != NULL) delete baseB; }; // surcharge de l'operator de lecture, avec typage istream & operator >> (istream & ent, Noeud & noe) { // lecture du type et vérification string nomType,nom; ent >> nomType; if (nomType != "Noeud") { Sortie(1); return ent; }; // puis le numéro de noeud et le numéro de maillage ent >> noe.num_noeud >> noe.num_Mail ; // les liaisons éventuelles bool test; ent >> nom >> test; // tab_enu_liaison if (test) { int nb;int toto; ent >> nb; if (noe.tab_enu_liaison != NULL) {noe.tab_enu_liaison->Change_taille(nb);} else {noe.tab_enu_liaison = new Tableau (nb);}; for (int i=1;i<= nb;i++) { ent >> nom >> toto >> nom; (*noe.tab_enu_liaison)(i) = Id_nom_liaison_noeud(nom); }; } else {if (noe.tab_enu_liaison != NULL) { delete noe.tab_enu_liaison; noe.tab_enu_liaison = NULL;} }; ent >> nom >> test; // tab_ddl_lier if (test) { int nb;int toto; ent >> nb; if (noe.tab_ddl_lier != NULL) {noe.tab_ddl_lier->Change_taille(nb);} else {noe.tab_ddl_lier = new Tableau >(nb);}; for (int i=1;i<= nb;i++) ent >> nom >> toto >> (*noe.tab_ddl_lier)(i); } else {if (noe.tab_ddl_lier != NULL) { delete noe.tab_ddl_lier; noe.tab_ddl_lier = NULL;} }; // le tableau des degrés de liberté ent >> noe.tab_ddl; // coordonnee initiale on les récupère par défaut // ensuite on fera la mise à jour ent >> *(noe.coord0); ent >> nom >> noe.tab_0; // valeurs a l'instant 0 des ddl ent >> nom >> noe.tab_tdt; // valeurs a l'instant t+dt des ddl // les coordonnees a un instant t et tdt sont reconstruit avec // la mise à jour si nécessaire noe.MiseAjour(); // vérif si les coordonnees a un instant t+dt existent // si oui liaison ent >> nom; if (nom == "coord2Existe") noe.Liaison_tdt(noe.Existe(X1)); // ent >> nom >> noe.tab_var_actives; // les numéros des ddl actifs // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl noe.MiseAjourActif(); noe.MiseAjourEnum(); // mise en place de l'adressage directe // %% cas des types quelconques éventuelles %% noe.Lecture_grandeurs_quelconque(ent); // idem pour les ddl_etendu noe.Lecture_Ddl_etendu(ent); // cas d'une base locale éventuelle {int existe_base; ent >> existe_base; if (existe_base == 1) {if (noe.baseB_0 == NULL) {noe.baseB_0=new BaseB();}; ent >> nom >> (*noe.baseB_0); }; ent >> existe_base; if (existe_base == 1) {if (noe.baseB_t == NULL) {noe.baseB_t=new BaseB();}; ent >> nom >> (*noe.baseB_t); }; ent >> existe_base; if (existe_base == 1) {if (noe.baseB == NULL) {noe.baseB=new BaseB();}; ent >> nom >> (*noe.baseB); }; }; return ent; }; // surcharge de l'operator d'ecriture avec typage ostream & operator << (ostream & sort , const Noeud & noe) { // le type, le numéro de noeud et le numéro de maillage sort << "Noeud " << noe.num_noeud << " " << noe.num_Mail ; // les liaisons éventuelles if (noe.tab_enu_liaison != NULL) { sort << "\n tab_enu_liaison " << 1 << " "; // on signale la présence du tableau int nb = (noe.tab_enu_liaison)->Taille(); sort << nb << " "; for (int i=1;i<= nb;i++) sort << " ass: "<< i << Nom_liaison_noeud((*noe.tab_enu_liaison)(i)) << " "; } else sort << "\n tab_enu_liaison " << 0 << " "; // on signale l'absence du tableau ; if (noe.tab_ddl_lier != NULL) { sort << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau int nb = (noe.tab_ddl_lier)->Taille(); sort << nb << " "; for (int i=1;i<= nb;i++) sort << "\n ass: "<< i << " "<< (*noe.tab_ddl_lier)(i); } else sort << "\n tab_ddl_lier " << 0 << " "; // on signale l'absence du tableau ; // le tableau des degrés de liberté sort << noe.tab_ddl; // coordonnee initiale on les sauvegarde par défaut // ensuite on fera la mise à jour sort << *(noe.coord0); sort << " ddl_a_0 " << noe.tab_0; // valeurs a l'instant 0 des ddl sort << " ddl_a_tdt " << noe.tab_tdt; // valeurs a l'instant t+dt des ddl // les coordonnees a un instant t ne sont pas sauvegardées elles seront // reconstruites si besoin avec la mise à jour // coordonnee a un instant t+dt on signale son existence if (noe.coord2 != NULL) sort << "coord2Existe \n"; else sort << "pascoord2 \n"; // sort << "ddl_actif " << noe.tab_var_actives; // les numéros des ddl actifs // %% cas des types quelconques éventuelles %% noe.Ecriture_grandeurs_quelconque(sort); // idem pour les ddl_etendu noe.Ecriture_Ddl_etendu(sort); // cas d'une base locale éventuelle if (noe.baseB_0 != NULL) {sort << "\n 1 base_locale_0: " << (*noe.baseB_0);} else {sort << "\n 0 base_locale_0: "; }; if (noe.baseB_t != NULL) {sort << "\n 1 base_locale_t: " << (*noe.baseB_t);} else {sort << "\n 0 base_locale_t: "; }; if (noe.baseB != NULL) {sort << "\n 1 base_locale: " << (*noe.baseB);} else {sort << "\n 0 base_locale: "; }; return sort; }; // lecture du noeud en mémoire void Noeud::Lecture(UtilLecture *entreePrinc) { int numero; Coordonnee co(Dimension()); // def d'un tableau de coordonnées *(entreePrinc->entree) >> numero ; // lecture brut des coordonnées sans la dimension co.Lecture(*entreePrinc); Change_coord0(co); // transmission a noeud if (numero != num_noeud) { cout << " ***ATTENTION dans la lecture du noeud "; cout << " le numero d identification du noeud attribue par " << " le constructeur (" << num_noeud << ") est different de celui lu !!! " << " (" << numero << ") " << " Noeud::Lecture((UtilLecture *entreePrinc) " << endl ; }; }; // affichage et definition interactive des commandes // coor: des coordonnees fixée pour un affichage different pour chaque noeud void Noeud::Info_commande_Noeud(UtilLecture * entreePrinc,Coordonnee& co,int numero) { ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier int dima = ParaGlob::Dimension(); sort << "\n" << setw (6) << numero <<" "; double sero = 0.; #ifndef ENLINUX_STREAM sort.setf(ios_base::scientific); #else sort.setf(ios::scientific); #endif // sort.setf(ios_base::scientific); for (int j=1;j<=3;j++) if (j<=dima) sort << setw (18) << setprecision(ParaGlob::NbdigdoCA()) < 0) {// les liaisons éventuelles if (tab_enu_liaison != NULL) { cout << "\n tab_enu_liaison " << 1 << " "; // on signale la présence du tableau int nb = (tab_enu_liaison)->Taille(); cout << nb << " "; for (int i=1;i<= nb;i++) cout << " ass: "<< i << Nom_liaison_noeud((*tab_enu_liaison)(i)) << " "; } else cout << "\n tab_enu_liaison " << 0 << " "; // on signale l'absence du tableau ; if (tab_ddl_lier != NULL) { cout << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau int nb = (tab_ddl_lier)->Taille(); cout << nb << " "; for (int i=1;i<= nb;i++) cout << "\n ass: "<< i << " "<< (*tab_ddl_lier)(i); } else cout << "\n tab_ddl_lier " << 0 << " "; // on signale l'absence du tableau ; }; cout << "Coordonnee(s) initiale(s) du noeud : \n"; coord0->Affiche(); if (coord1.Taille() != 0) { cout << "Coordonnee(s) a l'instant t : \n"; Coord1().Affiche(); } if (coord2 != NULL) { cout << "Coordonnee(s) a l'instant t+dt : \n"; coord2->Affiche(); } cout << "Degre(s) de liberte lie(s) au noeud : \n"; cout << "Taille du tableau : " << tab_ddl.Taille() << " , a 0, a t ( et t+dt ?)\n"; for (int i=1;i<=tab_ddl.Taille();i++) { if (tab_0.Taille() != 0) cout << tab_0(i) << " "; tab_ddl(i).Affiche(); if (tab_tdt.Taille() != 0) cout << tab_tdt(i) << " "; }; // affichage éventuelle des grandeurs enum étendue stockées au noeud int tail_tab_ddletendu = tab_ddletendu.Taille(); if (tail_tab_ddletendu != 0) {cout << "\nddl_etendu: "; for (int itq=1;itq<=tail_tab_ddletendu;itq++) {Ddl_etendu& ddlenum = tab_ddletendu(itq); if (ddlenum.DdlEnumEtendu().Nom_vide()) { cout << Nom_ddl(ddlenum.DdlEnumEtendu().Enum()) ;} else { cout << ddlenum.DdlEnumEtendu().Nom() ;}; cout << " " << ddlenum.ConstValeur()<< " "; }; }; // affichage éventuelle des grandeurs quelconques stockées au noeud int tail_tab_type_quel = tab_type_quel.Taille(); if (tail_tab_type_quel != 0) {cout << "\nddl_quelconque: "; for (int itq=1;itq<=tail_tab_type_quel;itq++) {cout << tab_type_quel(itq).EnuTypeQuelconque().NomPlein() << " " << *(tab_type_quel(itq).Grandeur_pointee()) << " \n"; }; }; // cas d'une base locale éventuelle if (baseB_0 != NULL) {cout << "\n base_locale_0: " << (*baseB_0);} if (baseB_t != NULL) {cout << "\n base_locale_t: " << (*baseB_t);} if (baseB != NULL) {cout << "\n base_locale: " << (*baseB);} // dans le cas ou la variable niveau est plus grande que 0 on affiche plus d'information if (niveau > 0) { cout << "\n le tableau d'adressage directe " << (* pos_enum) << endl; }; cout << "-- fin noeud --\n"; }; // Affiche les donnees liees au noeud void Noeud::Affiche (ofstream& sort) const { // l'entete sort << " Numero : [ " << num_noeud << " ]****/////, du maillage: < "<< num_Mail << " > "; // les liaisons éventuelles if (tab_enu_liaison != NULL) { int nb = (tab_enu_liaison)->Taille(); sort << nb << " liaison(s) (ass,type): "; for (int i=1;i<= nb;i++) sort << i << " " << Nom_liaison_noeud((*tab_enu_liaison)(i)) << " "; }; if (tab_ddl_lier != NULL) { cout << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau int nb = (tab_ddl_lier)->Taille(); sort << nb << " , ddl_lie(s) (ass,maill,noe,enu): "; for (int i=1;i<= nb;i++) sort << i << " "<< (*tab_ddl_lier)(i); }; sort << " =======================\n"; // les coordonnees sort << "Coord t=0 : "; coord0->Affiche(sort,16); sort << ", " ; if (coord1.Taille() != 0) { sort << "\nCoord a t : "; Coord1().Affiche(sort,16); sort << ", " ;}; if (coord2 != NULL) {sort << "\nCoord a t+dt: " ; coord2->Affiche(sort,16); sort << ", " ;}; // les ddl et variations sort << '\n' << tab_ddl.Taille() << " Ddl a "; if (tab_0.Taille() != 0) sort << " <<0>> "; sort << " <> ( et variation) "; if (tab_tdt.Taille() != 0) sort << " <> (et variation) : \n"; for (int i=1;i<=tab_ddl.Taille();i++) { sort << tab_ddl(i).Nom() << " = "; // le nom if (tab_0.Taille() != 0) sort << setw (16) << tab_0(i) << ", "; // val a t=0 sort << setw (16) << tab_ddl(i).Valeur() << " "; // val a t if (tab_0.Taille() != 0) sort << "( " << setw (16) << (tab_ddl(i).Valeur() - tab_0(i)) << "), "; // delta 0 t if (tab_tdt.Taille() != 0) sort << setw (16) << tab_tdt(i) << " "; // val a tdt if ((tab_0.Taille() != 0)&&(tab_tdt.Taille() != 0)) sort << "(" << setw (16) << (tab_tdt(i) - tab_0(i)) << " );"; // deltat 0 tdt // decalage pour la ligne suivante sort << "\n"; }; // affichage éventuelle des grandeurs quelconques stockées au noeud int tail_tab_type_quel = tab_type_quel.Taille(); for (int itq=1;itq<=tail_tab_type_quel;itq++) {sort << (tab_type_quel(itq).EnuTypeQuelconque()).NomPlein() << " " << *(tab_type_quel(itq).Grandeur_pointee()) << " \n"; }; // cas d'une base locale éventuelle if (baseB_0 != NULL) {sort << "\n base_locale_0: " << (*baseB_0);} if (baseB_t != NULL) {sort << "\n base_locale_t: " << (*baseB_t);} if (baseB != NULL) {sort << "\n base_locale: " << (*baseB);} sort << "\n"; }; // insert des coordonnees coord1 si elles n'existent pas encore // permet de définir des coordonnées à t, dans ce cas des ddl XI sont inclus // et sont mis inactif par défaut void Noeud::Insert_coord1(const Coordonnee& nouveau_coord1) { // si les coordonnées n'existe pas encore il faut les créer if ( Existe(X1) == 0) { // le ddl X1 n'existe pas on le rajoute int an = tab_ddl.Taille(); tab_ddl.Change_taille(an+Dimension()); tab_0.Change_taille(an+Dimension()); int dim = Dimension(); for (int jj=1;jj<=dim;jj++) tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); // on effectue la liaison ddl/ deplacement Liaison_t(Existe(X1)); // on met les XI hors service for (int i = 1; i<=dim; i++) tab_ddl(an+i).Met_hors_service(); // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); MiseAjourEnum(); // mise en place de l'adressage directe }; // copie des ddl for (int i=1;i<=coord1.Taille();i++) *(coord1(i)) = nouveau_coord1(i); }; // idem mais sans paramètre indique que l'on initialise aux coordonnées à t=0 // s'ils n'existent pas, sinon on ne fait rien void Noeud::Insert_coord1() { // si les coordonnées n'existe pas encore il faut les créer if ( Existe(X1) == 0) { // le ddl X1 n'existe pas on le rajoute int an = tab_ddl.Taille(); tab_ddl.Change_taille(an+Dimension()); tab_0.Change_taille(an+Dimension()); int dim = Dimension(); for (int jj=1;jj<=dim;jj++) tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); // on effectue la liaison ddl/ deplacement // donc le ddl X1 se situe maintenant à la place an+1 dans le tableau // des ddl Liaison_t(an+1); //(Existe(X1)); // on met les XI hors service for (int i = 1; i<=dim; i++) tab_ddl(an+i).Met_hors_service(); // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); MiseAjourEnum(); // mise en place de l'adressage directe // copie des ddl for (int i=1;i<=coord1.Taille();i++) *(coord1(i)) = (*coord0)(i); }; }; // Modifie les valeurs des coordonnees coord1 void Noeud::Change_coord1(const Coordonnee& nouveau_coord1) { // si les coordonnées n'existe pas encore il faudrait les créer avant de les utiliser #ifdef MISE_AU_POINT // vérif if ((nouveau_coord1.Dimension() != Dimension()) || (coord1.Taille() == 0) || ((coord1(1)) == NULL)) { cout << "\nErreur : dans l'affectation de coordonnées à t, elles ne sont pas définies !\n"; cout << " Noeud::Change_coord1(Coordonnee& nouveau_coord1)\n"; Sortie(1); } #endif for (int i=1;i<=coord1.Taille();i++) *(coord1(i)) = nouveau_coord1(i); }; // Retourne les coordonnees coord1 du noeud // uniquement pour la lecture //Coordonnee Noeud::Coord1 () // { int nbcoo = coord1.Taille(); // Coordonnee coo(nbcoo); // for (int i=1;i<=nbcoo;i++) // coo(i) = *(coord1(i)); // return coo; // }; // Retourne le nombre de degres de liberte du noeud // qui sont actuellement actifs //int Noeud::Nombre_var_ddl_actives () // { int total = 0; // int imax = tab_ddl.Taille(); // for (int i=1;i<=imax;i++) // if (tab_ddl(i).Service()) total ++; // return total; // }; // retourne la liste de tous les types de ddl actuellement utilisé // par le noeud (actif ou non) List_io Noeud::Les_type_de_ddl(bool) { int tail = tab_ddl.Taille(); List_io tab_enum; for (int i= 1;i<= tail;i++) tab_enum.push_back(tab_ddl(i).Id_nom()); return tab_enum; }; // retourne la liste de tous les Ddl_enum_etendu disponible List_io Noeud::Les_type_de_ddl_etendu(bool) { int tail = tab_ddletendu.Taille(); List_io tab_enum_etendu; for (int i= 1;i<= tail;i++) tab_enum_etendu.push_back(tab_ddletendu(i).Const_DdlEnumEtendu()); return tab_enum_etendu; }; // retourne la liste de tous les TypeQuelconque disponibles List_io Noeud::Les_TypeQuelconque(bool ) { int tail = tab_type_quel.Taille(); List_io tab_TypeQuelconque; for (int i= 1;i<= tail;i++) tab_TypeQuelconque.push_back(tab_type_quel(i)); return tab_TypeQuelconque; }; // récupération d'une liste d'info // le tableau de retour à la taille de li_enu_scal et contient // les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud // en fait ici on cumule les ddl pur "et" les ddl_étendue, // li_quelc : est modifié par les valeurs contenues au noeud Tableau Noeud::Valeur_multi_et_Tensorielle (const List_io & li_enu_scal,List_io & li_quelc) const {int nb_ddl_enum_etendu = li_enu_scal.size(); // la taille du tableau de retour Tableau tab_ret(nb_ddl_enum_etendu); // le tableau de retour // on balaie les ddl_enum_etendu pour les alimenter {List_io ::const_iterator il,il_fin = li_enu_scal.end(); int i_tab=1; // init for (il= li_enu_scal.begin(); il != il_fin; il++,i_tab++) { // on regarde s'il s'agit d'un ddl pur const Ddl_enum_etendu& ddl = (*il); // pour simplifier if (ddl.Nom_vide()) // cas d'un ddl pur { if (Existe_ici(ddl.Enum())) {tab_ret(i_tab)= Valeur_tdt(ddl.Enum());} else {cout << "\n *** erreur d'acces, le ddl "<< Nom_ddl(ddl.Enum()) << " n'est pas disponible au temps tdt " << "\n Noeud::Valeur_multi_et_Tensorielle(..."; Noeud::Affiche(0); Sortie(1); }; } else // cas d'un ddl étendu { if (Existe_ici_ddlEtendu(ddl)) {tab_ret(i_tab)= DdlEtendue(ddl).ConstValeur();} else {cout << "\n *** erreur d'acces, le ddl etendue "<< ddl.Nom_plein() << " n'est pas disponible au temps tdt " << "\n Noeud::Valeur_multi_et_Tensorielle(..."; Noeud::Affiche(0); Sortie(1); }; }; }; }; //on balaie les types quelconques {List_io ::iterator il,il_fin = li_quelc.end(); int i_tab=1; // init for (il= li_quelc.begin(); il != il_fin; il++,i_tab++) { TypeQuelconque& etq = (*il); // pour simplifier // on regarde s'il existe TypeQuelconque_enum_etendu en = etq.EnuTypeQuelconque(); // pour simplifier if (Existe_ici(en)) { etq = Grandeur_quelconque(en);} else {// on test s'il s'agit d'un type correspondant à une grandeur // stockée naturellement au noeud bool trouver = false; // init if(en.Nom_vide()) // on ne prend en compte que les types initiaux {switch (en.EnumTQ()) { case NUM_NOEUD: { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) (etq.Grandeur_pointee())); *(gr.ConteneurEntier()) = this->Num_noeud(); trouver = true; break; } case NUM_MAIL_NOEUD: { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) (etq.Grandeur_pointee())); *(gr.ConteneurEntier()) = this->Num_Mail(); trouver = true; break; } case POSITION_GEOMETRIQUE: {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee())); (*gr.ConteneurCoordonnee())= this->Coord2(); trouver = true; break; } case POSITION_GEOMETRIQUE_t: {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee())); (*gr.ConteneurCoordonnee())= this->Coord1(); trouver = true; break; } case POSITION_GEOMETRIQUE_t0: {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee())); (*gr.ConteneurCoordonnee())= this->Coord0(); trouver = true; break; } //*** fin default: trouver = false; break; }; }; if (!trouver) {cout << "\n *** erreur d'acces, le ddl "<< en.NomPlein() << " n'est pas disponible " << "\n Noeud::Valeur_multi_et_Tensorielle(..."; Noeud::Affiche(0); Sortie(1); }; }; }; }; // retour return tab_ret; }; // ramene le nombre de variables ddl actives pour un type de ddl donné, // c'est-à-dire 1 ou la dimension, suivant que le type dépend // ou pas de la dimension int Noeud::Nombre_var_ddl_actives (Enum_ddl en) const { int retour = 0; if ((Existe(en) != 0) && (En_service(en)) && (UneVariable(en))) { switch (TypeGrandeur(en)) { case SCALAIRE : retour=1; break; case VECTEUR : case COORDONNEE : // là il y a un mélange pas sain ! // dans le cas où le calcul est axisymétrique // on ne prend pas en compte le 3 ième ddl if (ParaGlob::AxiSymetrie()) {retour = 2; }// on est forcément en 3D else {retour=ParaGlob::Dimension();}; break; case TENSEUR : retour = ParaGlob::NbCompTens(); break; case RIEN_TYPEGRANDEUR : retour = 0; break; default : cout << "\nErreur : valeur incorrecte du type Enum_ddl !\n"; cout << "Nombre_var_ddl_actives (Enum_ddl en) \n"; Sortie(1); }; }; return retour; }; // surcharge de l'affectation entre deux noeuds Noeud& Noeud::operator= (const Noeud& nd) { // recopie des tableaux tab_0 = nd.tab_0; tab_ddl = nd.tab_ddl; tab_tdt = nd.tab_tdt; num_Mail = nd.num_Mail; // // liaison éventuelle // enu_liaison = nd.enu_liaison; // noeud_lier = nd.noeud_lier; // puis les variables num_noeud=nd.num_noeud; posiAssemb = nd.posiAssemb; // cas d'une base locale éventuelle if (nd.baseB != NULL) {if (baseB != NULL) { (*baseB) = (*(nd.baseB));} else {baseB = new BaseB(*nd.baseB);}; } else // cas où nulle { if (baseB != NULL) delete baseB;} if (nd.baseB_t != NULL) {if (baseB_t != NULL) { (*baseB_t) = (*(nd.baseB_t));} else {baseB_t = new BaseB(*nd.baseB_t);}; } else // cas où nulle { if (baseB_t != NULL) delete baseB_t;} if (nd.baseB_0 != NULL) {if (baseB_0 != NULL) { (*baseB_0) = (*(nd.baseB_0));} else {baseB_0 = new BaseB(*nd.baseB_0);}; } else // cas où nulle { if (baseB_0 != NULL) delete baseB_0;} coord2 = NULL; // initialisation if ( Existe(X1) != 0) { // on met à null coord0 pour éviter de prendre ses valeurs coord0 = NULL; if ( tab_tdt.Taille() != 0) // cas avec les coordonnees a t+dt //on effectue la liaison ddl/ deplacement Liaison_tdt(Existe(X1)); else Liaison_t(Existe(X1)); } else // cas où il n'y a pas de liaison {coord0 = new Coordonnee(*(nd.coord0)); // la taille de coord1 est initialisé à 0 par défaut }; tab_var_actives = nd.tab_var_actives;tab_actif = nd.tab_actif; pos_enum = nd.pos_enum; // mise en place de l'adressage directe t_enum_s = nd.t_enum_s; // mise en place // dans le cas où il y a des ddl_etendu // on recopie les différents tableaux et on met à jour tab_ddletendu=nd.tab_ddletendu; update_ddletendu=nd.update_ddletendu; nbddletendu_update=nd.nbddletendu_update; // on ne recopie pas le pointeur pos_ddletendu, car se sera dans la méthode MiseAjourDdl_etendu // qu'il sera mis à jour MiseAjourDdl_etendu(); // dans le cas où il y a des grandeurs quelconques (mêmes remarques que dans le cas des enum étendus) tab_type_quel = nd.tab_type_quel; update_type_quel = nd.update_type_quel; nbTypeQ_update = nd.nbTypeQ_update; MiseAjourTypeQuelconque(); return (*this); }; // initialisation d'un ou de plusieurs nouveaux cas d'assemblage void Noeud::InitNouveauCasAssemb(int nb_cas) { // récup de la taille actuelle int taille_actuelle = posiAssemb.Taille(); // nouvelle taille int nouvelle_taille = taille_actuelle + nb_cas; // changement de taille, normalement les anciennes valeurs sont gardée // en début de tableau posiAssemb.Change_taille(nouvelle_taille); t_enum_s.Change_taille(nouvelle_taille); // on initialise les nouveaux éléments -> pour l'instant pointe sur rien // car c'est la fin de la liste for (int i= taille_actuelle+1;i<= nouvelle_taille;i++) t_enum_s(i)=list_tab_posi_actif.end(); }; // enregistrement de l'ordre des variables ddl actives, ceci pour un cas d'assemblage // donné, cette fonction permet ensuite d'utiliser la fonction // Position_ddl qui donne la position d'un ddl pour un cas d'assemblage // donné void Noeud::Enreg_ordre_variable_ddl_actives(int nb_assemb) { // l'objectif est de déterminer ou de construire s'il n'existe pas, un tableau // indexé par les types énumérés des ddl actifs // le programme est construit sur le même modèle que MiseAjourEnum() // mais ici on ne s'intéresse qu'au ddl actif List_io >::iterator& pos_enum_s = t_enum_s(nb_assemb); // pour simplifier // tout d'abord on regarde si le dernier tableau construit dans la liste // list_tab_posi_actif, convient, car ce sera le cas pour le cas courant // le dernier tableau est positionné en début de liste. List_io >::iterator ideb; ideb = list_tab_posi_actif.begin(); List_io >::iterator iancien = pos_enum_s; int taille = tab_var_actives.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_posi_actif.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(tab_var_actives(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_s = 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(tab_var_actives(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_io >::iterator ifin = list_tab_posi_actif.end(); List_io >::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_posi_actif.push_front(tab_indi_enum); // allocation // on attribue le nouveau pointage pos_enum_s = list_tab_posi_actif.begin(); // sauvegarde de la position } else // cas où on a trouvé un tableau dans la liste pos_enum_s = iter; }; // on regarde si pos_enum_s était déjà attribué if (iancien != list_tab_posi_actif.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_posi_actif.erase(iancien); else // sinon on décrémente le compteur ((*iancien)(NbEnum_ddl()+1))--; // maintenant on s'occupe du nouveau pointage ((*pos_enum_s)(NbEnum_ddl()+1))++; } else // c'est la première initialisation // on incrémente le compteur du tableau ((*pos_enum_s)(NbEnum_ddl()+1))++; }; // test si le noeud est complet // = 1 tout est ok, =0 element incomplet int Noeud::TestComplet() const { bool ret=true; if ((num_noeud == -3) || (num_Mail == -3)) { if (num_noeud == -3) cout << "\n le numero du noeud n'est pas defini"; if (num_Mail == -3) cout << "\n le numero de maillage n'est pas defini"; if (ParaGlob::NiveauImpression() >= 6) this->Affiche(); ret = false; } if (tab_ddl.Taille() == 0) { cout << "\n ***** warning : il n'y a pas de ddl rattache au noeud " << num_noeud << ", du maillage " << num_Mail; // ret = false; // maintenant normalement ce n'est plus un pb } else { int nbdd = tab_ddl.Taille(); for (int i=1;i<= nbdd ;i++) if (tab_ddl(i).TestComplet() == 0) { cout << "\n probleme avec le ddl " << i << "du noeud " << num_noeud << ", du maillage " << num_Mail; ret = false; }; // if (posiAssemb.Taille() == 0) return 0; }; return ret; }; // ajout de ddl // 1) s'il n'y a pas de ddl il y a initialisation // 2) si les ddl existent deja, on égalise au ddl passé en paramètre // 3) lorsque le ddl appartient à une famille, tous les ddl de la famille sont // ajoutées, les ddl supplémentaires ont une valeurs par défaut nulle void Noeud::PlusDdl(Ddl& a) { // on regarde si le tableau des ddl existant est vide int taille = tab_ddl.Taille(); if (taille == 0) { tab_ddl.Change_taille(1); tab_ddl(1) = a; // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour MiseAjourEnum(); // mise en place de l'adressage directe // mise a jour des tableaux et des liaisons ddl/deplacement MiseAjour(); } else { // on regarde si le Ddl existe for (int i=1;i<= taille; i++) // on test uniquement sur l'identificateur du ddl, ces caractéristiques // pouvant être différents suite à un précédent calcul if ((tab_ddl(i)).Id_nom() == a.Id_nom()) { tab_ddl(i) = a; MiseAjourActif(); return; }; // dans le cas où la dimension est supérieur à 1 et que le ddl appartient // à une famille dépendant de la dimension, on ajoute tous les ddl de la famille Enum_ddl enu = a.Id_nom(); if ((ParaGlob::Dimension()>1)&&FoncDim(enu)) {// on récupère tous les ddl de la famille Tableau t_enu =TableauTypeDdl(enu); // fabrication d'un tableau de ddl associé int ttaille = t_enu.Taille(); Tableau t_ddl(ttaille,a);// tous les nouveaux ddl on le même statut que a for (int il=1;il<=ttaille;il++) {t_ddl(il).Change_nom(t_enu(il)); if (t_ddl(il).Id_nom() != enu) t_ddl(il).Valeur() = 0.; // mise à 0 pour les valeurs des ddl supplémentaires } // appel de la méthode gérant un tableau de ddl PlusTabDdl(t_ddl); return; }; // dans le cas ou la dimension est supérieur à 1 et que les ddl est un XI // erreur // if ( (PremierDdlFamille(a.Id_nom())==X1) && (ParaGlob::Dimension() != 1)) // { cout <<"\n Erreur, la dimension etant superieur a 1 il n'est pas " // << " possible d'ajouter qu'un seul ddl de position \n"; // cout << "void Noeud::PlusDdl(Ddl& a)" << endl; // Sortie (1); // } // on regarde s'il y a une incompatibilite Xi Ui if ((Existe_ici(X1) && (PremierDdlFamille(a.Id_nom())==UX)) || (Existe_ici(UX) && (PremierDdlFamille(a.Id_nom())==X1)) || (Existe_ici(UY) && (PremierDdlFamille(a.Id_nom())==X1)) || (Existe_ici(UZ) && (PremierDdlFamille(a.Id_nom())==X1)) ) { cout <<"\n Erreur, on ne peut pas avoir de coordonnees entrainees" << " avec des ddl Ui \n"; cout << "void Noeud::PlusDdl(Ddl& a)" << endl; Sortie (1); }; // sauvegarde éventuelle des coordonnées if (coord0 != NULL) // il existe déjà des coordonnées 0 // si les coordonnees existent deja on les sauvegarde dans une //instance réelle et non éventuellement pointé // sera ensuite modifié avec MiseAjour() éventuellement { Coordonnee truc(*coord0); delete coord0; coord0 = new Coordonnee(truc); }; int coord1Taille = coord1.Taille(); Vecteur* toto = NULL; if (coord1Taille != 0) // signifie qu'il y a une liaison entre les ddl à t et coord1 if (coord1(1) != NULL) // tableau existant et affecte, on cré un tableau //intermédiaire, qui est supprimé à la fin de la routine toto = new Vecteur(coord1Taille); // réécriture dans toto, place qui sera utilisée dans mise à jour // puis après MiseAjour() suppression de toto for (int ii=1;ii<=coord1Taille;ii++) { (*toto)(ii) = *(coord1(ii)); coord1(ii) = &(*toto)(ii); }; if (coord2 != NULL) // il existe déjà des coordonnées finales // si les coordonnees existent deja on les sauvegarde dans // une instance réelle et non éventuellement pointé { Coordonnee truc(*coord2); delete coord2; coord2 = new Coordonnee(truc); }; // maintenant on peut changer le tableau de ddl // on augmente la taille du tableau tab_ddl.Change_taille(taille+1); tab_ddl(taille+1) = a; // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour MiseAjourEnum(); // mise en place de l'adressage directe // mise a jour des tableaux et des liaisons ddl/deplacement MiseAjour(); if (toto != NULL) delete toto; }; // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); // MiseAjourEnum(); // mise en place de l'adressage directe }; // ajout d'un tableau de ddl // 1) s'il n'y a pas de ddl il y a initialisation // 2) si les ddl existent deja, on égalise avec les ddl passés en par // 3) lorsque un nouveau ddl appartient à une famille, et que tous les ddl de la famille // ne sont pas présents dans les ddl passés en paramètre, tous les ddl manquant de la famille sont // ajoutées, avec une valeurs par défaut nulle void Noeud::PlusTabDdl(Tableau& ta) { // on commence par ordonner le tableau ta OrdonnerTableauDdl(ta); // maintenant tous les ddl de ta sont dans le bonne ordre et à suivre // on regarde si le tableau est vide int taille = tab_ddl.Taille(); if (taille == 0) { tab_ddl = ta; // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour MiseAjourEnum(); // mise en place de l'adressage directe // mise a jour des tableaux et des liaisons ddl/deplacement MiseAjour(); } else {// on regarde combien de Ddl existe deja // et on crée une liste des ddl à ajouter // les ddl qui existent déjà sont éventuellement updaté list liDdl; bool change_donn_var=false; ListeDdlAajouter(liDdl,ta,change_donn_var); // on augmente la taille du tableau en consequence // mais auparavant dans le cas où les coordonnées sont connues // que sous la forme de valeurs pointées il faut les sauvegarder if (liDdl.size() == 0) { // dans le cas où on a aucun ddl a ajouter // on regarde cependant si il y a eu un changement de type if (change_donn_var) MiseAjourActif(); return; } else { // sauvegarde éventuelle des coordonnées if (coord0 != NULL) // il existe déjà des coordonnées 0 // si les coordonnees existent deja on les sauvegarde // dans une instance réelle et non éventuellement pointé { Coordonnee truc(*coord0); delete coord0; coord0 = new Coordonnee(truc); }; int coord1Taille = coord1.Taille(); Vecteur* toto = NULL; if (coord1Taille != 0) if (coord1(1) != NULL) {// tableau existant et affecte, on crée un tableau intermédiaire, // qui est supprimé à la fin de la routine toto = new Vecteur(coord1Taille); // réécriture dans toto, place qui sera utilisée dans mise à jour // puis après MiseAjour() suppression de toto for (int ii=1;ii<=coord1Taille;ii++) { (*toto)(ii) = *(coord1(ii)); coord1(ii) = &(*toto)(ii); }; }; if (coord2 != NULL) // il existe déjà des coordonnées finales // si les coordonnees existent deja on les sauvegarde dans // une instance réelle et non éventuellement pointé { Coordonnee truc(*coord2); delete coord2; coord2 = new Coordonnee(truc); }; // maintenant on peut changer le tableau de ddl int nbddl_a_ajouter=liDdl.size(); tab_ddl.Change_taille(taille+nbddl_a_ajouter); // on rempli le tableau list ::iterator il=liDdl.begin(); for (int j1=1;j1<= nbddl_a_ajouter;j1++,il++) { tab_ddl(taille+j1)=(*il);}; // on peut maintenant mettre en place l'adressage directe // ce qui permettra d'utiliser Existe(..) dans MiseAjour par exemple MiseAjourEnum(); // mise en place de l'adressage directe // on regarde s'il y a une incompatibilite Xi Ui int tab_ddlTaille = tab_ddl.Taille(); if (Existe_ici(X1)) for (int i=1;i<= tab_ddlTaille;i++) if (Meme_famille(tab_ddl(i).Id_nom(),UX)) { cout <<"\n Erreur, on ne peut pas avoir de coordonnees entrainees" << " avec des ddl Ui \n"; cout << "void Noeud::PlusTabDdl(Tableau& ta)" << endl; Sortie (1); }; // mise a jour des tableaux et des liaisons ddl/deplacement MiseAjour(); if (toto != NULL) delete toto; }; }; // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl MiseAjourActif(); // MiseAjourEnum(); // mise en place de l'adressage directe }; // ajout du tableau de ddl d'un autre noeud void Noeud::PlusTabDdl(const Noeud & noe) { // on récupère le tableau de ddl géné par noe Tableau ta = noe.tab_ddl; if (ta.Taille() != 0) Noeud::PlusTabDdl(ta); }; // modification du statut d'un ddl // si en est inconnu, aucune action void Noeud::Met_hors_service(Enum_ddl en) { tab_ddl(Existe(en)).Met_hors_service(); MiseAjourActif(); }; void Noeud::Met_en_service(Enum_ddl en) { tab_ddl(Existe(en)).Met_en_service(); MiseAjourActif(); }; // modification du statut d'un tableau de ddl // si un des elements du tableau est inconnu, aucune action void Noeud::Met_hors_service(const Tableau& taben) { int tabenTaille = taben.Taille(); for (int i = 1; i<=tabenTaille; i++) tab_ddl(Existe(taben(i))).Met_hors_service(); MiseAjourActif(); }; void Noeud::Met_en_service(const Tableau& taben) { int tabenTaille = taben.Taille(); for (int i = 1; i<=tabenTaille; i++) tab_ddl(Existe(taben(i))).Met_en_service(); MiseAjourActif(); }; // modification du statut de tous les ddl actuellements présent // y compris les données // si un des elements du tableau est inconnu, aucune action void Noeud::Met_hors_service() { int tab_ddlTaille = tab_ddl.Taille(); for (int i = 1; i<=tab_ddlTaille; i++) tab_ddl(i).Met_hors_service(); MiseAjourActif(); }; void Noeud::Met_en_service() // y compris les données { int tab_ddlTaille = tab_ddl.Taille(); for (int i = 1; i<=tab_ddlTaille; i++) tab_ddl(i).Met_en_service(); MiseAjourActif(); }; // modification du statut de tous les ddl actuellements présent // sauf les données qui ne sont pas modifiées // si un des elements du tableau est inconnu, aucune action void Noeud::Met_hors_service_ddl() { int tab_ddlTaille = tab_ddl.Taille(); for (int i = 1; i<=tab_ddlTaille; i++) tab_ddl(i).Met_hors_service_ddl(); MiseAjourActif(); }; void Noeud::Met_en_service_ddl() // y compris les données { int tab_ddlTaille = tab_ddl.Taille(); for (int i = 1; i<=tab_ddlTaille; i++) tab_ddl(i).Met_en_service_ddl(); MiseAjourActif(); }; // changement du statut de variable à donnée pour un tableau d'enum de ddl void Noeud::ChangeVariable_a_Donnee(const Tableau& taben) { int tabenTaille = taben.Taille(); for (int i = 1; i<=tabenTaille; i++) tab_ddl(Existe(taben(i))).ChangeVariable_a_Donnee(); MiseAjourActif(); }; // changement du statut de donnée à variable pour un tableau d'enum de ddl void Noeud::ChangeDonnee_a_Variable(const Tableau& taben) { int tabenTaille = taben.Taille(); for (int i = 1; i<=tabenTaille; i++) tab_ddl(Existe(taben(i))).ChangeVariable_a_Donnee(); MiseAjourActif(); }; // changement de toutes les conditions données (service, variable, fixage ..) // selon le tableau de ddl passé en paramètre // par contre la valeur n'est pas utilisé donc la valeur actuelle reste inchangé void Noeud::ChangeToutesLesConditions(const Tableau& ta) { int taTaille = ta.Taille(); for (int i = 1; i<=taTaille; i++) { tab_ddl(Existe(ta(i).Id_nom())).CopieToutesLesConditions(ta(i).Retour_Fixe());}; MiseAjourActif(); }; // changement de statu des ddl d'une combinaison, (cf. Enum_ddl) // les ddl de la combinaison, prennent le même statut que celui // actuellement stocké, correspondant à enuta // cas est la combinaison, void Noeud::ChangeStatut(int cas,Enum_ddl enuta) { // on récupère tous les membres de la combinaison Tableau tenu= Combinaison(cas); int tenuTaille = tenu.Taille(); Enum_boolddl enubold=tab_ddl(Existe(enuta)).Retour_Fixe(); for (int i = 1; i<=tenuTaille; i++) { tab_ddl(Existe(tenu(i))).CopieToutesLesConditions(enubold);}; MiseAjourActif(); }; // changement de statu des ddl d'une combinaison, (cf. Enum_ddl) // les ddl de la combinaison, prennent le même statut que celui de enubold // cas est la combinaison, void Noeud::ChangeStatut(int cas,Enum_boolddl enubold) { // on récupère tous les membres de la combinaison Tableau tenu= Combinaison(cas); int tenuTaille = tenu.Taille(); for (int i = 1; i<=tenuTaille; i++) { tab_ddl(Existe(tenu(i))).CopieToutesLesConditions(enubold);}; MiseAjourActif(); }; /*// retourne le numero du ddl recherche identifie par en, // s'il existe sinon 0 int Noeud::Existe(const Enum_ddl en) { int tab_ddl_Taille = tab_ddl.Taille(); // on commence par tester a partir de la derniere position sauvegardee for (short int i=(short)(posiddl);i<= tab_ddl_Taille;i++) if (en == tab_ddl(i).Id_nom()) { posiddl=i; return i; } // on continue la recherche a partir du debut for (short int i=1;i< posiddl;i++) if (en == tab_ddl(i).Id_nom()) { posiddl=i; return i; } // sinon retour 0 return 0; }; */ // indique que l'on va utiliser les ddl en 0, t et tdt // les grandeurs en tdt sont cree s'ils n'existent pas // et initialisees par defaut void Noeud::Travail_tdt() { if (tab_tdt.Taille() == 0) tab_tdt.Change_taille(tab_ddl.Taille()); // les grandeurs à tdt peuvent changer des coordonnées vers // autre chose, pour cela on commence par les supprimer, ensuite // dans la procédure MiseAjour() elles sont recréées si besoin est // a partir du tableau de tab_tdt if (coord2 != NULL) delete coord2; coord2 = NULL; MiseAjour(); }; // indique que l'on va utiliser les ddl en 0, t // si les grandeurs en tdt existaient, elles sont supprimées void Noeud::Travail_t() { if (tab_tdt.Taille() != 0) { tab_tdt.Libere(); if (coord2 != NULL) delete coord2; coord2 = NULL; } MiseAjour(); }; // mise a zero de tous les variables ddl actives // sauf dans le cas de coordonnees entrainees. dans ce dernier // cas les coordonnees correspondants a Xi pour t et t+dt // sont mis a la valeur de celles de t=0 // a moins que le paramètre booléen est mis à false, // dans ce cas les coordonnées à t sont inchangées void Noeud::ZeroVariablesDdl(bool cas) { int nbactif = tab_var_actives.Taille(); for (int j=1; j<= nbactif; j++) {int i = tab_var_actives(j); if (((tab_ddl(i)).Nom())[0] != 'X') { tab_ddl(i).Valeur() = 0.; tab_0(i) = 0.; } else // cas de coordonnees entrainees if (cas) tab_ddl(i).Valeur() = tab_0(i); }; if (tab_tdt.Taille() != 0) // cas de l'utilisation du tableau a tdt for (int j1=1; j1<= nbactif; j1++) {int ii = tab_var_actives(j1); if (((tab_ddl(ii)).Nom())[0] != 'X') tab_tdt(ii) = 0.; else tab_tdt(ii) = tab_0(ii); }; }; // actualisation des ddl actifs (variable et donnee) de t+dt vers t void Noeud::TdtversT() { int nbactif = tab_actif.Taille(); for (int j=1; j<= nbactif; j++) {int i = tab_actif(j); tab_ddl(i).Valeur() = tab_tdt(i); }; // cas d'une base locale if (baseB != NULL) {(*baseB_t) = (*baseB);} }; // actualisation des ddl actifs (variables et donnees) de t vers t+dt void Noeud::TversTdt() { int nbactif = tab_actif.Taille(); for (int j=1; j<= nbactif; j++) {int i = tab_actif(j); tab_tdt(i)= tab_ddl(i).Valeur(); }; // cas d'une base locale if (baseB != NULL) {(*baseB) = (*baseB_t);} }; // retourne dans le vecteur d'entrée les réels représentant les contraintes // si les degrés de liberté contrainte existent // sinon retourne false, en ne modifiant pas l'entrée bool Noeud::Contrainte(Vecteur& Sig) { int position = Existe(SIG11); int l_sigma; // dimension des contraintes // test pour l'existence des ddl de sigma if ( position != 0) { l_sigma = 1 ; // c'est au moins un tenseur d'ordre 1 if (Existe(SIG22) != 0) { l_sigma = 3 ; // c'est au moins un tenseur d'ordre 2 // donc trois coordonnées if (Existe(SIG33) != 0) l_sigma = 6 ; // c'est un tenseur d'ordre 3 // donc 6 coordonnées }; if (Sig.Taille() != l_sigma) Sig.Change_taille(l_sigma); int fin = position + l_sigma-1; int j = 1; for (int i=position;i<= fin; i++,j++) Sig(j) = tab_ddl(i).Valeur(); return true; } else return false; // pas de contrainte }; // retourne dans le tenseur d'entrée les réels représentant les contraintes // si les degrés de liberté contrainte existent // sinon retourne l'entrée sans modification // le tenseur est choisit mixte pour représenter tous les cas // !!! important : le tenseur Sig doit avoir la bonne dimension // en entrée, car il n'est pas redimensionné dans la méthode TenseurHB& Noeud::Contrainte(TenseurHB& Sig) { int position = Existe(SIG11); if (position == 0) return Sig; // cas où il n'y a pas de contrainte // ----- sinon on remplit les composantes du tenseur ------ int l_sigma = Sig.Dimension(); // dimension des contraintes #ifdef MISE_AU_POINT // vérif des dimensions pour le debug // comme position n'est pas nulle la dimension dans les ddl est au moins 1 int dimm = 1; if (Existe(SIG22) != 0) { dimm = 2 ; // c'est au moins un tenseur d'ordre 2 if (Existe(SIG33) != 0) dimm = 3 ; // c'est un tenseur d'ordre 3 }; if (l_sigma != dimm) { cout << "\nErreur : dimensions du tenseur d'entrée incorrecte Sig = " << dimm << " !\n"; cout << " Noeud::Contrainte(TenseurHB& Sig)\n"; Sortie(1); }; #endif switch (l_sigma) { case 1 : // cas à une dimension Sig.Coor(1,1) = tab_ddl(position).Valeur(); break; case 2 : // cas à 2 dimension Sig.Coor(1,1) = tab_ddl(position).Valeur(); Sig.Coor(2,2) = tab_ddl(position+1).Valeur(); Sig.Coor(1,2) = tab_ddl(position+2).Valeur(); Sig.Coor(2,1) = tab_ddl(position+2).Valeur(); break; case 3 : // cas à 3 dimension Sig.Coor(1,1) = tab_ddl(position).Valeur(); Sig.Coor(2,2) = tab_ddl(position+1).Valeur(); Sig.Coor(3,3) = tab_ddl(position+2).Valeur(); Sig.Coor(1,2) = tab_ddl(position+3).Valeur();Sig.Coor(2,1) = Sig(1,2); Sig.Coor(2,3) = tab_ddl(position+4).Valeur();Sig.Coor(3,2) = Sig(2,3); Sig.Coor(1,3) = tab_ddl(position+5).Valeur();Sig.Coor(3,1) = Sig(1,3); break; default : { cout <<"\n Erreur, la dimension du tenseur Sig n'est pas correcte "; cout << "Noeud::Contrainte(TenseurHB& Sig)" << endl; Sortie (1); } }; return Sig; }; // lecture sur le flot d'entée de déplacement // et mise à jour des positions à t et t+dt correspondantes void Noeud::LectureDeplacements(UtilLecture *entreePrinc) { // récup de la dimension // définition du déplacement Coordonnee dep = *coord0; // lecture brut des coordonnées du déplacement sans la dimension dep.Lecture(*entreePrinc); // on ajoute aux coordonnées initiales pour avoir celles à t dep += (*coord0); // on insert les coordonnées à t qui sont créées si elles n'existent pas // elles ont le statut inactif par défaut Insert_coord1(dep); }; //----- lecture écriture dans base info ----- // cas donne le niveau de la récupération // = 1 : on récupère tout // = 2 : on récupère uniquement les données variables (supposées comme telles) // ( ici on ne redimentionne pas, // cela signifie que le nombre de ddl augmente mais ne diminue pas !!) void Noeud::Lecture_base_info(ifstream& ent,int cas) { // traitement en fonction du cas switch (cas) { case 1 : // ------- on récupère tout ------------------------- { ent >> (*this) ; break; } case 2 : // ----------- récup uniquement de se qui varie -------------------- { // ici se sont les degrés de liberté string toto;int nb; ent >> toto >> nb; #ifdef MISE_AU_POINT // vérification du numéro if (nb != num_noeud ) { cout << "\nErreur : numero de noeud lu : " << nb << " au lieu de " << num_noeud << " \n";; cout << " Noeud::Lecture_base_info"; Sortie(1); }; #endif /* // ici on ne redimentionne pas, /// // cela signifie que le nombre de ddl augmente mais ne diminue pas ! /// Tableau * pt_tableau = tab_ddl.New_en_lecture_si_taille_superieur_a_lire(ent); /// // on regarde si le tableau a été redimensionné /// if (pt_tableau != NULL) /// // cas d'une redimension on ajoute les ddl /// PlusTabDdl(*pt_tableau); */ // le code précédent pose des pb lorsque les ddl à lire sont différents de ceux existants // donc systématiquement, on en crée des nouveaux et on met à jour Tableau tableau; tableau.Entree(ent); // on ajoute les ddl PlusTabDdl(tableau); // on recopie les valeurs à t int taille_tabddl=tab_ddl.Taille(); // en fait ce n'est pas la peine, ça a été fait dans PlusTabDdl !! // cas de valeur à tdt if (tab_tdt.Taille() != 0) {for (int i=1;i<=taille_tabddl;i++) tab_tdt(i) = tab_ddl(i).Valeur(); }; // cas d'une base locale éventuelle {int existe_base; ent >> existe_base >> toto; if (existe_base == 1) {if (baseB == NULL) {baseB=new BaseB();}; ent >> toto >> (*baseB); // dans le cas où la grandeur à t n'existe pas // on l'a crée et on lui donne la valeur de tdt // sinon on fait une affectation, pour redémarrer avec quelque chose de correcte à t if (baseB_t == NULL) {baseB_t=new BaseB(*baseB);} else // sinon on affecte {(*baseB_t) = (*baseB);}; // cas à 0 if (baseB_0 == NULL) {baseB_0=new BaseB(*baseB);}; // sinon on ne fait rien car la base est sensée avoir été correctement // définit au départ }; }; break; } default : { cout << "\nErreur : valeur incorrecte du type d'écriture !\n"; cout << "Noeud::Ecriture_base_info(ofstream& sort,int cas)" << " cas= " << cas << endl; Sortie(1); } } }; // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void Noeud::Ecriture_base_info(ofstream& sort,int cas) { // traitement en fonction du cas switch (cas) { case 1 : // ------- on sauvegarde tout ------------------------- { sort << (*this) << "\n"; break; } case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- { // ici se sont les degrés de liberté sort << "Noeud " << num_noeud << " "; sort << tab_ddl ; if (baseB != NULL) {sort << " 1 baseLoc: " << (*baseB);} else {sort << " 0 baseLoc: "; }; sort << "\n"; break; } default : { cout << "\nErreur : valeur incorrecte du type d'écriture !\n"; cout << "Noeud::Ecriture_base_info(ofstream& sort,int cas)" << " cas= " << cas << endl; Sortie(1); } }; // pour l'instant on ne sauvegarde pas les ddl_étendu et les type_quelconque car on considère // que ce sont des résultats et non pas des données indispensables. // idem pour enu_liaison et noeud_lier, qui sont liées aux conditions limites // A priori, c'est infos sont reconstruites // à chaque démarrage };