// FICHIER : Maillage.cp // CLASSE : Maillage // This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-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 "Maillage.h" # include using namespace std; //introduces namespace std #include #include "Sortie.h" #include #include #include "List_io.h" #include "CharUtil.h" //#ifndef SYSTEM_MAC_OS_X_unix // #include "Frontier.h" //#endif #include "ConstMath.h" #include "ReferenceNE.h" #include "ReferenceAF.h" #include "Util.h" #include "MvtSolide.h" // --------- utilitaires de manipulation de maillage // test pour savoir si le maillage contiend des éléments à interpolation linéaire bool Maillage::Contient_lineaire() { // on balaie les éléments int taille_elem = tab_element.Taille(); for (int i=1; i<=taille_elem;i++) { Enum_interpol eninter = tab_element(i)->Id_interpolation(); // LINEAIRE indique que l'on a une interpolation linéaire if (eninter == LINEAIRE) return true; } // sinon pas d'élément incomplet quadratique return false; }; bool Maillage::Contient_quadratique_incomplet() { // on balaie les éléments int taille_elem = tab_element.Taille(); for (int i=1; i<=taille_elem;i++) { Enum_interpol eninter = tab_element(i)->Id_interpolation(); // QUADRATIQUE indique que l'on a une interpolation quadratique incomplète // alors que QUADRACOMPL indique que c'est quadratique complet if (eninter == QUADRATIQUE) return true; } // sinon pas d'élément incomplet quadratique return false; }; // transformation des éléments linéaires du maillage en quadratiques. // les éléments linéaires sont supprimés, // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage void Maillage::Transfo_lin_quadraIncomp(LesReferences &lesRef) {list nv_remplace; list li_nv_noeud; list li_bornes; // 1) on balaie les éléments int nbnt=tab_noeud.Taille(); // le nombre de noeud total (évolue pendant la transformation) // nbnt permet à Construct_from_imcomplet de donner des numéros de noeud licite, en particulier // permet d'éviter que deux noeuds aient le même numéro int taille_elem = tab_element.Taille(); for (int i=1; i<=taille_elem;i++) { Enum_interpol eninter = tab_element(i)->Id_interpolation(); // LINEAIRE indique que l'on a une interpolation linéaire if (eninter == LINEAIRE) {// 2) on a trouvé un linéaire // on crée un quadratique incomplet de même type Element * elem = tab_element(i); // pour simplifier Element::Signature signa = elem->Signature_element(); // on change l'interpolation signa.id_interpol=QUADRATIQUE; // on crée le nouvel élément quadratique avec le même numéro que le linéaire (car il le remplacera // par la suite) Element* elem2= Element::Choix_element(elem->Num_maillage(),elem->Num_elt(),signa); if (elem2 == NULL) { cout << "\n erreur de creation d'un element quadratique incomplet a partir d'un lineaire" << "\n signature du lineaire: interpolation " << Nom_interpol(signa.id_interpol) << " geometrie: " << Nom_geom(signa.id_geom) << " problem: " << NomElemTypeProblem(signa.id_problem) << " infos_annexes: " << signa.infos_annexes << "\n Maillage::Transfo_lin_quadraIncomp(..."; Sortie(1); } // 3) on demande à l'élément de définir ses noeuds, d'une part à partir des noeuds // déjà existants de l'élément linéaire, et d'autre part à partir de nouveaux noeuds // construit à partir de l'interpolation initiale linéaire. // on fournit également le premier numéro -1 du nouveau noeud list li_bo; // les bornes pour la renumérotation list l_nv_noe = elem2->Construct_from_lineaire(*elem,li_bo,nbnt); nbnt += l_nv_noe.size(); // 4) on ajoute les nouveaux noeuds list ::iterator lni,lnifin=l_nv_noe.end(); for (lni=l_nv_noe.begin();lni!=lnifin;lni++) {li_nv_noeud.push_back(Maillage::PosiEtNoeud(*lni,elem2)); } list ::iterator pni,pnifin=li_bo.end(); for (pni=li_bo.begin();pni!=pnifin;pni++) {li_bornes.push_back(*pni); } // 5) on enregistre l'élément linéaire et on le remplace par le quadratique dans // la liste d'élément nv_remplace.push_back(elem); tab_element(i) = elem2; } } // 6) on supprime les doublons dans la liste des noeuds en réaffectant les bons pointeurs dans les éléments // li_nv_noeud.sort(); // ordonne la liste // suppression des doublons et réaffectation des pointeurs de noeuds supprimés dans les éléments if (li_nv_noeud.size() != 1) {list ::iterator lili,lilifin = li_nv_noeud.end(); list ::iterator lila = li_nv_noeud.begin();lili=lila; lili++; list ::iterator pili,pilifin = li_bornes.end(); list ::iterator pila = li_bornes.begin();pili=pila; pili++; do { if (*lila == *lili) { //cas de deux noeuds identiques, on réaffecte le pointeur de noeud dans l'élément (*lila).el->Reaffectation_pointeur_noeud((*lila).noe,(*lili).noe); // on supprime le noeud doublon delete (*lila).noe; // on supprime les éléments de la liste li_nv_noeud.erase(lila); li_bornes.erase(pila); } lila = lili; lili++; pila = pili; pili++; } while (lili!= lilifin); } // 7) insertion des nouveaux noeuds dans le tableau définitif et renumérotation // a) on commence par définir une liste de noeud, équivalente au tableau tab_noeud List_io li_no; int nbn = tab_noeud.Taille(); // petite vérif: il faut que le maillage contienne au moins un noeud #ifdef MISE_AU_POINT if (nbn == 0) { cout << "\n erreur le maillage contiend 0 noeud en propre, ce qui est insufisent pour la routine" << "\n list Maillage::Transfo_quadraIncomp_quadraComp()"; Sortie(1); } #endif // b) on définit un tableau de listes de pointeurs de noeud Tableau > tab_ln(nbn); // c) on remplit chaque liste des noeuds qu'il faudrait ajouter pour avoir une bonne numérotation list ::iterator lili,lilifin = li_nv_noeud.end(); list ::iterator pilifin = li_bornes.end(); list ::iterator pili = li_bornes.begin(); for (lili=li_nv_noeud.begin();lili != lilifin; lili++,pili++) { // récup de la position moyenne d'insertion et remplissage de la liste correspondante // cout << "\n un= " << (*pili).un << "deux= " << (*pili).deux ; int bi=( (*pili).un + (*pili).deux ) / 2; // division entière // cout << " bi= " << bi << endl; tab_ln(bi).push_back((*lili).noe); } // d) on définit un nouveau tableau de noeud qui comprend les anciens et les nouveaux noeuds, ordonnées int nbn_nv = nbn+li_nv_noeud.size(); Tableau tab_noe_nv(nbn_nv); // définition également d'un tableau d'indiçage inverse Tableau indic(nbn); int ino=0; for (int ivo=1;ivo<= nbn;ivo++) { // tout d'abord le noeud ancien ino++; tab_noe_nv(ino)=tab_noeud(ivo); indic(ivo)=ino; // puis éventuellement les noeuds à intercaler List_io& li_ln = tab_ln(ivo); // pour simplifier if (li_ln.size() != 0) { List_io::iterator iln,iln_end=li_ln.end(); for (iln=li_ln.begin(); iln != iln_end; iln++) { ino++; tab_noe_nv(ino)=*iln;}; } } tab_noeud = tab_noe_nv; // remplacement du tableau du maillage // e) on renumérote les différents noeuds for (int j=1;j<= nbn_nv;j++) tab_noeud(j)->Change_num_noeud(j); // 7) modification des références sur les noeuds // a) on passe en revue les références et on sélectionne les références relatives aux noeuds // de l'ancien maillage const Reference* ref1 = lesRef.Init_et_Premiere(); do { if((ref1->Nbmaille() == idmail) && (ref1->Indic() == 1)) // on a trouvé une référence de noeud à considérer { ReferenceNE * refNE = ( ReferenceNE *) ref1; // pour simplifier int nb_num=refNE->Taille(); for (int it= 1;it<=nb_num;it++) refNE->Change_num_dans_ref(it,indic(refNE->Numero(it))); } ref1 = lesRef.Reference_suivante(); // la référence suivante } while (ref1 != NULL); cout << "\n *** attention les references generes ici ne sont pas bonnes !! , seul le maillage est " << " actuellement correcte "; // 8) suppression des éléments linéaires qui n'ont plus lieu d'être list ::iterator lele,lelefin=nv_remplace.end(); for (lele=nv_remplace.begin();lele!=lelefin;lele++) delete (*lele); // 9) rien à faire sur les références d'élément, ou de face d'élément ou d'arrête d'élément // car d'une part les nouveaux éléments ont le même numéro que les anciens, et d'autre part // le fait de passer en élément complet ne modifie pas les arrêtes ou faces }; // transformation des éléments quadratiques incomplet du maillage en quadratiques complets. // les éléments incomplets sont supprimée, // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage void Maillage::Transfo_quadraIncomp_quadraComp(LesReferences &lesRef) {list nv_remplace; list li_nv_noeud; list li_bornes; // 1) on balaie les éléments int nbnt=tab_noeud.Taille(); // le nombre de noeud total (évolue pendant la transformation) // nbnt permet à Construct_from_imcomplet de donner des numéros de noeud licite, en particulier // permet d'éviter que deux noeuds aient le même numéro int taille_elem = tab_element.Taille(); for (int i=1; i<=taille_elem;i++) { Enum_interpol eninter = tab_element(i)->Id_interpolation(); // QUADRATIQUE indique que l'on a une interpolation quadratique incomplète // alors que QUADRACOMPL indique que c'est quadratique complet if (eninter == QUADRATIQUE) {// 2) on a trouvé un quadratique incomplet // on crée un quadratique complet de même type Element * elem = tab_element(i); // pour simplifier Element::Signature signa = elem->Signature_element(); // on change l'interpolation signa.id_interpol=QUADRACOMPL; // on crée le nouvel élément complet avec le même numéro que l'incomplet (car il le remplacera // par la suite) Element* elem2= Element::Choix_element(elem->Num_maillage(),elem->Num_elt(),signa); if (elem2 == NULL) { cout << "\n erreur de creation d'un element quadratique complet a partir d'un incomplet" << "\n signature du quadratique incomplet: interpolation " << Nom_interpol(signa.id_interpol) << " geometrie: " << Nom_geom(signa.id_geom) << " problem: " << NomElemTypeProblem(signa.id_problem) << " infos_annexes: " << signa.infos_annexes << "\n Maillage::Transfo_quadraIncomp_quadraComp(..."; Sortie(1); } // 3) on demande à l'élément de définir ses noeuds, d'une part à partir des noeuds // déjà existants de l'élément incomplet, et d'autre part à partir de nouveaux noeuds // construit à partir de l'interpolation initiale incomplète. // on fournit également le premier numéro -1 du nouveau noeud list li_bo; // les bornes pour la renumérotation list l_nv_noe = elem2->Construct_from_imcomplet(*elem,li_bo,nbnt); nbnt += l_nv_noe.size(); // 4) on ajoute les nouveaux noeuds list ::iterator lni,lnifin=l_nv_noe.end(); for (lni=l_nv_noe.begin();lni!=lnifin;lni++) {li_nv_noeud.push_back(Maillage::PosiEtNoeud(*lni,elem2)); } list ::iterator pni,pnifin=li_bo.end(); for (pni=li_bo.begin();pni!=pnifin;pni++) {li_bornes.push_back(*pni); } // 5) on enregistre l'élément incomplet et on le remplace par le complet dans // la liste d'élément nv_remplace.push_back(elem); tab_element(i) = elem2; } } // 6) on supprime les doublons dans la liste des noeuds en réaffectant les bons pointeurs dans les éléments // non car cela ne sert à rien et il faudrait également traiter li_bornes li_nv_noeud.sort(); // ordonne la liste // suppression des doublons et réaffectation des pointeurs de noeuds supprimés dans les éléments if (li_nv_noeud.size() != 1) {list ::iterator lili,lilifin = li_nv_noeud.end(); list ::iterator lila = li_nv_noeud.begin();lili=lila; lili++; list ::iterator pili,pilifin = li_bornes.end(); list ::iterator pila = li_bornes.begin();pili=pila; pili++; do { if (*lila == *lili) { //cas de deux noeuds identiques, on réaffecte le pointeur de noeud dans l'élément (*lila).el->Reaffectation_pointeur_noeud((*lila).noe,(*lili).noe); // on supprime le noeud doublon delete (*lila).noe; // on supprime les éléments de la liste li_nv_noeud.erase(lila); li_bornes.erase(pila); } lila = lili; lili++; pila = pili; pili++; } while (lili!= li_nv_noeud.end()); }; ////------ debug //{ //cout << "\n debug: Maillage::Transfo_quadraIncomp_quadraComp "; //list ::iterator pili = li_bornes.begin(); //int i=1; //for (pili;pili != li_bornes.end();pili++,i++) // cout << "\n borne "<< i <<": " << *pili; //cout << endl; //}; ////----- fin debug // 7) insertion des nouveaux noeuds dans le tableau définitif et renumérotation // a) on commence par définir une liste de noeud, équivalente au tableau tab_noeud List_io li_no; int nbn = tab_noeud.Taille(); // petite vérif: il faut que le maillage contienne au moins un noeud #ifdef MISE_AU_POINT if (nbn == 0) { cout << "\n erreur le maillage contiend 0 noeud en propre, ce qui est insufisent pour la routine" << "\n list Maillage::Transfo_quadraIncomp_quadraComp()"; Sortie(1); } #endif // b) on définit un tableau de listes de pointeurs de noeud Tableau > tab_ln(nbn); // c) on remplit chaque liste des noeuds qu'il faudrait ajouter pour avoir une bonne numérotation list ::iterator lili,lilifin = li_nv_noeud.end(); list ::iterator pilifin = li_bornes.end(); list ::iterator pili = li_bornes.begin(); for (lili=li_nv_noeud.begin();lili != lilifin; lili++,pili++) { // récup de la position moyenne d'insertion et remplissage de la liste correspondante int bi=( (*pili).un + (*pili).deux ) / 2; // division entière ////------ debug //{ //cout << "\n debug: Maillage::Transfo_quadraIncomp_quadraComp "; // cout << "\n bornes : " << *pili << endl; //}; ////----- fin debug tab_ln(bi).push_back((*lili).noe); }; // d) on définit un nouveau tableau de noeud qui comprend les anciens et les nouveaux noeuds, ordonnées int nbn_nv = nbn+li_nv_noeud.size(); Tableau tab_noe_nv(nbn_nv); // définition également d'un tableau d'indiçage inverse Tableau indic(nbn); int ino=0; for (int ivo=1;ivo<= nbn;ivo++) { // tout d'abord le noeud ancien ino++; tab_noe_nv(ino)=tab_noeud(ivo); indic(ivo)=ino; // puis éventuellement les noeuds à intercaler List_io& li_ln = tab_ln(ivo); // pour simplifier if (li_ln.size() != 0) { List_io::iterator iln,iln_end=li_ln.end(); for (iln=li_ln.begin(); iln != iln_end; iln++) { ino++; tab_noe_nv(ino)=*iln;}; } } tab_noeud = tab_noe_nv; // remplacement du tableau du maillage // e) on renumérote les différents noeuds for (int j=1;j<= nbn_nv;j++) tab_noeud(j)->Change_num_noeud(j); // 7) modification des références sur les noeuds // a) on passe en revue les références et on sélectionne les références relatives aux noeuds // de l'ancien maillage const Reference* ref1 = lesRef.Init_et_Premiere(); do { if((ref1->Nbmaille() == idmail) && (ref1->Indic() == 1)) // on a trouvé une référence de noeud à considérer { ReferenceNE * refNE = ( ReferenceNE *) ref1; // pour simplifier int nb_num=refNE->Taille(); for (int it= 1;it<=nb_num;it++) refNE->Change_num_dans_ref(it,indic(refNE->Numero(it))); } ref1 = lesRef.Reference_suivante(); // la référence suivante } while (ref1 != NULL); // 8) suppression des élément incomplet qui n'ont plus lieu d'être list ::iterator lele,lelefin=nv_remplace.end(); for (lele=nv_remplace.begin();lele!=lelefin;lele++) delete (*lele); // 9) rien à faire sur les références d'élément, ou de face d'élément ou d'arrête d'élément // car d'une part les nouveaux éléments ont le même numéro que les anciens, et d'autre part // le fait de passer en élément complet ne modifie pas les arrêtes ou faces }; // Affiche les donnees du maillage dans un fichier // dont le nom est construit à partir du nom du maillage // au format ".her" et ".lis" void Maillage::Affiche_dans_her_lis(LesReferences &lesRef,Enum_dure temps) { //------------- écriture du .her ------------- // ouverture du fichier pour les noeuds char nomm[132]; char*fileName = nomm; strcpy(fileName, nomDuMaillage.c_str()); ofstream * sur_sort = new ofstream (strcat(fileName,".her")); ofstream & sort = * sur_sort; if(!(sort.is_open())) // le fichier ne peut être ouvert, message d'erreur { cout << "\n erreur en ouverture pour l'ecriture du fichier " << fileName << "\n" << " Maillage::Affiche_dans_her_lis(.... " << endl; Sortie(1); }; // écriture de l'entete sort << "\n ###########################################################################" << "\n # ecriture automatique d'un maillage au format .her, par Herezh++ #" << "\n ###########################################################################" << "\n # version: " << ParaGlob::NbVersion() << "\n \n \n "; // écriture du nom du maillage sort << "\n nom_maillage " << nomDuMaillage << " # nom du maillage" << "\n" << "\n noeuds ------------ # definition des noeuds"; int dimen = ParaGlob::Dimension(); // l'entete des noeuds int nbn = tab_noeud.Taille(); sort << "\n "<< nbn << " NOEUDS # definition du nombre de noeuds" << "\n \n" << "\n#---------------------------------------------------------------" << "\n#|NO DU| X | Y | Z |" << "\n#|NOEUD| | | |" << "\n#---------------------------------------------------------------" << "\n"; // écriture des noeuds double sero = 0.; for (int ine=1;ine<=nbn; ine++) { sort << "\n" << setw (6) << ine <<" "; Coordonnee co; switch (temps) { case TEMPS_0 : co=tab_noeud(ine)->Coord0(); break; // si les noeuds n'ont pas bougés on sort les coordonnées à 0 case TEMPS_t : { if (tab_noeud(ine)->ExisteCoord1()) { co=tab_noeud(ine)->Coord1(); } else co=tab_noeud(ine)->Coord0(); break; } case TEMPS_tdt : { if (tab_noeud(ine)->ExisteCoord2()) { co=tab_noeud(ine)->Coord2(); } else co=tab_noeud(ine)->Coord0(); break; } default : cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; cout << "Maillage::Affiche_dans_her_lis(.. \n"; Sortie(1); }; #ifndef ENLINUX_STREAM sort.setf(ios_base::scientific); #else sort.setf(ios::scientific); #endif for (int j=1;j<=3;j++) if (j<=dimen) sort << setw (18) << setprecision(ParaGlob::NbdigdoCA()) <Signature_element(); sort << Nom_geom(sign.id_geom) << " " << Nom_interpol(sign.id_interpol) << " " << sign.infos_annexes << " "; Tableau& tab_n = tab_element(ie)->Tab_noeud(); int taille_tab_n = tab_n.Taille(); for (int ite=1;ite<=taille_tab_n;ite++) sort << tab_n(ite)->Num_noeud() << " "; } // quelques lignes blanches à la fin du fichier sort << "\n \n \n"; // fermeture du fichier delete sur_sort; //------------- écriture du .lis ------------- // Affiche les donnees des références pour le maillage imail dans un fichier // dont le nom est construit à partir du nom du maillage au format ".lis" lesRef.Affiche_dans_lis(nomDuMaillage,idmail); }; //modification du maillage pour le restreindre 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 void Maillage::Restreint_sous_maillage(LesReferences* lesRef, string nom_ref) { // on définit un tableau d'indicateur donnant les éléments non référencés Tableau tab_el_non_referencer(tab_element.Taille(),true); // par défaut on ne conserve pas // on définit un tableau d'indicateur donnant les noeuds non référencés Tableau tab_noe_non_referencer(tab_noeud.Taille(),true); // récup de la référence des éléments const ReferenceNE & ref =((ReferenceNE &) lesRef->Trouve(nom_ref,idmail)); if (ref.Indic() != 2) {cout << "\n *** erreur: la reference "< 2) cout << "\n Maillage::Restreint_sous_maillage(... "; Sortie(1); }; // récup du tableau d'éléments de la référence const Tableau& tab_E_ref = ref.Tab_num(); // on marque les éléments à conserver ainsi que les noeuds // qui appartiennent à des éléments à conserver int nb_el = tab_E_ref.Taille(); for (int i=1;i<=nb_el;i++) {tab_el_non_referencer(tab_E_ref(i)) = false; Element * el = tab_element(tab_E_ref(i)); const Tableau& tab_noeu = el->Tab_noeud_const(); int nb_noe = tab_noeu.Taille(); for (int noe = 1;noe <= nb_noe; noe++) tab_noe_non_referencer(tab_noeu(noe)->Num_noeud())=false; }; // suppression des éléments non référencés int NBE=tab_element.Taille(); for (int i=1;i<=NBE;i++) if (tab_el_non_referencer(i)) delete tab_element(i); // suppression des noeuds non référencés int NBN = tab_noeud.Taille(); int nb_noeud_final = 0; // init for (int i=1;i<= NBN;i++) if (tab_noe_non_referencer(i)) {delete tab_noeud(i);} else {nb_noeud_final++;}; // sinon on compte // on redimentionne et réafecte le tableau de noeuds Tableau tab_old_noe = tab_noeud; // sauvegarde de l'ancien tableau // nv_tab est tel que : nv_tab_noe(i) est le nouveau numéro qui avait auparavant le numéro "i" Tableau nv_tab_noe(NBN); tab_noeud.Change_taille(nb_noeud_final); int indice_noeu=1; // pour parcourir le tableau final de noeud for (int i=1;i<=NBN;i++) if (!tab_noe_non_referencer(i)) {tab_noeud(indice_noeu) = tab_old_noe(i); nv_tab_noe(i)=indice_noeu; tab_noeud(indice_noeu)->Change_num_noeud(indice_noeu); indice_noeu++; }; // on redimentionne et réafecte le tableau d'élément Tableau tab_old_El = tab_element; // sauvegarde de l'ancien tableau // nv_tab est tel que : nv_tab_ele(i) est le nouveau numéro qui avait auparavant le numéro "i" Tableau nv_tab_ele(NBE); tab_element.Change_taille(nb_el); int indice_ele=1; // pour parcourir le tableau final d'élément for (int i=1;i<=NBE;i++) if (!tab_el_non_referencer(i)) {tab_element(indice_ele) = tab_old_El(i); nv_tab_ele(i)=indice_ele; tab_element(indice_ele)->Change_num_elt(indice_ele); indice_ele++; }; // on s'occupe maintenant des références lesRef->Mise_a_jour_ref_element(nv_tab_ele,idmail,tab_el_non_referencer); lesRef->Mise_a_jour_ref_noeud(nv_tab_noe,idmail,tab_noe_non_referencer); // toilettage final listFrontiere.clear();tab_noeud_front.Change_taille(0);indice.Change_taille(0); mitoyen_de_chaque_element.Change_taille(0); }; // relocalisation des points milieux des arrêtes des éléments quadratiques void Maillage::RelocPtMilieuMailleQuadra() { // on passe en revue les différents éléments pour voir s'il ont une arrête quadratique int nbe = tab_element.Taille(); for (int ne=1;ne<=nbe;ne++) { // récup de l'élément géométrique const ElemGeomC0& elgeom = tab_element(ne)->ElementGeometrique_const(); // récup du nombre de segment int nbse= elgeom.NbSe(); // on boucle sur les segments pour voir s'il y a un quadratique for (int iseg=1;iseg<=nbse;iseg++) { ElemGeomC0 const & elseg = elgeom.ElemSeg(iseg); if (elseg.TypeInterpolation() == QUADRACOMPL) { // récup de la connection des noeuds des arêtes par rapport a ceux de l'element Tableau > const & nonStout = elgeom.NonS(); Tableau const & nonS = nonStout(iseg); Tableau& t_noeud = tab_element(ne)->Tab_noeud(); Noeud & N1=*t_noeud(nonS(1));Noeud & N2=*t_noeud(nonS(2));Noeud & N3=*t_noeud(nonS(3)); // ------------- étape de modification du noeud milieu ----------------------- Coordonnee M01= N1.Coord0();Coordonnee M02= N2.Coord0();Coordonnee M03= N3.Coord0(); Coordonnee M1M3=(M03-M01);Coordonnee M1M2=(M02-M01);Coordonnee M2M3=(M03-M02); double d12=M1M2.Norme();double d13=M1M3.Norme();double d23=M2M3.Norme(); if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit)) { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant 0" << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment" << "\n Maillage::RelocPtMilieuMailleQuadra()"; N1.Affiche(); N2.Affiche(); N3.Affiche(); break; } Coordonnee U=M1M3/d13; // le vecteur normal à U int dim = ParaGlob::Dimension(); Coordonnee V(dim); double sinusangle; switch (dim) { case 1: // ici il suffit de prendre le point milieu { sinusangle=0.; break;} case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;} case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2); if (sinusangle > ConstMath::unpeupetit) { W.Normer(); V = Util::ProdVec_coor(W,U);} break; } }; // on vérifie que les 3 points ne sont pas naturellement alignés if (sinusangle > ConstMath::unpeupetit) // cas où l'on peut considérer une base locale { double N1H = M1M2*U; double HN2 = M1M2*V; double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H)); Coordonnee P = M01 + p1 * U + p2 * V;; N2.Change_coord0(P); break; } else // cas où les 3 points sont originalement alignés { Coordonnee milieu = (M01+M03)/2.; N2.Change_coord0(milieu); break; } // +++++++ si les coordonnées à t existent, même traitement if (N1.ExisteCoord1()) { M01= N1.Coord1();M02= N2.Coord1();M03= N3.Coord1(); M1M3=(M03-M01); M1M2=(M02-M01); M2M3=(M03-M02); d12=M1M2.Norme(); d13=M1M3.Norme(); d23=M2M3.Norme(); if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit)) { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant t" << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment" << "\n Maillage::RelocPtMilieuMailleQuadra()"; N1.Affiche(); N2.Affiche(); N3.Affiche(); break; } U=M1M3/d13; // le vecteur normal à U switch (dim) { case 1: // ici il suffit de prendre le point milieu { sinusangle=0.; break;} case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;} case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2); if (sinusangle > ConstMath::unpeupetit) { W.Normer(); V = Util::ProdVec_coor(W,U);} break; } }; // on vérifie que les 3 points ne sont pas naturellement alignés if (sinusangle > ConstMath::unpeupetit) // cas où l'on peut considérer une base locale { double N1H = M1M2*U; double HN2 = M1M2*V; double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H)); Coordonnee P = M01 + p1 * U + p2 * V;; N2.Change_coord1(P); break; } else // cas où les 3 points sont originalement alignés { Coordonnee milieu = (M01+M03)/2.; N2.Change_coord1(milieu); break; } } // +++++ si les coordonnées à t existent, même traitement if (N1.ExisteCoord2()) { M01= N1.Coord2();M02= N2.Coord2();M03= N3.Coord2(); M1M3=(M03-M01); M1M2=(M02-M01); M2M3=(M03-M02); d12=M1M2.Norme(); d13=M1M3.Norme(); d23=M2M3.Norme(); if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit)) { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant tdt" << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment" << "\n Maillage::RelocPtMilieuMailleQuadra()"; N1.Affiche(); N2.Affiche(); N3.Affiche(); break; } U=M1M3/d13; // le vecteur normal à U switch (dim) { case 1: // ici il suffit de prendre le point milieu { sinusangle=0.; break;} case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;} case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2); if (sinusangle > ConstMath::unpeupetit) { W.Normer(); V = Util::ProdVec_coor(W,U);} break; } }; // on vérifie que les 3 points ne sont pas naturellement alignés if (sinusangle > ConstMath::unpeupetit) // cas où l'on peut considérer une base locale { double N1H = M1M2*U; double HN2 = M1M2*V; double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H)); Coordonnee P = M01 + p1 * U + p2 * V;; N2.Change_coord2(P); break; } else // cas où les 3 points sont originalement alignés { Coordonnee milieu = (M01+M03)/2.; N2.Change_coord2(milieu); break; } } // ------------- fin de l'étape de modification du noeud milieu - -------------- } } } }; // sortie du schemaXML: en fonction de enu void Maillage::SchemaXML_Maillages(ostream& sort,const Enum_IO_XML enu) { switch (enu) {case XML_TYPE_GLOBAUX: {// on définit des types pour un maillage Noeud::SchemaXML_Noeud(sort,enu); // def du type maillage sort << "\n " << "\n " << "\n un nom de maillage, des noeuds, des references de noeuds," << "\n des elements, des references d'elements " << "\n " << "\n " << "\n " << "\n " << "\n "; /* << "\n " << "\n " << "\n " */ sort << "\n " << "\n "; break; } case XML_IO_POINT_INFO: {// cas de la définition d'un maillage /* sort << "\n " << "\n " << "\n " << "\n un nom de maillage, des noeuds, des references de noeuds," << "\n des elements, des references d'elements " << "\n " << "\n " << "\n " << "\n " << "\n "*/ /* << "\n " << "\n " << "\n " */ /* sort << "\n " << "\n " << "\n ";*/ // def de Maillage // SchemaXML_Maillage(sort,niveau); break; } }; }; //---------------------- class de travail --------------------------- // classe de travail qui sert pour pouvoir classer les noeuds par leur position géométrique initiale // deux élément sont identiques si leur position initiale sont identique // a >= b si : soit a.x >= b.x, ou a.x==b.x et a.y >= b.y, ou a.x==b.x et a.y == b.y et a.z >= b.z Maillage::PosiEtNoeud& Maillage::PosiEtNoeud::operator= (const Maillage::PosiEtNoeud& po) // affectation { noe=po.noe; return *this;}; bool Maillage::PosiEtNoeud::operator == (const Maillage::PosiEtNoeud& po) const // test d'égalité { if ((noe->Coord0()-po.noe->Coord0()).Norme() <= ConstMath::unpeupetit) return true; else return false; }; bool Maillage::PosiEtNoeud::operator != (const Maillage::PosiEtNoeud& po) const // test d'inégalité { if (noe->Coord0() != po.noe->Coord0()) return true; else return false; }; bool Maillage::PosiEtNoeud::operator < (const Maillage::PosiEtNoeud& po) const // relation d'ordre { Coordonnee co1=noe->Coord0(); Coordonnee co2=po.noe->Coord0(); switch (co1.Dimension()) { case 1: return (co1(1) < co2(1));break; case 2: {if (co1(1) < co2(1)) return true; else if (co1(1) == co2(1)) { return (co1(2) < co2(2));} else return false; break;} case 3: {if (co1(1) < co2(1)) return true; else if (co1(1) == co2(1)) { if (co1(2) < co2(2)) return true; else if (co1(2) == co2(2)) { return (co1(3) < co2(3));} else { return false;}; } return false; break; } default: { cout << "\n erreur le cas différent de 1 2 3 n'est pas admissible ici= " << co1.Dimension() << "\n bool Maillage::PosiEtNoeud::operator < (co... "; Sortie(1); } }; Sortie(1); // ne doit jamais passer ici !! return false; }; bool Maillage::PosiEtNoeud::operator <= (const Maillage::PosiEtNoeud& po) const // relation d'ordre { Coordonnee co1=noe->Coord0(); Coordonnee co2=po.noe->Coord0(); switch (co1.Dimension()) { case 1: return (co1(1) <= co2(1));break; case 2: {if (co1(1) < co2(1)) return true; else if (co1(1) == co2(1)) { return (co1(2) <= co2(2));} else return false; break;} case 3: {if (co1(1) < co2(1)) return true; else if (co1(1) == co2(1)) { if (co1(2) < co2(2)) return true; else if (co1(2) == co2(2)) { return (co1(3) <= co2(3));} else {return false;}; } return false; break; } default: { cout << "\n erreur le cas différent de 1 2 3 n'est pas admissible ici= " << co1.Dimension() << "\n bool Maillage::PosiEtNoeud::operator <= (co... "; Sortie(1); } }; Sortie(1); // ne doit jamais passer ici !! return false; }; bool Maillage::PosiEtNoeud::operator > (const Maillage::PosiEtNoeud& po) const // relation d'ordre { return !(*this <= po);}; bool Maillage::PosiEtNoeud::operator >= (const Maillage::PosiEtNoeud& po) const // relation d'ordre { return !(*this < po);}; // transfert de grandeurs des points d'intégration aux noeuds // 1- en entrée les type évolués et quelconques que l'on veut transférer // 2- en entrée: cas qui indique la méthode de transfert à utiliser // =1 : les valeurs aux noeuds sont obtenue par moyennage // des valeurs des pts d'integ les plus près // des éléments qui entourent le noeud // on décompose le processus en 3 étapes pour éviter d'initialiser plusieurs // fois lorque l'on refait à chaque fois // le même transfert // A) première étape def des conteneurs et c'est tout, la méthode peut donc être utilisée // pour autre chose. tabQ: permet d'avoir plusieurs listes de TypeQuelconque // en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur // est nulle on n'en tient pas compte void Maillage::AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu ,const Tableau * >& tabQ) { // on crée des tableaux pour optimiser le nombre d'appel aux fonctions d'ajout de grandeur aux noeuds // 1) cas des Ddl_enum_etendu Tableau tab_ddlEnuEtendu(lienu.size()); {List_io < Ddl_enum_etendu >::const_iterator ilienu,ilienufin = lienu.end(); int indice = 1; for (ilienu = lienu.begin();ilienu != ilienufin; ilienu++,indice++) tab_ddlEnuEtendu(indice) = (*ilienu); }; // 2) cas des grandeurs quelconques Tableau < TypeQuelconque > tabglobQ; int ttai = 0; if (tabQ(1) != NULL) ttai += tabQ(1)->size(); if (tabQ(2) != NULL) ttai += tabQ(2)->size(); tabglobQ.Change_taille(ttai); int indice = 1; if (tabQ(1) != NULL) {List_io < TypeQuelconque >::const_iterator itabQ,itabQfin = tabQ(1)->end(); for (itabQ = tabQ(1)->begin();itabQ != itabQfin; itabQ++,indice++) {tabglobQ(indice).ChangeGrandeur(*itabQ); // on commence par changer la grandeur tabglobQ(indice) = (*itabQ); // et on affecte }; }; if (tabQ(2) != NULL) {List_io < TypeQuelconque >::const_iterator itabQ,itabQfin = tabQ(2)->end(); for (itabQ = tabQ(2)->begin();itabQ != itabQfin; itabQ++,indice++) {tabglobQ(indice).ChangeGrandeur(*itabQ); // on commence par changer la grandeur tabglobQ(indice) = (*itabQ); // et on affecte }; }; int nbN=tab_noeud.Taille(); // on met à jour les noeuds for(int i=1;i<=nbN;i++) { // Pour les grandeurs ddl étendu on les ajoutes aux noeuds si ce n'est pas déjà fait tab_noeud(i)->AjoutTabDdl_etendu(tab_ddlEnuEtendu); // on ajoute également les différents types quelconques aux noeuds tab_noeud(i)->AjoutTabTypeQuelconque(tabglobQ); // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté tab_noeud(i)->Mise_non_update_Ddl_etendu(); tab_noeud(i)->Mise_non_update_grandeurs_quelconques(); }; }; // B) initialisation des updates sur les noeuds void Maillage::InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienetendu ,const Tableau * >& tabQ, int ) {int nbN=tab_noeud.Taille(); List_io ::const_iterator iliet,ilietfin = lienetendu.end(); List_io ::const_iterator iliGQ,iliGQfin; // on met à jour tous les noeuds for(int inoeud=1;inoeud<=nbN;inoeud++) {for (iliet = lienetendu.begin();iliet != ilietfin; iliet++) {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); // on initialise la grandeur pointée: dd.Valeur()=0.; // mise à 0 du nombre d'appel tab_noeud(inoeud)->Mise_non_update_Ddl_etendu(*iliet); }; for (int iQu=1;iQu<=tabQ.Taille();iQu++) {if (tabQ(iQu) != NULL) {iliGQfin = tabQ(iQu)->end(); for (iliGQ = tabQ(iQu)->begin();iliGQ != iliGQfin; iliGQ++) {TypeQuelconque& tq = tab_noeud(inoeud)->ModifGrandeur_quelconque((*iliGQ).EnuTypeQuelconque()); TypeQuelconque::Grandeur & grandeur = *(tq.Grandeur_pointee()); // on initialise la grandeur pointée: grandeur *= 0.; // mise à 0 du nombre d'appel tab_noeud(inoeud)->Mise_non_update_grandeurs_quelconques((*iliGQ).EnuTypeQuelconque()); }; } }; }; }; // D) dernière étape: (par exemple calcul des moyennes en chaque noeuds) void Maillage::FinTransfertPtIntegAuNoeud (const List_io < Ddl_enum_etendu >& lienetendu,const Tableau * >& tabQ,int cas) {switch(cas) { case 1: // cas du transfert par moyennage { int nbN=tab_noeud.Taille(); List_io ::const_iterator iliet,ilietfin = lienetendu.end(); List_io ::const_iterator iliGQ,iliGQfin; // on passe en revue les grandeurs aux noeuds, et on les moyennes for(int inoeud=1;inoeud<=nbN;inoeud++) { // .. pour les ddl étendus .. for (iliet = lienetendu.begin();iliet != ilietfin; iliet++) {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); // on modifie la grandeur pointée: -1 car ici on vient d'appeler // ModifDdl_etendu qui comptabilise un appel de + // dd.Valeur()/=(tab_noeud(inoeud)->DdlEtendue_update(*iliet)-1); int nbappel = MaX((tab_noeud(inoeud)->DdlEtendue_update(*iliet)-1),1); dd.Valeur()/=nbappel; }; // .. pour les grandeurs quelconques .. for (int iQu=1;iQu<=tabQ.Taille();iQu++) {if (tabQ(iQu) != NULL) {iliGQfin = tabQ(iQu)->end(); for (iliGQ = tabQ(iQu)->begin();iliGQ != iliGQfin; iliGQ++) {TypeQuelconque_enum_etendu enuQ = (*iliGQ).EnuTypeQuelconque(); TypeQuelconque& tq = tab_noeud(inoeud)->ModifGrandeur_quelconque(enuQ); TypeQuelconque::Grandeur & grandeur = *(tq.Grandeur_pointee()); // on modifie les grandeurs pointées: -1 car ici on vient d'appeler // ModifGrandeur_quelconque qui comptabilise un appel de + grandeur /= MaX((tab_noeud(inoeud)->Grandeur_quelconque_update(enuQ)-1),1); //--- debug //if (iliGQ == tabQ(iQu)->begin()) // cout << " noeud " << inoeud << " grandeur " << grandeur << endl; //--- fin debug }; } }; }; break; } default : cout << "\n *** cas non implante, cas = " << cas << "\n FinTransfertPtIntegAuNoeud(... "; Sortie(1); }; }; // fonctions utilitaires du même genre // ajout sur le maillage d'un conteneur particulier quelconque void Maillage::AjoutConteneurAuNoeud(TypeQuelconque& tQ) { int nbN=tab_noeud.Taille(); // on met à jour les noeuds for(int i=1;i<=nbN;i++) { // on ajoute le type quelconque au noeud tab_noeud(i)->AjoutUnTypeQuelconque(tQ); // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté tab_noeud(i)->Mise_non_update_grandeurs_quelconques(); }; }; // ajout sur le maillage d'un ou plusieur ddl_enum_etendu comme conteneur void Maillage::AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu) { // on crée des tableaux pour optimiser le nombre d'appel aux fonctions d'ajout de grandeur aux noeuds // 1) cas des Ddl_enum_etendu Tableau tab_ddlEnuEtendu(lienu.size()); {List_io < Ddl_enum_etendu >::const_iterator ilienu,ilienufin = lienu.end(); int indice = 1; for (ilienu = lienu.begin();ilienu != ilienufin; ilienu++,indice++) tab_ddlEnuEtendu(indice) = (*ilienu); }; int nbN=tab_noeud.Taille(); int nb_ienu = lienu.size(); // on met à jour les noeuds for(int i=1;i<=nbN;i++) { // Pour les grandeurs ddl étendu on les ajoutes aux noeuds si ce n'est pas déjà fait tab_noeud(i)->AjoutTabDdl_etendu(tab_ddlEnuEtendu); // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté for (int idee=1; idee <= nb_ienu; idee++) tab_noeud(i)->Mise_non_update_Ddl_etendu(tab_ddlEnuEtendu(idee)); }; }; // initialisation des updates de ddl_étendu uniquement sur les noeuds: on met à 0 les ddl_etendu correspondant, // les compteurs, comptant le nombre de fois où les noeuds sont modifiés, sont mis à 0 void Maillage::InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienetendu) {int nbN=tab_noeud.Taille(); List_io ::const_iterator iliet,ilietfin = lienetendu.end(); // on met à jour tous les noeuds for(int inoeud=1;inoeud<=nbN;inoeud++) {for (iliet = lienetendu.begin();iliet != ilietfin; iliet++) {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); // on initialise la grandeur pointée: dd.Valeur()=0.; }; // on met à 0 le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté tab_noeud(inoeud)->Mise_non_update_Ddl_etendu(); }; }; // initialisation des updates d'un seul ddl_étendu uniquement sur les noeuds: on met à 0 le ddl_etendu correspondant, // le compteur, comptant le nombre de fois où le noeud est modifié, est mis à 0 void Maillage::InitUpdateAuNoeud(const Ddl_enum_etendu & enetendu) {int nbN=tab_noeud.Taille(); // on met à jour tous les noeuds for(int inoeud=1;inoeud<=nbN;inoeud++) { // on initialise la grandeur pointée: (tab_noeud(inoeud)->ModifDdl_etendu(enetendu)).Valeur()=0.; // on met à 0 le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté tab_noeud(inoeud)->Mise_non_update_Ddl_etendu(); }; }; // moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié) void Maillage::MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu) { int nbN=tab_noeud.Taille(); // on passe en revue les grandeurs aux noeuds, et on les moyennes for(int inoeud=1;inoeud<=nbN;inoeud++) { Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(enu); // on modifie la grandeur pointée: -1 car ici on vient d'appeler // ModifDdl_etendu qui comptabilise un appel de + int nbappel = (tab_noeud(inoeud)->DdlEtendue_update(enu)-1); dd.Valeur()/=nbappel; }; }; // initialisation des coordonnées à t et tdt aux mêmes valeurs qu'à 0 // utile quand on veut utiliser les métriques pour un pb non couplés void Maillage::Init_Xi_t_et_tdt_de_0() { int nbN=tab_noeud.Taille(); // on passe en revue les grandeurs aux noeuds, et on les moyennes for(int inoeud=1;inoeud<=nbN;inoeud++) { Noeud & noe = *tab_noeud(inoeud); const Coordonnee& co1 = noe.Coord0(); noe.Change_coord1(co1); noe.Change_coord2(co1); }; }; // lecture des mouvements solides si nécessaire void Maillage::Lecture_des_mouvements_solides(UtilLecture * entreePrinc) { // on définit un mouvement solide (vide par défaut) MvtSolide mvtsolide; if (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL) // cas de mouvements initiaux initiaux { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ; entreePrinc->NouvelleDonnee(); // on passe le mot clé }; // lecture éventuelle des mouvements solides mvtsolide.Lecture_mouvements_solides(entreePrinc); // traitement au cas où il y a eu lecture de mouvements non nul if (mvtsolide.ExisteMvtSolide()) { if (ParaGlob::NiveauImpression() >= 6) cout << " traitement des mouvements solides initiaux sur le maillage " << endl ; // on passe le mot clé de fin de mouvement solides pour les lectures suivantes entreePrinc->NouvelleDonnee(); // --- dans le cas où il y a des centres de rotation qui sont des positions de noeud, on renseigne // a) récupération des centres de rotation noeud, éventuellement const list & lis_centre_noeud = mvtsolide.Liste_ident_centreNoeud(); if (lis_centre_noeud.size() != 0) { list ::const_iterator ict,ictfin=lis_centre_noeud.end(); list list_coor; // liste des coordonnées des noeuds centre de rotation for (ict = lis_centre_noeud.begin();ict!=ictfin;ict++) { // a priori ne concerne que le maillage en question if (((*ict).nom == "")|| ((*ict).nom == nomDuMaillage)) // cas normal { int num_noeud = (*ict).n; if ((num_noeud < 0) || (num_noeud > tab_noeud.Taille())) { cout << "\n *** erreur sur le numero de noeud de centre de rotation = "<< num_noeud << " on ne peut pas appliquer la rotation " << endl; if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ; }; list_coor.push_back(tab_noeud(num_noeud)->Coord0()); // on récupère les coordonnées initiales } else // cas où il s'agit d'un autre maillage, pour l'instant non pris en compte { cout << "\n *** erreur sur le numero de noeud concerne un autre maillage = "<< (*ict).nom << " cette option n'est pas prise en compte " << endl; if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ; }; }; // b) maintenant on passe l'info au mouvement solide mvtsolide.RenseigneCentreNoeud(list_coor); }; int nbnoeud = tab_noeud.Taille(); Coordonnee point_inter; for (int ne=1;ne<=nbnoeud;ne++) { point_inter = tab_noeud(ne)->Coord0(); // récupération des coordonnées initiales mvtsolide.AppliqueMvtSolide(point_inter); // on applique le mouvement solide tab_noeud(ne)->Change_coord0(point_inter); // on met à jour les nouvelles coordonnées }; }; }; // ajout d'une liste de noeud à un maillage // si le numéro de maillage associé au noeud est nul, il est remplacé par celui du maillage // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a // création d'un nouveau noeud identique, avec le numéro this // ajout éventuel d'une liste de référence de noeuds, si celle-ci est non-nulle // il y a création de nouvelles ref correspondantes au numéro de maillage de this // et ces références sont rajoutées à lesRef void Maillage::Ajout_de_Noeuds(const list & lisN, list * lref,LesReferences* lesRef ) { // on change de taille du tableau de noeud et on ajoute les noeuds passés en paramètre int nbN = tab_noeud.Taille(); int nb_lisN = lisN.size(); tab_noeud.Change_taille(nbN+nb_lisN); list::const_iterator il,ilfin=lisN.end(); // on définit un tableau indiquant les nouveaux numéros indicés par les anciens // t_new_num(i) : = le numéro du nouveau noeud correspondant au noeud initial i int taille_maxi = 0; for(il=lisN.begin();il!=ilfin;il++) // un premier passage pour avoir la dimension maxi du tableau if ((*il)->Num_noeud() > taille_maxi) taille_maxi = (*il)->Num_noeud(); Tableau t_new_num(taille_maxi,0); // les données du tableau sont initialisées à 0 int i=1; for(il=lisN.begin();il!=ilfin;il++,i++) { int ancien_num = (*il)->Num_noeud(); if (((*il)->Num_Mail() != 0) && ((*il)->Num_Mail() != idmail)) { // on crée un nouveau noeud identique Noeud* new_noe = new Noeud(*(*il)); // on change les numéros de noeud et de maillage new_noe->Change_num_noeud(i+nbN); new_noe->Change_num_Mail(idmail); // affectation tab_noeud(i+nbN) = new_noe; } else // sinon cela signifie que le noeud n'appartient pas pour l'instant à un maillage { // on change les numéros de noeud et de maillage (*il)->Change_num_noeud(i+nbN); (*il)->Change_num_Mail(idmail); // affectation tab_noeud(i+nbN) = (*il); }; // on enregistre le nouveau num que si l'ancien est non nul if (ancien_num != 0) t_new_num(ancien_num) = i+nbN; }; // cas de la présence d'une liste de référence éventuellement à ajouter if (lref != NULL) { #ifdef MISE_AU_POINT if (lesRef == NULL) { cout << "\n erreur le conteneur de reference n'est pas defini " << "\n Maillage::Ajout_de_Noeuds(... "; Sortie(1); }; #endif // on va passer en revue la liste des références à ajouter list::const_iterator im,imfin = lref->end(); for (im=lref->begin();im!=imfin;im++) { if ((*im)->Indic() == 1) {const ReferenceNE & refN = *((ReferenceNE *) (*im)); // on va contruire une nouvelle référence ad hoc: string nouveau_nom = (refN.Nom()); // 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; while (lesRef->Existe((refN.Nom()+ajout),idmail)) {num++;ajout = "_"+ChangeEntierSTring(num);}; if (ajout != "") { nouveau_nom += ajout; if (ParaGlob::NiveauImpression() > 0) cout << "\n >>> attention la reference "< tt = refN.Tab_num(); // on récupère une copie du tableau de ref // on le met à jour / aux nouveaux numéros int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref for (int k=1;k<= tai; k++) {if (t_new_num(k) != 0) { kn++; tt(kn) = t_new_num(k); // cas où effectivement on a rajouté un noeud qui était déjà référencé // dans l'ancienne référence } else {if (ParaGlob::NiveauImpression() > 0) cout << "\n le noeud "<Ajout_reference(newref); }; }; }; }; }; // ajout d'une liste d'éléments et de noeud à un maillage // si le numéro de maillage associé à l'élément ou noeud est nul, il est remplacé par celui du maillage // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a // création d'un nouvel item identique, avec le numéro this // ajout éventuel d'une liste de références associées , si celle-ci est non-nulle // il y a création de nouvelles ref correspondantes au numéro de maillage de this // et ces références sont rajoutées à lesRef // les noeuds qui sont associés aux éléments de lisE, doivent faire partie : soit de lisN, soit du maillage this void Maillage::Ajout_elements_et_noeuds (const list & lisN, const list & lisE,list * lref,LesReferences* lesRef ) { // -- on commence par ajouter les noeuds en gardant une trace du type d'ajout // on change de taille du tableau de noeud et on ajoute les noeuds passés en paramètre int nbN = tab_noeud.Taille(); int nb_lisN = lisN.size(); tab_noeud.Change_taille(nbN+nb_lisN); list::const_iterator il,ilfin=lisN.end(); // on définit un tableau indiquant les nouveaux numéros indicés par les anciens // t_new_num(i) : = le numéro du nouveau noeud correspondant au noeud initial i int taille_maxi = 0; for(il=lisN.begin();il!=ilfin;il++) // un premier passage pour avoir la dimension maxi du tableau if ((*il)->Num_noeud() > taille_maxi) taille_maxi = (*il)->Num_noeud(); Tableau t_new_num(taille_maxi,0); // les données du tableau sont initialisées à 0 list li_nevez_noeud; // la liste des nouvelles positions de noeuds int i=1; for(il=lisN.begin();il!=ilfin;il++,i++) { int ancien_num = (*il)->Num_noeud(); if (((*il)->Num_Mail() != 0) && ((*il)->Num_Mail() != idmail)) { // on crée un nouveau noeud identique Noeud* new_noe = new Noeud(*(*il)); // on change les numéros de noeud et de maillage new_noe->Change_num_noeud(i+nbN); new_noe->Change_num_Mail(idmail); // affectation tab_noeud(i+nbN) = new_noe; li_nevez_noeud.push_back(new_noe); } else // sinon cela signifie que le noeud n'appartient pas pour l'instant à un maillage { // on change les numéros de noeud et de maillage (*il)->Change_num_noeud(i+nbN); (*il)->Change_num_Mail(idmail); // affectation tab_noeud(i+nbN) = (*il); li_nevez_noeud.push_back((*il)); }; // on enregistre le nouveau num que si l'ancien est non nul // sinon if (ancien_num != 0) t_new_num(ancien_num) = i+nbN; }; // -- puis on s'occupe des éléments // on change de taille du tableau d'éléments et on ajoute les éléments passés en paramètre int nbE = tab_element.Taille(); int nb_lisE = lisE.size(); tab_element.Change_taille(nbE+nb_lisE); list::const_iterator ie,iefin=lisE.end(); // on définit un tableau indiquant les nouveaux numéros indicés par les anciens // t_new_num_elem(i) : = le numéro du nouvel élément correspondant à l'élément initial i taille_maxi = 0; for(ie=lisE.begin();ie!=iefin;ie++) // un premier passage pour avoir la dimension maxi du tableau if ((*ie)->Num_elt_const() > taille_maxi) taille_maxi = (*ie)->Num_elt_const(); Tableau t_new_num_elem(taille_maxi,0); // les données du tableau sont initialisées à 0 i=1; for(ie=lisE.begin();ie!=iefin;ie++,i++) { int num_elt = i+nbE; // numéro interne de l'élément int ancien_num = (*ie)->Num_elt_const(); Element* new_elem = NULL; // sera affecté dans le if qui suit if (((*ie)->Num_maillage() != 0) && ((*ie)->Num_maillage() != idmail)) { Element::Signature signa = (*ie)->Signature_element(); // récupération de la signature de l'élément // on crée un nouveau element identique new_elem = Element::Choix_element(idmail,num_elt,signa); if (new_elem == NULL) { // l'operation a echouee cout << "\n Erreur dans la creation d'un nouvel element ****** "; cout << "\n element : " << Nom_interpol(signa.id_interpol) << " " << Nom_geom(signa.id_geom) << "\n Maillage::Ajout_elements_et_noeuds(... " << endl; Sortie (1); }; // on affecte les données internes (*new_elem) = (*(*ie)); // il faut de nouveau définir les numéros de maillage et d'élément new_elem->Change_num_elt(num_elt); new_elem->Change_num_maillage(idmail); } else // sinon cela signifie que l'éléments n'appartient pas pour l'instant à un maillage { // on change les numéros d'élément et de maillage, et peut directement l'affecté (*ie)->Change_num_elt(num_elt); (*ie)->Change_num_maillage(idmail); new_elem = (*ie); }; // maintenant on va s'occuper de la connexion Tableau& t_n_elem = new_elem->Tab_noeud(); int nbnoe = t_n_elem.Taille(); for (int inoe = 1; inoe <= nbnoe; inoe++) {// on regarde si le noeud fait partie de la liste des noeuds en entrée // ou alors, qu'il utilise les noeuds existants bool fait_partie = false; list::iterator it=li_nevez_noeud.begin(); for(il=lisN.begin();il!=ilfin;il++,it++) if ((*il) == t_n_elem(inoe)) { fait_partie = true; break;}; // deux cas if (fait_partie) // on réaffecte {t_n_elem(inoe)=(*it);} else // sinon cela signifie que l'on utilise les noeuds existants // on vérifie qu'il s'agit bien de noeud existant { bool verif = false; for (int j=1;j<= nbN;j++) // on boucle jusqu'à nbN = le nombre initial de noeud if (tab_noeud(j) == t_n_elem(inoe)) {verif = true; break;}; if (!verif) { cout << "\n erreur, la connexion de l'element a ajouter n'est pas recevable " << " le noeud "<Num_noeud()<< " de l'element " << new_elem->Num_elt() << " n'existe pas dans le maillage initial " << "\n Maillage::Ajout_elements_et_noeuds(... " << endl; Sortie (1); }; } }; // arrivée ici c'est que tout est ok, on ajoute l'élément tab_element(nbE+i)=new_elem; // on enregistre le nouveau num que si l'ancien est non nul if (ancien_num != 0) t_new_num_elem(ancien_num) = nbE+i; }; // cas de la présence d'une liste de référence éventuellement à ajouter if (lref != NULL) { #ifdef MISE_AU_POINT if (lesRef == NULL) { cout << "\n erreur le conteneur de reference n'est pas defini " << "\n Maillage::Ajout_de_Noeuds(... "; Sortie(1); }; #endif // on va passer en revue la liste des références à ajouter list::const_iterator im,imfin = lref->end(); for (im=lref->begin();im!=imfin;im++) {int indic = (*im)->Indic(); // pour simplifier switch (indic) {case 1: // cas d'une ref de noeuds {const ReferenceNE & refN = *((ReferenceNE *) (*im)); // on va contruire une nouvelle référence ad hoc: string nouveau_nom = (refN.Nom()); // 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; while (lesRef->Existe((refN.Nom()+ajout),idmail)) {num++;ajout = "_"+ChangeEntierSTring(num);}; if (ajout != "") { nouveau_nom += ajout; if (ParaGlob::NiveauImpression() > 0) cout << "\n >>> attention la reference "< tt = refN.Tab_num(); // on récupère une copie du tableau de ref Tableau tt_new = tt; // le nouveau tableau // on le met à jour / aux nouveaux numéros int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref for (int k=1;k<= tai; k++) {if (t_new_num(tt(k)) != 0) { kn++; tt_new(kn) = t_new_num(tt(k)); // cas où effectivement on a rajouté un noeud qui était déjà référencé // dans l'ancienne référence } else {if (ParaGlob::NiveauImpression() > 0) cout << "\n le noeud "<Ajout_reference(newref); }; break; } case 2: // cas d'une ref d'éléments {const ReferenceNE & refE = *((ReferenceNE *) (*im)); // on va contruire une nouvelle référence ad hoc: string nouveau_nom = (refE.Nom()); // 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; while (lesRef->Existe((refE.Nom()+ajout),idmail)) {num++;ajout = "_"+ChangeEntierSTring(num);}; if (ajout != "") { nouveau_nom += ajout; if (ParaGlob::NiveauImpression() > 0) cout << "\n >>> attention la reference "< tt = refE.Tab_num(); // on récupère une copie du tableau de ref // on le met à jour / aux nouveaux numéros int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref Tableau tt_new = tt; // le nouveau tableau for (int k=1;k<= tai; k++) {if (t_new_num_elem(tt(k)) != 0) { kn++; tt_new(kn) = t_new_num_elem(tt(k)); // cas où effectivement on a rajouté un élément qui était déjà référencé // dans l'ancienne référence } else {if (ParaGlob::NiveauImpression() > 0) cout << "\n l'element "<Ajout_reference(newref); }; break; } case 3: case 4: case 5: case 6:// cas des autres refs: exemple surfaces {const ReferenceAF & refAF = *((ReferenceAF *) (*im)); // on va contruire une nouvelle référence ad hoc: string nouveau_nom = (refAF.Nom()); // 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; while (lesRef->Existe((refAF.Nom()+ajout),idmail)) {num++;ajout = "_"+ChangeEntierSTring(num);}; if (ajout != "") { nouveau_nom += ajout; if (ParaGlob::NiveauImpression() > 0) cout << "\n >>> attention la reference "< te = refAF.Tab_Elem(); // on récupère une copie du tableau des éléments Tableau te_new = te; // le nouveau tableau // apriori seules les numéros d'élément sont succeptible d'avoir changé, les numéros // locaux: surface, arête, noeuds relatifs à l'éléments, et pti restent inchangé // par contre ils peuvent être supprimés si le num d'élément est supprimé Tableau tl = refAF.Tab_FA(); // on récupère une copie du tableau des num locaux // on met à jour le tableau de d'éléments / aux nouveaux numéros int tai = te.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref for (int k=1;k<= tai; k++) {if (t_new_num_elem(te(k)) != 0) { kn++; te_new(kn) = t_new_num_elem(te(k)); // cas où effectivement on a rajouté un élément qui était déjà référencé // dans l'ancienne référence tl(kn) = tl(k); // normalement k est > kn, donc cela revient à décaler // en ne gardant que les termes viables } else {if (ParaGlob::NiveauImpression() > 0) cout << "\n l'element "<Ajout_reference(newref); }; break; } }; }; }; // -------------- ajout de références globales si elles n'existent pas --------------------- // ---- mise à jour de la référence de tous les éléments si elle n'existe pas déjà int nbElement = tab_element.Taille(); string etout("E_tout"); if (lesRef->Existe(etout,idmail)) lesRef->SupprimeReference("E_tout",idmail); // on supprime la référence E_tout // on construit le tableau des numéros des éléments Tableau tabE(nbElement); for (int i=1;i<=nbElement;i++) tabE(i)=i; ReferenceNE* retout = new ReferenceNE(tabE,idmail,2,etout);// construction de la référence lesRef->Ajout_reference(retout); // ajout de la ref, qui est maintenant géré par lesRef // ---- dans tous les cas on ajoute ou modifie la référence de tous les noeuds string ntout("N_tout"); int nbNoeud = tab_noeud.Taille(); if (lesRef->Existe(ntout,idmail)) lesRef->SupprimeReference("N_tout",idmail); // on supprime la référence N_tout // on construit le tableau des numéros de noeuds Tableau tabN(nbNoeud); for (int i=1;i<=nbNoeud;i++) tabN(i)=i; ReferenceNE* rtout = new ReferenceNE(tabN,idmail,1,ntout);// construction de la référence lesRef->Ajout_reference(rtout); // ajout de la ref, qui est maintenant géré par lesRef //debug //cout << "\n nbElement " << nbElement << ", nbNoeud "<< nbNoeud << endl; // fin debug }; // force la mise à une valeur d'un ddl (ou de la liste de ddl fonction de la dimention) particulier, quelques soit son activité // si fonction_de_la_dimension = true : c'est toute les ddl fct de la dimension qui sont mis à la valeur void Maillage::Force_Ddl_aux_noeuds_a_une_valeur(Enum_ddl enu, const double& val,Enum_dure temps, bool fonction_de_la_dimension) { int nbnoeud = tab_noeud.Taille(); int dima = ParaGlob::Dimension(); switch (temps) {case TEMPS_0: { if (!(fonction_de_la_dimension) || !FoncDim(enu)) {for (int i=1;i<= nbnoeud;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (noe.Existe_ici(enu)) // on intervient que si le ddl existe noe.Change_val_0(enu,val); }; } else {for (int i=1;i<= nbnoeud;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (noe.Existe_ici(enu)) // on intervient que si le ddl existe { switch (dima) { case 3: noe.Change_val_0(Enum_ddl(enu+2),val); case 2: noe.Change_val_0(Enum_ddl(enu+1),val); case 1: noe.Change_val_0(Enum_ddl(enu),val); }; }; }; }; break; } case TEMPS_t: { if (!(fonction_de_la_dimension) || !FoncDim(enu)) {for (int i=1;i<= nbnoeud;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (noe.Existe_ici(enu)) // on intervient que si le ddl existe noe.Change_val_t(enu,val); }; } else {for (int i=1;i<= nbnoeud;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (noe.Existe_ici(enu)) // on intervient que si le ddl existe { switch (dima) { case 3: noe.Change_val_t(Enum_ddl(enu+2),val); case 2: noe.Change_val_t(Enum_ddl(enu+1),val); case 1: noe.Change_val_t(Enum_ddl(enu),val); }; }; }; }; break; } case TEMPS_tdt: { if (!(fonction_de_la_dimension) || !FoncDim(enu)) {for (int i=1;i<= nbnoeud;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (noe.Existe_ici(enu)) // on intervient que si le ddl existe noe.Change_val_tdt(enu,val); }; } else {for (int i=1;i<= nbnoeud;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (noe.Existe_ici(enu)) // on intervient que si le ddl existe { switch (dima) { case 3: noe.Change_val_tdt(Enum_ddl(enu+2),val); case 2: noe.Change_val_tdt(Enum_ddl(enu+1),val); case 1: noe.Change_val_tdt(Enum_ddl(enu),val); }; }; }; }; break; } }; }; // mise à zéro de dd_enum_etendu aux noeuds : force la mise à une valeur à 0 void Maillage::Force_Ddl_etendu_aux_noeuds_a_zero(const Tableau& tab_enu) { int nbnoeud = tab_noeud.Taille(); int nb_enu = tab_enu.Taille(); for (int i=1;i<=nb_enu;i++) {const Ddl_enum_etendu& enu = tab_enu(i); for (int i=1;i<= nbnoeud;i++) { Noeud& noe = *tab_noeud(i); // pour simplifier if (noe.Existe_ici_ddlEtendu(enu)) // on intervient que si le ddl existe noe.ModifDdl_etendu(enu).Valeur() = 0.; }; }; }; // on s'occupe de mettre à jour les types de pb et les ddl types associés void Maillage::Mise_a_jour_type_pb_type_associe_ddl() { //types_de_problemes.clear(); //ddl_representatifs_des_physiques.clear(); // types_de_problemes.Libere();ddl_representatifs_des_physiques.Libere(); // int nbElement = tab_element.Taille(); //string titi; //cout << "\n nbElement "<> titi; // // on définit un tableau intermédiaire // int nombre_de_EnumElemTypeProblem = Nombre_de_EnumElemTypeProblem(); //cout << "\n nombre_de_EnumElemTypeProblem "<> titi; // Tableau < int> types_de_problemes_actif(nombre_de_EnumElemTypeProblem,0); // types_de_problemes_actif(1)=1; //cout << "\n taill "<> titi; //cout << "\n types_de_problemes_actif(1) "<> titi; // // for (int i;i<=nbElement;i++) // {Element& ele = *tab_element(i); //cout << "\n i"<> titi; //ele.Affiche(); //cout << "\n i"<> titi; // EnumElemTypeProblem enu = ele.Id_TypeProblem(); //cout << "\n i"<> titi; //int truc =enu; //cout << "\n enu= "<> titi; //cout << "\n types_de_problemes_actif(1) "<> titi; //types_de_problemes_actif(1) = 1; //cout << "\n types_de_problemes_actif(1) "<> titi; //types_de_problemes_actif(int(enu)) = 1; //cout << "\n types_de_problemes_actif(1) "<> titi; // // types_de_problemes_actif(truc) = 1; // on rend actif l'élément du tableau // }; //cout << "\n une valeur ? "; //cin >> titi; // // maintenant on regarde le nombre de pb actif // int nb_pb = 0; // init // for (int i=1;i<=nombre_de_EnumElemTypeProblem;i++) // if (types_de_problemes_actif(i)) nb_pb++; //cout << "\n une valeur ? "; //cin >> titi; // // on redimentionne et on rempli // types_de_problemes.Change_taille(nb_pb); //cout << "\n une valeur ? "; //cin >> titi; // nb_pb = 0; // init // for (int i=1;i<=nombre_de_EnumElemTypeProblem;i++) // if (types_de_problemes_actif(i)) // {nb_pb++;types_de_problemes(nb_pb)=EnumElemTypeProblem(i);}; //cout << "\n une valeur ? "; //cin >> titi; // // ////cout << "\n enu"<> titi; //// bool trouve = false; //// list ::iterator il,ilfin=types_de_problemes.end(); ////if (!types_de_problemes.empty()) ////cout << "\n ilfin il begin " << (*types_de_problemes.begin())<< " une valeur ? "; ////cin >> titi; //// for (il=types_de_problemes.begin();il != ilfin; il++) //// {cout << "\n "<> titi; //// //// if ((*il)==enu) {trouve = true; break;}; //// }; //// if (find(types_de_problemes.begin(),types_de_problemes.end(),enu) == types_de_problemes.end()) //// if (!trouve) ////EnumElemTypeProblem tutu = MECA_SOLIDE_DEFORMABLE; // // { types_de_problemes.push_back(tutu);}; //// //// int taill = types_de_problemes.Taille(); //// for (int j=1;j<=taill;j++) //// if (types_de_problemes(j) == enu) //// { types_de_problemes.Change_taille(taill+1); //// types_de_problemes(taill+1)=enu; //// break; //// }; //// }; //// inter.sort(); inter.unique(); //// types_de_problemes = inter; // // on parcours les types de pb pour attribuer les types de ddl //// list ::iterator il,ilfin=types_de_problemes.end(); //// for (il=types_de_problemes.begin();il != ilfin;il++) //// //// { switch (types_de_problemes(j)) //// {case MECA_SOLIDE_DEFORMABLE : //// ddl_representatifs_des_physiques.push_back(X1);break; //// case THERMIQUE : //// ddl_representatifs_des_physiques.push_back(TEMP);break; //// default : //// cout << "\n***Erreur : pour l'instant le type de probleme: "<