// 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 "LesMaillages.h" #include "ElemMeca.h" #include "ReferenceNE.h" #include "ReferenceAF.h" #include "MathUtil.h" #include "ConstMath.h" #include "CharUtil.h" #include "TypeQuelconqueParticulier.h" //#ifndef SYSTEM_MAC_OS_X_unix // #include "Frontier.h" //#endif // --------- calcul dynamique --------- // ajout des ddl de vitesse pour tous les maillages // pour tous les noeuds qui ont un ddl de déplacement // val_fixe indique si l'on veut des ddl libres ou pas void LesMaillages::Plus_Les_ddl_Vitesse(Enum_boolddl val_fixe) { // recup de la dimension int dimen = ParaGlob::Dimension(); // recup de la position de VI-1 int posi = Id_nom_ddl("V1") -1; // création du tableau de ddl de travail Tableau ta(dimen); for (int ii=1; ii<= dimen; ii++) {//ta(ii) = Enum_ddl(ii+posi); // ERREUR D'AFFECTATION, À VOIRE EN DEBUG OU IL VA ta(ii) = Ddl (Enum_ddl(ii+posi),0.,val_fixe); // bonne version }; // dans le cas où le calcul est axisymétrique // le dernier ddl en z est mis en HSLIBRE, car on ne le prend pas en compte dans le calcul // axisymétrique if (ParaGlob::AxiSymetrie()) ta(3) = Ddl (Enum_ddl(3+posi),0.,HSLIBRE); // bonne version; // maintenant on passe en revu les noeuds for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); // on regarde si le déplacement existe if (noo->Existe_ici(X1)) noo->PlusTabDdl(ta); } }; }; // ajout des ddl d'accélération pour tous les maillages // pour tous les noeuds qui ont un ddl de déplacement // val_fixe indique si l'on veut des ddl libres ou pas void LesMaillages::Plus_Les_ddl_Acceleration(Enum_boolddl val_fixe) { // recup de la dimension int dimen = ParaGlob::Dimension(); // recup de la position de GAMMA1-1 int posi = Id_nom_ddl("GAMMA1") -1; // création du tableau de ddl de travail Tableau ta(dimen); for (int ii=1; ii<= dimen; ii++) ta(ii) = Ddl (Enum_ddl(ii+posi),0.,val_fixe); // bonne version // dans le cas où le calcul est axisymétrique // le dernier ddl en z est mis en HSLIBRE, car on ne le prend pas en compte dans le calcul // axisymétrique if (ParaGlob::AxiSymetrie()) ta(3) = Ddl (Enum_ddl(3+posi),0.,HSLIBRE); // bonne version; // maintenant on passe en revu les noeuds for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); // on regarde si le déplacement existe if (noo->Existe_ici(X1)) noo->PlusTabDdl(ta); } } // on va passer en revue les éléments pour initialiser si nécessaire les conteneurs // d'accélération si on est en mécanique // on balaie les maillages et les éléments for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbelementmax = tabMaillage(i1)->Nombre_element(); for (int i2 = 1; i2 <= nbelementmax; i2++) { Element & elem = Element_LesMaille(i1,i2); if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) ((ElemMeca&) elem).Active_conteneurs_metrique_acceleration(); }; }; }; // calcul de la longueur d'arrête d'élément minimal // divisé par la célérité dans le matériau double LesMaillages::Longueur_arrete_mini_sur_c(Enum_dure temps) { double dist_ret = ConstMath::tresgrand; // def de la distance de retour // on balaie les maillages et les éléments for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbelementmax = tabMaillage(i1)->Nombre_element(); for (int i2 = 1; i2 <= nbelementmax; i2++) { Element & elem = Element_LesMaille(i1,i2); if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) { double dist = ((ElemMeca&) elem).Long_arrete_mini_sur_c(temps); dist_ret = MiN(dist_ret,dist); } } } return dist_ret; }; // initialisation éventuelle du bulk viscosity void LesMaillages::Init_bulk_viscosity(int choix,const DeuxDoubles & coef) { // on renseigne la classe générique d'éléments mécanique si besoin // choix peut-être égale à 0, 1 ou 2 if (choix) { ElemMeca::ActiveBulkViscosity(choix); // activation du bulk viscosity ElemMeca::ChangeCoefsBulkViscosity(coef); // passage des coeffs } }; // -- encore plus générique // changement de toutes les conditions données (service, variable, fixage ..) // selon le tableau de ddl passé en paramètre // par contre les valeurs de ta ne sont pas utilisé donc les valeurs actuelles restent inchangé void LesMaillages::ChangeToutesLesConditions(const Tableau& ta) { // création d'une liste qui contiendra tous les ddl à passer aux noeuds list liddl; // on boucle sur le tableau int taTaille = ta.Taille(); for (int ita=1;ita<=taTaille;ita++) { Ddl& taa=ta(ita);Enum_boolddl enub=taa.Retour_Fixe(); Tableau tenu = TableauTypeDdl(taa.Id_nom()); // récup du tableau d'enum int tenuTaille = tenu.Taille(); for (int i=1;i<=tenuTaille;i++) liddl.push_back(Ddl(tenu(i),0.,enub)); }; // création du tableau de travail que l'on passera aux noeuds Tableau tddl(liddl.size()); list::iterator il,ifin=liddl.end();int iii=1; for (il=liddl.begin();il!=ifin;il++,iii++) tddl(iii)=(*il); // maintenant on passe en revue les noeuds for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); noo->ChangeToutesLesConditions(tddl); } } }; // changement de statu des ddl d'une combinaison, en fonction du statut // de enuta dans chaque noeud, les ddl de la combinaison, prennent le même statut que celui // de enuta dans chaque noeud. // cas est la combinaison, void LesMaillages::ChangeStatut(int cas,Enum_ddl enuta) {// on passe en revue les noeuds for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); noo->ChangeStatut(cas,enuta); } } }; // changement de statu des ddl d'une combinaison dans chaque noeud, en fonction // de enubold, les ddl de la combinaison, prennent le même statut que enubold // cas est la combinaison, void LesMaillages::ChangeStatut(int cas,Enum_boolddl enubold) {// on passe en revue les noeuds for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); noo->ChangeStatut(cas,enubold); } } }; //change le statut de tous les ddl liés à la physique en cours //par exemple: met à libre ou bloque les ddl liés à la physique en cours void LesMaillages::Libere_Ddl_representatifs_des_physiques(Enum_boolddl enubold) { // ddl_representatifs_des_physiques représentent tous les ddl de la physique if (ddl_representatifs_des_physiques.size()) // on ne continue que si c'est diff de 0 {list ::iterator il,ilfin= ddl_representatifs_des_physiques.end(); list ::iterator ildebut = ddl_representatifs_des_physiques.begin(); // on fait un premier balayage, car il s'agit des "types" de ddl mais pas de la liste // qui elle dépend de la dimension éventuellement int nbddl = 0; // init for (il = ildebut;il != ilfin; il++) nbddl += TableauTypeDdl(*il).Taille(); // on définit un tableau "ta" pour appeler les noeuds // qui contient tous les ddl (et pas seulement les types) Ddl enu((*ildebut),0.0,enubold); // def du premier ddl Tableau ta(nbddl,enu); int ita=1; for (il = ildebut;il != ilfin; il++) {Tableau tddl = TableauTypeDdl(*il); int ndPlus1 = tddl.Taille() + 1; for (int i=1;i< ndPlus1;i++,ita++) ta(ita).Change_nom(tddl(i)); }; // on passe en revue les noeuds for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); // on change les conditions données par ta noo->ChangeToutesLesConditions(ta); }; }; }; }; //----- lecture écriture base info ----- // lecture base info // cas donne le niveau de la récupération // = 1 : on récupère tout // = 2 : on récupère uniquement les données variables (supposées comme telles) void LesMaillages::Lecture_base_info(ifstream& ent,const int cas) { string toto; // cout << "\n debug **** LesMaillages::Lecture_base_info\n" // << "\n entr.rdstate() " << ent.rdstate() << flush; // lecture du nombre de maillage total ent >> toto >> nbMaillageTotal; // cout << "\n debug **** LesMaillages::Lecture_base_info\n" // << " toto= "<< toto << nbMaillageTotal // << "\n entr.rdstate() " << ent.rdstate() << flush; switch (cas) { case 1 : // ------- on récupère tout ------------------------- {for (int i1 = 1; i1<= nbMaillageTotal; i1++) { // tout d'abord création du maillage tabMaillage(i1) = new Maillage (mapNomMail,i1,paraGlob->Dimension()); // puis lecture tabMaillage(i1)->Lecture_base_info(ent,cas); }; // on s'occupe de mettre à jour les types de pb et les ddl types associés Mise_a_jour_type_pb_type_associe_ddl(); break; } case 2 : // ----------- on ne récupère que ce qui varie { for (int i1 = 1; i1<= nbMaillageTotal; i1++) tabMaillage(i1)->Lecture_base_info(ent,cas); // ----- cas des grandeurs intégrés éventuelles----- // utile pour pouvoir post-traiter et également pour le cumul sur le temps ent >> toto; if (toto != "int_vol_mail") { cout << "\nErreur : en lecture de l'entete de l'integration de volume eventuelle" << " on attendait le mot cle int_vol_mail et on a lu "<< toto <<" !\n"; cout << "LesMaillages::Lecture_base_info(....)" << flush; Sortie(1); }; int integ_vol_typeQuel_taille = 0; ent >> integ_vol_typeQuel_taille; // on boucle sur les grandeurs à lire // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée // mais dans ce cas elle ne changera plus pendant le calcul for (int i=1;i<= integ_vol_typeQuel_taille;i++) { // on lit l'entête d'un type quelconque // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); // lecture de l'entête et récup d'enu // on utilise: avec création, car il peut s'agir d'une intégrale qui n'est plus active // du coup le tableau existant ne contient pas cette intégrale EnuTypeQuelParticulier enu_t = pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); int indice_t = integ_vol_typeQuel_t.Contient(pour_lire_t); if (indice_t) {// là il suffit de lire la grandeur associée ent >> (*integ_vol_typeQuel_t(indice_t).Grandeur_pointee()); }; // normalement le cas a tdt est identique EnuTypeQuelParticulier enu = pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur // le test se fait uniquement sur le TypeQuelconque_enum_etendu // qui est supposé suffisant comme signature int indice = integ_vol_typeQuel.Contient(pour_lire); if (indice) {// là il suffit de lire la grandeur associée ent >> (*integ_vol_typeQuel(indice).Grandeur_pointee()); }; if (!indice) { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur // figée, dont la valeur ne changera pas pendant le calcul // création d'une grandeur associée et lecture des information sur le flot TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); // création du type quelconque TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); delete grandeur_t; // car il ne sert plus à rien TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); // création du type quelconque TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); delete grandeur; // car il ne sert plus à rien // maintenant on va mettre à jour le stockage interne // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue // à l'initialisation du .info indice_t = integ_vol_typeQuel_t.Taille()+1; indice = integ_vol_typeQuel.Taille()+1; integ_vol_typeQuel_t.Change_taille(indice_t); integ_vol_typeQuel.Change_taille(indice); integ_vol_typeQuel(indice) = typQ; integ_vol_typeQuel_t(indice_t) = typQ_t; ref_integ_vol.Change_taille(indice);// normalement c'est le même qu'indice_t // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est // figé, car aucun domaine d'intégration n'a été définit ref_integ_vol(indice) = NULL; }; // on va créer ou mettre à jour une grandeur globale associée {TypeQuelconque& TQ_t = integ_vol_typeQuel_t(indice); // pour simplifier // cas des grandeurs à t: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); const string* nom_de_ref = g_TG_t->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans l'integration !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_typeQuel_t(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); }; }; // idem pour la grandeur courante {TypeQuelconque& TQ = integ_vol_typeQuel(indice); // pour simplifier // cas des grandeurs à tdt: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans l'integration !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_typeQuel(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); // la valeur passée en paramétre est celle de t !! (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); }; }; }; // boucle sur les grandeurs lues // maintenant les intégrales de volume et en temps ent >> toto; if (toto != "int_vol_temps_mail") { cout << "\nErreur : en lecture de l'entete de l'integration de volume et en temps eventuelle" << " on attendait le mot cle int_vol_temps_mail et on a lu "<< toto <<" !\n"; cout << "LesMaillages::Lecture_base_info(....)" << flush; Sortie(1); }; int integ_vol_t_typeQuel_taille = 0; ent >> integ_vol_t_typeQuel_taille; // on boucle sur les grandeurs à lire // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée // mais dans ce cas elle ne changera plus pendant le calcul for (int i=1;i<= integ_vol_t_typeQuel_taille;i++) { // on lit l'entête d'un type quelconque // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); // lecture de l'entête et récup d'enu // on utilise: avec création, car il peut s'agire d'une intégrale qui n'est plus active // du coup le tableau exitant ne contient pas cette intégrale EnuTypeQuelParticulier enu_t = pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur // le test se fait uniquement sur le TypeQuelconque_enum_etendu // qui est supposé suffisant comme signature int indice_t = integ_vol_t_typeQuel_t.Contient(pour_lire_t); if (indice_t) {// là il suffit de lire la grandeur associée ent >> (*integ_vol_t_typeQuel_t(indice_t).Grandeur_pointee()); }; // idem à t EnuTypeQuelParticulier enu = pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); int indice = integ_vol_t_typeQuel.Contient(pour_lire); if (indice) {// là il suffit de lire la grandeur associée ent >> (*integ_vol_t_typeQuel(indice).Grandeur_pointee()); }; if (!indice) { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur // figée, dont la valeur ne changera pas pendant le calcul // création d'une grandeur associée et lecture des information sur le flot TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); // création du type quelconque TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); delete grandeur_t; // car il ne sert plus à rien TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); // création du type quelconque TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); delete grandeur; // car il ne sert plus à rien // maintenant on va mettre à jour le stockage interne // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue // à l'initialisation du .info indice = integ_vol_t_typeQuel_t.Taille()+1; integ_vol_t_typeQuel_t.Change_taille(indice); integ_vol_t_typeQuel.Change_taille(indice); integ_vol_t_typeQuel(indice) = typQ; integ_vol_t_typeQuel_t(indice) = typQ_t; ref_integ_vol_t.Change_taille(indice); // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est // figé, car aucun domaine d'intégration n'a été définit ref_integ_vol_t(indice) = NULL; }; // on va créer ou mettre à jour une grandeur globale associée {TypeQuelconque& TQ_t = integ_vol_t_typeQuel_t(indice); // pour simplifier TypeQuelconque& TQ = integ_vol_t_typeQuel(indice); // pour simplifier // transfert des intégrales finalisées // on considère que les grandeurs à tdt doivent être initialisées à celles de t (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); // cas des grandeurs à t: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); const string* nom_de_ref = g_TG_t->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans l'integration !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_t_typeQuel_t(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); }; }; // cas des grandeurs à tdt // integ_vol_t_typeQuel(i) = integ_vol_t_typeQuel_t(i); // on va créer ou mettre à jour une grandeur globale associée {TypeQuelconque& TQ = integ_vol_t_typeQuel(indice); // pour simplifier // cas des grandeurs à tdt: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans l'integration !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_t_typeQuel(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); }; }; }; // boucle sur les grandeurs lues // déjà fait // integ_vol_t_typeQuel = integ_vol_t_typeQuel_t; // init // ----- cas des statistiques éventuelles----- // utile pour pouvoir post-traiter et également pour le cumul sur le temps ent >> toto; if (toto != "statistique_mail") { cout << "\nErreur : en lecture de l'entete de statistique eventuelle" << " on attendait le mot cle statistique_mail et on a lu "<< toto <<" !\n"; cout << "LesMaillages::Lecture_base_info(....)" << flush; Sortie(1); }; int statistique_typeQuel_taille = 0; ent >> statistique_typeQuel_taille; // on boucle sur les grandeurs à lire // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée // mais dans ce cas elle ne changera plus pendant le calcul for (int i=1;i<= statistique_typeQuel_taille;i++) { // on lit l'entête d'un type quelconque // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); // lecture de l'entête et récup d'enu // on utilise: avec création, car il peut s'agir d'une statistique qui n'est plus active // du coup le tableau existant ne contient pas cette statistique EnuTypeQuelParticulier enu_t = pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); int indice_t = statistique_typeQuel_t.Contient(pour_lire_t); if (indice_t) {// là il suffit de lire la grandeur associée ent >> (*statistique_typeQuel_t(indice_t).Grandeur_pointee()); }; // normalement le cas a tdt est identique EnuTypeQuelParticulier enu = pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur // le test se fait uniquement sur le TypeQuelconque_enum_etendu // qui est supposé suffisant comme signature int indice = statistique_typeQuel.Contient(pour_lire); if (indice) {// là il suffit de lire la grandeur associée ent >> (*statistique_typeQuel(indice).Grandeur_pointee()); }; if (!indice) { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur // figée, dont la valeur ne changera pas pendant le calcul // création d'une grandeur associée et lecture des information sur le flot TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); // création du type quelconque TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); delete grandeur_t; // car il ne sert plus à rien TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); // création du type quelconque TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); delete grandeur; // car il ne sert plus à rien // maintenant on va mettre à jour le stockage interne // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue // à l'initialisation du .info indice_t = statistique_typeQuel_t.Taille()+1; indice = statistique_typeQuel.Taille()+1; statistique_typeQuel_t.Change_taille(indice_t); statistique_typeQuel.Change_taille(indice); statistique_typeQuel(indice) = typQ; statistique_typeQuel_t(indice_t) = typQ_t; ref_statistique.Change_taille(indice);// normalement c'est le même qu'indice_t // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est // figé, car aucune ref de statistique n'a été définie ref_statistique(indice) = NULL; }; // on va créer ou mettre à jour une grandeur globale associée {TypeQuelconque& TQ_t = statistique_typeQuel_t(indice); // pour simplifier // cas des grandeurs à t: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); const string* nom_de_ref = g_TG_t->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans statistique !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&statistique_typeQuel_t(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); }; }; // idem pour la grandeur courante {TypeQuelconque& TQ = statistique_typeQuel(indice); // pour simplifier // cas des grandeurs à tdt: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans statistique !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&statistique_typeQuel(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); // la valeur passée en paramétre est celle de t !! (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); }; }; }; // boucle sur les grandeurs lues // maintenant les statistiques avec cumul en temps ent >> toto; if (toto != "statistique_temps_mail") { cout << "\nErreur : en lecture de l'entete de la statistique avec cumul en temps eventuelle" << " on attendait le mot cle statistique_temps_mail et on a lu "<< toto <<" !\n"; cout << "LesMaillages::Lecture_base_info(....)" << flush; Sortie(1); }; int statistique_t_typeQuel_taille = 0; ent >> statistique_t_typeQuel_taille; // on boucle sur les grandeurs à lire // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée // mais dans ce cas elle ne changera plus pendant le calcul for (int i=1;i<= statistique_t_typeQuel_taille;i++) { // on lit l'entête d'un type quelconque // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); // lecture de l'entête et récup d'enu // on utilise: avec création, car il peut s'agir d'une statistique qui n'est plus active // du coup le tableau exitant ne contient pas cette statistique EnuTypeQuelParticulier enu_t = pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur // le test se fait uniquement sur le TypeQuelconque_enum_etendu // qui est supposé suffisant comme signature int indice_t = statistique_t_typeQuel_t.Contient(pour_lire_t); if (indice_t) {// là il suffit de lire la grandeur associée ent >> (*statistique_t_typeQuel_t(indice_t).Grandeur_pointee()); }; // idem à t EnuTypeQuelParticulier enu = pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); int indice = statistique_t_typeQuel.Contient(pour_lire); if (indice) {// là il suffit de lire la grandeur associée ent >> (*statistique_t_typeQuel(indice).Grandeur_pointee()); }; if (!indice) { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur // figée, dont la valeur ne changera pas pendant le calcul // création d'une grandeur associée et lecture des information sur le flot TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); // création du type quelconque TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); delete grandeur_t; // car il ne sert plus à rien TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); // création du type quelconque TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); delete grandeur; // car il ne sert plus à rien // maintenant on va mettre à jour le stockage interne // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue // à l'initialisation du .info indice = statistique_t_typeQuel_t.Taille()+1; statistique_t_typeQuel_t.Change_taille(indice); statistique_t_typeQuel.Change_taille(indice); statistique_t_typeQuel(indice) = typQ; statistique_t_typeQuel_t(indice) = typQ_t; ref_statistique_t.Change_taille(indice); // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est // figé, car aucune ref de noeuds n'a été définie ref_statistique_t(indice) = NULL; }; // on va créer ou mettre à jour une grandeur globale associée {TypeQuelconque& TQ_t = statistique_t_typeQuel_t(indice); // pour simplifier TypeQuelconque& TQ = statistique_t_typeQuel(indice); // pour simplifier // transfert des statistiques finalisées // on considère que les grandeurs à tdt doivent être initialisées à celles de t (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); // cas des grandeurs à t: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); const string* nom_de_ref = g_TG_t->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans l'integration !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&statistique_t_typeQuel_t(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); }; }; // on va créer ou mettre à jour une grandeur globale associée {TypeQuelconque& TQ = statistique_t_typeQuel(indice); // pour simplifier // cas des grandeurs à tdt: on alimente les grandeurs globales // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans statistique avec cuml en temps !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); if (pointe == NULL) // la grandeur n'existe pas on la définie ParaGlob::param->Ajout_grandeur_consultable(&statistique_t_typeQuel(indice),*nom_de_ref); else // sinon on affecte {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); }; }; }; // boucle sur les grandeurs lues break; } default : { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n"; cout << "LesMaillages::Lecture_base_info(....)" << " cas= " << cas << flush; Sortie(1); }; }; }; // écriture base info // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void LesMaillages::Ecriture_base_info(ofstream& sort,const int cas) { sort << "\n ****les_maillages:_nombre= " << nbMaillageTotal ; for (int i1 = 1; i1<= nbMaillageTotal; i1++) tabMaillage(i1)->Ecriture_base_info(sort,cas); switch (cas) { case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- { // ----- cas des grandeurs intégrés éventuelles----- // utile pour pouvoir post-traiter et également pour le cumul sur le temps // 1) les intégrales de volume sort << "\n\n int_vol_mail "; int integ_vol_typeQuel_taille = integ_vol_typeQuel.Taille(); if (integ_vol_typeQuel_taille == 0) sort << 0; else sort << integ_vol_typeQuel_taille; sort << " "; for (int i=1;i<= integ_vol_typeQuel_taille;i++) // il faut que l'on sauvegarde à t et tdt sinon au restart les grandeurs à tdt n'existe pas sort << "\n" << integ_vol_typeQuel_t(i) << " "<" << "\n " << "\n " << "\n une suite de maillages " << "\n " << "\n " << "\n " << "\n " << "\n " << "\n "; // def de Maillage // SchemaXML_Maillage(sort,niveau); break; } }; }; // ------ informations utiles par exemples pour la visualisation // retourne les dimensions minis et maxi suivant les axes du repère // absolu du maillage numéro nbmail (en faite le calcul est fondé // uniquement sur la position des noeuds du maillage // le premier vecteur contient les minimums // le deuxième vecteur contient les maximums Tableau LesMaillages::Taille_boite(int nbmail) { #ifdef MISE_AU_POINT // vérification que le numéro de maillage est correcte if (( nbmail <= 0) || (nbmail > nbMaillageTotal)) { cout << "\n erreur, le numéro de maillage demandé est érroné," << " nbmail = " << nbmail << " \n LesMaillages::Taille_boite(int nbmail) " ; Sortie(1); } #endif return tabMaillage(nbmail)->Taille_boiteMail(); }; // dans le cas ou aucun numéro de maillage n'est fournis // c'est l'encombrement de tous les maillages qui est fourni Tableau LesMaillages::Taille_boite() { if (nbMaillageTotal == 0) // cas particulier ou aucun maillage n'est définit { Tableau toto(2); return toto; } // l'objectif est de balayer tous les maillages // tout d'abord initialisation du tableau de retour sur le premier // maillage Tableau tabsortie = tabMaillage(1)->Taille_boiteMail(); for (int i1 = 2; i1<= nbMaillageTotal; i1++) { // récupération du tableau calculé Tableau tabinter = tabMaillage(i1)->Taille_boiteMail(); // différent tests int dima = tabsortie(1).Taille(); for (int it=1;it<=dima;it++) { if (tabsortie(1)(it) > tabinter(1)(it)) tabsortie(1)(it) = tabinter(1)(it); if (tabsortie(2)(it) < tabinter(2)(it)) tabsortie(2)(it) = tabinter(2)(it); } } // retour return tabsortie; }; // mise à jour des boites d'encombrements des éléments, qui contiennent des éléments frontières // et des éléments frontières eux-même void LesMaillages::Mise_a_jour_boite_encombrement_elem_front(Enum_dure temps) {for (int i1 = 1; i1<= nbMaillageTotal; i1++) { // tout d'abord les boites des éléments: on passe en revue tous les éléments int nbelmax = Nombre_element(i1); for (int jel = 1; jel <= nbelmax; jel++) { // récup de l'élément Element& elem = tabMaillage(i1)->Element_mail(jel); // on regarde si l'élément contient des éléments frontières if (elem.Existe_frontiere()) elem.Boite_encombre_element(temps); }; // maintenant on s'occupe des frontières LaLIST * lisfrontmail = listFrontiere(i1); // pour simplifier LaLIST ::iterator il,ilfin=lisfrontmail->end(); for (il=lisfrontmail->begin();il != ilfin; il++) (*il).Boite_encombrement_frontiere(temps); }; }; // crée et ramene pour tous les maillages, la liste des éléments qui contiennent chaque noeud // mis à jour lorsque lors de la création des frontières const Tableau < const Tableau > *>& LesMaillages::Indice() { tous_indices.Change_taille(nbMaillageTotal); for (int i1 = 1; i1<= nbMaillageTotal; i1++) { tous_indices(i1)= &(tabMaillage(i1)->Maillage::Indice());}; return tous_indices; }; // ----------------------------------------------------- // | utilitaires de manipulation de maillage |-- // ----------------------------------------------------- // création de maillage quadratiques incomplets à partir de maillages linéaires. // En fait il y création de maillages identiques aux maillages déjà existants, les éléments qui sont de types // linéaires sont remplacés par des éléments quadratiques incomplets correspondants. // Il y a création de références correspondantes void LesMaillages::CreeMaillagesQuadratiques_a_partir_des_lineaires(LesReferences* lesRef) { // création de la liste qui sert pour repérer les maillages créés list tab_lin_vers_comp; // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets for (int im=1;im<=nbMaillageTotal;im++) if (tabMaillage(im)->Contient_lineaire()) { nb_final_maillage++; tab_lin_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage)); }; // dans le cas où des maillages linéaires existent, création de nouveaux maillages nbMaillageTotal = nb_final_maillage; // on vérifie et augmente éventuellement la taille du nombre de maillage while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // maintenant on passe en revue les maillages candidats list::iterator il,ifin= tab_lin_vers_comp.end(); for (il=tab_lin_vers_comp.begin();il!=ifin;il++) { // on commence par créé le futur maillage quadratique à l'identique du maillage linéaire // original, il y a ici création de nouveau noeud et élément // on utilise un nouveau nom de maillage construit a partir de l'ancien string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { if(ref1->Nbmaille() == (*il).un) // on a trouvé une référence à considérer { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille((*il).deux); list_inter_ref.push_back(ref_nv); // on intègre la référence dans lesRéférences // lesRef->Ajout_reference(ref_nv); } ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques // complets. Les références sont également transformés en cohérence. tabMaillage((*il).deux)->Transfo_lin_quadraIncomp(*lesRef); } }; // création de maillage quadratiques complets à la place des maillages incomplet // les éléments qui sont de types quadratiques incomplets sont remplacés par des éléments // quadratiques complets correspondants. // Il y a création de références correspondantes void LesMaillages::CreeMaillagesQuadratiquesComplets_a_partir_des_incomplets(LesReferences* lesRef) { // création de la liste qui sert pour repérer les maillages complets créés list tab_quadra_inc_vers_comp; // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets for (int im=1;im<=nbMaillageTotal;im++) if (tabMaillage(im)->Contient_quadratique_incomplet()) { nb_final_maillage++; tab_quadra_inc_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage)); } // dans le cas où des maillages de quadratiques incomplet existent, création de nouveaux maillages nbMaillageTotal = nb_final_maillage; while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // maintenant on passe en revue les maillages candidats list::iterator il,ifin= tab_quadra_inc_vers_comp.end(); for (il=tab_quadra_inc_vers_comp.begin();il!=ifin;il++) { // on commence par créé le futur maillage complet à l'identique du maillage incomplet // original, il y a ici création de nouveau noeud et élément // on utilise un nouveau nom de maillage construit a partir de l'ancien string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { if(ref1->Nbmaille() == (*il).un) // on a trouvé une référence à considérer { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille((*il).deux); list_inter_ref.push_back(ref_nv); // on intègre la référence dans lesRéférences // lesRef->Ajout_reference(ref_nv); } ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques // complets. Les références sont également transformés en cohérence. tabMaillage((*il).deux)->Transfo_quadraIncomp_quadraComp(*lesRef); } }; // Affiche les donnees des maillages dans des fichiers dont le nom est construit à partir du nom de // chaque maillage au format ".her" et ".lis" // le paramètre optionnel indique le numéro du maillage à afficher, s'il vaut -1, on affiche tous les maillages void LesMaillages::Affiche_maillage_dans_her_lis(Enum_dure temps,LesReferences &lesRef,int imail) { if (imail == -1) {// cas de l'affichage de tous les maillages, on passe en revue les différents maillages for (int im=1;im<=nbMaillageTotal;im++) tabMaillage(im)->Affiche_dans_her_lis(lesRef,temps); } else {// cas de l'affichage d'un maillage particulier if ((imail < 1)||(imail > nbMaillageTotal)) { cout << "\n erreur dans l'affichage d'un maillage en format .her et .lis" << "\n le numero propose: " << imail << " de maillage n'existe pas !! " << "\n LesMaillages::Affiche_maillage_dans_her_lis(LesReferences &lesRef,int imail)"; Sortie(1); } tabMaillage(imail)->Affiche_dans_her_lis(lesRef,temps); } }; // relocalisation des points milieux des arrêtes des éléments quadratiques void LesMaillages::RelocPtMilieuMailleQuadra() { // on passe en revue les différents maillages for (int im=1;im<=nbMaillageTotal;im++) tabMaillage(im)->RelocPtMilieuMailleQuadra(); }; // création et ajout d'un nouveau maillage en fonction d'un nom et d'une liste // d'éléments et de noeuds // *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments, // ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé // >> ramène le numéro du nouveau maillage int LesMaillages::Creation_nouveau_maillage (list & li_noeud,list & list_elem,const string& nom_maillage) { if (ParaGlob::NiveauImpression() >= 4) cout << " debut de l'ajout d'un nouveau maillage " << flush; // recherche d'un numéro du maillage nbMaillageTotal++; if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; int nbElem= list_elem.size(); tabMaillage(nbMaillageTotal) = new Maillage (mapNomMail,paraGlob->Dimension() ,li_noeud,list_elem ,nbMaillageTotal,nom_maillage); // indique le nb de maillage pour l'enregistrement des prochaines references lesRef->NbMaille(nbMaillageTotal); if (ParaGlob::NiveauImpression() >= 4) cout << " fin de l'ajout d'un nouveau maillage " << flush; // retour du numéro de maillage return nbMaillageTotal; }; // suppression d'un maillage existant // par défaut, tous les noeuds et éléments du maillage sont supprimés // si sans_conservation_noeuds_elements est false: les noeuds et les éléments ne sont pas supprimés // mais ils ne sont plus référencés dans ce maillage ! void LesMaillages::Suppression_maillage( const string& nom_maillage,const bool sans_conservation_noeuds_elements) { // on commence par récupérer le numéro du maillage int num_mail = NumMaillage(nom_maillage); if (num_mail != 0 ) // sinon il n'y a rien n'a supprimer { if (ParaGlob::NiveauImpression() >= 4) cout << " delet of the mesh " << nom_maillage << flush ; // on supprime le maillage // Dans le cas particulier où l'on veut garder les noeuds et éléments, on l'indique au maillage // avant sa suppression if(!sans_conservation_noeuds_elements) tabMaillage(num_mail)->Preparation_destruction_avec_conservation_noeuds_elements(); delete tabMaillage(num_mail); // 1) il faut également supprimer les références qui sont relative au maillage que l'on vient de supprimer // on commence par stocker la liste des ref à supprimer, on ne les supprime pas à la volée // de manière à ne pas modifier les bornes de l'algo de parcours // 2) il faut changer de numéro de maillage, toutes les ref qui sont pour les maillages après le maillage supprimé bool avec_diminution_num_maillage = true; lesRef->Supprime_tour_lesRef_un_maillage(num_mail,avec_diminution_num_maillage); // la map des noms mapNomMail.erase(nom_maillage); // -- maintenant il faut que l'on gère tous les tableaux internes qui sont relatifs aux maillages // on retasse les tableaux nbMaillageTotal--; // le tableau de maillage for (int i = num_mail;i<= nbMaillageTotal;i++) {tabMaillage(i) = tabMaillage(i+1); tabMaillage(i)->Change_numero_maillage(i); // changement du numéro de maillage }; tabMaillage(nbMaillageTotal+1)=NULL; // les frontières si elles ont été construite if (listFrontiere.Taille() != 0) {for (int i = num_mail;i<= nbMaillageTotal;i++) {tabMaillage(i) = tabMaillage(i+1); listFrontiere(i) = listFrontiere(i+1); tt_noeud_front(i) = tt_noeud_front(i+1); }; listFrontiere.Change_taille(nbMaillageTotal); tt_noeud_front.Change_taille(nbMaillageTotal); }; // le nombre de domaine esclave if (num_mail <= domEsclave ) // il faut diminuer le nombre d'esclave domEsclave--; }; }; // création de maillage par extrusion // Il y a création de références correspondantes void LesMaillages::CreeMaillageExtrusion2D3D(LesReferences* lesRef) { // création de la liste qui sert pour repérer les maillages complets créés list tab_quadra_inc_vers_comp; // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets for (int im=1;im<=nbMaillageTotal;im++) if (tabMaillage(im)->Contient_quadratique_incomplet()) { nb_final_maillage++; tab_quadra_inc_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage)); } // dans le cas où des maillages de quadratiques incomplet existent, création de nouveaux maillages nbMaillageTotal = nb_final_maillage; while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // maintenant on passe en revue les maillages candidats list::iterator il,ifin= tab_quadra_inc_vers_comp.end(); for (il=tab_quadra_inc_vers_comp.begin();il!=ifin;il++) { // on commence par créé le futur maillage complet à l'identique du maillage incomplet // original, il y a ici création de nouveau noeud et élément // on utilise un nouveau nom de maillage construit a partir de l'ancien string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { if(ref1->Nbmaille() == (*il).un) // on a trouvé une référence à considérer { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille((*il).deux); list_inter_ref.push_back(ref_nv); // on intègre la référence dans lesRéférences // lesRef->Ajout_reference(ref_nv); } ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques // complets. Les références sont également transformés en cohérence. tabMaillage((*il).deux)->Transfo_quadraIncomp_quadraComp(*lesRef); } }; // définition interactive de listes de références void LesMaillages::CreationInteractiveListesRef(LesReferences* lesRef) { // on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = nbMaillageTotal; cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; // on va boucler sur les maillages et définir des ref pour chaque maillages for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) tabMaillage(imail)->CreationInteractiveListesRef(lesRef); }; // modification de l'orientation d'éléments void LesMaillages::Modif_orientation_element(int cas_orientation,LesReferences* lesRef) { // on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = nbMaillageTotal; cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; switch(cas_orientation) { case 1: case 2: case 3: // cas d'une orientation automatique des maillages: { // on vérifie et augmente éventuellement la taille du nombre de maillage while (nbMaillageTotal > nbPortion) { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // on va boucler sur les maillages et définir de nouveaux maillages identiques for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) { // il y a ici création de nouveau noeud et élément // on utilise un nouveau nom de maillage construit a partir de l'ancien int imailnew = imail+nb_maillages_actifs_initiaux; string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez"; while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail)); nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { if(ref1->Nbmaille() == imail) // on a trouvé une référence à considérer { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille(imailnew); list_inter_ref.push_back(ref_nv); }; ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // on modifie l'orientation du nouveau maillage en fonction du cas tabMaillage(imailnew)->Modif_orientation_element(cas_orientation,lesRef); }; break; } case -1: // uniquement vérification { // on va boucler sur les maillages for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) tabMaillage(imail)->Modif_orientation_element(cas_orientation,lesRef); break; } default: cout << "\n erreur le cas : " << cas_orientation << " n'est pas actuellement pris en compte" << "\n LesMaillages::Modif_orientation_element(..."; Sortie(1); }; }; // Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe void LesMaillages::Collapse_element_supperpose(LesReferences* lesRef) { // on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = nbMaillageTotal; cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; // on vérifie et augmente éventuellement la taille du nombre de maillage while (nbMaillageTotal > nbPortion) { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // on va boucler sur les maillages et définir de nouveaux maillages identiques for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) { // il y a ici création de nouveau noeud et élément // on utilise un nouveau nom de maillage construit a partir de l'ancien int imailnew = imail+nb_maillages_actifs_initiaux; string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez"; while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail)); nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { if(ref1->Nbmaille() == imail) // on a trouvé une référence à considérer { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille(imailnew); list_inter_ref.push_back(ref_nv); }; ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // on fusionne les noeuds tabMaillage(imailnew)->Collapse_element_superpose(lesRef); }; }; // collapse de noeuds très proche: appartenant à des éléments différents // rayon : donne la distance maxi entre les noeuds qui doivent être collapsé void LesMaillages::Collapse_noeuds_proches(double rayon, LesReferences* lesRef) { // on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = nbMaillageTotal; cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; // on vérifie et augmente éventuellement la taille du nombre de maillage while (nbMaillageTotal > nbPortion) { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // on va boucler sur les maillages et définir de nouveaux maillages identiques for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) { // il y a ici création de nouveau noeud et élément // on utilise un nouveau nom de maillage construit a partir de l'ancien int imailnew = imail+nb_maillages_actifs_initiaux; string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez"; while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail)); nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { if(ref1->Nbmaille() == imail) // on a trouvé une référence à considérer { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille(imailnew); list_inter_ref.push_back(ref_nv); }; ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // on fusionne les noeuds tabMaillage(imailnew)->Collapse_noeuds_proches(rayon,lesRef); }; }; // création d'un nouveau maillage issue de la fusion de maillages existants // nom_mails_a_fusionner : la liste des maillages à fusionner // new_mail : le nom du nouveau maillage à construire // NB: si new_mail correspond à un maillage déjà existant, il y a fusion de ce maillage // avec les autres, sans création d'un nouveau maillage void LesMaillages::Fusion_maillages(List_io < string >& nom_mails_a_fusionner,const string& new_mail ,LesReferences* lesRef) { // on va commencer par créer un nouveau maillage if (ParaGlob::NiveauImpression() >= 4) cout << " debut d'une operation de fusion de maillage " << flush; // on regarde s'il s'agit d'une fusion avec un maillage existant ou non: Maillage* nevez_mail_ = NULL; // est renseigné dans le if suivant bool creation_nouveau_maillage = false; if (NumMaillage(new_mail) == 0) { // le retour est nulle: cas d'un nouveau maillage, on va créer un nouveau maillage // recherche d'un numéro du maillage nbMaillageTotal++; if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // le premier maillage est vide int dim = ParaGlob::Dimension(); tabMaillage(nbMaillageTotal) = new Maillage(mapNomMail,nbMaillageTotal,dim,new_mail); nevez_mail_ = (tabMaillage(nbMaillageTotal)); // pour simplifier creation_nouveau_maillage = true; } else { // il s'agit ici d'un maillage qui existe déjà nevez_mail_ = (tabMaillage(NumMaillage(new_mail))); }; // on récupère le maillage de base, qui intègrera les autres Maillage& nevez_mail = *nevez_mail_; // avant de faire l'opération de fusion, on va faire un traitement spécial pour les // références automatiques E_tout, N_tout, F_tout, A_tout, P_tout, G_tout {Tableau tab_tout(6); tab_tout(1) = "E_tout";tab_tout(2) = "N_tout"; tab_tout(3) = "F_tout"; tab_tout(4) = "A_tout";tab_tout(5) = "P_tout"; tab_tout(6) = "G_tout"; int idmail = NumMaillage(new_mail); for (int i=1;i<= 6; i++) {string& nreftout= tab_tout(i); if (lesRef->Existe(nreftout,idmail)) { const Reference& ref1 = lesRef->Trouve(nreftout,idmail); // récup de la ref Reference* ref2 = ref1.Nevez_Ref_copie(); // on crée une ref identique string nevez_nom=nreftout+"_1";int num=1; // on cherche un nom qui n'existe pas encore while (lesRef->Existe(nevez_nom,idmail)) {nevez_nom += "_"+ChangeEntierSTring(num);num++;}; ref2->Change_nom(nevez_nom); // change le nom de la nouvelle ref lesRef->Ajout_reference(ref2); // ajout de la ref if (ParaGlob::NiveauImpression() > 0) cout << "\n >>> attention la reference " << nreftout << " du maillage " << nevez_mail.NomDuMaillage() << " a un nouveau nom "<< nevez_nom; }; }; }; // maintenant on va passer en revue tous les maillages à fusionner List_io < string >::iterator il,ilfin=nom_mails_a_fusionner.end(); for (il = nom_mails_a_fusionner.begin();il != ilfin;il++) { // récup du numéro de maillage, // et éventuellement on passe le maillage identique à new_mail // debug //cout << "\n maillage de la liste à fusionner " << (*il) << " newmail= "<& tabN = mail_a_fusion.Tab_noeud(); int nbN = tabN.Taille();list li_Noe; for (int i=1;i<=nbN;i++) li_Noe.push_back(tabN(i)); // constitution de la liste d'éléments Tableau& tabE = mail_a_fusion.Tab_element(); int nbE = tabE.Taille();list li_Elem; for (int i=1;i<=nbE;i++) li_Elem.push_back(tabE(i)); // on récupère les références associées à ce maillage list lref; // la liste qui contiendra les ref recherchées const Reference* ref1 = lesRef->Init_et_Premiere(); // on parcours la liste pour récupérer les ref appartenant au maillage do { if(ref1->Nbmaille() == num_mail_a_fusion) // on a trouvé une référence à considérer {// si l'on est dans le cas de la fusion avec un maillage existant // on regarde s'il y a déjà une ref avec le même nom dans le maillage // si oui on change le nom de la ref à ajouter string ajout="";int num=0; if (!creation_nouveau_maillage) {while (lesRef->Existe((ref1->Nom()+ajout),NumMaillage(new_mail))) {num++;ajout = "_"+ChangeEntierSTring(num); // debug //cout << "\n (ref1->Nom()+ajout)" << (ref1->Nom()+ajout) << flush; // fin debug }; }; // on crée la référence à ajouter Reference* ref2 = ref1->Nevez_Ref_copie(); // on crée une ref identique ref2->Change_nom(ref1->Nom()+ajout); lref.push_back(ref2); // on averti que le nom de la référence a changé if ((ParaGlob::NiveauImpression() > 0) && (ajout != "")) cout << "\n >>> attention la reference "<Nom()<<" du maillage " << mail_a_fusion.NomDuMaillage() << " a un nouveau nom "<< (ref1->Nom()+ajout); // debug //cout << "\n ref2= " << ref2->Nom() << " num maille "<< ref2->Nbmaille() << flush; // fin debug }; // debug //cout << "\n " << ref1->Nom() << " num maille "<< ref1->Nbmaille() << flush; // fin debug ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // appel de la méthode de fusion nevez_mail.Ajout_elements_et_noeuds(li_Noe,li_Elem,&lref,lesRef); }; }; if (ParaGlob::NiveauImpression() >= 4) cout << "\n fin de l'operation de fusion de maillage " << flush; }; // création d'un nouveau maillage issue d'un maillages existants et d'une ref d'éléments // le nouveau maillage = les éléments de la ref void LesMaillages::Cree_sous_maillage(int num_mail,LesReferences* lesRef, string nom_ref,const string& new_mail) { // on va commencer par créer un nouveau maillage if (ParaGlob::NiveauImpression() >= 4) cout << " debut d'une operation de creation de sous-maillage " << flush; // on va créer un nouveau maillage // recherche d'un numéro du maillage nbMaillageTotal++; if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // le premier maillage est vide int dim = ParaGlob::Dimension(); // si le nom du nouveau maillage existe déjà, on met nevez en suffixe string nvnom(new_mail); // init while (NumMaillage(nvnom)) // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; // on commence par créé le futur maillage à l'identique du maillage contenant la ref // originale, il y a ici création de nouveaux noeuds et éléments // tabMaillage(nbMaillageTotal) = new Maillage(mapNomMail,nbMaillageTotal,dim,nvnom); tabMaillage(nbMaillageTotal) = new Maillage (mapNomMail,nbMaillageTotal,nvnom,*tabMaillage(nbMaillageTotal-1)); Maillage* nevez_mail_ = (tabMaillage(nbMaillageTotal)); // pour simplifier // pour simplifier Maillage& nevez_mail = *nevez_mail_; // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille(nbMaillageTotal); list_inter_ref.push_back(ref_nv); ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // puis, pour le nouveau maillage, // on restreint le maillage aux seuls éléments de la référence passée en paramètre // toutes les infos relatives à des éléments supprimés, sont également supprimés nevez_mail.Restreint_sous_maillage(lesRef, nom_ref); if (ParaGlob::NiveauImpression() >= 4) cout << "\n fin de l'operation de creation de sous-maillage " << flush; }; // création d'éléments SFE en fonction d'éléments classiques void LesMaillages::CreationMaillageSFE() // on passe en revue les différents maillages { // création de la liste qui sert pour repérer les maillages créés list tab_tri_vers_sfe; // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets for (int im=1;im<=nbMaillageTotal;im++) if (tabMaillage(im)->OKPourTransSfe()) { nb_final_maillage++; tab_tri_vers_sfe.push_back(DeuxEntiers(im,nb_final_maillage)); }; // dans le cas où des maillages candidats existent, création de nouveaux maillages nbMaillageTotal = nb_final_maillage; // on vérifie et augmente éventuellement la taille du nombre de maillage while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage { nbPortion = nbPortion+nbEnreg; tabMaillage.Change_taille(nbPortion); }; // maintenant on passe en revue les maillages candidats list::iterator il,ifin= tab_tri_vers_sfe.end(); for (il=tab_tri_vers_sfe.begin();il!=ifin;il++) { // on commence par créer le futur maillage SFE à l'identique du maillage triangulaire // original, il y a ici création de nouveau noeud et élément // on utilise un nouveau nom de maillage construit a partir de l'ancien string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; // init while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez // on utilise un nouveau nom de maillage construit a partir de l'ancien nvnom += "_nevez"; tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); // création de références identiques aux cas du maillage initial const Reference* ref1 = lesRef->Init_et_Premiere(); list list_inter_ref; // une liste intermédiaire de travail // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours // 1) donc premier temps on enregistre do { if(ref1->Nbmaille() == (*il).un) // on a trouvé une référence à considérer { // on crée une référence identique Reference* ref_nv = ref1->Nevez_Ref_copie(); // on met à jour le numéro de maillage associé ref_nv->Change_Nbmaille((*il).deux); list_inter_ref.push_back(ref_nv); }; ref1 = lesRef->Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 2) deuxième temps on enregistre list ::iterator kl,klfin=list_inter_ref.end(); for (kl=list_inter_ref.begin();kl != klfin; kl++) lesRef->Ajout_reference((*kl)); // On transforme les éléments triangulaire du nouveau maillage en SFE // Les références sont conservées, car a priori identiques tabMaillage((*il).deux)->CreationMaillageSFE(); } }; // renumérotation des noeuds de tous les maillages en même temps, + prise en compte // des conditions linéaires qui existent entre les noeuds // attention, ne peut fonctionner que si les maillages ont des relations entre eux, //sinon l'arbre de descendance ne sera pas complet !! // ramène false si rien n'a changé, vrai sinon // si le pointeur d'assemblage est non nulle, cela veut dire que l'on veut également une mise à jour // globale des pointeurs d'assemblages (ce qui est différent de la méthode : MiseAJourPointeurAssemblage( // qui agit maillage après maillage) // si le pointeur d'assemblage est non nulle et le drapeau: sans_changement_num_noeud = true // cela signifie que l'on désire uniquement une renumérotation de pointeur sans celle des noeuds // ramène dans tous les cas les nouvelles largeurs en ddl // nouvelles_largeur_en_ddl.un = la largeur totale // nouvelles_largeur_en_ddl.deux = la demie largeur // nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis // uniquement (sans les CLL) bool LesMaillages::Renumerotation(LesReferences& lesRef,const Tableau >& tab_condCLL ,TroisEntiers& nouvelles_largeur_en_ddl ,const Nb_assemb* nb_casAssemb,bool sans_changement_num_noeud) { // pour effectuer la renumérotation il est nécessaire de créer un tableau global de tous les noeuds et // de tous les éléments, de manière à pouvoir les gérer en même temps // a1) on calcul les nombres maxi int nb_noeud = 0; int nb_element = 0; for (int imail=1;imail<=nbMaillageTotal;imail++) { nb_noeud += tabMaillage(imail)->Nombre_noeud(); nb_element += tabMaillage(imail)->Nombre_element(); }; // a2) on crée maintenant les éléments frontières car cela utilise les numéros des noeuds, qui vont être changé // mais ce n'est pas toujours bien de recréer les frontières, car on peut avoir des grandeurs qui dépendent des frontières // comme par exemple les éléments de contact: si on refait les frontières, il faut refaire les éléments de contact // or la renumérotation n'a pas à changer les frontières en elles-mêmes // donc on adopte une création conditionnelle if ((listFrontiere.Taille() == 0) || (tt_noeud_front.Taille() == 0)) LesMaillages::CreeElemFront(); // on crée les éléments frontières // b) on crée les tableaux Tableau t_noe(nb_noeud); // le tableau global de noeuds Tableau t_oldNumNoeud(nb_noeud); // tableau des anciens numéros de noeuds Tableau t_elem(nb_element); // le tableau global des éléments // c) on rempli les tableaux en changeant les numéros des noeuds (pour avoir une seule numérotation) // normalement cela n'influe pas sur les éléments car eux ils contiennent des tableaux de pointeur de noeuds {int numGlobNoeud=1; int numGlobEle = 1; for (int imil=1;imil<=nbMaillageTotal;imil++) { int nbn = tabMaillage(imil)->Nombre_noeud(); Tableau& tab_noeud = tabMaillage(imil)->Tab_noeud(); for (int inoe = 1; inoe <= nbn; inoe++,numGlobNoeud++) { t_noe(numGlobNoeud) = tab_noeud(inoe); t_oldNumNoeud(numGlobNoeud) = tab_noeud(inoe)->Num_noeud(); t_noe(numGlobNoeud)->Change_num_noeud(numGlobNoeud); }; int nb_ele = tabMaillage(imil)->Nombre_element(); Tableau& tab_element = tabMaillage(imil)->Tab_element(); for (int iel = 1; iel <= nb_ele; iel++,numGlobEle++) { t_elem(numGlobEle) = tab_element(iel); }; }; }; // on encapsule pour isoler les variables numGlobNoeud et numGlobEle qui ne // doivent exister que dans la boucle // avant tout changement on calcul la largeur initiale due aux conditions linéaires // celle-ci n'est valide que dans le cas où tous les noeuds ont des numéros différents // ce qui est le cas maintenant int taille_tab_cll = tab_condCLL.Taille(); int largeur_initiale_CLL = 0; // init for (int i = 1; i<= taille_tab_cll;i++) { Tableau & condCLL = tab_condCLL(i); int taille = condCLL.Taille(); for (int j=1;j<= taille;j++) largeur_initiale_CLL=MaX(largeur_initiale_CLL,condCLL(j).DiffMaxiNumeroNoeud()); }; if ((ParaGlob::NiveauImpression() > 4) || ((nb_casAssemb == NULL)&&(ParaGlob::NiveauImpression() > 0)) ) { cout << "\n pour l'ensemble des conditions linaires: via une numerotation unique pour tous les maillages, " << " la 1/2 largeur de bande en noeud initiale est " << largeur_initiale_CLL << flush; }; bool nouvelle_numerotation = false; // pour le contrôle de la fin // on calcul le point de départ Tableau < LaLIST_io > t_voisin; // def du tableau des voisins des noeuds list < list < Maillage::Noeud_degre > > lis_descent; // stockage des descendants bool calcul_ok = false; // init par défaut Noeud* noe_dep = Maillage::Point_de_depart(t_elem,t_noe,tt_noeud_front,t_voisin,lis_descent,tab_condCLL,calcul_ok); if (calcul_ok) // on ne continue que si c'est ok {// on appelle l'algorithme de Cuthill Mac Kee Tableau tab_N_final = Maillage::Cuthill_Mac_Kee(nb_noeud,noe_dep,t_voisin,lis_descent); // --- maintenant on regarde l'évolution de la largeur de bande en noeud // tout d'abord la largeur initiale int largeur_initiale = Maillage::LargeurBandeEnNoeuds(t_elem); // on change la numérotation for (int ia=1;ia <= nb_noeud; ia++) tab_N_final(ia)->Change_num_noeud(ia); // nouvelle largeur de bande int largeur_Cuthill = Maillage::LargeurBandeEnNoeuds(t_elem); // idem pour les CLL int largeur_Cuthill_CLL = 0; // init for (int i = 1; i<= taille_tab_cll;i++) { Tableau & condCLL = tab_condCLL(i); int taille = condCLL.Taille(); for (int j=1;j<= taille;j++) largeur_Cuthill_CLL=MaX(largeur_Cuthill_CLL,condCLL(j).DiffMaxiNumeroNoeud()); }; // on change en numérotation inverse : Cuthill Mac Kee inverse // car on pense qu'a priori c'est celle-là qui sera la meilleur ///// Tableau tab_N_inverse(tab_N_final); for (int ia=1;ia <= nb_noeud; ia++) {tab_N_final(ia)->Change_num_noeud(1+nb_noeud-ia); // avec les modifs que j'ai fait après la ligne qui suit ne sert plus ??? ///// tab_N_inverse(1+nb_noeud-ia) = tab_N_final(ia); }; int largeur_Cuthill_inverse = Maillage::LargeurBandeEnNoeuds(t_elem); // idem pour les CLL int largeur_Cuthill_inverse_CLL = 0; // init for (int i = 1; i<= taille_tab_cll;i++) { Tableau & condCLL = tab_condCLL(i); int taille = condCLL.Taille(); for (int j=1;j<= taille;j++) largeur_Cuthill_inverse_CLL=MaX(largeur_Cuthill_inverse_CLL,condCLL(j).DiffMaxiNumeroNoeud()); }; if ((ParaGlob::NiveauImpression() > 3) || ((nb_casAssemb == NULL)&&(ParaGlob::NiveauImpression() > 0)) ) { cout << "\n $$ Premiere etape: optimisation sur l'ensemble des maillages sous forme d'un seul groupe $$ "; cout << "\n pour l'ensemble des maillages: 1/2 largeur de bande en noeud, initiale= " << largeur_initiale << "\n partie conditions lineaires initiales : " << largeur_initiale_CLL << " --> maxi des deux: " << MaX(largeur_initiale_CLL, largeur_initiale) << " \n apres l'algo de Cuthill Mac Kee= " << largeur_Cuthill << ", conditions lineaires : " << largeur_Cuthill_CLL << " --> maxi des deux: " << MaX(largeur_Cuthill_CLL, largeur_Cuthill) << " \n en Cuthill Mac Kee inverse= " << largeur_Cuthill_inverse << ", conditions lineaires : " << largeur_Cuthill_inverse_CLL << " --> maxi des deux: " << MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse)<< flush ; }; // normalement le dernier est le meilleur, en tout cas il est meilleur que le cas 2 // ----- dernières opérations: on regarde si effectivement il faut appliquer la nouvelle // ----- numérotation int demi_largeur_totale=MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse); if (MaX(largeur_initiale_CLL, largeur_initiale) < MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse)) // if (largeur_initiale < largeur_Cuthill_inverse) // bizarre, cela veut dire qu'il faut revenir à la forme initiale { for (int ia=1;ia <= nb_noeud; ia++) t_noe(ia)->Change_num_noeud(t_oldNumNoeud(ia)); demi_largeur_totale = MaX(largeur_initiale_CLL, largeur_initiale); } else if (MaX(largeur_Cuthill_CLL, largeur_Cuthill) < MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse) ) // else if (largeur_Cuthill < largeur_Cuthill_inverse ) // bizarre, cela veut dire qu'il faut revenir à la forme de Cuthill directe { nouvelle_numerotation = true; // on met la numérotation définitive relativement au tableau directe Tableau num_courant(nbMaillageTotal); // tableau des numéros courant de noeud // pour chaque maillage for (int ia=1;ia <= nb_noeud; ia++) // je ne comprend pas ce que j'ai fait. je modifie en faisant ce que je pense être bon ??? ////modifié { Noeud* noe = tab_N_final(ia); // pour simplifier ////modifié int num = (num_courant(noe->Num_Mail())++); ////modifié noe->Change_num_noeud(num); ////modifié }; tab_N_final(ia)->Change_num_noeud(ia); demi_largeur_totale = MaX(largeur_Cuthill_CLL, largeur_Cuthill); } else // c'est le cas normale { nouvelle_numerotation=true; // on met la numérotation définitive relativement au tableau inverse // là je ne comprend pas ce que j'ai fait, car la numérotation inverse a déjà été faite donc il n'y a rien // à faire, je comment donc la suite //// Tableau num_courant(nbMaillageTotal); // tableau des numéros courant de noeud //// // pour chaque maillage //// for (int ia=1;ia <= nb_noeud; ia++) //// { Noeud* noe = tab_N_inverse(ia); // pour simplifier //// int num = (num_courant(noe->Num_Mail())++); //// noe->Change_num_noeud(num); //// }; }; // on calcule si demandé, la largeur de bande en ddl qui résulte de la nouvelle numérotation // avant de changer les numéros de noeuds // et la mise à jour des pointeurs d'assemblages Tableau tab_N_final_final;// ne sert que pour le cas nb_casAssemb != NULL if (nouvelle_numerotation && (nb_casAssemb != NULL)) { // on garde en mémoire la numérotation des noeuds, dans l'ordre de tab_N_final // car on ne connait pas exactement le cheminement précédent de ce qui est retenue au final tab_N_final_final.Change_taille(nb_noeud); for (int i=1;i<=nb_noeud;i++) tab_N_final_final(tab_N_final(i)->Num_noeud()) = tab_N_final(i); // on met à jour les pointeurs d'assemblage en suivant le nouvel ordre de noeud MiseAJourPointeurAssemblage_interne(*nb_casAssemb,tab_N_final_final,false); // on calcul la largeur finale int demi = 0; int total = 0; int cumule = 0; // cas des CLL: for (int i = 1; i<= taille_tab_cll;i++) { Tableau & condCLL = tab_condCLL(i); int taille = condCLL.Taille(); for (int j=1;j<= taille;j++) condCLL(j).Largeur_Bande(demi,total,*nb_casAssemb); }; // on s'occupe des maillages int demi_pour_mail=0; int total_pour_mail=0; for (int imil=1;imil<=nbMaillageTotal;imil++) {int demi_inter=0; int total_inter=0; tabMaillage(imil)->Largeur_Bande(demi_inter,total_inter,*nb_casAssemb); demi_pour_mail = MaX(demi_pour_mail,demi_inter); total_pour_mail =MaX(total_pour_mail,total_inter); }; // on garde les maxi demi = MaX(demi,demi_pour_mail); total =MaX(total,total_pour_mail); // enregistrement nouvelles_largeur_en_ddl.deux = demi; nouvelles_largeur_en_ddl.un = total; nouvelles_largeur_en_ddl.trois = demi_pour_mail; if (ParaGlob::NiveauImpression() > 2) cout << "\n $$$ ==>> opti. glob. numerot. $$$ " << " 1/2 larg. ddl ==> " << demi << " larg. totale ==> " << total; //cout << "\n entrer une valeur pour continuer "; //int toto; cin >> toto; }; // dans le cas d'une nouvelle numérotation + dans le cas où on veut un changement // de numérotation effectif dans les noeuds // ->> introduction de la nouvelle numérotation dans les noeuds et mise à jour des reférences if ((nouvelle_numerotation) && (!sans_changement_num_noeud)) // il faut donc redéfinir une numérotation pour chaque maillage. Celle-ci // ne sera pas aussi optimum que dans le cas d'un seul maillage, mais elle devrait // être meilleure // -- un tableau d'indice qui donne le nouveau numéro en cours pour chaque maillage { Tableau num_noeu_par_maillage(nbMaillageTotal,0); // un nouveau tableau intermédiaire tel que le noeud t_noe_ordonnee(i), a le numéro i Tableau t_noe_ordonnee(nb_noeud); // le tableau global de noeuds for (int ia=1;ia <= nb_noeud; ia++) { Noeud* noe = t_noe(ia); // pour simplifier t_noe_ordonnee(noe->Num_noeud()) = noe; }; // si nouvelle numérotation est vrai, on parcourt le tableau et on renumérote à la volée // la méthode revient à compresser la numérotation pour chaque maillage de manière a // rester dans les limites du nombre de noeud pour chaque maillage for (int ia=1;ia <= nb_noeud; ia++) { Noeud* noe = t_noe_ordonnee(ia); // pour simplifier int num_mail = noe->Num_Mail(); num_noeu_par_maillage(num_mail)++; ////--debug //cout << "\n debug LesMaillages::Renumerotation( " // << "\n num_noeu_par_maillage("<Change_num_noeud(num_noeu_par_maillage(num_mail)); }; // Maintenant on s'occupe des références et de la numérotation définitive // si on a introduit une nouvelle numérotation // -- on s'occupe des numéros de référence // 1) on définit un tableau par maillage qui contient les nouveaux numéros // t_nv_num(j)(i) est pour le maillage j, le nouveau numéro du noeud // qui avait auparavant le numéro "i" Tableau > t_nv_num(nbMaillageTotal); // nouveau num/ au ancien for (int iml=1; iml<= nbMaillageTotal;iml++) t_nv_num(iml).Change_taille(tabMaillage(iml)->Nombre_noeud()); // init for (int ia=1;ia <= nb_noeud; ia++) { Noeud* noe = t_noe(ia); // pour simplifier, on utilise t_noe et non t_noe_ordonnee // car ensuite on utilise t_oldNumNoeud qui suit le même ordre que t_noe // //--debug // cout << "\n debug LesMaillages::Renumerotation( " // << "\n noe->Num_Mail()= "<Num_Mail() <<", ia= "<< ia // << " noe->Num_noeud()= "<Num_noeud() // << " t_oldNumNoeud(ia)= "<< t_oldNumNoeud(ia) << flush; ////--- fin debug t_nv_num(noe->Num_Mail())(t_oldNumNoeud(ia))=noe->Num_noeud(); }; // 2) maintenant on change les références for (int idmail=1;idmail<=nbMaillageTotal;idmail++) lesRef.Mise_a_jour_ref_noeud(t_nv_num(idmail),idmail); // --- on reconstruit les tableaux de pointeurs de noeuds dans chaque maillage // a) on crée un tableau intermédiaire de tous les tableaux de noeuds Tableau *> t_t_noeud(nbMaillageTotal); for (int iml=1; iml<= nbMaillageTotal;iml++) t_t_noeud(iml) = &(tabMaillage(iml)->Tab_noeud()); // init // b) on le remplit for (int ia=1;ia <= nb_noeud; ia++) { Noeud* noe = t_noe_ordonnee(ia); // pour simplifier (*t_t_noeud(noe->Num_Mail()))(noe->Num_noeud()) = noe; }; }; // affichage du résultat et éventuellement deuxième étape concernant le // changement des pointeurs d'assemblage if (nouvelle_numerotation) {if (nb_casAssemb == NULL) // cas sans changement des pointeurs // si on ne veut pas changer les pointeurs d'assemblage dans la foulée // on met une information sur la largeur de bande nouvelle, en noeud, // qui découle de la nouvelle numérotation (et non de l'assemblage) { int largeur_finale_CLL = 0; // init for (int i = 1; i<= taille_tab_cll;i++) { Tableau & condCLL = tab_condCLL(i); int taille = condCLL.Taille(); for (int j=1;j<= taille;j++) largeur_finale_CLL=MaX(largeur_finale_CLL,condCLL(j).DiffMaxiNumeroNoeud()); }; if (ParaGlob::NiveauImpression() > 0) { cout << "\n pour l'ensemble des conditions linaires: la 1/2 largeur de bande en noeud, finale est " << largeur_finale_CLL << flush; }; // non c'est débile, car on n'a pas fait de nouvelle numérotation en ddl, donc cela ne sert à rien de les imprimer // et au niveau de la numérotation en noeud, c'est déja visualisé /* int demi = 0; int total = 0; int cumule = 0; // on est quand même obligé de considérer un cas d'assemblage, on prend le dernier // par défaut // on récupère le nombre actuel de cas d'assemblage int nb_actuel = tab_nb_assemb; #ifdef MISE_AU_POINT if (nb_actuel == 0) {cout << "\n erreur Renumerotation : pas de cas d'assemblage encore defini !! " << " la renumerotation n'est pas possible ...."; Sortie(1); }; #endif Nb_assemb nbAssemble(nb_actuel); // cas des CLL: for (int i = 1; i<= taille_tab_cll;i++) { Tableau & condCLL = tab_condCLL(i); int taille = condCLL.Taille(); for (int j=1;j<= taille;j++) condCLL(j).Largeur_Bande(demi,total,nbAssemble); }; // on s'occupe des maillages int demi_pour_mail=0; int total_pour_mail=0; for (int imil=1;imil<=nbMaillageTotal;imil++) {int demi_inter=0; int total_inter=0; tabMaillage(imil)->Largeur_Bande(demi_inter,total_inter,nbAssemble); demi_pour_mail = MaX(demi_pour_mail,demi_inter); total_pour_mail =MaX(total_pour_mail,total_inter); }; // on garde les maxi demi = MaX(demi,demi_pour_mail); total =MaX(total,total_pour_mail); // enregistrement nouvelles_largeur_en_ddl.deux = demi; nouvelles_largeur_en_ddl.un = total; nouvelles_largeur_en_ddl.trois = demi_pour_mail; // affichage du résultat if (ParaGlob::NiveauImpression() >= 3) cout << "\n $$$ =>> opti. glob. numerot. $$$ " << " 1/2 larg. ddl => " << demi << " larg. totale => " << total << flush; */ } else // sinon c'est le cas où on veut changer les pointeurs d'assemblage {// deuxième partie pour les pointeurs d'assemblage: // on doit mettre à jour le tableau t_i_n pour les pointeurs d'assemblage // concernant uniquement les numéros de noeuds // --> deux cas suivant que l'on ne veut pas enregistrer la nouvelle numérotation // des noeuds ou non if (sans_changement_num_noeud) { // mise à jour des numéros de noeud, on revient aux numéros initiaux // on revient au numéro initiaux for (int i=1;i<=nb_noeud;i++) t_noe(i)->Change_num_noeud(t_oldNumNoeud(i)); // pour chaque noeud, tab_N_final(i) correspond au noeud qui avait le numéro i ancien // et qui a maintenant le numéro tab_N_final(i)->Num_noeud() // mise à jour de t_i_n MiseAJourTableau_t_i_n(*nb_casAssemb,tab_N_final_final); } else {MiseAJourTableau_t_i_n(*nb_casAssemb,tab_N_final_final); }; }; } else {// on remet néanmoins l'ancienne numérotation, car elle a changé int nbN = t_noe.Taille(); for (int i=1;i<=nbN;i++) t_noe(i)->Change_num_noeud(t_oldNumNoeud(i)); if (ParaGlob::NiveauImpression() >= 3) cout << "\n $$$ au final numerot. idem $$$ " << flush; nouvelle_numerotation = false; calcul_ok = true; }; } else {// si Maillage::Point_de_depart n'a pas fonctionné correctement il faut remettre l'ancienne numérotation if (ParaGlob::NiveauImpression() > 2) cout << "\n calcul du demarrage infructeux de l'algorithme de Gibbs (voisins, descendance etc.) " << " on conserve l'ancienne renumerotation "; for (int nue =1; nue<= nb_noeud; nue++) t_noe(nue)->Change_num_noeud(t_oldNumNoeud(nue)); }; // retour return (calcul_ok && nouvelle_numerotation); }; // renumérotation des noeuds maillages par maillage, // === sans prise en compte de conditions linéaires === // en sortie les maillages sont mis à jour si la nouvelle numérotation conduit à une largeur de bande // plus faible que la largeur initiale: en noeuds // ramène: false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure) // vrai sinon bool LesMaillages::Renumerotation(LesReferences& lesRef) { // on crée les éléments frontières car cela utilise les numéros des noeuds, qui vont être changé // mais ce n'est pas toujours bien de recréer les frontières, car on peut avoir des grandeurs // qui dépendent des frontières // comme par exemple les éléments de contact: si on refait les frontières, // il faut refaire les éléments de contact // or la renumérotation n'a pas à changer les frontières en elles-mêmes // donc on adopte une création conditionnelle if ((listFrontiere.Taille() == 0) || (tt_noeud_front.Taille() == 0)) LesMaillages::CreeElemFront(); // on crée les éléments frontières // on passe en revue tous les maillages pour une renumérotation individuelle bool calcul_ok = false; // init par défaut Tableau > condCLL; // un tableau vide pour l'appel for (int imail=1;imail<=nbMaillageTotal;imail++) { if (ParaGlob::NiveauImpression() > 2) cout << "\n ===>> traitement du maillage: " << tabMaillage(imail)->NomDuMaillage(); bool inter = tabMaillage(imail)->Renumerotation(lesRef,condCLL); calcul_ok = calcul_ok || inter; }; // retour return calcul_ok ; }; // indique aux éléments un niveau de précision de calcul désiré pour les prochains calculs // precision = 0 : aucune précision demandée, precision >=0 : précision maximale demandée void LesMaillages::Drapeau_preparation_calcul_precis(int precision) {for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbelmax = Nombre_element(i1); Maillage* maillage = tabMaillage(i1); // pour simplifier for (int jel = 1; jel <= nbelmax; jel++) { maillage->Element_mail(jel).Drapeau_preparation_calcul_precis(precision);}; }; }; // on s'occupe de mettre à jour les types de pb et les ddl types associés void LesMaillages::Mise_a_jour_type_pb_type_associe_ddl() { types_de_problemes.clear(); ddl_representatifs_des_physiques.clear(); for (int i = 1; i<= nbMaillageTotal; i++) { {//const list & type_pb = (tabMaillage(i))->Types_de_problemes(); // pour simplifier const Tableau & type_pb = (tabMaillage(i))->Types_de_problemes(); // pour simplifier // list ::const_iterator il,ilfin=type_pb.end(); // for (il=type_pb.begin();il != ilfin;il++) int taill = type_pb.Taille(); for (int j=1;j<=taill;j++) if (find(types_de_problemes.begin(),types_de_problemes.end(),type_pb(j)) == types_de_problemes.end()) types_de_problemes.push_back(type_pb(j));//(*il); }; {//const list & type_ddl = (tabMaillage(i))->Ddl_representatifs_des_physiques(); // pour simplifier //list ::const_iterator il,ilfin=type_ddl.end(); //for (il=type_ddl.begin();il != ilfin;il++) const Tableau & type_ddl = (tabMaillage(i))->Ddl_representatifs_des_physiques(); // pour simplifier int taill = type_ddl.Taille(); for (int j=1;j<=taill;j++) if (find(ddl_representatifs_des_physiques.begin(),ddl_representatifs_des_physiques.end() ,type_ddl(j)) == ddl_representatifs_des_physiques.end()) ddl_representatifs_des_physiques.push_back(type_ddl(j)); }; }; types_de_problemes.sort(); types_de_problemes.unique(); ddl_representatifs_des_physiques.sort(); ddl_representatifs_des_physiques.unique(); }; // --- utilitaires pour calculs particuliers------- // Tableau integ_vol_typeQuel, integ_vol_typeQuel_t; // Tableau ref_integ_vol; // les références associées // // 2) intégration de volume et en temps: donc on commule le delta // Tableau integ_vol_t_typeQuel, integ_vol_t_typeQuel_t; // Tableau ref_integ_vol_t; // les références associées // LesReferences* lesRef; // references // calcul des diverses intégrations: volume et volume + temps, // alimentation des grandeurs globales associées void LesMaillages::Integration() { // on passe en revue les références de volumes a intégrer // Tableau ref_integ_vol; // les références associées // les références sont ordonnées par apparition dans le fichier .info // des intégrales, ceci permet de repérer les bonnes grandeurs à cummuler int taill = ref_integ_vol.Taille(); for (int rang_integ =1;rang_integ<= taill;rang_integ++) if (ref_integ_vol(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas // l'intégrale stockée reste fixe pendant le calcul { const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol(rang_integ)); // initialisation du conteneur relatif à chaque ref TypeQuelconque& TQ = integ_vol_typeQuel(rang_integ); // pour simplifier // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); g_TG->InitParDefaut(); // on initialise le conteneur // cumule des valeurs: on récupère les infos à partir des éléments concernés int ref_Taille=ref->Taille(); for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero de l'element dans le maillage int nnn = ref->Nbmaille(); // le numero du maillage // recup de l'element Element * poi = & Element_LesMaille(nnn,nbb); // demande a l'element des infos const Tableau * tab_Q = poi->Integ_vol_typeQuel(); const Tableau & index_integ = *(poi->Index_Integ_vol_typeQuel()); // la grandeur à cumuler c'est celle qui a le bon indexe int indice = index_integ.Contient(rang_integ); *(g_TG) += *((*tab_Q)(indice).Grandeur_pointee()); // -- les deux lignes d'avant sont a priori équivalentes aux lignes qui suivent // int nb_integ = tab_Q->Taille(); // le nombre d'intégrale à considérer // for (int iteg = 1;iteg <= nb_integ;iteg++) // {if ((index_integ)(iteg)==rang_integ) // si l'index est négatif, on ne cumule pas // // cela veut aussi dire que l'intégrale est figée // // sinon si on a le bon index: on cumule l'intégrale // {*(g_TG) += *((*tab_Q)(iteg).Grandeur_pointee()); // break; // }; // }; }; // maintenant il s'agit d'alimenter les grandeurs globales // on récupère le pointeur correspondant à la grandeur correspondant au nom // de référence const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans l'integration !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Integration()"<GrandeurGlobal(*nom_de_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'integration !! " << " la variable globale "<< (*nom_de_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesMaillages::Integration()"<Nom_ref() // << " :: " << *(g_TG) << flush; // //// -- fin debug TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); *(gr_quelc->Grandeur_pointee()) = *(g_TG); }; // même chose pour les intégrales en volume et en temps int taill1 = ref_integ_vol_t.Taille(); for (int rang_integ =1;rang_integ<= taill1;rang_integ++) if (ref_integ_vol_t(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas // l'intégrale stockée reste fixe pendant le calcul { const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol_t(rang_integ)); // initialisation du conteneur relatif à chaque ref TypeQuelconque& TQ = integ_vol_t_typeQuel(rang_integ); // pour simplifier // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); g_TG->InitParDefaut(); // on initialise le conteneur // cumule des valeurs: on récupère les infos à partir des éléments concernés int ref_Taille=ref->Taille(); for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero de l'element dans le maillage int nnn = ref->Nbmaille(); // le numero du maillage // recup de l'element Element * poi = & Element_LesMaille(nnn,nbb); // demande a l'element des infos const Tableau * tab_Q = poi->Integ_vol_t_typeQuel(); const Tableau & index_integ = *(poi->Index_Integ_vol_t_typeQuel()); // la grandeur à cumuler c'est celle qui a le bon indexe int indice = index_integ.Contient(rang_integ); *(g_TG) += *((*tab_Q)(indice).Grandeur_pointee()); // -- les deux lignes d'avant sont a priori équivalentes aux lignes qui suivent // int nb_integ = tab_Q->Taille(); // le nombre d'intégrale à considérer // for (int iteg = 1;iteg <= nb_integ;iteg++) // {if ((index_integ)(iteg)==rang_integ) // // sinon si on a le bon index: on cumule l'intégrale // {*(g_TG) += *((*tab_Q)(iteg).Grandeur_pointee()); // break; // }; // }; }; // maintenant il s'agit d'alimenter les grandeurs globales // on récupère le pointeur correspondant à la grandeur correspondant au nom // de référence const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans l'integration !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::Integration()"<GrandeurGlobal(*nom_de_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'integration !! " << " la variable globale "<< (*nom_de_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesMaillages::Integration()"<Grandeur_pointee()) = *(g_TG); }; }; // calcul des diverses statistiques sur des ref de noeuds et avec éventuellement // cumul sur le temps // alimentation des grandeurs globales associées void LesMaillages::CalStatistique() { // on passe en revue les références de noeud des statistiques {// Tableau ref_statistique; // les références associées int NB_ref = ref_statistique.Taille(); if (NB_ref) {// on boucle sur les ref for (int i_ref =1;i_ref<= NB_ref;i_ref++) if (ref_statistique(i_ref) != NULL) // si null cela veut que l'on ne fait rien // la statistique stockée reste fixe pendant le calcul { const ReferenceNE * ref = ((ReferenceNE *) ref_statistique(i_ref)); // initialisation du conteneur relatif à chaque ref TypeQuelconque& TQ = statistique_typeQuel(i_ref); // pour simplifier // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); g_TG->InitParDefaut(); // on initialise le conteneur int ref_Taille=ref->Taille(); int i_mail = ref->Nbmaille(); // le numero du maillage Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier Fonction_nD* fct = gr.Fct(); // récupération d'un pointeur de fonction nD // différent choix if (fct == NULL) { // cas d'un stockage pour ddl_etendu Ddl_enum_etendu& ddl_enu_eten = pour_statistique_de_ddl(i_ref);// récup du ddl // on veut : (1) la somme, (2) la moyenne, (3) le max, (4) le min, (5) le max des | | , (6) le min des | | // tab_val(k) : la grandeur k // tab_index(k) : k= 1 -> le numéro du noeud pour le max // k= 2 -> le numéro du noeud pour le min // k= 3 -> le numéro du noeud pour le max des | | // k= 4 -> le numéro du noeud pour le min des | | // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) Vecteur& t10 = (gr.ConteneurVecteur()); t10(4)=t10(6)=ConstMath::tresgrand; // on met les mini très grand // t10(i), i=7 à 10 --> correspond aux numéros de noeud, stockés en double au lieu de int // == tab_index(k) // ceci pour utiliser uniquement un seul conteneur global double& tab_pour_MAXI_1 = t10(7); double& tab_pour_MAXI_2 = t10(8); double& tab_pour_MAXI_3 = t10(9); double& tab_pour_MAXI_4 = t10(10); // on regarde s'il s'agit d'un ddl pur ou étendu if (ddl_enu_eten.Nom_vide()) // cas d'un ddl pur {// récup de l'énumération Enum_ddl enu = ddl_enu_eten.Enum(); // cumule des valeurs: on récupère les infos à partir des noeuds concernés for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage // récupération du Noeud Noeud& noe = Noeud_LesMaille(i_mail,nbb); // récup de la valeur du ddl double val_du_ddl = 0.; // init if (noe.Existe_ici(enu)) {val_du_ddl = noe.Ddl_noeud_tdt(enu).Valeur();} #ifdef MISE_AU_POINT else {if (ParaGlob::NiveauImpression() >= 4) {if (ParaGlob::Francais()) {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() << " n'est pas disponible pour statistique, on met 0 a la place";} else {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() << " is not available for statistic, the value will be 0 ";}; }; }; #endif // le calcul des grandeurs t10(1) += val_du_ddl; t10(2) += 1.; // on s'en sert ici comme compteur int num_noeud = noe.Num_noeud(); if (t10(3) < val_du_ddl) { t10(3) = val_du_ddl; tab_pour_MAXI_1 = num_noeud; }; if (t10(4) > val_du_ddl) { t10(4) = val_du_ddl; tab_pour_MAXI_2 = num_noeud; }; if (Dabs(t10(5)) < Dabs(val_du_ddl)) { t10(5) = val_du_ddl; tab_pour_MAXI_3 = num_noeud; }; if (Dabs(t10(6)) > Dabs(val_du_ddl)) { t10(6) = val_du_ddl; tab_pour_MAXI_4 = num_noeud; }; }; // calcul de la moyenne t10(2) = t10(1) / t10(2); } else // cas d'un ddl étendu {// cumule des valeurs: on récupère les infos à partir des noeuds concernés for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage // récupération du Noeud Noeud& noe = Noeud_LesMaille(i_mail,nbb); // récup de la valeur du ddl double val_du_ddl = 0.; // init // on examine tout d'abord le cas particulier des positions bool trouver = false; // on regarde d'abord s'il s'agit d'une info spécifique au contact int posi = ddl_enu_eten.Position()-NbEnum_ddl(); switch (posi) { case 123: // "X1_t" { val_du_ddl = noe.Coord1()(1);trouver=true; break;} case 124: // "X2_t" { val_du_ddl = noe.Coord1()(2);trouver=true; break;} case 125: // X3_t { val_du_ddl = noe.Coord1()(3);trouver=true; break;} case 126: // X1_t0 { val_du_ddl = noe.Coord0()(1);trouver=true; break;} case 127: // X2_t0 { val_du_ddl = noe.Coord0()(2);trouver=true; break;} case 128: // X3_t0 { val_du_ddl = noe.Coord0()(3);trouver=true; break;} default: ;// rien }; // si ce n'était pas un cas particulier on continue la recherche if (!trouver) // on regarde si la grandeur existe {if (noe.Existe_ici_ddlEtendu(ddl_enu_eten)) {val_du_ddl = noe.DdlEtendue(ddl_enu_eten).ConstValeur();} #ifdef MISE_AU_POINT else {if (ParaGlob::NiveauImpression() >= 4) {if (ParaGlob::Francais()) {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() << " n'est pas disponible pour statistique, on met 0 a la place";} else {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() << " is not available for statistic, the value will be 0 ";}; }; }; #endif }; // le calcul des grandeurs t10(1) += val_du_ddl; t10(2) += 1.; // on s'en sert ici comme compteur int num_noeud = noe.Num_noeud(); if (t10(3) < val_du_ddl) { t10(3) = val_du_ddl; tab_pour_MAXI_1 = num_noeud; }; if (t10(4) > val_du_ddl) { t10(4) = val_du_ddl; tab_pour_MAXI_2 = num_noeud; }; if (Dabs(t10(5)) < Dabs(val_du_ddl)) { t10(5) = val_du_ddl; tab_pour_MAXI_3 = num_noeud; }; if (Dabs(t10(6)) > Dabs(val_du_ddl)) { t10(6) = val_du_ddl; tab_pour_MAXI_4 = num_noeud; }; }; // calcul de la moyenne t10(2) = t10(1) / t10(2); } ////------- debug --------- // cout << "\n debug statistique: "; // cout << t10; // // ////------- fin debug -------- } else // cas d'un stockage pour fonction nD { Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier Fonction_nD* fct = gr.Fct(); // récupération de la fonction nD // supposons que la fonction nD ramène n valeurs, // pour chaque valeur on va avoir pour la valeur i : // ((6*(i-1)+1) la somme, ((6*(i-1)+2) la moyenne, ((6*(i-1)+3) le max, ((6*(i-1)+4) le min, // ((6*(i-1)+5) -> le numéro du noeud pour le max, ((6*(i-1)+6) -> le numéro du noeud pour le min, // donc en tout cela donne 6*n valeurs // ensuite on a: // (6*n + 1) le max des | |, (6*n + 2) le min des | |, // (6*n + 3) -> le numéro du noeud pour le max des | | // (6*n + 4) -> le numéro du noeud pour le min des | | // d'où un vecteur de taille (6*n + 4) // on commence par récupérer les conteneurs des grandeurs à fournir List_io & li_enu_scal = fct->Li_enu_etendu_scalaire(); List_io & li_quelc = fct->Li_equi_Quel_evolue(); int nb_composante = fct->NbComposante(); // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) Vecteur& t6 = (gr.ConteneurVecteur()); t6(4)=t6(6)=ConstMath::tresgrand; // on met les mini très grand // cumule des valeurs: on récupère les infos à partir des noeuds concernés for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage // récupération du Noeud Noeud& noe = Noeud_LesMaille(i_mail,nbb); // 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 tab = noe.Valeur_multi_et_Tensorielle(li_enu_scal,li_quelc); // récup des valeurs de la fonction Tableau & t_ret = fct->Valeur_FnD_Evoluee(&tab,&li_enu_scal,&li_quelc,NULL,NULL); int num_noeud = noe.Num_noeud(); // le calcul des grandeurs sur chaque composante double norme=0; for (int i=1;i<= nb_composante;i++) { int decal = 6*(i-1); double val_composante = t_ret(i); t6(decal+1) += val_composante; t6(decal+2) += 1.; // on s'en sert ici comme compteur if (t6(decal+3) < val_composante) { t6(decal+3) = val_composante; t6(decal+5) = num_noeud; }; if (t6(decal+4) > val_composante) { t6(decal+4) = val_composante; t6(decal+6) = num_noeud; }; norme +=val_composante*val_composante; }; // on traite la norme int decal = 6*nb_composante; norme = sqrt(norme); if (t6(decal+1) < norme) { t6(decal+1) = norme; t6(decal+3) = num_noeud; }; if (t6(decal+2) > norme) { t6(decal+2) = norme; t6(decal+4) = num_noeud; }; }; // on calcule les moyennes for (int i=1;i<= nb_composante;i++) { int decal = 6*(i-1); t6(decal+2) = t6(decal+1)/t6(decal+2); }; }; // maintenant il s'agit d'alimenter les grandeurs globales // on récupère le pointeur correspondant à la grandeur correspondant au nom // de référence const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans le transfert d'une statistique !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::CalStatistique()"<GrandeurGlobal(*nom_de_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans le transfert d'une statistique !! " << " la variable globale "<< (*nom_de_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesMaillages::CalStatistique()"<Grandeur_pointee()) = *(g_TG); }; }; // fin de la boucle sur les ref }; // idem pour l'accumulation en temps {// Tableau ref_statistique_t; // les références associées int NB_ref = ref_statistique_t.Taille(); if (NB_ref) {// on boucle sur les ref for (int i_ref =1;i_ref<= NB_ref;i_ref++) if (ref_statistique_t(i_ref) != NULL) // si null cela veut que l'on ne fait rien // la statistique stockée reste fixe pendant le calcul { const ReferenceNE * ref = ((ReferenceNE *) ref_statistique_t(i_ref)); // initialisation du conteneur relatif à chaque ref TypeQuelconque& TQ = statistique_t_typeQuel(i_ref); // pour simplifier TypeQuelconque& TQ_t = statistique_t_typeQuel_t(i_ref); // le précédent // le conteneur qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); g_TG->InitParDefaut(); // on initialise le conteneur int ref_Taille=ref->Taille(); int i_mail = ref->Nbmaille(); // le numero du maillage Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier Fonction_nD* fct = gr.Fct(); // récupération d'un pointeur de fonction nD // le conteneur à t qui contient le résultat globalisé TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); Grandeur_Vecteur_Nommer& gr_t = *((Grandeur_Vecteur_Nommer*) g_TG_t); // différent choix if (fct == NULL) { // cas d'un stockage pour ddl_etendu Ddl_enum_etendu& ddl_enu_eten = pour_statistique_t_de_ddl(i_ref);// récup du ddl // on veut : (1) la somme, (2) la moyenne, (3) le max, (4) le min, (5) le max des | | , (6) le min des | | // tab_val(k) : la grandeur k // tab_index(k) : k= 1 -> le numéro du noeud pour le max // k= 2 -> le numéro du noeud pour le min // k= 3 -> le numéro du noeud pour le max des | | // k= 4 -> le numéro du noeud pour le min des | | // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) Vecteur& t10 = (gr.ConteneurVecteur()); t10(4)=t10(6)=ConstMath::tresgrand; // on met les mini très grand // t10(i), i=7 à 10 --> correspond aux numéros de noeud, stockés en double au lieu de int // == tab_index(k) // ceci pour utiliser uniquement un seul conteneur global double& tab_pour_MAXI_1 = t10(7); double& tab_pour_MAXI_2 = t10(8); double& tab_pour_MAXI_3 = t10(9); double& tab_pour_MAXI_4 = t10(10); // on regarde s'il s'agit d'un ddl pur ou étendu if (ddl_enu_eten.Nom_vide()) // cas d'un ddl pur {// récup de l'énumération Enum_ddl enu = ddl_enu_eten.Enum(); // cumule des valeurs: on récupère les infos à partir des noeuds concernés for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage // récupération du Noeud Noeud& noe = Noeud_LesMaille(i_mail,nbb); // récup de la valeur du ddl double val_du_ddl = 0.; // init // on regarde si la grandeur existe if (noe.Existe_ici(enu)) {val_du_ddl = noe.Ddl_noeud_tdt(enu).Valeur();} #ifdef MISE_AU_POINT else {if (ParaGlob::NiveauImpression() >= 4) {if (ParaGlob::Francais()) {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() << " n'est pas disponible pour statistique cumulee, on met 0 a la place";} else {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() << " is not available for statistic cumuled, the value will be 0 ";}; }; }; #endif // le calcul des grandeurs t10(1) += val_du_ddl; t10(2) += 1.; // on s'en sert ici comme compteur int num_noeud = noe.Num_noeud(); if (t10(3) < val_du_ddl) { t10(3) = val_du_ddl; tab_pour_MAXI_1 = num_noeud; }; if (t10(4) > val_du_ddl) { t10(4) = val_du_ddl; tab_pour_MAXI_2 = num_noeud; }; if (Dabs(t10(5)) < Dabs(val_du_ddl)) { t10(5) = val_du_ddl; tab_pour_MAXI_3 = num_noeud; }; if (Dabs(t10(6)) > Dabs(val_du_ddl)) { t10(6) = val_du_ddl; tab_pour_MAXI_4 = num_noeud; }; }; // calcul de la moyenne t10(2) = t10(1) / t10(2); // cumule sur le temps Vecteur& t10_t = (gr_t.ConteneurVecteur()); t10(1) += t10_t(1); t10(2) += t10_t(2); t10(3) += t10_t(3); t10(4) += t10_t(4); t10(5) += t10_t(5); t10(6) += t10_t(6); } else // cas d'un ddl étendu {// cumule des valeurs: on récupère les infos à partir des noeuds concernés for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage // récupération du Noeud Noeud& noe = Noeud_LesMaille(i_mail,nbb); // récup de la valeur du ddl double val_du_ddl = 0.; // init // on examine tout d'abord le cas particulier des positions bool trouver = false; // on regarde d'abord s'il s'agit d'une info spécifique au contact int posi = ddl_enu_eten.Position()-NbEnum_ddl(); switch (posi) { case 123: // "X1_t" { val_du_ddl = noe.Coord1()(1);trouver=true; break;} case 124: // "X2_t" { val_du_ddl = noe.Coord1()(2);trouver=true; break;} case 125: // X3_t { val_du_ddl = noe.Coord1()(3);trouver=true; break;} case 126: // X1_t0 { val_du_ddl = noe.Coord0()(1);trouver=true; break;} case 127: // X2_t0 { val_du_ddl = noe.Coord0()(2);trouver=true; break;} case 128: // X3_t0 { val_du_ddl = noe.Coord0()(3);trouver=true; break;} default: ;// rien }; // si ce n'était pas un cas particulier on continue la recherche if (!trouver) {if (noe.Existe_ici_ddlEtendu(ddl_enu_eten)) {val_du_ddl = noe.DdlEtendue(ddl_enu_eten).ConstValeur();} #ifdef MISE_AU_POINT else {if (ParaGlob::NiveauImpression() >= 4) {if (ParaGlob::Francais()) {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() << " n'est pas disponible pour statistique cumulee, on met 0 a la place";} else {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() << " is not available for statistic cumuled, the value will be 0 ";}; }; }; #endif }; // le calcul des grandeurs t10(1) += val_du_ddl; t10(2) += 1.; // on s'en sert ici comme compteur int num_noeud = noe.Num_noeud(); if (t10(3) < val_du_ddl) { t10(3) = val_du_ddl; tab_pour_MAXI_1 = num_noeud; }; if (t10(4) > val_du_ddl) { t10(4) = val_du_ddl; tab_pour_MAXI_2 = num_noeud; }; if (Dabs(t10(5)) < Dabs(val_du_ddl)) { t10(5) = val_du_ddl; tab_pour_MAXI_3 = num_noeud; }; if (Dabs(t10(6)) > Dabs(val_du_ddl)) { t10(6) = val_du_ddl; tab_pour_MAXI_4 = num_noeud; }; }; // calcul de la moyenne t10(2) = t10(1) / t10(2); // cumule sur le temps Vecteur& t10_t = (gr_t.ConteneurVecteur()); t10(1) += t10_t(1); t10(2) += t10_t(2); t10(3) += t10_t(3); t10(4) += t10_t(4); t10(5) += t10_t(5); t10(6) += t10_t(6); }; // ensuite on cumule sur le temps ////------- debug --------- //cout << "\n debug statistique: "; //cout << t10; // // ////------- fin debug -------- } else // cas d'un stockage pour fonction nD { Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier Fonction_nD* fct = gr.Fct(); // récupération de la fonction nD // supposons que la fonction nD ramène n valeurs, // pour chaque valeur on va avoir pour la valeur i : // ((6*(i-1)+1) la somme, ((6*(i-1)+2) la moyenne, ((6*(i-1)+3) le max, ((6*(i-1)+4) le min, // ((6*(i-1)+5) -> le numéro du noeud pour le max, ((6*(i-1)+6) -> le numéro du noeud pour le min, // donc en tout cela donne 6*n valeurs // ensuite on a: // (6*n + 1) le max des | |, (6*n + 2) le min des | |, // (6*n + 3) -> le numéro du noeud pour le max des | | // (6*n + 4) -> le numéro du noeud pour le min des | | // d'où un vecteur de taille (6*n + 4) // on commence par récupérer les conteneurs des grandeurs à fournir List_io & li_enu_scal = fct->Li_enu_etendu_scalaire(); List_io & li_quelc = fct->Li_equi_Quel_evolue(); int nb_composante = fct->NbComposante(); // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) Vecteur& t6 = (gr.ConteneurVecteur()); t6(4)=t6(6)=ConstMath::tresgrand; // on met les mini très grand // cumule des valeurs: on récupère les infos à partir des noeuds concernés for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage // récupération du Noeud Noeud& noe = Noeud_LesMaille(i_mail,nbb); // 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 tab = noe.Valeur_multi_et_Tensorielle(li_enu_scal,li_quelc); // récup des valeurs de la fonction Tableau & t_ret = fct->Valeur_FnD_tab_scalaire(&tab); int num_noeud = noe.Num_noeud(); // le calcul des grandeurs sur chaque composante double norme=0; for (int i=1;i<= nb_composante;i++) { int decal = 6*(i-1); double val_composante = t_ret(i); t6(decal+1) += val_composante; t6(decal+2) += 1.; // on s'en sert ici comme compteur if (t6(decal+3) < val_composante) { t6(decal+3) = val_composante; t6(decal+5) = num_noeud; }; if (t6(decal+4) > val_composante) { t6(decal+4) = val_composante; t6(decal+6) = num_noeud; }; norme +=val_composante*val_composante; }; // on traite la norme int decal = 6*nb_composante; norme = sqrt(norme); if (t6(decal+1) < norme) { t6(decal+1) = norme; t6(decal+3) = num_noeud; }; if (t6(decal+2) > norme) { t6(decal+2) = norme; t6(decal+4) = num_noeud; }; }; // on calcule les moyennes et on cumule dans le temps // pour les composantes i Vecteur& t6_t = (gr_t.ConteneurVecteur()); for (int i=1;i<= nb_composante;i++) { int decal = 6*(i-1); t6(decal+2) = t6(decal+1)/t6(decal+2); // le cumul dans le temps t6(decal+1) += t6_t(decal+1);t6(decal+2) += t6_t(decal+2); t6(decal+3) += t6_t(decal+3);t6(decal+4) += t6_t(decal+4); }; // idem pour les normes int decal = 6*nb_composante; t6(decal+1) += t6_t(decal+1) ; t6(decal+2) += t6_t(decal+2); }; // maintenant il s'agit d'alimenter les grandeurs globales // on récupère le pointeur correspondant à la grandeur correspondant au nom // de référence const string* nom_de_ref = g_TG->Nom_ref(); #ifdef MISE_AU_POINT if (nom_de_ref == NULL) { cout << "\n *** pb dans le transfert d'une statistique cumulee !! " << " nom_de_ref est nul, on ne peut pas continuer " << "\n LesMaillages::CalStatistique()"<GrandeurGlobal(*nom_de_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans le transfert d'une statistique cumulee !! " << " la variable globale "<< (*nom_de_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesMaillages::CalStatistique()"<Grandeur_pointee()) = *(g_TG); }; }; // fin de la boucle sur les ref }; }; // mise à jour des repères d'anisotropie void LesMaillages::Mise_a_jour_repere_anisotropie (DiversStockage* divers,LesFonctions_nD* lesFonctionsnD) { // l'idée est d'éviter de stocker les infos déjà présentes dans DiversStockage ... // on reprend le caneva de la méthode LesMaillages::Completer // par contre on considère que tous les dimensionnements sont corrects // cas de la définition de repère d'anisotropie int divers_TabRepAnisotrope_Taille=divers->TabRepAnisotrope().Taille(); for (int ii=1;ii<= divers_TabRepAnisotrope_Taille;ii++) { string nomRepAnisotrope = (divers->TabRepAnisotrope())(ii).NomRef(); // recup du nom de la ref const BlocDdlLim& div_TabRepAnisotrope = (divers->TabRepAnisotrope())(ii); const Reference & refG = lesRef->Trouve(nomRepAnisotrope,div_TabRepAnisotrope.NomMaillage()); // recup de la reference const ReferenceNE & ref = (ReferenceNE &) refG; int ref_Taille=ref.Taille(); // creation d'un bloc general contenant des informations // n= nombre de string, m nombre de double BlocGen bloc(5,0) ; // par defaut string nom_inter("repere_anisotropie_"); bloc.Change_nom(1,nom_inter); // le mot clé // ensuite le type l'identificateur de repere bloc.Change_nom(2,div_TabRepAnisotrope.Nom(2)); // ensuite le type de repere bloc.Change_nom(3,div_TabRepAnisotrope.Nom(3)); // puis la méthode de définition du repère bloc.Change_nom(4,div_TabRepAnisotrope.Nom(4)); // un string qui contient le nom de la fonction nD bloc.Change_nom(5,div_TabRepAnisotrope.Nom(6)); // puis on alimente les éléments concernés par ces calculs ////--- debug //cout << "\n -- debug LesMaillages::Completer( "; //bloc.Affiche(); cout << endl; ////--- fin debug for (int jj= 1; jj<= ref_Taille; jj++) {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage int nnn = ref.Nbmaille(); // le numero du maillage // recup de l'element Element * poi = & Element_LesMaille(nnn,nbb); // demande a l'element de se completer poi->Mise_a_jour_repere_anisotropie(bloc,lesFonctionsnD); }; }; }; // initialisation par défaut de tous les conteneurs aux noeuds // de tous les maillages // contenant li_restreinte_TQ et li_restreinte_ddl // ces conteneurs sont supposés déjà existés // typiquement si le conteneurs est un scalaire, on met 0 void LesMaillages::Init_par_defaut_conteneurs(List_io < TypeQuelconque >& li_restreinte_TQ ) {List_io < TypeQuelconque >::iterator il,ilfin=li_restreinte_TQ.end(); for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); // on parcours la liste for (il = li_restreinte_TQ.begin(); il != ilfin;il++) {TypeQuelconque_enum_etendu enuTypeQuelconque = (*il).EnuTypeQuelconque(); TypeQuelconque& tyqN = noo->ModifGrandeur_quelconque(enuTypeQuelconque); tyqN.Grandeur_pointee()->InitParDefaut(); }; } } }; // idem pour une seule grandeur void LesMaillages::Init_par_defaut_conteneurs(TypeQuelconque_enum_etendu enuTypeQuelconque) {for (int i1 = 1; i1<= nbMaillageTotal; i1++) { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); for (int i2 = 1; i2 <= nbnoeudmax; i2++) { // recup du noeud Noeud * noo = & Noeud_LesMaille(i1,i2); TypeQuelconque& tyqN = noo->ModifGrandeur_quelconque(enuTypeQuelconque); tyqN.Grandeur_pointee()->InitParDefaut(); }; }; };