// 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 "LesCondLim.h" #include "CharUtil.h" #include "SfeMembT.h" #include "TypeQuelconqueParticulier.h" // --- conteneur pour les réactions ----- // surcharge de l'operator de lecture typée istream & operator >> (istream & ent , LesCondLim::ReactStoc & a) { // lecture du type et vérification string nom_type; ent >> nom_type; if (nom_type != "ReactStoc") Sortie(1); // lecture des infos ent >> a.numMail >> a.numNoeud >> a.ddl >> a.casAss; return ent; }; // surcharge de l'operator d'ecriture typée ostream & operator << (ostream & sort , const LesCondLim::ReactStoc & a) { // écriture du type sort << "ReactStoc "; // les données sort << a.numMail << " " << a.numNoeud << " " << a.ddl <<" "<< a.casAss; return sort; }; // surcharge de l'operator de lecture typée istream & operator >> (istream & ent , LesCondLim::TorseurReac & a) { // lecture du type et vérification string nom_type; ent >> nom_type; if (nom_type != "TorseurReac") Sortie(1); // lecture des infos ent >> a.existe_torseur_reac >> a.resultante >> a.moment ; return ent; }; // surcharge de l'operator d'ecriture typée ostream & operator << (ostream & sort , const LesCondLim::TorseurReac & a) { // écriture du type sort << " TorseurReac "; // les données sort << a.existe_torseur_reac << " " << a.resultante << " " << a.moment <<" "; return sort; }; // --- fin conteneur pour les réactions ----- // CONSTRUCTEURS : LesCondLim::LesCondLim () : // par defaut tabBloq(),tabInit(),condlim() ,reaction(),reaction_CLin(),reactionApresCHrepere() ,tab_torseurReac(),ttRG(),ttorBloq() ,tab_iocondiline(),tab_CLinApplique(),ttRGCLL(),ttorCLL() ,ttRG_noms_ref(),ttRGCLL_noms_ref() // ,map_reaction() ,nb_maillage(0) ,tempsCL(),tempsCLL() { }; // DESTRUCTEUR : LesCondLim::~LesCondLim () { }; // METHODES PUBLIQUES : // lecture des conditions limites : ddl bloque void LesCondLim::Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef) { MotCle motCle; // ref aux mots cle // on se positionne sur un mot cle while ( !motCle.SimotCle(entreePrinc.tablcar)) entreePrinc.NouvelleDonnee(); bool sortie_info = false; if ( (strstr(entreePrinc.tablcar,"blocages")!=NULL) ) // à rajouter tous les cas de lectures éventuelles {if (ParaGlob::NiveauImpression() >= 4) cout << " debut de la lecture des conditions limites ddl bloque " << endl; sortie_info = true; }; // def d'une instance de classe de lecture de Ddl LectBloc lecDdl; // lecture eventuelle des blocages en condition limite lecDdl.Lecture(entreePrinc,lesRef,"blocages", "lecture des blocages de ddl en condition limite",tabBloq); // dimensionnement du tableau des torseurs résultants LesCondLim::DimensionneTorseurs(); if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info) cout << " fin de la lecture des conditions limites ddl bloque " << endl; }; // lecture des conditions limites linéaire void LesCondLim::Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef) { MotCle motCle; // ref aux mots cle // on se positionne sur un mot cle while ( !motCle.SimotCle(entreePrinc.tablcar)) entreePrinc.NouvelleDonnee(); bool sortie_info = false; if ( (strstr(entreePrinc.tablcar,"condition_limite_lineaire_")!=NULL) ) // à rajouter tous les cas de lectures éventuelles {if (ParaGlob::NiveauImpression() >= 4) cout << " debut de la lecture des conditions limites lineaires " << endl; sortie_info = true; }; // def d'une instance de classe de lecture de Ddl LectBloc lecI_O_Condli; // lecture eventuelle des conditions linéaire en condition limite lecI_O_Condli.Lecture(entreePrinc,lesRef,"condition_limite_lineaire_", "lecture des conditions limites lineaires ",tab_iocondiline); // mise à jour de la dimension du tableau associé: tab_CLinApplique tab_CLinApplique.Change_taille(tab_iocondiline.Taille()); // dimensionnement du tableau des torseurs résultants LesCondLim::DimensionneTorseurs(); if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info) cout << " fin de la lecture des conditions limites lineaire " << endl; }; // lecture des conditions limites : initialisation void LesCondLim::Lecture3(UtilLecture & entreePrinc,LesReferences& lesRef) { MotCle motCle; // ref aux mots cle // on se positionne sur un mot cle while ( !motCle.SimotCle(entreePrinc.tablcar)) entreePrinc.NouvelleDonnee(); bool sortie_info = false; if ( (strstr(entreePrinc.tablcar,"initialisation")!=NULL) ) // à rajouter tous les cas de lectures éventuelles {if (ParaGlob::NiveauImpression() >= 4) cout << " debut de la lecture des conditions d'initialisation " << endl; sortie_info = true; }; // def d'une instance de classe de lecture de Ddl LectBloc lecDdl; // lecture eventuelle des conditions limites d'initialisation lecDdl.Lecture(entreePrinc,lesRef,"initialisation", "lecture des conditions limites d\'initialisation",tabInit); if ((ParaGlob::NiveauImpression() >= 4) && sortie_info) cout << " fin de la lecture des conditions d'initialisation " << endl; //debug //Affiche(); //fin debug }; // affichage des informations concernant les conditions limites void LesCondLim::Affiche() const // affichage de tous les infos { Affiche1(); Affiche2(); Affiche3(); }; void LesCondLim::Affiche1() const { if (tabBloq.Taille() != 0) {cout << "\n ******** conditions limites : ddl bloque ******** \n"; cout << tabBloq.Taille() << " reference de conditions limites lue \n"; int tabBloqTaille = tabBloq.Taille(); for (int i=1; i<=tabBloqTaille; i++) tabBloq(i).Affiche(); cout << "\n\n"; } }; void LesCondLim::Affiche2() const { if (tabInit.Taille() != 0) {cout << "\n ******** conditions limites : lineaire ******** \n"; cout << tab_iocondiline.Taille() << " reference de conditions limites lue \n"; int tabInitTaille = tabInit.Taille(); for (int i=1; i<=tabInitTaille; i++) tabInit(i).Affiche(); cout << "\n\n"; } }; void LesCondLim::Affiche3() const { if (tabInit.Taille() != 0) {cout << "\n ******** conditions limites : initialisation ******** \n"; cout << tabInit.Taille() << " reference de conditions limites lue \n"; int tabInitTaille = tabInit.Taille(); for (int i=1; i<=tabInitTaille; i++) tabInit(i).Affiche(); cout << "\n\n"; } }; // introduction des données et variables pour leurs emplois futures, avec init par défaut void LesCondLim::IntroductionDonnees(LesMaillages * lesMail,LesReferences* lesRef ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD) { tempsCL.Mise_en_route_du_comptage(); // temps cpu // 1) on parcours le tableau de ddl d'initialisation int tabInitTaille = tabInit.Taille(); for (int i=1;i<= tabInitTaille;i++) { DdlLim& tabInit_i = tabInit(i); // recup de la reference correspondant au mot cle const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage()); if ((refinitial.Indic() == 4) && (tabInit_i.TypeDeCL()==TANGENTE_CL)) {// cas des références d'arêtes, avec des conditions initiales de tangente imposée // ici on vérifie que les données d'entrées sont cohérentes, c'est tout const ReferenceAF & ref = ((ReferenceAF &) refinitial); // on renseigne les éléments ad hoc int refTaille = ref.Taille(); for (int ne =1; ne<= refTaille;ne++) {int tabInitiTaille = tabInit_i.Taille(); // dans le cas d'une référence de champ on vérifie le nombre de ddlLim if ((tabInit_i.Champ()) && (tabInitiTaille != ref.Taille())) {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" << " que le nombre d'element de la reference associee !! " << "\n void LesCondLim::IntroductionDonnees(... "; cout << " condition limite : "; tabInit_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabInitiTaille;// début normale if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;}; for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 // affectation de la valeur d'initialisation { Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl // on vérifie qu'il s'agit bien de 3 coordonnées if (ddl1.Id_nom()!=X1) {cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 " << "\n void LesCondLim::IntroductionDonnees(... "; cout << " condition limite : "; tabInit_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; if (ddl2.Id_nom()!=X2) {cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 " << "\n void LesCondLim::IntroductionDonnees(... "; cout << " condition limite : "; tabInit_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; if (ddl3.Id_nom()!=X3) {cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 " << "\n void LesCondLim::IntroductionDonnees(... "; cout << " condition limite : "; tabInit_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; // on vérifie que le numéro de l'arête existe bien int num_elem = ref.NumeroElem(ne); int num_ar = ref.NumeroFA(ne); // récup de l'élément Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem); if (!(el.AreteExiste(num_ar))) {cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar << " pour l'element " << num_elem << " n'existe pas !! " << "\n void LesCondLim::IntroductionDonnees(... "; cout << " condition limite : "; tabInit_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; // on vérifie que c'est un élément sfe if (!(ElementSfe(el.Id_interpolation()))) {cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre " << " de type SFE : et non l'element= "; el.Affiche(1); cout << "\n void LesCondLim::IntroductionDonnees(... "; cout << " condition limite : "; tabInit_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; }// fin boucle sur tabInit_i }// fin boucle sur les éléments de la référence } // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE else if (refinitial.Indic() != 1) // cas d'element { cout << "\n introduction autre que des noeuds, pas d\'action implentee a ce sujet !!"; cout << "void LesCondLim::IntroductionDonnees(... " << endl; tempsCL.Arret_du_comptage(); Sortie(1); } else // cas de noeuds {// traitement proprement dit const ReferenceNE & ref = ((ReferenceNE &) refinitial); int refTaille = ref.Taille(); for (int nn =1; nn<= refTaille;nn++) {int tabInitiTaille = tabInit_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabInitiTaille;// début normale if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // affectation de la valeur d'initialisation { Ddl ddl = tabInit_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // ---modif 10 sep 2017 // cas ou le ddl n'existe pas // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être // utilisé à t et tdt, donc il ne faut pas le mettre en HS // par contre on le met en lisible c-a-d en donnée par défaut ddl.ChangeVariable_a_Donnee(); if (!(noe.Existe_ici(ddl.Id_nom()))) // cas ou le ddl n'existe pas // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien // { if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) { if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) { // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis // initialisation a zero et on indique qu'il est hors service (non !! voir la modif 10 sept 2017) noe.PlusDdl(ddl); noe.Change_val_0(ddl.Id_nom(),0.); noe.Change_val_t(ddl.Id_nom(),0.); // ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service // ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom()); noe.Met_en_service(ddl.Id_nom()); noe.Change_fixe(ddl.Id_nom(),true); } } // fin du if (!(noe.Existe_ici(ddl.Id_nom()))) } // fin de la boucle sur les ddl } // fin de la boucle sur les noeuds de la référence } // fin du traitement pour les noeuds } // fin de la boucle sur le tableau générale d'initialisation // 2) cas des ddl imposes on verifie leurs existences et on crée si besoin // on parcours le tableau de ddl bloques // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt int tabBloqTaille = tabBloq.Taille(); for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); if ((refinitial.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) {// cas des références d'arêtes, avec des conditions de tangente imposée // on s'occupe de vérifier la cohérence de l'entrée des données, c'est tout const ReferenceAF & ref = ((ReferenceAF &) refinitial); // on renseigne les éléments ad hoc int refTaille = ref.Taille(); for (int ne =1; ne<= refTaille;ne++) {int tabBloqiTaille = tabBloq_i.Taille(); // dans le cas d'une référence de champ on vérifie le nombre de ddlLim if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" << " que le nombre d'element de la reference associee !! " << "\n void LesCondLim::IntroductionDonnees(... "; cout << " condition limite : "; tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); } // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqiTaille;// début normale if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;}; for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 // affectation de la valeur d'initialisation { Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl // on vérifie qu'il s'agit bien de 3 coordonnées if (ddl1.Id_nom()!=X1) {cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 " << "\n void LesCondLim::InitialDonnees(... "; cout << " condition limite : "; tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; if (ddl2.Id_nom()!=X2) {cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 " << "\n void LesCondLim::InitialDonnees(... "; cout << " condition limite : "; tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; if (ddl3.Id_nom()!=X3) {cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 " << "\n void LesCondLim::InitialDonnees(... "; cout << " condition limite : "; tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; // on vérifie que le numéro de l'arête existe bien int num_elem = ref.NumeroElem(ne); int num_ar = ref.NumeroFA(ne); // récup de l'élément Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem); if (!(el.AreteExiste(num_ar))) {cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar << " pour l'element " << num_elem << " n'existe pas !! " << "\n void LesCondLim::InitialDonnees(... "; cout << " condition limite : "; tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; // on vérifie que c'est un élément sfe if (!(ElementSfe(el.Id_interpolation()))) {cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre " << " de type SFE : et non l'element= "; el.Affiche(1); cout << "\n void LesCondLim::InitialDonnees(... "; cout << " condition limite : "; tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; }// fin boucle sur tabBloq_i }// fin boucle sur les noeuds de la référence } // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE else if (refinitial.Indic() != 1) // cas d'une autre référence que des noeuds // cas d'element { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!"; cout << "\n void LesCondLim::InitialDonnees(... " << endl; tempsCL.Arret_du_comptage(); Sortie (1); } else // cas de noeuds {const ReferenceNE & ref = ((ReferenceNE &) refinitial); int refTaille = ref.Taille(); for (int nn =1; nn<= refTaille;nn++) {int tabBloqiTaille = tabBloq_i.Taille(); // dans le cas d'une référence de champ on vérifie le nombre de ddlLim if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" << " que le nombre de noeud de la reference associee !! " << "\n void LesCondLim::InitialDonnees(... "; cout << " condition limite : "; tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); } // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqiTaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // affectation de la valeur d'initialisation { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl // récup du noeud Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // on regarde si les temps dépendent d'une fct nD // si oui on modifie les bornes du ddl if (tabBloq_i.Temps_depend_nD()) LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); // on regarde si le temps est actif ou pas if ((tabBloq_i.Temps_actif(0.))) {tabBloq_i.ElemLim(nd).Met_en_service();} else { tabBloq_i.ElemLim(nd).Met_hors_service();}; // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé // on regarde du coté du noeuds if (!noe.Existe_ici(ddl.Id_nom())) // cas ou il faut creer un ddl sup // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien // {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) { if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) {// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis // initialisation a zero et on indique qu'il est hors service // ---modif 10 sep 2017 // cas ou le ddl n'existe pas // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être // utilisé à t et tdt, donc il ne faut pas le mettre en HS // par contre on le met en lisible c-a-d en donnée par défaut ddl.ChangeVariable_a_Donnee(); noe.PlusDdl(ddl); noe.Change_val_0(ddl.Id_nom(),0.); noe.Change_val_t(ddl.Id_nom(),0.); // ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service // ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom()); noe.Met_en_service(ddl.Id_nom()); noe.Change_fixe(ddl.Id_nom(),true); }; }; // pour le reste on ne fait rien, se sera géré par les mises à jour // en fonction de l'évolution du temps } // fin boucle sur tabBloq_i } // fin boucle sur les noeuds de la référence } // fin du cas des noeuds } // fin bouble sur tabBloq // définition du nombre de maillage en cours dans le calcul nb_maillage=lesMail->NbMaillage(); tempsCL.Arret_du_comptage(); // temps cpu }; // initialisation des ddl avec le tableau de ddl d'init // verif de l'existence de tous les ddl (initialisation et imposes) // ajout si necessaire // choix =false : indique qu'il faut initialiser que les ddl t // choix = true : indique qu'il faut initialiser les ddl a t et t+dt // vérification de l'existence des courbes de charge adoc si nécessaire // idem pour les fonctions nD de charge adoc si nécessaire // cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque // le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont // leur statut modifié de manière équivalente // =0 pas d'association // =1 association X V GAMMA void LesCondLim::Initial(LesMaillages * lesMail,LesReferences* lesRef ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,bool choixtdt,int cas) { tempsCL.Mise_en_route_du_comptage(); // temps cpu // 1) on parcours le tableau de ddl d'initialisation int tabInitTaille = tabInit.Taille(); for (int i=1;i<= tabInitTaille;i++) { DdlLim& tabInit_i = tabInit(i); // recup de la reference correspondant au mot cle const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage()); if ((refinitial.Indic() == 4) && (tabInit_i.TypeDeCL()==TANGENTE_CL) ) {// cas des références d'arêtes, avec des conditions de tangente imposée const ReferenceAF & ref = ((ReferenceAF &) refinitial); // on renseigne les éléments ad hoc int refTaille = ref.Taille(); for (int ne =1; ne<= refTaille;ne++) {int tabInitiTaille = tabInit_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabInitiTaille;// début normale if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;}; for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 // affectation de la valeur d'initialisation { Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl // récup de l'élément Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); SfeMembT & elsfe = (SfeMembT&) el; // on renseigne l'élément Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); }// fin boucle sur tabInit_i }// fin boucle sur les éléments de la référence } // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE else if (refinitial.Indic() != 1) // cas d'element { cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!"; cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; tempsCL.Arret_du_comptage(); Sortie(1); } else // cas de noeuds {// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon // la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout // cas peut de fois, const ReferenceNE & ref = ((ReferenceNE &) refinitial); // traitement proprement dit int refTaille = ref.Taille(); for (int nn =1; nn<= refTaille;nn++) {int tabInitiTaille = tabInit(i).Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabInitiTaille;// début normale if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // affectation de la valeur d'initialisation { Ddl ddl = tabInit_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // on vérifie que le ddl est compatible avec la dimension sinon message d'erreur if (!CompatDim(ddl.Id_nom())) {cout << "\n *** erreur, le ddl d'initialisation : " << ddl.Nom() << " pour la reference " << ref.Nom() << " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension() << ") de l'espace de travail " ; if (ParaGlob::NiveauImpression()>6) cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ; cout << endl; tempsCL.Arret_du_comptage(); Sortie (1); }; if (noe.Existe_ici(ddl.Id_nom())) // cas ou le ddl existe deja { noe.Change_val_t(ddl.Id_nom(),ddl.Valeur()); if (choixtdt) noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur()); // mise a jour des ddl aux temps 0 pour tous les ddl sauf ceux de position // car ces derniers sont les seuls dont la position initiale est déterminées à la lecture // du maillage if (!(Meme_famille(ddl.Id_nom(),X1))) noe.Change_val_0(ddl.Id_nom(),ddl.Valeur()); // on regarde s'il fait partie de la combinaison // si oui on met en place les ddl correspondant à HSLIBRE Enum_ddl en = ddl.Id_nom(); Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); } else // cas ou le ddl n'existe pas { // tout d'abord on regarde si c'est un déplacement // if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) {if(!CompatDim(ddl.Nom())) // vérif de dimension { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; cout << " \n cas des ddl bloquees "; cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; tempsCL.Arret_du_comptage(); Sortie (1); }; // cas ok on impose le déplacement sur le Xi correspondant Enum_ddl en = ddl.Id_nom(); //on cherche l'equivalent Ui en Xi en = UxyzXi(en); noe.Ajout_val_t(en,ddl.Valeur()); // mise a jour des ddl aux autres temps // noe.Ajout_val_0(en,ddl.Valeur()); if (choixtdt) noe.Ajout_val_tdt(en,ddl.Valeur()); // puis on regarde si le ddl initial fait partie de la combinaison // si oui on met en place les ddl correspondant à HSLIBRE Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); } else { // cas ou il faut creer un ddl sup //noe.PlusDdl(ddl); cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues" << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; cout << "\n cas des ddl d'initialisation "; cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl; tempsCL.Arret_du_comptage(); Sortie (1); }; }; }; }; }; }; // 2) cas des ddl imposes on verifie leurs existences // on vérifie également l'existence des courbes de charge adoc si nécessaire // idem pour les fonctions nD de charge adoc si nécessaire // on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple // vitesse et position ou accélération pour un même ddl // on parcours le tableau de ddl bloques // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt int tabBloqTaille = tabBloq.Taille(); for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); if ((refinitial.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) {// cas des références d'arêtes, avec des conditions de tangente imposée // ici on s'occupe de renseigner les éléments const ReferenceAF & ref = ((ReferenceAF &) refinitial); // on renseigne les éléments ad hoc int refTaille = ref.Taille(); for (int ne =1; ne<= refTaille;ne++) {int tabBloqiTaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqiTaille;// début normale if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;}; for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 // affectation de la valeur d'initialisation { Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl // récup de l'élément Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); SfeMembT & elsfe = (SfeMembT&) el; // on regarde si les temps dépendent d'une fct nD // si oui on modifie les bornes du ddl if (tabBloq_i.Temps_depend_nD()) LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD); // on continue que si le temps est actif ou pas if ((tabBloq_i.Temps_actif(0.))) { // on renseigne l'élément Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); }; };// fin boucle sur tabBloq_i };// fin boucle sur les noeuds de la référence } // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE else if (refinitial.Indic() != 1) // cas autre d'element par exemple { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!"; cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; tempsCL.Arret_du_comptage(); Sortie (1); } else // cas de noeuds {const ReferenceNE & ref = ((ReferenceNE &) refinitial); int refTaille = ref.Taille(); for (int nn =1; nn<= refTaille;nn++) {int tabBloqiTaille = tabBloq_i.Taille(); /* // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" << " que le nombre de noeud de la reference associee !! "; cout << " condition limite : "; tabBloq_i.Affiche(); Sortie(1); }*/ // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqiTaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // affectation de la valeur d'initialisation { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl // on vérifie que le ddl est compatible avec la dimension sinon message d'erreur if (!CompatDim(ddl.Id_nom())) {cout << "\n *** erreur, le ddl de blocage : " << ddl.Nom() << " pour la reference " << ref.Nom() << " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension() << ") de l'espace de travail " ; if (ParaGlob::NiveauImpression()>6) cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ; cout << endl; tempsCL.Arret_du_comptage(); Sortie (1); }; // récup du noeud Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // on regarde si les temps dépendent d'une fct nD // si oui on modifie les bornes du ddl if (tabBloq_i.Temps_depend_nD()) LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); // on regarde si le temps est actif ou pas if ((tabBloq_i.Temps_actif(0.))) { // on n'intervient que si le temps initial est actif tabBloq_i.ElemLim(nd).Met_en_service(); // récup du noeud string nom_courbe = tabBloq_i.Nom_courbe(nd); Courbe1D * pt_courbe = NULL; if (nom_courbe != "") // cas de l'existence d'une courbe de charge // appel pour récupérer la courbe (juste pour la vérif // car on ne s'en sert pas aprés !) { pt_courbe = lesCourbes1D->Trouve(nom_courbe); }; // idem pour les fonctions nD string nom_fctnD = tabBloq_i.NomF_charge(nd); Fonction_nD * pt_fctnD = NULL; if (nom_fctnD != "") // cas de l'existence d'une fonction de charge // appel pour récupérer la fct (juste pour la vérif // car on ne s'en sert pas aprés !) { pt_fctnD = lesFonctionsnD->Trouve(nom_fctnD); }; // maintenant on regarde du coté des noeuds if (!noe.Existe_ici(ddl.Id_nom())) // cas ou il faut creer un ddl sup // on regarde le cas eventuel des coordonnees entrainees // si on est en entraine et que le ddl a imposer est un Ui // alors on ne verifie que les dimensions et on indique le blocage // {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) {if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) { // cas d'un ddl de déplacement, et que le ddl X1 existe déjà if(!CompatDim(ddl.Nom())) { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" << " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ; cout << " \n cas des ddl bloquees "; cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; tempsCL.Arret_du_comptage(); Sortie (1); } else // cas ou c'est Xi le ddl bloque, on indique le blocage { Enum_ddl en = ddl.Id_nom(); //on cherche l'equivalent Ui en Xi en = UxyzXi(en); noe.Change_fixe(en,true); // on regarde s'il fait partie de la combinaison et on fixe les blocages Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); } } else // cas d'un ddl inexistant diff de U, création puis initialisation a zero { noe.PlusDdl(ddl); noe.Change_val_0(ddl.Id_nom(),0.); noe.Change_val_t(ddl.Id_nom(),0.); if (choixtdt) noe.Change_val_tdt(ddl.Id_nom(),0.); // puis on indique que le ddl est bloque noe.Change_fixe(ddl.Id_nom(),true); // on regarde s'il fait partie de la combinaison et on fixe les blocages Enum_ddl en = ddl.Id_nom(); Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); } } else // cas ou le ddl existe // on indique que le ddl est bloque, mais on ne change pas sa valeur // ce sera fait au moment de la mise à jour à tdt { // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1) // dans ce cas il est libre, on peut le bloquer sans pb, // soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement noe.Change_fixe(ddl.Id_nom(),true); // on regarde s'il fait partie de la combinaison et on fixe les blocages Enum_ddl en = ddl.Id_nom(); Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); }; } else {// si le ddl bloqué n'est pas actif pour le temps 0. tabBloq_i.ElemLim(nd).Met_hors_service(); // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé // récup du noeud Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // on regarde du coté du noeuds if (!noe.Existe_ici(ddl.Id_nom())) // cas ou il faut creer un ddl sup // on regarde le cas eventuel des coordonnees entrainees // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien // {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) {if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) { // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis // initialisation a zero et on indique qu'il est hors service (non cf modif qui suit) // ---modif 10 sep 2017 // cas ou le ddl n'existe pas // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être // utilisé à t et tdt, donc il ne faut pas le mettre en HS // par contre on le met en lisible c-a-d en donnée par défaut Ddl ddl_inter(ddl); // pour pas que cela influe sur les autres noeuds ddl_inter.ChangeVariable_a_Donnee(); noe.PlusDdl(ddl_inter); noe.Change_val_0(ddl_inter.Id_nom(),0.); noe.Change_val_t(ddl_inter.Id_nom(),0.); if (choixtdt) noe.Change_val_tdt(ddl_inter.Id_nom(),0.); // ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service // ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom()); noe.Met_en_service(ddl.Id_nom()); noe.Change_fixe(ddl.Id_nom(),true); }; }; // pour le reste on ne fait rien, se sera géré par les mises à jour // en fonction de l'évolution du temps }; // fin du cas ddl bloqué et pas actif pour le temps 0. }; }; }; }; // on initialise la situation de blocage et condition linéaires Validation_blocage (lesRef,0.); // vérif qu'il n'y a pas de surcharge de blocage Verif_surcharge_blocage(lesMail,lesRef,0.,cas); // pour le tps cpu, il y a une petite part de CLL, mais on la néglige tempsCL.Arret_du_comptage(); // temps cpu }; //// mise à jour de l'initialisation, par exemple après un restart //// même paramètres que Initial, par contre ici il n'y a aucune création //void LesCondLim::Re_initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D // ,bool choixtdt,int cas) // { // 1) on parcours le tableau de ddl d'initialisation // int tabInitTaille = tabInit.Taille(); // for (int i=1;i<= tabInitTaille;i++) // { DdlLim& tabInit_i = tabInit(i); // // recup de la reference correspondant au mot cle // const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage()); // if ((refinitial.Indic() == 4) && // (tabInit_i.TypeDeCL()==TANGENTE_CL) ) // {// cas des références d'arêtes, avec des conditions de tangente imposée // const ReferenceAF & ref = ((ReferenceAF &) refinitial); // // on renseigne les éléments ad hoc // int refTaille = ref.Taille(); // for (int ne =1; ne<= refTaille;ne++) // {int tabInitiTaille = tabInit_i.Taille(); // // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer // // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage // int idebut=1; int ifinfin = tabInitiTaille;// début normale // if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;}; // for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 // // affectation de la valeur d'initialisation // { Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl // Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl // Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl // // récup de l'élément // Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); // SfeMembT & elsfe = (SfeMembT&) el; // // on renseigne l'élément // Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); // elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); // // }// fin boucle sur tabInit_i // }// fin boucle sur les éléments de la référence // } // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE // // else if (refinitial.Indic() != 1) // // cas d'element // { cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!"; // cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; // Sortie(1); // } // else // // cas de noeuds // {// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon // // la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout // // cas peut de fois, // const ReferenceNE & ref = ((ReferenceNE &) refinitial); // // traitement proprement dit // int refTaille = ref.Taille(); // for (int nn =1; nn<= refTaille;nn++) // {int tabInitiTaille = tabInit(i).Taille(); // // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage // int idebut=1; int ifinfin = tabInitiTaille;// début normale // if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;}; // for (int nd=idebut;nd<= ifinfin ;nd++) // // affectation de la valeur d'initialisation // { Ddl ddl = tabInit_i.ElemLim(nd); // Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // if (noe.Existe_ici(ddl.Id_nom())) // // cas ou le ddl existe deja // { noe.Change_val_t(ddl.Id_nom(),ddl.Valeur()); // if (choixtdt) // noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur()); // // mise a jour des ddl aux temps 0 pour tous les ddl sauf ceux de position // // car ces derniers sont les seuls dont la position initiale est déterminées à la lecture // // du maillage // if (!(Meme_famille(ddl.Id_nom(),X1))) // noe.Change_val_0(ddl.Id_nom(),ddl.Valeur()); // // on regarde s'il fait partie de la combinaison // // si oui on met en place les ddl correspondant à HSLIBRE // Enum_ddl en = ddl.Id_nom(); // Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); // } // else // // cas ou le ddl n'existe pas // { // tout d'abord on regarde si c'est un déplacement // // if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) // if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) // { if(!CompatDim(ddl.Nom())) // vérif de dimension // { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" // << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; // cout << " \n cas des ddl bloquees "; // cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; // Sortie (1); // } // // cas ok on impose le déplacement sur le Xi correspondant // Enum_ddl en = ddl.Id_nom(); // //on cherche l'equivalent Ui en Xi // en = UxyzXi(en); // noe.Ajout_val_t(en,ddl.Valeur()); // // mise a jour des ddl aux autres temps // // noe.Ajout_val_0(en,ddl.Valeur()); // if (choixtdt) // noe.Ajout_val_tdt(en,ddl.Valeur()); // // puis on regarde si le ddl initial fait partie de la combinaison // // si oui on met en place les ddl correspondant à HSLIBRE // Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); // } // else // { // cas ou il faut creer un ddl sup // //noe.PlusDdl(ddl); // cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues" // << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; // cout << "\n cas des ddl d'initialisation "; // cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl; // Sortie (1); // } // } // } // } // } // } // // 2) cas des ddl imposes on verifie leurs existences // // on vérifie également l'existence des courbes de charge adoc si nécessaire // // on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple // // vitesse et position ou accélération pour un même ddl // // on parcours le tableau de ddl bloques // // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt // int tabBloqTaille = tabBloq.Taille(); // for (int i=1;i<= tabBloqTaille;i++) // { DdlLim& tabBloq_i = tabBloq(i); // // recup de la reference correspondant au mot cle // const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); // if ((refinitial.Indic() == 4) && // (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) // {// cas des références d'arêtes, avec des conditions de tangente imposée // // ici on s'occupe de renseigner les éléments // const ReferenceAF & ref = ((ReferenceAF &) refinitial); // // on renseigne les éléments ad hoc // int refTaille = ref.Taille(); // for (int ne =1; ne<= refTaille;ne++) // {int tabBloqiTaille = tabBloq_i.Taille(); // // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer // // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage // int idebut=1; int ifinfin = tabBloqiTaille;// début normale // if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;}; // for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 // // affectation de la valeur d'initialisation // { Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl // Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl // Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl // // récup de l'élément // Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); // SfeMembT & elsfe = (SfeMembT&) el; // // on continue que si le temps est actif ou pas // if ((tabBloq_i.Temps_actif(0.))) // { // on renseigne l'élément // Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); // elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); // }; // }// fin boucle sur tabBloq_i // }// fin boucle sur les noeuds de la référence // } // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE // // else if (refinitial.Indic() != 1) // // cas autre d'element par exemple // { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!"; // cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; // Sortie (1); // } // else // // cas de noeuds // {const ReferenceNE & ref = ((ReferenceNE &) refinitial); // int refTaille = ref.Taille(); // for (int nn =1; nn<= refTaille;nn++) // {int tabBloqiTaille = tabBloq_i.Taille(); // /* // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim // if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) // {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" // << " que le nombre de noeud de la reference associee !! "; // cout << " condition limite : "; tabBloq_i.Affiche(); // Sortie(1); // }*/ // // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage // int idebut=1; int ifinfin = tabBloqiTaille;// début normale // if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; // for (int nd=idebut;nd<= ifinfin ;nd++) // // affectation de la valeur d'initialisation // { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl // // on regarde si le temps est actif ou pas // if ((tabBloq_i.Temps_actif(0.))) // { // on n'intervient que si le temps initial est actif // tabBloq_i.ElemLim(nd).Met_en_service(); // // récup du noeud // Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // string nom_courbe = tabBloq_i.Nom_courbe(nd); // Courbe1D * pt_courbe = NULL; // if (nom_courbe != "") // // cas de l'existence d'une courbe de charge // // appel pour récupérer la courbe (juste pour la vérif // // car on ne s'en sert pas aprés !) // { pt_courbe = lesCourbes1D->Trouve(nom_courbe); // } // // maintenant on regarde du coté des noeuds // if (!noe.Existe_ici(ddl.Id_nom())) // // cas ou il faut creer un ddl sup // // on regarde le cas eventuel des coordonnees entrainees // // si on est en entraine et que le ddl a imposer est un Ui // // alors on ne verifie que les dimensions et on indique le blocage // // {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) // {if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) // { // cas d'un ddl de déplacement, et que le ddl X1 existe déjà // if(!CompatDim(ddl.Nom())) // { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" // << " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ; // cout << " \n cas des ddl bloquees "; // cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; // Sortie (1); // } // else // cas ou c'est Xi le ddl bloque, on indique le blocage // { Enum_ddl en = ddl.Id_nom(); // //on cherche l'equivalent Ui en Xi // en = UxyzXi(en); // noe.Change_fixe(en,true); // // on regarde s'il fait partie de la combinaison et on fixe les blocages // Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); // } // } // else // // cas d'un ddl inexistant diff de U, création puis initialisation a zero // { noe.PlusDdl(ddl); // noe.Change_val_0(ddl.Id_nom(),0.); // noe.Change_val_t(ddl.Id_nom(),0.); // if (choixtdt) // noe.Change_val_tdt(ddl.Id_nom(),0.); // // puis on indique que le ddl est bloque // noe.Change_fixe(ddl.Id_nom(),true); // // on regarde s'il fait partie de la combinaison et on fixe les blocages // Enum_ddl en = ddl.Id_nom(); // Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); // } // } // else // cas ou le ddl existe // // on indique que le ddl est bloque, mais on ne change pas sa valeur // // ce sera fait au moment de la mise à jour à tdt // { // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1) // // dans ce cas il est libre, on peut le bloquer sans pb, // // soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement // noe.Change_fixe(ddl.Id_nom(),true); // // on regarde s'il fait partie de la combinaison et on fixe les blocages // Enum_ddl en = ddl.Id_nom(); // Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); // } // } // else // {// si le ddl bloqué n'est pas actif pour le temps 0. // tabBloq_i.ElemLim(nd).Met_hors_service(); // // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé // // récup du noeud // Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // // on regarde du coté du noeuds // if (!noe.Existe_ici(ddl.Id_nom())) // // cas ou il faut creer un ddl sup // // on regarde le cas eventuel des coordonnees entrainees // // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien // // {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) // {if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) // {// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis // // initialisation a zero et on indique qu'il est hors service // noe.PlusDdl(ddl); // noe.Change_val_0(ddl.Id_nom(),0.); // noe.Change_val_t(ddl.Id_nom(),0.); // if (choixtdt) noe.Change_val_tdt(ddl.Id_nom(),0.); // // puis on indique que le ddl est bloque et hors service // noe.Met_hors_service(ddl.Id_nom()); // noe.Change_fixe(ddl.Id_nom(),true); // } // } // // pour le reste on ne fait rien, se sera géré par les mises à jour // // en fonction de l'évolution du temps // } // fin du cas ddl bloqué et pas actif pour le temps 0. // } // } // } // } // // on initialise la situation de blocage et condition linéaires // Validation_blocage (lesRef,0.); // // vérif qu'il n'y a pas de surcharge de blocage // Verif_surcharge_blocage(lesMail,lesRef,0.,cas); // }; // incrementation des coordonnees a t+dt et des ddl en fonctions des ddl imposes // et du chargement // coef: est un facteur multiplicatif des ddl sans courbes de charge, // est supposé intégrer déjà le multiplicateur général // en fait du chargement impose // mult_gene : multiplicateur général de tous les chargements // deltat : le pas de temps en cours // temps : le temps courant où sont calculées les conditions // ch_statut : indique s'il y a changement ou non de statut des conditions limites (pour les ddl aux noeuds) // c-a-d un ddl qui passe de bloqué à non bloqué ou inversement: il s'agit uniquement des ddl aux noeuds // c-a-d ceux qui ont une influence sur la mise en place des cl sur la raideur et le résidu // cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque // le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont // leur statut modifié de manière équivalente // =0 pas d'association // =1 association X V GAMMA // lorsque en_ddl est égal à NU_DDL, cela signifie que l'on met les conditions limites sur tous les // ddl de noeud actifs // lorsque en_ddl est différent de NU_DDL, il donne le type des seules ddl pour lesquels on met les // conditions de blocage: par exemple X1 -> blocage sur X1,X2,X3 selon la dimension void LesCondLim::MiseAJour_tdt (const double& mult_gene,LesMaillages * lesMail,const double& deltat,const LesReferences* lesRef ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,const double& coef,bool& ch_statut ,int cas,Enum_ddl en_ddl) { tempsCL.Mise_en_route_du_comptage(); // temps cpu // préparation bool tous_les_blocages = true; if (en_ddl != NU_DDL) tous_les_blocages = false; // la mise en place des blocages s'effectue en deux temps, ceci pour préparer la vérification // de la non sur imposition de ddl: ceci pour les ddl aux noeuds // 1- au premier passage : on met en libre les ddl qui sont relachés, on met tous les ddl actifs // en libre // 2- au second passage : les ddl au temps actifs sont fixés (et éventuellement surfixé si pb) // // pour les ddl d'encastrement ou de symétrie pour les sfe, tout ce fait au premier passage uniquement // ---- premier passage ---- int tabBloqTaille =tabBloq.Taille(); for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // on regarde si les temps dépendent d'une fct nD // si oui on modifie les bornes du ddl if (tabBloq_i.Temps_depend_nD()) LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD); // pour le ddlLim, si le temps est inférieur au temps actif // ou si d'une part le temps n'est pas actif et qu'au pas précédent // il n'était pas également actif on ne fait rien if (!(tabBloq_i.Pas_a_prendre_en_compte(temps))) {bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier // recup de la reference correspondant au mot cle const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); if ((refinitial.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) {// cas des références d'arêtes, avec des conditions de tangente imposée bool devient_actif = (actif_pour_le_temps && (!tabBloq_i.Etat_validation())); bool devient_inactif = ((!actif_pour_le_temps) && (tabBloq_i.Etat_validation())); // on n'intervient que s'il y a un changement d'état if (devient_actif || devient_inactif) {//int tabBloqitaille = tabBloq_i.Taille(); const ReferenceAF & ref = ((ReferenceAF &) refinitial); int reftaille = ref.Taille(); // on boucle sur les numéros de la référence for (int ne =1; ne<= reftaille;ne++) {// on regarde si le temps est actif ou pas if (devient_actif) // cas ou on veut le blocage mais qu'au temps précédent ce n'était pas valide { // récup de l'élément SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); // que ce soit dans le cas d'un champ ou normal, on n'a pas besoin d'itérer sur les ddl du ddlLim // car d'un part pour le champ, on a autant de dim_espace ddl que d'élément dans la référence // et d'autre part dans le cas normal on a uniquement un seul dim_espace ddl -> vecteur // !!!!!! pour l'instant on considère que c'est en 3D #ifdef MISE_AU_POINT if ((ParaGlob::Dimension() < 3) || (tabBloq_i.Taille() != 3)) { cout << "\n erreur, pour l'instant les conditions de type TANGENTE_CL ne sont operationnelles " << " que pour la dimension 3 !! "; cout << "\n reference concernee: "; ref.Affiche(); cout << "\n condition limite concernee: ";tabBloq_i.Affiche(); tempsCL.Arret_du_comptage(); Sortie(1); }; #endif int tabBloqitaille = tabBloq_i.Taille(); // normalement = 3 ici Tableau t_ddl(tabBloqitaille); // les valeurs du vecteur qui permet le calcul de la tangence for (int nd=1;nd<=tabBloqitaille;nd++) {Ddl ddl = tabBloq_i.ElemLim(nd); // choix entre valeur simple et valeur qui varie if(tabBloq_i.Nom_courbe(nd) != "") { // cas d'une courbe de charge, récup de la courbe Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd)); // on change la valeur du ddl if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent { // pour l'instant ce n'est pas implanté // en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la // position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à // l'élément qui updaterait sa position (qui peut être différente pour chaque élément) // $$$ à faire s'il y a une demande, pour l'instant on attend $$$$ cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant" << " ce cas n'est pas implante, donc le demander !!! " << "\n LesCondLim::MiseAJour_tdt(.... "; tempsCL.Arret_du_comptage(); Sortie(1); } else { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd); }; t_ddl(nd) = ddl; } else if (tabBloq_i.NomF_charge(nd) != "") { // cas d'une fonction nD de charge, récup Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd)); // on change la valeur du ddl if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent { // pour l'instant ce n'est pas implanté // en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la // position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à // l'élément qui updaterait sa position (qui peut être différente pour chaque élément) // $$$ à faire s'il y a une demande, pour l'instant on attend $$$$ cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant" << " ce cas n'est pas implante, donc le demander !!! " << "\n LesCondLim::MiseAJour_tdt(.... "; tempsCL.Arret_du_comptage(); Sortie(1); } else {// pour l'instant on limite l'utilisation des fonctions aux seules grandeurs globales if (pt_fctnD->NbVariable_locale() != 0) {cout << "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements, pour l'instant" << " seule une dependance a des variables globales est possible !!! " << "\n LesCondLim::MiseAJour_tdt(.... "; tempsCL.Arret_du_comptage(); Sortie(1); }; Tableau & tab_ret = pt_fctnD->Valeur_pour_variables_globales(); #ifdef MISE_AU_POINT if (tab_ret.Taille() != 1) {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " << "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements" << "\n LesCondLim::MiseAJour_tdt(.... "; tempsCL.Arret_du_comptage(); Sortie(1); }; #endif // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd); }; t_ddl(nd) = ddl; } else // cas d'un ddl à valeur fixe { // cas d'un ddl à valeur fixe t_ddl(nd) = ddl; }; }; // on renseigne l'élément Coordonnee3 vpla(t_ddl(1).Valeur(),t_ddl(2).Valeur(),t_ddl(3).Valeur()); elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); } else if (devient_inactif) // on relache le blocage si nécessaire, pour cela on regarde donc s'il y a changement de statut { // récup de l'élément SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); // on renseigne l'élément Coordonnee3 vpla; // initalisé à 0 par défaut, ne sert pas ici elsfe.DefCondLim(RIEN_TYPE_CL,vpla, ref.NumeroFA(ne) ); }; // sinon on ne fait rien }; //-- fin de la boucle sur ne }//-- fin du test sur devient_actif ou devient_inactif }//-- fin du cas ref d'encastrement ou de symétrie else // cas d'une référence de noeud {const ReferenceNE & ref = ((ReferenceNE &) refinitial); int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // incrementation en fonction de la valeur de blocage et du coef {Ddl ddl = tabBloq_i.ElemLim(nd); // concernant le temps, soit le ddlLim est actif ou il change de statut: actif à non actif Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) // cas de deplacements imposes en entraine on change les Ui en Xi ddl.Change_nom(UxyzXi(ddl.Id_nom())); bool a_considerer = tous_les_blocages; if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux {if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;} Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier if (a_considerer) { if ( noe.En_service(ddlenu) ) { // on regarde si le temps est actif ou pas if (!actif_pour_le_temps) // cas du temps non actif, on relache le blocage si nécessaire // on regarde donc s'il y a changement de statut {if (tabBloq_i.Etat_validation() && (noe.Ddl_fixe(ddlenu))) {ch_statut = true; Retire_cl(nd,tabBloq_i,ddlenu,noe,cas); } } //-- fin du test ou le temps n'est pas actif else // cas du temps actif // on regarde s'il y a changement de statut {if (!(tabBloq_i.Etat_validation())&& (!(noe.Ddl_fixe(ddlenu)))) { // on change le statut que si c'est une variable, les données n'influencent pas les raideurs et seconds membres if (noe.UneVariable(ddlenu)) ch_statut = true; // Mise_cl(nd,tabBloq_i,ddlenu,noe,cas); }; // gestion des surcharges de blocage // au premier passage on met tous les ddl en libre s'ils sont actifs if (noe.Ddl_fixe(ddlenu)) Retire_cl(nd,tabBloq_i,ddlenu,noe,cas); }//-- fin du test si le temps est actif }//-- fin du test si le ddl du noeud est une variable et est en service }//-- fin du test si le noeud est à considérer ou pas }//-- fin de la boucle sur tabBloq_i: indice nd }//-- fin de la boucle nn }//-- fin du cas des noeuds } // fin du if (!(tabBloq_i.Pas_a_prendre_en_compte(temps))) }//-- fin de la boucle sur tabBloq // ---- second passage ---- for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); // on ne continue que si c'est une référence de noeud if (ref.Indic() == 1) { int reftaille = ref.Taille(); // cas particulier des mouvements solides if (tabBloq_i.Mouvement_Solide()) {MiseAjour_tdt_second_passage_mvtSolide(mult_gene,lesMail,deltat,cas ,lesCourbes1D,lesFonctionsnD,coef,tabBloq_i,ref,temps,en_ddl); } else // cas différent des mouvements solides {for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // incrementation en fonction de la valeur de blocage et du coef {Ddl ddl = tabBloq_i.ElemLim(nd); // pour le ddlLim, si le temps est inférieur au temps actif // ou si d'une part le temps n'est pas actif et qu'au pas précédent // il n'était pas également actif on ne fait rien if (tabBloq_i.Pas_a_prendre_en_compte(temps)) break; // maintenant soit le ddlLim est actif ou il change de statut: actif à non actif Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) ////--debug //if (noe.Num_noeud()==197) // {cout << "\n debug1: LesCondLim::MiseAJour_tdt(.."; // noe.Affiche();cout << endl; // }; ////--fin debug if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) // cas de deplacements imposes en entraine on change les Ui en Xi ddl.Change_nom(UxyzXi(ddl.Id_nom())); bool a_considerer = tous_les_blocages; if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux {if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;} Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier if (a_considerer) { // on regarde si les temps dépendent d'une fct nD // si oui on modifie les bornes du ddl if (tabBloq_i.Temps_depend_nD()) LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier bool une_variable = noe.UneVariable(ddlenu); // pour simplifier // cas des variables: si le ddl du noeud est en service on continue sinon on ne fait rien // ou cas d'une donnée et le temps actif if ( ( une_variable && noe.En_service(ddlenu)) ||(!une_variable && actif_pour_le_temps) ) { // on regarde si le temps est actif ou pas, seul le cas actif est ici considérer if (actif_pour_le_temps) // gestion des surcharges de blocage // au second passage on fixe les ddl actifs {Mise_cl(nd,tabBloq_i,ddlenu,noe,cas); // on choisit entre ddl à valeur fixe ou avec une courbe de charge // coef intègre le multiplicateur global: mult_gene if ((tabBloq_i.Nom_courbe(nd) != "")&&(tabBloq_i.NomF_charge(nd) == "")) { // cas d'une courbe de charge, récup de la courbe Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd)); // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle // car au paravant il pouvait être non nul // ici changement et non ajout , prise en compte de la relativité du blocage double val_final = 0.; if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent { // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat ddl.Valeur() = ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) * tabBloq_i.Echelle_courbe(nd); val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu); } else { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd); val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu); }; noe.Change_val_tdt(ddlenu,val_final); // mise à jour } else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) == "")) { // cas d'une fonction nD de charge, récup Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd)); // on commence par récupérer les conteneurs des grandeurs à fournir List_io & li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire(); List_io & li_quelc = pt_fctnD->Li_equi_Quel_evolue(); // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire Tableau val_ddl_enum(Valeur_multi_interpoler_ou_calculer (noe, TEMPS_tdt,li_enu_scal)); // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc); // calcul de la valeur et retour dans tab_ret Tableau & tab_ret = pt_fctnD->Valeur_FnD_Evoluee (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL); #ifdef MISE_AU_POINT if (tab_ret.Taille() != 1) {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " << "\n *** blocage via une fonction nD pour l'evolution du ddl" << Nom_ddl(ddlenu) << "\n LesCondLim::MiseAJour_tdt(.... "; tempsCL.Arret_du_comptage(); Sortie(1); }; #endif // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle // car au paravant il pouvait être non nul // ici changement et non ajout , prise en compte de la relativité du blocage double val_final = 0.; if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent { // pour l'instant a priori ce n'est pas possible car le temps // est une variable globale que l'on ne peut pas modifier pour les fonctions nD // il faut donc utiliser conjointement une courbe1D pour le temps et la fonction nD pour le reste cout << "\n *** blocage relatif avec uniquement une fonction nD: ce n'est pas possible" << " pour avoir un blocage relatif il faut utiliser conjointement une courbe de charge " << " pour le temps et une fonction nD pour le reste !!!!" << "\n LesCondLim::MiseAJour_tdt(.... "; tempsCL.Arret_du_comptage(); Sortie(1); } else { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd); val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu); }; noe.Change_val_tdt(ddlenu,val_final); // mise à jour } else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) != "")) { // cas d'une fonction nD de charge, récup Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd)); // on commence par récupérer les conteneurs des grandeurs à fournir List_io & li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire(); List_io & li_quelc = pt_fctnD->Li_equi_Quel_evolue(); // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire Tableau val_ddl_enum(Valeur_multi_interpoler_ou_calculer (noe, TEMPS_tdt,li_enu_scal)); // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc); // calcul de la valeur et retour dans tab_ret Tableau & tab_ret = pt_fctnD->Valeur_FnD_Evoluee (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL); #ifdef MISE_AU_POINT if (tab_ret.Taille() != 1) {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " << "\n *** blocage via une fonction nD pour l'evolution du ddl" << Nom_ddl(ddlenu) << "\n LesCondLim::MiseAJour_tdt(.... "; tempsCL.Arret_du_comptage(); Sortie(1); }; #endif // idem pour la courbe 1D Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd)); // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle // car au paravant il pouvait être non nul // ici changement et non ajout , prise en compte de la relativité du blocage double val_final = 0.; if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent { // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat ddl.Valeur() = tab_ret(1) * (((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) * tabBloq_i.Echelle_courbe(nd) ); val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu); } else { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 ddl.Valeur() = tab_ret(1) * (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd); val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu); }; noe.Change_val_tdt(ddlenu,val_final); // mise à jour } else { // cas d'un ddl à valeur fixe // du au fait de l'initialisation d'un incrément à l'autre dans les algos globaux on change double val_final=noe.Valeur_t(ddlenu); // récup de la valeur à t val_final += coef * ddl.Valeur(); // mise en place du delta noe.Change_val_tdt(ddlenu,val_final); }; }; //-- fin du test si le temps est actif }; //-- fin du test si le ddl du noeud est en service }; //-- fin du test si le noeud est à considérer ou pas }; //-- fin de la boucle sur tabBloq_i }; //-- fin de la boucle sur nn }; //-- fin du else du if (tabBloq_i.Mouvement_Solide()) }; //-- fin du du test : if (ref.Indic() == 1) };//-- fin de la boucle sur tabBloq // vérif qu'il n'y a pas de surcharge de blocage Verif_surcharge_blocage(lesMail,lesRef,temps,cas); tempsCL.Arret_du_comptage(); // temps cpu }; // validation des conditions de blocages, pour l'incrément. // concernant l'activité des ddlLim, elle est enregistrée en fonction du temps // idem pour les conditions linéaires void LesCondLim::Validation_blocage (LesReferences* lesRef,const double& temps) { // tout d'abord les conditions de blocage int tabBloqTaille =tabBloq.Taille(); for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); if (ref.Indic() == 1) // ok que si c'est une ref de noeud { int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); for (int nd=1;nd<= tabBloqitaille;nd++) // validation de l'activité du ddlLim tabBloq_i.Validation(temps); }; }; }; // maintenant les conditions linéaires int tabTaille = tab_iocondiline.Taille(); ////----- debug //cout << "\n LesCondLim::Validation_blocage: avant validation \n temps = " << temps << "\n"; //cout << tab_iocondiline; ////--- fin debug for (int icondli=1;icondli<= tabTaille; icondli++) tab_iocondiline(icondli).Validation(temps); ////----- debug //cout << "\n LesCondLim::Validation_blocage: après validation \n"; //cout << tab_iocondiline; ////--- fin debug }; // test s'il y a changement de statut pour le temps indiqué par rapport à la situation actuelle ou pas // n'effectue aucune autre opération // si en_ddl est différent de NU_DDL on test le changement de statut uniquement pour le ddl en_ddl bool LesCondLim::Changement_statut(const LesMaillages * lesMail,const LesReferences* lesRef ,LesFonctions_nD* lesFonctionsnD ,const double& temps,const Enum_ddl en_ddl) // *************** a mettre en conformité avec miseà jour tdt ***************$ { cout << "\n methode pas operationnelle, a mettre a jour !!!!" << "\n LesCondLim::Changement_statut(...."; Sortie(1); // préparation bool tous_les_blocages = true; if (en_ddl != NU_DDL) tous_les_blocages = false; bool ch_statut = false; // valeur de retour int tabBloqTaille =tabBloq.Taille(); // on parcours le tableau de ddl bloques for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); for (int nd=1;nd<= tabBloqitaille;nd++) // incrementation en fonction de la valeur de blocage et du coef {Ddl ddl = tabBloq_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // on regarde si les temps dépendent d'une fct nD // si oui on modifie les bornes du ddl if (tabBloq_i.Temps_depend_nD()) LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) // cas de deplacements imposes en entraine on change les Ui en Xi ddl.Change_nom(UxyzXi(ddlenu)); bool a_bloquer = tous_les_blocages; if (! a_bloquer) // cas ou on ne veut que certain blocage, a_bloque est faux {if (Meme_famille(en_ddl,ddlenu)) a_bloquer = true;} if (a_bloquer) { if (!(tabBloq_i.Temps_actif(temps))) // cas de la courbe non active pour le temps { // si le ddl du noeud est en service on continue sinon on ne fait rien if ( noe.En_service(ddlenu) ) // on regarde s'il y a changement de statut et que c'est une variable {if ((noe.Ddl_fixe(ddlenu)) && (noe.UneVariable(ddlenu))) ch_statut = true; } //-- fin du test si le ddl du noeud est en service } //-- fin du test ou le temps n'est pas actif else // cas du temps actif { if (ddl.Valeur() != 0) {// si le ddl du noeud est en service on continue sinon on ne fait rien if ( noe.En_service(ddlenu) ) // on regarde s'il y a changement de statut et que c'est une variable {if ( (!(noe.Ddl_fixe(ddlenu))) && (noe.UneVariable(ddlenu))) ch_statut = true; } //-- fin du test si le ddl du noeud est en service } //-- fin du test si la valeur a bloquer est différente de 0 } //-- fin du test si le temps est actif } } } } return ch_statut; }; // récupération des tableaux d'indices généraux des variables ddl bloqués // cas : donne le type d'association de ddl que l'on veut // =0 -> pas d'association // =1 -> association de Xi avec Vi avec Gammai // t_assemb: donne pour chaque type d'association, le numéro d'assemblage correspondant au different ddl // de l'association // cas=1 -> numéro d'assemblage de X1 puis V1 puis GAMMA1 // : en sortie une liste de Gene_asso, correspondant à tous les ddl bloqués et les // les ddl associés list LesCondLim::Tableau_indice (const LesMaillages * lesMail,const Tableau & t_assemb ,const LesReferences* lesRef,const double& temps,int cas) { // def de la liste de retour list li_ret; // préparation int tabBloqTaille =tabBloq.Taille(); // on parcours le tableau de ddl bloques for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); if (ref.Indic() == 1) // ok pour les noeuds uniquement {int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // incrementation en fonction de la valeur de blocage {Ddl ddl = tabBloq_i.ElemLim(nd); const Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) // cas de deplacements imposes en entraine on change les Ui en Xi ddl.Change_nom(UxyzXi(ddl.Id_nom())); // si le blocage est relatif à une donnée et non à une variable arrêt if (!(noe.UneVariable(ddl.Id_nom()))) break; // si le ddl concerne la direction 3 et que l'on est en axi, arrêt // car le ddl 3 n'est pas utilisé en blocage en axi Enum_ddl en_ddl = ddl.Id_nom(); // le type principal de l'élément Gene_asso if (ParaGlob::AxiSymetrie() && FoncDim(en_ddl)) {Enum_ddl prem_ddl = PremierDdlFamille(en_ddl); // pour l'instant on ne traite que X, U, V et Gamma bool fin_traitement = false; // init switch (prem_ddl) { case X1: if (en_ddl == X3)fin_traitement = true; break; case V1: if (en_ddl == V3)fin_traitement = true; break; case GAMMA1:if (en_ddl == GAMMA3)fin_traitement = true; break; default: cout << "\n *** erreur pour l'instant en axi, seules les cas " << " Xi, Vi, GAMMAi sont pris en compte pour les CL selon dir 3 " << " \n LesCondLim::Tableau_indice(... "<< endl; break; }; if (fin_traitement) break; }; // on regarde si le ddl fait partie de la liste à scruter, si l'on est // dans le cas d'une combinaison, sinon c'est ok bool choix = true; // vrai a priori, c'est à dire le cas = 0 // qui convient que dans le cas = 0, sinon: if (cas!= 0) { if (Dans_combinaison(cas,en_ddl)) {choix = true;} else {choix = false;} // cas d'une combinaison , et d'un ddl qui ni appartiend pas }; if (choix) { // on test que si le temps est actif // ici les tmin et tmax du ddl ne sont pas modifiés, on considère que ce sont // ceux qui ont été mise à jour à la précédente mise à jour if ((tabBloq_i.Temps_actif(temps))) { switch (cas) { case 0 : // cas pas d'association { // def du tableau de position pour l'élément Gene_asso Tableau pointe(1); // dimension pour Xi,Vi,GAMMAi // recup de la position du ddl pointe(1) = noe.Pointeur_assemblage(en_ddl,t_assemb(1).n); // ajout dans la liste Gene_asso aa(en_ddl,pointe); li_ret.push_back(aa); break; } case 1 : // cas de l'association X V GAMMA { // def du tableau de position pour l'élément Gene_asso Tableau pointe(3); // dimension pour Xi,Vi,GAMMAi // récup des ddl secondaire et du ddl principal bloqué Tableau t_enu = MemeCombinaison(cas,en_ddl); pointe(1) = noe.Pointeur_assemblage(t_enu(1),t_assemb(1).n); pointe(2) = noe.Pointeur_assemblage(t_enu(2),t_assemb(2).n); pointe(3) = noe.Pointeur_assemblage(t_enu(3),t_assemb(3).n); // ajout dans la liste Gene_asso aa(en_ddl,pointe); li_ret.push_back(aa); ////// --debug //cout << "\n debug LesCondlim::Tableau_indice(" // << "\n li_ret.size= "<< li_ret.size() << endl; ////// -- fin debug break; } }; //-- fin du switch (cas) }; //-- fin du if ((tabBloq_i.Temps_actif(temps))) }; //-- fin du if (choix) }; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++) }; //-- fin du for (int nn =1; nn<= reftaille;nn++) }; //-- fin du if (ref.Indic() == 1) }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) //// --debug //cout << "\n debug LesCondlim::Tableau_indice(" // << "\n li_ret.size= "<< li_ret.size() ; //list ::iterator ie,iefin=li_ret.end();; // def d'un iterator adoc //int ih=1; // indice //for(ie=li_ret.begin(),ih=1;ie!=iefin;ie++,ih++) // // comme les valeurs des X V Gamma vont être écrasé par le calcul global, on utilise // // des conteneurs intermédiaires // {//trois cas // LesCondLim::Gene_asso & s = (*ie); // pour simplifier // int ix=s.pointe(1); // début des Xi // int iv=s.pointe(2); // début des Vi // int ig=s.pointe(3); // début des gammai // cout << "\n ix= " << ix << ", iv= "<< iv << ", ig= "<< ig; // }; //cout << endl; //// -- fin debug // retour de la liste return li_ret; }; // mise en place des conditions limites sur les matrices et/ou second membres // cas : indique un type d'association de ddl // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès // lors que l'un a été fixé par l'utilisateur // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob // mais sans sauvegarde (correspond par exemple à une partie de vecglob) void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef, Mat_abstraite & matglob,Vecteur& vecglob ,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return ; #endif tempsCL.Mise_en_route_du_comptage(); // temps cpu int tabBloqTaille =tabBloq.Taille(); int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage Tableau tmc; // tableau de travail // on parcours le tableau de ddl bloques for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); if (ref.Indic() == 1) // ok pour les noeuds uniquement {int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // mise en place de la condition limite { Ddl ddl = tabBloq_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); // on continue uniquement si le ddl du tableau de blocage est en service // et si pour le noeud c'est une variable if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) { // récup des enu_ddl équivalent au groupe tmc = MemeCombinaison(cas,ddl.Id_nom()); int tailletmc = tmc.Taille(); for (int itc=1;itc <= tailletmc;itc++) {// on boucle sur tous les ddl a imposer // calcul du pointeur correspondant au ddl cherche int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif if ((pt != -1) && (noe.En_service(tmc(itc)))) {// ce que l'on veut c'est une variation nulle des ddl imposee // -> valeur imposee = 0 // cas de la matrice, et modif du second membre si la valeur imposee // est differente de zero (ce qui n'est pas le cas ici !) condlim(nb_casAss).Val_imposee_Mat(matglob,vecglob,pt,0.,vec2); // cas du second membre et sauvegarde des reactions condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2); }; }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) }; //-- fin de for (int nn =1; nn<= reftaille;nn++) }; //-- fin de if (ref.Indic() == 1) }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) // affichage éventuelle de la matrice de raideur et du second membre if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage de la matrice apres conditions limites des ddl initialement bloques "; matglob.Affichage_ecran(entete); entete = " affichage du second membre apres conditions limites des ddl initialement bloques "; vecglob.Affichage_ecran(entete); }; tempsCL.Arret_du_comptage(); // temps cpu }; // mise en place des conditions limites sur le second membres // nb_casAssemb : le cas d'assemblage // cas : indique un type d'association de ddl // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un // a été fixé par l'utilisateur // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob // mais sans sauvegarde (correspond par exemple à une partie de vecglob) void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef ,Vecteur& vecglob,const Nb_assemb& nb_casAssemb ,int cas,Vecteur* vec2) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return ; #endif tempsCL.Mise_en_route_du_comptage(); // temps cpu int tabBloqTaille =tabBloq.Taille(); int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage Tableau tmc; // tableau de travail // on parcours le tableau de ddl bloques for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); if (ref.Indic() == 1) // ok pour les noeuds uniquement {int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // mise en place de la condition limite { Ddl ddl = tabBloq_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); // on continue uniquement si le ddl du tableau de blocage est en service // et si pour le noeud c'est une variable if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) { // récup des enu_ddl équivalent au groupe tmc = MemeCombinaison(cas,ddl.Id_nom()); int tailletmc = tmc.Taille(); for (int itc=1;itc <= tailletmc;itc++) {// on boucle sur tous les ddl a imposer // calcul du pointeur correspondant au ddl cherche int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif if ((pt != -1) && (noe.En_service(tmc(itc)))) {// ce que l'on veut c'est une variation nulle des ddl imposee // -> valeur imposee = 0 // cas du second membre et sauvegarde des reactions condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2); }; }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) }; //-- fin de for (int nn =1; nn<= reftaille;nn++) }; //-- fin de if (ref.Indic() == 1) }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) // affichage éventuelle du second membre if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage du second membre apres conditions limites des ddl initialement bloques "; vecglob.Affichage_ecran(entete); }; tempsCL.Arret_du_comptage(); // temps cpu }; // mise en place des conditions limites sur deux matrices // utilisé par exemple pour le flambement // la première matrice est initialisée avec des 1 sur la diagonale // la seconde avec des 0 sur la diagonale // cas : indique un type d'association de ddl // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un // a été fixé par l'utilisateur void LesCondLim::ImpConLimtdt2Mat(LesMaillages * lesMail,LesReferences* lesRef, Mat_abstraite & matglob,Mat_abstraite & matgeom ,const Nb_assemb& nb_casAssemb,int cas) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return ; #endif tempsCL.Mise_en_route_du_comptage(); // temps cpu int tabBloqTaille =tabBloq.Taille(); int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage Tableau tmc; // tableau de travail // on parcours le tableau de ddl bloques for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); if (ref.Indic() == 1) // ok pour les noeuds uniquement {int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // mise en place de la condition limite { Ddl ddl = tabBloq_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); // on continue uniquement si le ddl du tableau de blocage est en service // et si pour le noeud c'est une variable if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) { // récup des enu_ddl équivalent au groupe tmc = MemeCombinaison(cas,ddl.Id_nom()); int tailletmc = tmc.Taille(); for (int itc=1;itc <= tailletmc;itc++) {// on boucle sur tous les ddl a imposer // calcul du pointeur correspondant au ddl cherche int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif if ((pt != -1) && (noe.En_service(tmc(itc)))) {// ici on ne fait que modifier les matrices -> un 1 sur la diagonale // et 0 sur le reste de la ligne et colonne correspondantes condlim(nb_casAss).Val_imposSimple_Mat(matglob,pt,1.); condlim(nb_casAss).Val_imposSimple_Mat(matgeom,pt,0.); }; }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) }; //-- fin de for (int nn =1; nn<= reftaille;nn++) }; //-- fin de if (ref.Indic() == 1) }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) // affichage éventuelle des deux matrices de raideur if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage de la premiere matrice de raideur apres conditions limites (matglob) "; entete += " des ddl initialement bloques"; matglob.Affichage_ecran(entete); entete = " affichage de la seconde matrice de raideur apres conditions limites (matgeom) "; entete += " des ddl initialement bloques"; matgeom.Affichage_ecran(entete); }; tempsCL.Arret_du_comptage(); // temps cpu }; // récupération des reactions initiales, avant les rotations dues aux conditions linéaires // il s'agit des réactions dues aux ddl bloqués et dues aux conditions linéaires // et calcul des torseurs de réaction void LesCondLim::ReacAvantCHrepere(Vecteur& residu,LesMaillages * lesMail, LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas) { #ifdef UTILISATION_MPI // cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return ; #endif int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage Tableau tmc; // tableau de travail // on cree une liste de stockage intermediaire list lili; list indice_tabBloq; // tableau de travail, qui sert pour le calcul des torseurs de réaction ReactStoc elem; // element courant de stockage des réactions //----------- cas des ddl bloqués ----------------- // on parcours le tableau de ddl bloques int tabBloqTaille =tabBloq.Taille(); for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); if (!((ref.Indic() == 4) && // le cas des conditions de tangence sur (tabBloq_i.TypeDeCL()==TANGENTE_CL )) // les arrêtes n'est pas à prendre en compte && (ref.Indic() == 1)) // s'applique uniquement au cas des ref de noeuds {int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // récupération de la condition limite { Ddl ddl = tabBloq_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); // on continue uniquement si le ddl du tableau de blocage est en service // et si pour le noeud c'est une variable if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) { // récup des enu_ddl équivalent au groupe tmc = MemeCombinaison(cas,ddl.Id_nom()); int tailletmc = tmc.Taille(); for (int itc=1;itc <= tailletmc;itc++) {// on boucle sur tous les ddl a imposer // calcul du pointeur correspondant au ddl cherche int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif if ((pt != -1) && (noe.En_service(tmc(itc)))) { // maintenant on peut récupérer la réaction elem.ddl = ddl; elem.ddl.Valeur() = residu(pt); elem.numMail = ref.Nbmaille(); elem.numNoeud = ref.Numero(nn); elem.casAss = nb_casAss; lili.push_back(elem); // sauvegarde de la réaction indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq }; }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) }; //-- fin de for (int nn =1; nn<= reftaille;nn++) }; //-- fin de if (!((ref.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) ) }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) //----------- cas des conditions linéaires ----------------- // on cree une liste de stockage intermediaire list lili_CLin;List_io indice_dans_tab_iocondiline; // on a besoin d'enregistrer une seule fois chaque réaction, or le mode de fabrication des CLL // fait que cela conduit à des redondances. Pour les repérer, on va utiliser un conteneur de drapeau // de manière à limiter la taille de ce conteneur on utilise une map, c'est moins rapide en acces // qu'un tableau, mais c'est mieux qu'une liste et c'est plus petit qu'un tableau, car a priori // il y a moins beaucoup moins de ddl bloqué par les CLL que de ddl total du pb map < int , bool, std::less > reac_deja_stocke; // on parcours le tableau des CLL // on boucle sur le tableau de conditions limites linéaires enregistré int tabTaille = tab_CLinApplique.Taille(); for (int i=1;i<= tabTaille; i++) {int sous_taille = tab_CLinApplique(i).Taille(); for (int j=1; j<= sous_taille; j++) { Condilineaire& condi = tab_CLinApplique(i)(j); // on met à jour les pointeurs d'assemblage pour bien localiser les infos dans SM et K // ce sera refait dans l'assemblage... condi.ConditionPourPointeursAssemblage(nb_casAssemb); // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 if (condi.Iddl() > -1) { // chaque ddl qui appartient à une CLL et qui est associé // à un coefficient non nulle conduit à une condition limite const Vecteur& Vectval = condi.Val(); const Tableau& pt = condi.Pt_t(); const Tableau& t_enu = condi.Tab_Enum(); const Tableau < Noeud *>& t_noeud = condi.TabNoeud(); // on boucle sur les noeuds puis sur les ddl de la CLL int taille = pt.Taille(); int nb_noeud = t_noeud.Taille();int itab=1; int nbddlfamille = taille / nb_noeud; for (int i_noe=1;i_noe <= nb_noeud;i_noe++) for (int i_fa =1; i_fa<= nbddlfamille; i_fa++,itab++) { // on ne stocke que si la réaction n'a pas déjà été stockée if ((reac_deja_stocke.find(pt(itab))==reac_deja_stocke.end()) && (Vectval(itab) != 0.) ) // et que le coef est non nul { // on définit la réaction elem.ddl.Change_nom(t_enu(itab)); elem.ddl.Valeur() = residu(pt(itab)); elem.numMail = t_noeud(i_noe)->Num_Mail(); elem.numNoeud = t_noeud(i_noe)->Num_noeud(); // elem.casAss = condi.CasAssemb().n; elem.casAss = nb_casAssemb.n; lili_CLin.push_back(elem); // on sauvegarde la réaction // sauvegarde de l'indice dans tab_iocondiline car le premier indice "i" // de tab_CLinApplique est celui correspondant à la condition tab_iocondiline(i) // le second indice permet de retrouver la ref indice_dans_tab_iocondiline.push_back(DeuxEntiers(i,i_noe)); // on renseigne la map reac_deja_stocke[pt(itab)] = true; }; }; }; }; }; //----------- fin du cas des conditions linéaires ----------------- //--débug --- //cout << "\n " << indice_dans_tab_iocondiline << endl; //--débug--- // ----- on initialise le tableau des torseurs de réaction int tabtorsTaille = tab_torseurReac.Taille(); for (int i=1;i<= tabtorsTaille;i++) if (tab_torseurReac(i).existe_torseur_reac) tab_torseurReac(i).Zero_init_torseur(); int dima = ParaGlob::Dimension(); if(ParaGlob::AxiSymetrie()) // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les // dimension-1 coordonnées donc on décrémente dima--; // --- enregistrement des réactions pour ddl bloqué et calcul des torseurs { // on encapsule list ::iterator i; // def d'un iterator adoc reaction.Change_taille((int)lili.size()); // map_reaction.erase(map_reaction.begin(),map_reaction.end()); int j; list ::iterator i_taBloq=indice_tabBloq.begin(); for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++,i_taBloq++) { reaction(j) = *i; // map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)] // .push_back(&(reaction(j))); // transfert des informations aux noeuds ReactStoc& reac = reaction(j); // pour simplifier // récup du noeud j du maillage i Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud); Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction // dans le cas où la réaction n'existe pas on l'ajoute // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité { if (!noe.Existe_ici(enu_reac)) // { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE); { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE); noe.PlusDdl(reac_ddl); } else // sinon il faut le bloquer car la réaction est imposée { noe.Change_fixe(enu_reac,true);}; // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 if (ttRG(*i_taBloq) != 0) // si = 0 c'est que le ddl n'est pas un déplacement classique CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac); }; // mise à jour de la réaction noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt }; // on va maintenant exporter les composantes du tenseur vers des grandeurs globales int taille_tors_bloqu = ttRG_noms_ref.Taille(); int taille_tors_bloquplus1 = taille_tors_bloqu +1; // cas d'un blocage de ddl {int il = 1; for (int ia=1;iaGrandeurGlobal(nom_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'exportation de composantes de torseur !! " << " la variable globale "<< (nom_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic); }; // 2) le moment for (int ic= 1; ic < dimaPlus1; ic++) {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); // récup du pointeur de conteneur const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'exportation de composantes de torseur !! " << " la variable globale "<< (nom_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic); }; }; }; }; // fin encapsulation // --- enregistrement des réactions pour les CLL et calcul également des torseurs associés // il s'agit des réactions définies précédemment (-- cas des conditions linéaires --) { // on encapsule list ::iterator i; // def d'un iterator adoc List_io ::iterator iti = indice_dans_tab_iocondiline.begin(); reaction_CLin.Change_taille((int)lili_CLin.size()); int j; for (i=lili_CLin.begin(),j=1 ; i != lili_CLin.end(); i++,j++,iti++) { reaction_CLin(j) = *i; // transfert des informations aux noeuds ReactStoc& reac = reaction_CLin(j); // pour simplifier // récup du noeud j du maillage i Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud); Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction // dans le cas où la réaction n'existe pas on l'ajoute // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité { if (!noe.Existe_ici(enu_reac)) // { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE); { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE); noe.PlusDdl(reac_ddl); } else // sinon il faut le bloquer car la réaction est imposée { noe.Change_fixe(enu_reac,true);}; // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 CalculTorseurReaction(tab_torseurReac(ttRGCLL((*iti).un)((*iti).deux)),noe,reac); }; // mise à jour de la réaction noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt }; // exportation en grandeurs globales: cas d'un blocage venant d'une CLL int taille_tors_bloqu = ttRG_noms_ref.Taille(); int taille_tors_bloquplus1 = taille_tors_bloqu +1; int taille_torsP1 = tab_torseurReac.Taille() + 1; {int il = 1; //ttRGCLL_noms_ref.begin(); for (int ia=taille_tors_bloquplus1;iaGrandeurGlobal(nom_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'exportation de composantes de torseur !! " << " la variable globale "<< (nom_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic); }; // 2) le moment for (int ic= 1; ic < dimaPlus1; ic++) {string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); // récup du pointeur de conteneur const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'exportation de composantes de torseur !! " << " la variable globale "<< (nom_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic); }; }; }; }; // fin encapsulation }; // calcul des reactions et stockage des valeurs // ceci dans le cas ou il n'y a pas de conditions lineaires appliquee // on se sert des valeurs sauvegardees lors de la mise en place des CL bloquees // cas : indique un type d'association de ddl // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un // a été fixé par l'utilisateur void LesCondLim::CalculReaction(LesMaillages * lesMail,LesReferences* lesRef ,const Nb_assemb& nb_casAssemb,int cas) { #ifdef UTILISATION_MPI // cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return ; #endif int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage Tableau tmc; // tableau de travail // on cree une liste de stockage intermediaire list lili; list indice_tabBloq; // tableau de travail ReactStoc elem; // l'element courant // on parcours le tableau de ddl bloques int tabBloqTaille =tabBloq.Taille(); for (int i=1;i<= tabBloqTaille;i++) { DdlLim& tabBloq_i = tabBloq(i); // recup de la reference correspondant au mot cle const ReferenceNE & ref = ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); if (ref.Indic() == 1) // ok pour les noeuds uniquement {int reftaille = ref.Taille(); for (int nn =1; nn<= reftaille;nn++) {int tabBloqitaille = tabBloq_i.Taille(); // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage int idebut=1; int ifinfin = tabBloqitaille;// début normale if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; for (int nd=idebut;nd<= ifinfin ;nd++) // calcul de la reaction { Ddl ddl = tabBloq_i.ElemLim(nd); Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); // on continue uniquement si le ddl du tableau de blocage est en service // et si pour le noeud c'est une variable if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) { // récup des enu_ddl équivalent au groupe tmc = MemeCombinaison(cas,ddl.Id_nom()); int tailletmc = tmc.Taille(); for (int itc=1;itc <= tailletmc;itc++) {// on boucle sur tous les ddl a imposer // calcul du pointeur correspondant au ddl cherche int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif if ((pt != -1) && (noe.En_service(tmc(itc)))) { elem.ddl = ddl; elem.ddl.Valeur() = condlim(nb_casAss).ValReact(pt); elem.numMail = ref.Nbmaille(); elem.numNoeud = ref.Numero(nn); elem.casAss = nb_casAss; lili.push_back(elem); indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq }; }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) }; //-- fin de for (int nn =1; nn<= reftaille;nn++) }; //-- fin de if (ref.Indic() == 1) }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) // on initialise le tableau des torseurs de réaction int tabtorsTaille = tab_torseurReac.Taille(); for (int i=1;i<= tabtorsTaille;i++) if (tab_torseurReac(i).existe_torseur_reac) tab_torseurReac(i).Zero_init_torseur(); // enregistrement list ::iterator i,ilfin = lili.end(); // def d'un iterator adoc reaction.Change_taille((int)lili.size()); // map_reaction.erase(map_reaction.begin(),map_reaction.end()); int j; list ::iterator i_taBloq=indice_tabBloq.begin(); for (i=lili.begin(),j=1 ; i != ilfin; i++,j++,i_taBloq++) {reaction(j) = *i; // map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)] // .push_back(&(reaction(j))); // transfert des informations aux noeuds ReactStoc& reac = reaction(j); // pour simplifier // récup du noeud j du maillage i Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud); Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction // dans le cas où la réaction n'existe pas on l'ajoute // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité { if (!noe.Existe_ici(enu_reac)) // { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE); { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE); noe.PlusDdl(reac_ddl); } else // sinon il faut le bloquer car la réaction est imposée { noe.Change_fixe(enu_reac,true);}; // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac); }; // mise à jour de la réaction noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt }; // on va maintenant exporter les composantes du tenseur vers des grandeurs globales int taille_tors_bloqu = ttRG_noms_ref.Taille(); int taille_tors_bloquplus1 = taille_tors_bloqu +1; int dima = ParaGlob::Dimension(); if(ParaGlob::AxiSymetrie()) // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les // dimension-1 coordonnées donc on décrémente dima--; // cas d'un blocage de ddl {int il = 1; for (int ia=1;iaGrandeurGlobal(nom_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'exportation de composantes de torseur !! " << " la variable globale "<< (nom_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic); }; // 2) le moment for (int ic= 1; ic < dimaPlus1; ic++) {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); // récup du pointeur de conteneur const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref)); #ifdef MISE_AU_POINT if (pointe == NULL) { cout << "\n *** pb dans l'exportation de composantes de torseur !! " << " la variable globale "<< (nom_ref) << ", n'est pas disponible, on ne peut pas continuer " << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic); }; }; }; }; // récupération des reactions= residu et stockage des valeurs // NB: après changement de repère, il n'y a plus que des ddl bloqués // cas : indique un type d'association de ddl // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un // a été fixé par l'utilisateur void LesCondLim::ReacApresCHrepere(Vecteur& residu,LesMaillages * lesMail, LesReferences* ,const Nb_assemb& nb_casAssemb,int ) { #ifdef UTILISATION_MPI // cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return ; #endif int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage Tableau tmc; // tableau de travail // on cree une liste de stockage intermediaire list lili; list indice_tabBloq; // tableau de travail ReactStoc elem; // l'element courant //----------- cas des ddl bloqués ----------------- // l'indice des ddl bloqués reste inchangé après chgt de repère on utilise donc les // réactions avant rotation par simplicité // a priori ce sont exactement les mêmes conditions qui existent avant et après chgt de repère // sauf la valeur de la réaction int nb_reac = reaction.Taille(); for (int i=1; i<= nb_reac; i++) if (reaction(i).casAss == nb_casAss) // si ce n'est pas le bon cas d'assemblage on ne fait rien { elem = reaction(i); Noeud & noe=lesMail->Noeud_LesMaille(elem.numMail,elem.numNoeud); elem.ddl.Valeur() = residu(noe.Position_ddl(elem.ddl.Id_nom(),nb_casAss) ); lili.push_back(elem); }; // ------- cas des CLL -------------- // contrairement aux cas des ddl boqués ici on ne peut pas utiliser reaction_CLin // car il y a une seule réaction dans le nouveau repère alors qu'il y en avait autant que de ddl // dans la CLL, dans le repère initial, donc on reparcours le tableau des CLL // on parcours le tableau des CLL // on boucle sur le tableau de conditions limites linéaires enregistré // et pour chaque element on impose une condition lineaire int tabTaille = tab_CLinApplique.Taille(); for (int i=1;i<= tabTaille; i++) {int sous_taille = tab_CLinApplique(i).Taille(); for (int j=1; j<= sous_taille; j++) { Condilineaire& condi = tab_CLinApplique(i)(j); // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 if (condi.Iddl() > -1) { if (condi.CasAssemb() == nb_casAssemb) { // la condition limite concerne uniquement un ddl pour chaque CLL // il s'agit du premier ddl, pour le premier noeud // on définit la réaction elem.ddl.Change_nom(condi.Tab_Enum()(1)); elem.ddl.Valeur() = residu(condi.Pt_t()(1)); elem.numMail = condi.TabNoeud()(1)->Num_Mail(); elem.numNoeud = condi.TabNoeud()(1)->Num_noeud(); elem.casAss = condi.CasAssemb().n; lili.push_back(elem); // on sauvegarde la réaction }; }; }; }; // enregistrement list ::iterator i; // def d'un iterator adoc reactionApresCHrepere.Change_taille((int)lili.size()); int j; for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++) {reactionApresCHrepere(j) = *i;}; }; // affichage sur la sortie sort des reactions void LesCondLim::Affiche_reaction(ofstream& sort,const LesMaillages * lesMail) const { #ifdef UTILISATION_MPI // cas d'un calcul //, seule le CPU 0 est concerné if (ParaGlob::Monde()->rank() != 0) return ; #endif // l'entete sort << "\n=========================================================================="; sort << "\n sortie des efforts generes par l\'exterieur sur les noeuds "; sort << "\n==========================================================================\n"; sort << "\n\n 1) les reactions individuelles \n "; // on balaie le tableau de reaction et on constitue une liste intermédiaire, pour éviter // de sortir des doublons int reactionTaille = reaction.Taille(); List_io li_inter; // Tableau reaction; // les reactions pour les ddl bloqués for (int i= 1; i<= reactionTaille;i++) li_inter.push_back(reaction(i)); li_inter.sort(); // on organise la liste li_inter.unique(); // on supprime les doublons // *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non // le contraire List_io ::iterator il,ilfin=li_inter.end(); for (il= li_inter.begin(); il != ilfin;il++) { sort << "\ncas assemb " << (*il).casAss << " maillage " << (*il).numMail <<", noeud " <<(*il).numNoeud << ", ddl = " << (*il).ddl.Nom() << ", valeur = " << (-(*il).ddl.Valeur()) ; }; // on s'occupe maintenant des torseurs de réactions globales si éventuellement il en existe sort << "\n\n\n=========================================================================="; sort << "\n 2) les torseurs globaux "; sort << "\n==========================================================================\n"; // au niveau des références, il est possible d'avoir une référence qui sert pour plusieurs conditions limites // aussi on va globaliser les torseurs de réaction en sortie int dima = ParaGlob::Dimension(); if(ParaGlob::AxiSymetrie()) // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les // dimension-1 coordonnées donc on décrémente dima--; int ttail = tab_torseurReac.Taille(); for (int i=1;i<= ttail;i++) { TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier if (torseurReac.existe_torseur_reac) {// tout d'abord l'affichage de l'entête if (torseurReac.bloque_ou_CLL) // cas où le torseur provient d'une condition ddl bloquée {DdlLim& tabBloq_i = tabBloq(*(ttorBloq(i).begin())); // pour simplifier (on ne prend que le // premier des bloqués), tous les autres ont le même nom de maillage et de ref sort << "\n"; if (tabBloq_i.NomMaillage() != NULL) sort << " nom_maillage " << *(tabBloq_i.NomMaillage()); sort << " nom_ref " << tabBloq_i.NomRef() << "\n F= "; } else // cas où le torseur provient d'une condition CLL {I_O_Condilineaire& iocondiline_i = tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier sort << "\n"; if (iocondiline_i.NomMaillage() != NULL) // cas où on considère les noms de maillage { int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier if (num_ref == 1) {// cas d'une référence principale de CLL const string& nom_maillage = *(iocondiline_i.NomMaillage()); sort << " nom_maillage " << nom_maillage << " nom_ref " << iocondiline_i.NomRef() << "_CLL "; } else {// cas d'une référence associé // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1 // qui correspond à la référence principale //debug //cout << "\n (*(ttorCLL(i).begin())).deux= " << (*(ttorCLL(i).begin())).deux << endl ; //fin debug const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux - 1); sort << " nom_maillage " << nom_maillage << " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1) << "_CLL "; } } else {// cas où on ne considère pas les noms de maillage int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier if (num_ref == 1) // cas d'une référence principale de CLL { sort << " nom_ref " << iocondiline_i.NomRef() << "_CLL "; } else // cas d'une référence associé // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1 // qui correspond à la référence principale { sort << " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1) << "_CLL "; }; }; sort << "\n F= "; }; // et maintenant l'affichage des infos torseurReac.resultante.Affiche(sort,ParaGlob::NbdigdoCA()); switch (dima) {case 1: break; // pas de moment en dimension 1 case 2: sort << "\n M=" << setprecision(ParaGlob::NbdigdoCA()) << torseurReac.moment(1); // la première composante est le moment break; case 3: sort << "\n M="; torseurReac.moment.Affiche(sort,ParaGlob::NbdigdoCA()); break; }; }; }; // sortie des réactions dues aux conditions linéaires sort << "\n\n\n=========================================================================="; sort << "\n 3) les reactions dues aux conditions lineaires "; sort << "\n==========================================================================\n"; // on balaie le tableau de reaction_CLin // *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non le contraire // non, j'ai l'impression qu'il ne faut pas ici changer de signe ??? à voir par la suite en fonction des résultats // si finalement ?? int reaction_CLinTaille = reaction_CLin.Taille(); for (int i= 1; i<= reaction_CLinTaille;i++) { sort << "\ncas assemb " << reaction_CLin(i).casAss << " maillage " << reaction_CLin(i).numMail <<", noeud " < > tab_indi(nb_maillage); // un tableau de travail for (int i= 1; i<= reactionTaille;i++) // on remplit le tableau d'adressage indirecte tab_indi(reaction(i).numMail).push_back(DeuxEntiers(i,reaction(i).numNoeud)); // on trie et on ordonne for (int i=1;i<=nb_maillage;i++) { list & indica = (tab_indi(i)); // pour simplifier indica.sort(); // ordonne en fonction du numéro de noeud list ::iterator ili,ilifin=indica.end(); // --- tout d'abord on sort une ref sur la liste des noeuds en réaction au cas ou sort << "\n # pour information la ref des noeuds concernes\n "; sort << "\n # nom_mail= "<NomMaillage(i) <<"\n# N_list_noe_en_react "; int compteur=0; int total_force=0; for (ili=indica.begin();ili != ilifin;ili++) // là on suit la progression des numéros de noeuds { ReactStoc& rea = reaction((*ili).un); int num_noeud = (*ili).deux; // le noeud considéré bool sortie_valide=false; // la sortie est validée ou non while (num_noeud == (*ili).deux) {switch (rea.ddl.Id_nom()) // on regarde les ddl { case X1 : sortie_valide=true;break; case X2 : sortie_valide=true;break; case X3 : sortie_valide=true;break; default: break; }; ili++; }; // arrivée ici il y a une incrémentation de trop, on revient en arrière ili--; if (sortie_valide) { total_force++; sort << num_noeud << " ";compteur++; if (compteur > 20) {sort << "\n"; compteur=0;}; }; }; // --- maintenant on sort les forces sort << "\n\n # --- les (" <& listCondLine,const Nb_assemb& nb_casAssemb,Vecteur* vec2) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return false ; #endif tempsCLL.Mise_en_route_du_comptage(); // temps cpu // on boucle sur le tableau et pour chaque element on impose une condition lineaire /// int tabTaille = tab.Taille(); bool modification = false; // init du retour list ::iterator il,ilfin = listCondLine.end(); for (il = listCondLine.begin();il != ilfin;il++) // for (int i=1;i<= tabTaille; i++) {Condilineaire& condi = (*il); // calcul des pointeurs d'assemblage condi.ConditionPourPointeursAssemblage(nb_casAssemb); // application de la condition condlim(nb_casAssemb.n).CondlineaireCHRepere ( matglob,vecglob,condi.Pt_t(),condi.Val(),condi.Beta(),vec2); modification=true; }; // affichage éventuelle de la matrice de raideur et du second membre if ((ParaGlob::NiveauImpression() >= 10) && (listCondLine.size() != 0)) { string entete = " affichage de la matrice apres changement de repere du aux conditions limites externes (ex contact)"; matglob.Affichage_ecran(entete); entete = " affichage du second membre apres changement de repere du aux conditions limites externes (ex contact) "; vecglob.Affichage_ecran(entete); }; tempsCLL.Arret_du_comptage(); // temps cpu // retour du fait qu'il y a eu ou non une modification faite return modification; }; // mise en place de condition externe lineaires en une opération // retour de la raideur et du second membre sans changement de repere // ramène si oui ou non, il y a eu un changement effectué // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob // mais sans sauvegarde (correspond par exemple à une partie de vecglob) bool LesCondLim::CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob ,list & listCondLine ,const Nb_assemb& nb_casAssemb,Vecteur* vec2) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées if (ParaGlob::Monde()->rank() != 0) return false; #endif tempsCLL.Mise_en_route_du_comptage(); // temps cpu // on boucle dans la liste et pour chaque element on impose une condition lineaire bool modification = false; // init du retour list ::iterator il,ilfin = listCondLine.end(); for (il = listCondLine.begin();il != ilfin;il++) {Condilineaire& condi = (*il); // calcul des pointeurs d'assemblage condi.ConditionPourPointeursAssemblage(nb_casAssemb); // application d'une condition linéaire seule, avec en retour, la situation de la condition linéaire // imposée, ramené dans le repère initial condlim(nb_casAssemb.n).CondiLineaireImposeComplet ( matglob,vecglob,condi.Pt_t(),condi.Val(),condi.Beta(),vec2); modification=true; }; // affichage éventuelle de la matrice de raideur et du second membre if ((ParaGlob::NiveauImpression() >= 10) && (listCondLine.size() != 0)) { string entete = " affichage de la matrice apres application CLL externes (ex contact) "; matglob.Affichage_ecran(entete); entete = " affichage du second membre apres apres application CLL externes (ex contact) "; vecglob.Affichage_ecran(entete); }; tempsCLL.Arret_du_comptage(); // temps cpu // retour du fait qu'il y a eu ou non une modification faite return modification; }; //initialisation, mise a zero des sauvegarde void LesCondLim::InitSauve(const Nb_assemb& nb_casAssemb) { condlim(nb_casAssemb.n).EffaceSauvegarde(); // blocages : second membre et matrice, condlim(nb_casAssemb.n).EffaceCoLin(); // conditions lineaires // puis les torseurs de réactions int taille = tab_torseurReac.Taille(); for (int i=1; i<= taille; i++) if (tab_torseurReac(i).existe_torseur_reac) tab_torseurReac(i).Zero_init_torseur(); }; //----- lecture écriture dans base info ----- // le cas d'assemblage n'est pas sauvegardé, car ce n'est pas une variable // qui appartient réellement à la classe // 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 LesCondLim::Lecture_base_info(ifstream& ent,const int cas,LesReferences& ,LesCourbes1D& ,LesFonctions_nD& lesFonctionsnD) { // les conditions linéaires qui varies par exemples dues au contact sont stockées // autre part, dans LesContacts par exemple string toto; switch (cas) { case 1: { cout << "== lecture des conditions limites \n"; // lecture du type et vérification string nomtype; ent >> nomtype; if (nomtype != "****LesCondLim") Sortie(1); // lecture des différents tableaux ent >> toto >> tabBloq >> toto >> tabInit >> toto >> tab_iocondiline >> toto >> reaction >> toto >> reaction_CLin; // dimensionnement du tableau des torseurs résultants LesCondLim::DimensionneTorseurs(); break; } case 2: {// on lit les grandeurs relatives aux réactions ent >> toto; reaction.Entree(ent); ent >> toto; reaction_CLin.Entree(ent); // lectue des temps cpu de l'algo: ent >> toto >> tempsCL; ent >> toto >> tempsCLL; break; } default: { cout << "\n **** erreur !! cas non prevu: cas = " << cas << "\n LesCondLim::Lecture_base_info(..."; Sortie(1); } }; // on met à jour le tableau map_reaction // map_reaction.erase(map_reaction.begin(),map_reaction.end()); // int tail_reaction=reaction.Taille(); // for (int j=1; j<=tail_reaction; j++) // { map_reaction["mail"+ChangeEntierSTring(reaction(j).numMail) // +"noeud"+ChangeEntierSTring(reaction(j).numNoeud)].push_back(&(reaction(j))); // }; }; // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void LesCondLim::Ecriture_base_info(ofstream& sort,const int cas) { // les conditions linéaires qui varies par exemples dues au contact sont stockées // autre part, dans LesContacts par exemple switch (cas) { case 1: {// écriture du type sort << "\n ****LesCondLim \n"; // écriture des différents tableaux sort << " blocage " << tabBloq; sort << " initialisation " << tabInit; sort << " CLL_en_entree " << tab_iocondiline; sort << " reactions " << reaction; sort << " reac_CLineaire " << reaction_CLin << " "; break; } case 2: {// on sort les grandeurs relatives aux réactions // en fait les réactions sont également sauvé aux noeuds mais peut-être que ce sera utile // d'avoir ici le type réaction stocké ?? donc on laisse sort << " reac_ddl_bloque "; reaction.Sortir(sort); sort << " reac_CLineaire "; reaction_CLin.Sortir(sort); sort << " "; // écriture des temps cpu de l'algo: sort << "\n tps_cpu_CL " << tempsCL; sort << "\n tps_cpu_CLL " << tempsCLL; break; } default: { cout << "\n **** erreur !! cas non prevu: cas = " << cas << "\n LesCondLim::Ecriture_base_info(..."; Sortie(1); } }; };