// 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 "ReferenceNE.h" #include "ReferenceAF.h" #include "CharUtil.h" #include "TypeQuelconqueParticulier.h" // retourne la liste des types de ddl actuellement imposés // aux noeuds pour chaque maillage, la liste est exhaustive // elle contiend tous les types au moins une fois utilisée // cela ne signifie pas que le ddl en question soit présent // pour tous les noeud du maillage considéré // - le tableau de retour est indicé par le numéro de maillage correspondant // - il y a une liste par maillage Tableau > LesCondLim::Les_type_de_ddl_en_reaction() const { // définition du tableau de retour Tableau > tab_li(nb_maillage); // on boucle sur les réactions en cours pour remplir le tableau int nb_reac=reaction.Taille(); for (int i=1;i<=nb_reac;i++) { List_io & li=tab_li(reaction(i).numMail); Ddl_enum_etendu ddl_enu = (reaction(i).ddl.Id_nom()); if (find(li.begin(),li.end(),ddl_enu) == li.end()) li.push_back(ddl_enu); }; // retour du tableau de listes return tab_li; }; /* // retourne les réactions aux conditions limites à un noeud noe d'un maillage mail // en paramètre il y a un pointeur sur la liste de retour, pour éviter la création // d'une liste intermédiaire // s'il n'y a pas de conditions limites : retour d'une liste vide const list& LesCondLim::Reaction_noeud_mail(int numNoeud,int numMail) const { string cle("mail"+ChangeEntierSTring(numMail)+"noeud"+ChangeEntierSTring(numNoeud)); map < string, list , std::less >::const_iterator it = map_reaction.find(cle); if (it != map_reaction.end()) { return (*it).second;}; // sinon pas d'existence donc retour d'une liste vide const list li; // construction d'une liste vide return li; }; */ // retourne la liste des torseurs de réaction actuellement actif pour les maillages // appelons tab_lili la liste: // - tab_lili(i) concerne le maillage nb i // - les éléments de tab_lili(i) sont les noms des références qui conduisent à un torseur de réaction // actif, et un indice de gestion utilisé par LesCondLim pour retrouver // rapidemment les informations Tableau < List_io > LesCondLim::TabListTorseurReaction(const LesMaillages & lesmail) const { // def de la grandeur de retour Tableau < List_io > tab_lili(nb_maillage); string nom; // une variable de travail // on balaie le tableau des torseur int ttail = tab_torseurReac.Taille(); // tabBloq, tab_iocondiline et tab_torseurReac n'ont pas la même dimension for (int i=1;i<= ttail;i++) { TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier if (torseurReac.existe_torseur_reac) {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 if (tabBloq_i.NomMaillage() != NULL) { const string& nom_maillage = *(tabBloq_i.NomMaillage()); // nom de maillage lue tab_lili(lesmail.NumMaillage(nom_maillage)).push_back(String_et_entier(tabBloq_i.NomRef(),i)); } else {tab_lili(1).push_back(String_et_entier(tabBloq_i.NomRef(),i)); }; } else // cas où le torseur provient d'une condition CLL {I_O_Condilineaire& iocondiline_i = tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier 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()); tab_lili(lesmail.NumMaillage(nom_maillage)).push_back (String_et_entier(iocondiline_i.NomRef()+"_CLL",i)); } 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 const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux-1); tab_lili(lesmail.NumMaillage(nom_maillage)).push_back (String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i)); }; } 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 tab_lili(1).push_back(String_et_entier(iocondiline_i.NomRef()+"_CLL",i)); } 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 tab_lili(1).push_back (String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i)); }; }; }; }; }; // retour des infos return tab_lili; }; // affichage et definition interactive des commandes pour les conditions limites CL void LesCondLim::Info_commande_LesCondLim1(UtilLecture & entreePrinc) { cout << "\n# ----- definition des conditions limites cinematiques ----- "; bool plusieurs_maillages = false; string rep="_"; ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier // écriture de l'entête sort << "\n blocages #------------# " << "\n#-----------------------------------------------------------" << "\n# nom du maillage | Ref noeud | Blocages" << "\n#-----------------------------------------------------------"; // def des conditions try {cout << "\n cas d'un seul maillage (par defaut) : rep o " << "\n cas de plusieurs maillages : rep n "; rep = lect_return_defaut(true,"o"); if (rep == "n") { plusieurs_maillages = true; cout << "\n --> les prochaines CL seront associees a un nom de maillage ";}; rep="_"; // init // boucle globale while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { cout << "\n (0 ou f) (fin) " << "\n (1) def d'une nouvelle condition " << "\n "; rep = lect_return_defaut(false,"f"); if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe break; int num = ChangeEntier(rep); bool choix_valide=false; if ((num >= 0)&&(num<=1)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; }; switch (num) { case 0: // sortie { break;} // normalement cela a déjà été filtré avant case 1: // def d'une liste d'elements associe a un nom de loi { DdlLim unddl; // init unddl.Info_commande_DdlLim(sort,plusieurs_maillages); break; } default: cout << "\n le cas "< les prochaines CLL seront associees a un nom de maillage ";}; rep="_"; // init // boucle globale while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { cout << "\n (0 ou f) (fin) " << "\n (1) def d'une nouvelle condition " << "\n "; rep = lect_return_defaut(false,"f"); if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe break; int num = ChangeEntier(rep); bool choix_valide=false; if ((num >= 0)&&(num<=1)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; }; switch (num) { case 0: // sortie { break;} // normalement cela a déjà été filtré avant case 1: // def d'une liste d'elements associe a un nom de loi { I_O_Condilineaire uneCLL; // init uneCLL.Info_commande_conditionLineaire(sort,plusieurs_maillages); break; } default: cout << "\n le cas "< les prochaines CL seront associees a un nom de maillage ";}; rep="_"; // init // boucle globale while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { cout << "\n (0 ou f) (fin) " << "\n (1) def d'une nouvelle condition " << "\n "; rep = lect_return_defaut(false,"f"); if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe break; int num = ChangeEntier(rep); bool choix_valide=false; if ((num >= 0)&&(num<=1)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; }; switch (num) { case 0: // sortie { break;} // normalement cela a déjà été filtré avant case 1: // def d'une liste d'elements associe a un nom de loi { DdlLim unddl; // init unddl.Info_commande_DdlLim(sort,plusieurs_maillages); break; } default: cout << "\n le cas "< tmc = MemeCombinaison(cas,enu); int taille = tmc.Taille(); for (int i=1;i<=taille;i++) {if(tmc(i) != enu) // on ne traite que les cas différents du ddl principal { if (noe.Existe_ici(tmc(i))) { // le ddl existe déjà, on le met à fixe // mais on ne change pas sa valeur if (fixe) { noe.Change_fixe(tmc(i),true);} // en fait on ne met pas à libre si fixe en false, on ne vérifie pas qu'il y a superposition // de plusieurs initialisations en libre, celle-ci pouvant venir de plusieurs raisons que l'on ne peut // pas gérer ici : par exemple au moment de la création des éléments il y a mise en place des ddl à libre // avant l'initialisation donc si l'on impose par exemple la vitesse, X sera en souslibre !! // else // { noe.Change_fixe(tmc(i),false);} } else // sinon on le cré, et on met à zéro { if (fixe) { if (une_variable) { Ddl inter(tmc(i),0.0,HSFIXE); noe.PlusDdl(inter);} else { Ddl inter(tmc(i),0.0,HS_LISIBLE_FIXE); noe.PlusDdl(inter);}; } else { if (une_variable) { Ddl inter(tmc(i),0.0,HSLIBRE); noe.PlusDdl(inter);} else { Ddl inter(tmc(i),0.0,HS_LISIBLE_LIBRE); noe.PlusDdl(inter);}; }; noe.Change_val_0(tmc(i),0.); noe.Change_val_t(tmc(i),0.); if (choix) noe.Change_val_tdt(tmc(i),0.); }; }; }; }; //-- fin du cas ou le ddl fait partie d'une combinaison }; // mise en place du blocage sur un ddl ou un groupe si besoin est void LesCondLim::Mise_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas) { // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl // on vérifie que le ddl appartient au groupe sinon traitement simple if (Dans_combinaison(cas,enu)) { // le ddl appartient au groupe, on modifie globalement // récup des enu_ddl équivalent au groupe Tableau tmc = MemeCombinaison(cas,enu); int taille = tmc.Taille(); for (int i=1;i<=taille;i++) noe.Change_fixe(tmc(i),true); // le ddl du tableau des ddl bloqués est mis en service (ddlbloqu.ElemLim(nd)).Met_en_service(); } else // le ddl fixé n'appartient pas au groupe on le traite isolément { noe.Change_fixe(enu,true); // le noeud est fixé // le ddl du tableau est mis en service (ddlbloqu.ElemLim(nd)).Met_en_service(); }; }; // on retire le blocage sur un ddl ou un groupe si besoin est void LesCondLim::Retire_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas) { // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl // on vérifie que le ddl appartient au groupe sinon traitement simple if (Dans_combinaison(cas,enu)) { // le ddl appartient au groupe, on modifie globalement // récup des enu_ddl équivalent au groupe Tableau tmc = MemeCombinaison(cas,enu); int taille = tmc.Taille(); for (int i=1;i<=taille;i++) noe.Change_fixe(tmc(i),false); // le ddl du tableau des ddl bloqués est mis hors service (ddlbloqu.ElemLim(nd)).Met_hors_service(); } else // le ddl fixé n'appartient pas au groupe on le traite isolément { noe.Change_fixe(enu,false); // le noeud est libéré // le ddl du tableau est mis hors service (ddlbloqu.ElemLim(nd)).Met_hors_service(); }; }; // vérification qu'il n'y a pas de surcharge de blocage // choix indique si l'on vérifie à t ou à tdt void LesCondLim::Verif_surcharge_blocage (const LesMaillages * lesMail,const LesReferences* lesRef,const double& temps,int cas) { // prépa retour bool erreur_blocage = false; Tableau tmc; // tableau de travail 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() == 4) && // dans le cas des conditions de tangence sur (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) // les arrêtes on n'applique pas ces vérifs ) {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++) {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; Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); // on regarde si l'on a fixé plusieurs fois ou libéré plusieurs foix // 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())); // récup des enu_ddl équivalent au groupe, pour l'instant on n'a que la combinaison 1 qui comporte plus d'un élément if (Dans_combinaison(cas,ddl.Id_nom())) {tmc = MemeCombinaison(cas,ddl.Id_nom());} else // sinon pour l'instant on fait comme si cas == 0 c'est à dire pas de combinaison {tmc = MemeCombinaison(0,ddl.Id_nom());}; int tailletmc = tmc.Taille(); for (int itc=1;itc <= tailletmc;itc++) {if (noe.Ddl_sous_ou_sur_fixe(tmc(itc))) // cas d'un problème éventuel { // message d'avertissement if (ParaGlob::NiveauImpression() >= 6) cout << "\n ***** ATTENTION *****, le ddl " << ddl.Nom() << " du noeud " << noe.Num_noeud() << " du maillage " << lesMail->NomMaillage(noe.Num_Mail()) << " est bloque plusieurs fois"; if (ParaGlob::NiveauImpression() >= 7) cout << ", cela indique que plusieurs conditions limites sont supperposees"; if (ParaGlob::NiveauImpression() >= 8) { cout << " \n temps = " << temps << ", reference de blocage, et ddl limite correspondant"; ref.Affiche(); tabBloq_i.Affiche(); cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; } // remise à normal du ddl pour que le calcul puisse continuer noe.Retour_a_la_normal_sur_ou_sous_fixe(tmc(itc)); erreur_blocage = true; // pour un traitement global d'erreur éventuel }; }; //-- fin du for (int itc=1;itc <= tailletmc;itc++) }; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++) }; //-- fin du for (int nn =1; nn<= reftaille;nn++) }; //-- fin du if (!((ref.Indic() == 4) &&(tabBloq_i.TypeDeCL()==TANGENTE_CL) ) }; //-- fin du for (int i=1;i<= tabBloqTaille;i++) }; // fourni la liste des ddl associé de même dim, pour un du groupe et en fonction du cas d'association // ramène une référence sur tab_travail qui est mis à jour Tableau & LesCondLim::Ddl_associe (Ddl& ddl,Noeud& noe,Tableau & tab_travail,int cas) { // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); Enum_ddl enu = ddl.Id_nom(); // pour simplifier // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl // on vérifie que le ddl appartient au groupe sinon traitement simple if (Dans_combinaison(cas,enu)) { // le ddl appartient au groupe, on modifie globalement // récup des enu_ddl équivalent au groupe Tableau tmc = MemeCombinaison(cas,enu); int taille = tmc.Taille(); for (int i=1;i<=taille;i++) { ddl.Change_nom(tmc(i)); tab_travail(i) = ddl; } } else // le ddl fixé n'appartient pas au groupe on le traite isolément { tab_travail.Change_taille(1); tab_travail(1) = ddl; }; return tab_travail; }; // cas particulier des mouvements solides, dans le second passage pour la méthode MiseAJour_tdt void LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(const double& mult_gene,LesMaillages * lesMail ,const double& deltat,int cas ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD,const double& coef ,DdlLim& tabBloq_i,const ReferenceNE & ref,const double& temps,Enum_ddl en_ddl) { bool tous_les_blocages = true; if (en_ddl != NU_DDL) tous_les_blocages = false; int reftaille = ref.Taille(); 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--; // 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)) return; bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier if (!actif_pour_le_temps) return; // je ne vois pas trop pourquoi, mais semble cohérent avec le prog général (à voir) // petite vérif int tabBloqitaille = tabBloq_i.Taille(); // normalement il y a uniquement les déplacements #ifdef MISE_AU_POINT if (tabBloqitaille != dima) { cout << "\nErreur : le nombre de ddl bloque pour un mouvement solide doit etre egale a la dimension du pb " << " ici ParaGlob::Dimension() = " << dima << " et le nombre de ddl bloque = " << tabBloqitaille ; cout << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... "; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); Sortie(1); }; #endif // --- dans le cas où il y a des centres de rotation qui sont des positions de noeud, on renseigne // a) récupération des centres de rotation noeud, éventuellement const list & lis_centre_noeud = (tabBloq_i.MouvementSolide())->Liste_ident_centreNoeud(); if (lis_centre_noeud.size() != 0) { list ::const_iterator ict,ictfin=lis_centre_noeud.end(); list list_coor; // liste des coordonnées des noeuds centre de rotation for (ict = lis_centre_noeud.begin();ict!=ictfin;ict++) {if ((*ict).nom == "") // cas où on n'a pas de nom de maillage { list_coor.push_back(lesMail->Noeud_LesMaille(1, (*ict).n).Coord2()); } else // cas où on a plusieurs maillages { int num_maill= lesMail->NumMaillage((*ict).nom); list_coor.push_back(lesMail->Noeud_LesMaille(num_maill, (*ict).n).Coord2()); }; }; // b) maintenant on passe l'info au mouvement solide (tabBloq_i.MouvementSolide())->RenseigneCentreNoeud(list_coor); }; // maintenant soit le ddlLim est actif ou il change de statut: actif à non actif // on boucle sur les noeuds de la référence for (int nn =1; nn<= reftaille;nn++) {// ici on travaille sur les dima ddl de déplacements en même temps: // mais on se sert du premier comme indicateur Ddl ddl = tabBloq_i.ElemLim(1); // le premier ddl normalement est UX // on fait une manip sur les UX <-> Xi pour distinguer les cas méca du solide et les autres Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); if (noe.Existe_ici(X1)) // cas de deplacements imposes en entraine on change donc 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;}; if (a_considerer) { // def du point qui contiendra les coordonnées finales après rotation Coordonnee M(dima); // traitement en fonction du cas où il y courbe de charge ou pas if ((tabBloq_i.Nom_courbe(1) != "")&&(tabBloq_i.NomF_charge(1) == "")) { // cas d'une courbe de charge, récup de la courbe // pour les mouvements solides la courbe de charge et l'échelle sont stockées dans le premier ddl Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1)); if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent { // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat M = noe.Coord1(); // on travaille donc à partir des coordonnées à t double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1) * ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ; (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); } else { // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent // et ici on considère la totalité du chargement de 0 au temps actuel M = noe.Coord0(); // on travaille donc avec les coordonnées initiales double amplitude = mult_gene * (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(1); (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); }; } else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) == "")) { // cas d'une fonction nD de charge, récup Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1)); // 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 d'un mouvement solide " << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... "; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); Sortie(1); }; #endif 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 d'un mouvement solide 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_second_passage_mvtSolide(... "; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); Sortie(1); } else { // la fonction donne la valeur de l'amplitude de 0 au temps présent // et ici on considère la totalité du chargement de 0 au temps actuel M = noe.Coord0(); // on travaille donc avec les coordonnées initiales double amplitude = mult_gene * (tab_ret(1)) * tabBloq_i.Echelle_courbe(1); (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); }; } else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) != "")) { // cas d'une fonction nD de charge, récup Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1)); // 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 d'un mouvement solide " << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... "; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); Sortie(1); }; #endif // idem pour la courbe 1D Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1)); if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent { // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat M = noe.Coord1(); // on travaille donc à partir des coordonnées à t double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1) * tab_ret(1) * ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ; (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); } else { // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent // et ici on considère la totalité du chargement de 0 au temps actuel M = noe.Coord0(); // on travaille donc avec les coordonnées initiales double amplitude = mult_gene * (pt_courbe->Valeur(temps)) * tab_ret(1) * tabBloq_i.Echelle_courbe(1); (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); }; } else // cas d'un mouvement à valeur fixe, on calcul l'accroissement par rapport au pas précédent // coef intègre le multiplicateur global: mult_gene, et intègre l'acroissement par rapport au pas précédent { M = noe.Coord1(); (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,coef); }; // maintenant on s'occupe de la mise à jour ou non des positions du noeud for (int nd=1;nd<= tabBloqitaille ;nd++) // en fait ici nd =1 pour UX, =2 pour UY et =3 pour UZ {Ddl ddl = tabBloq_i.ElemLim(nd); if (noe.Existe_ici(X1)) // cas de deplacements imposes en entraine on change donc les Ui en Xi ddl.Change_nom(UxyzXi(ddl.Id_nom())); Enum_ddl ddlenu= ddl.Id_nom(); // 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, mais si on arrive ici le temps est forcément actif if ( ( une_variable && noe.En_service(ddlenu)) ||(!une_variable) ) { // gestion des surcharges de blocage // au second passage on fixe les ddl actifs Mise_cl(nd,tabBloq_i,ddlenu,noe,cas); // on met à jour les coordonnées finales noe.Change_val_tdt(ddlenu,M(nd)); // car nd =1 pour UX, =2 pour UY, =3 pour UZ };//-- fin du test si le ddl du noeud est en service }; //-- fin de la boucle sur tabBloq_i };//-- fin du test si le noeud est à considérer ou pas }; //-- fin de la boucle sur nn }; // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 // --> pour au final obtenir le torseur des efforts globaux résultant de l'application d'un DdlLim void LesCondLim::CalculTorseurReaction(TorseurReac& tr, const Noeud& noe, ReactStoc& reac) { int dimension = 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 dimension--; switch (dimension) { case 1: // pas de moment, et uniquement une résultante suivant x if (reac.ddl.Id_nom() == X1) tr.resultante(1) += reac.ddl.Valeur(); break; case 2 : // un moment autour de z, et deux composantes de résultante // le moment est en dim 2, on stocke le moment dans la première composante !!! switch (reac.ddl.Id_nom()) { case X1: { tr.resultante(1) += reac.ddl.Valeur(); tr.moment(1) -= noe.Valeur_tdt(X2) * reac.ddl.Valeur(); // correspond à z break; }; case X2: { tr.resultante(2) += reac.ddl.Valeur(); tr.moment(1) += noe.Valeur_tdt(X1) * reac.ddl.Valeur(); // correspond à z break; }; default: break; } break; case 3 : // 3 composante de moment et de résultante switch (reac.ddl.Id_nom()) { case X1: { tr.resultante(1) += reac.ddl.Valeur(); tr.moment(2) += noe.Valeur_tdt(X3) * reac.ddl.Valeur(); tr.moment(3) -= noe.Valeur_tdt(X2) * reac.ddl.Valeur(); break; }; case X2: { tr.resultante(2) += reac.ddl.Valeur(); tr.moment(1) -= noe.Valeur_tdt(X3) * reac.ddl.Valeur(); tr.moment(3) += noe.Valeur_tdt(X1) * reac.ddl.Valeur(); break; }; case X3: { tr.resultante(3) += reac.ddl.Valeur(); tr.moment(1) += noe.Valeur_tdt(X2) * reac.ddl.Valeur(); tr.moment(2) -= noe.Valeur_tdt(X1) * reac.ddl.Valeur(); break; }; default: break; } break; // les autres cas ne sont pas pris en compte }; }; // mise en place des conditions linéaires imposées par les données d'entrée // expression de la raideur et du second membre dans un nouveau 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::CoLinCHrepere_int(Mat_abstraite & matglob,Vecteur& vecglob ,const Nb_assemb& nb_casAssemb,Vecteur* vec2) { #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 true; #endif // on boucle sur le tableau de conditions limites linéaires enregistré // et pour chaque element on impose une condition lineaire bool modification = false; // init du retour 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); //debug //cout << "\n LesCondLim::CoLinCHrepere_int " << condi; //fin debug // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 if (condi.Iddl() > -1) { // 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(),0.,vec2); // ancienne version // la valeur imposée est systématiquement 0 comme pour le cas des autres conditions bloquée // car la résolution donnera delta_ddl' qui doit être null pour les ddl imposés modification=true; }; }; }; // affichage éventuelle de la matrice de raideur et du second membre if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0)) { string entete = " affichage de la matrice apres changements de reperes dus aux conditions lineaires "; matglob.Affichage_ecran(entete); entete = " affichage du second membre apres changements de reperes dus aux conditions lineaires "; vecglob.Affichage_ecran(entete); }; // retour du fait qu'il y a eu ou non une modification faite return modification; }; // effacement du marquage de ddl bloque du au conditions lineaire extérieures (hors du contact par exemple) void LesCondLim::EffMarque() { // préparation // on boucle sur le tableau des conditions limites linéaires imposées réellement int tabTaille = tab_CLinApplique.Taille(); for (int icondli=1;icondli<= tabTaille; icondli++) { Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli); int nbcondi = t_condiAppli.Taille(); // on boucle sur les conditions for (int ico=1;ico<=nbcondi;ico++) { Condilineaire & condi = t_condiAppli(ico); // pour simplifier // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 if (condi.Iddl() > -1) { // récup du noeud principal Noeud * noe=condi.Noe(); noe->Change_fixe(condi.Tab_Enum()(1),false); }; }; }; }; // def de la largeur de bande en fonction des conditions linéaire limite en entrée // casAssemb : donne le cas d'assemblage en cours // les condi linéaires ne donnent pas des largeurs de bande sup et inf égales !!! // demi = la demi largeur de bande , // total = le maxi = la largeur sup + la largeur inf +1 // cumule = la somme des maxis, ce qui donnera la largeur finale, due à des multiples multiplications: une par conditions linéaires // dans le cas où on tiens compte des conditions linéaires par rotation (c-a-d sans multiplicateur ou pénalisation) // en retour, ramène un booleen qui : // = true : si la largeur de bande en noeud est supérieure à 1 // = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur // en noeud bool LesCondLim::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb ,LesMaillages * lesMail,LesReferences* lesRef,int& cumule) { demi = total = cumule = 0; // initialisation bool retour = false; // par défaut int nb_ass = casAssemb.n; // on boucle sur le tableau et pour chaque condition int tabTaille = tab_iocondiline.Taille(); // le nombre de condition for (int icondli=1;icondli<= tabTaille; icondli++) {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier // recup de la reference principal correspondant au mot cle const ReferenceNE & refp = ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); int nb_n_princ = refp.Taille(); // recup du tableau des références secondaires associées si elles existent const Tableau & nomRefassocie = iocondiline_i.ReferenceAssociees(); const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); int tailrefasso = nomRefassocie.Taille(); Tableau * > tab_numNoeud_associe(tailrefasso); Tableau tab_numMail_associe(tailrefasso); if (tailrefasso != 0) {retour = true; // comme il y a des ref associés, la largeur en noeud sera > à 1 for (int k=1;k<=tailrefasso;k++) {const string * nom_maillage=NULL; if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); const ReferenceNE & refasso = ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés tab_numMail_associe(k)= refasso.Nbmaille(); }; }; // on boucles sur les noeuds de la ref principale int tail_t_noe = tailrefasso+1; Tableau t_noe(tail_t_noe); // tableau de travail // dans la boucle qui suit on définit t_noe, c'est à dire l'ensemble des noeuds // concernés par la condition linéaire. // puis avec ce tableau, on en déduit la largeur de bande associée for (int in=1;in<=nb_n_princ;in++) { // récup du noeud principal Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); t_noe(1)= &noe; // on ne continue que si le type de ddl de la condition limite est actif pour le noeud // et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier if (enu_condline==UX) enu_condline = X1; // les ui sont géré avec les xi if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline)) {// récupération des noeuds associés, on utilise le même indice dans les ref associées que // dans la ref principale for (int ia = 1;ia<=tailrefasso;ia++) t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); // maintenant on va effectivement pouvoir calculer la largeur de bande correspondant // aux noeuds du tableau t_noe // 1) on a par défaut au moins une relation entre les ddl du noeud principal int diprinc = noe.NB_ddl_actif_casAssemb(nb_ass); if ( diprinc-1 > demi) demi = diprinc-1; if ( (2*diprinc-1) > total) total = 2*diprinc-1; cumule += 2*diprinc-1; // 2) maintenant on s'occupe de la relation entre les différents noeuds de numéros différencts int maxiPourLaCondition=0; // stocke le maxi pour chaque condition linéaire for (int inoe=1; inoe<= tail_t_noe;inoe++) for ( int jnoe=inoe+1; jnoe<=tail_t_noe;jnoe++) { Noeud & nne = *(t_noe(inoe)); Noeud & nno = *(t_noe(jnoe)); int di=0; if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass)) { di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass) + nne.NB_ddl_actif_casAssemb(nb_ass); } else { di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass) + nno.NB_ddl_actif_casAssemb(nb_ass); }; if ( di > demi) demi = di; if ( di > maxiPourLaCondition) maxiPourLaCondition = di; if ( di > total) total = di; // cumule += di; }; cumule += maxiPourLaCondition; }; }; // -- fin de la boucle sur les noeuds de la liste principale }; // -- fin de la boucle sur le tableau des conditions linéaire // prise en compte de la diagonale demi += 1; total += 1; // retour return retour; }; // dimensionnement du tableau des torseurs ainsi que des tableaux ttRG et ttorBloq // en fonction de tabBloq (utilisé plusieurs fois), puis de ttRGCLL en fonction de tab_iocondiline void LesCondLim::DimensionneTorseurs() { // dimensionnement du tableau des torseurs résultants // 1) on s'occupe tout d'abord des ddl bloqués int taille = tabBloq.Taille(); ttRG.Change_taille(taille); 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--; // on remplit le tableau ttRG list li_nomRef; // liste de travail: list li_nomRef_CL; // idem, mais spécifique aux CL // sert ensuite pour définir ttRG_noms_ref int taille_tors=0; // on en profite pour définir un tableau de nom de ref qui contiendra les infos // en string nécessaires pour cibler les composantes du torseur, externalisées comme // grandeurs globales for (int i=1;i<=taille;i++) if (tabBloq(i).Existe_ici_un_deplacement()) {// on a un candidat possible, on regarde si la référence n'existe pas Deux_String candid(tabBloq(i).NomRef(),tabBloq(i).NomRef()); // le premier string ici est pour remplir string nom_Ref_CL(tabBloq(i).NomRef()); bool avec_nom_maillage=false; if (tabBloq(i).NomMaillage() != NULL) {candid.nom1 = *(tabBloq(i).NomMaillage());avec_nom_maillage=true; nom_Ref_CL = *(tabBloq(i).NomMaillage()) +"_"+ nom_Ref_CL; }; list ::iterator ili,ilifin=li_nomRef.end(); int it=1; // future position dans le tableau tab_torseurReac for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++) if (*ili == candid) break; if (ili == li_nomRef.end()) {// aucun élément trouvé, on ajoute un nouveau li_nomRef.push_back(candid); li_nomRef_CL.push_back(nom_Ref_CL); taille_tors++; ttRG(i)=taille_tors; } else // on a trouvé un élément identique déjà existant de numéro it {ttRG(i)=it;}; }; // 2) puis on s'occupe des CLL int taille_tors_CLL=0; list li_nomRef_CLL; // liste de travail, mais spécifique aux CLL // sert ensuite pour définir ttRGCLL_noms_ref // on boucle sur le tableau initiale des conditions lineaires en entrée int tabCLLTaille = tab_iocondiline.Taille(); ttRGCLL.Change_taille(tabCLLTaille); // premier dimensionnement // on en profite pour définir un tableau de nom de ref qui contiendra les infos // en string nécessaires pour cibler les composantes du torseur, externalisées comme // grandeurs globales for (int icondli=1;icondli<= tabCLLTaille; icondli++) {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier // on regarde s'il faut considérer la condition linéaire, en fonction de en_ddl Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1))) {// récup des références secondaires éventuelles const Tableau & tabnomRef = iocondiline_i.ReferenceAssociees(); int tabnomRefTaille = tabnomRef.Taille(); const Tableau & nom_mail_associe = iocondiline_i.NomMaillageAssociees(); // second dimensionnement ttRGCLL(icondli).Change_taille(tabnomRefTaille+1); // maintenant on rempli le tableau // a) tout d'abord la ref principal (on encapsule) {Deux_String candid(iocondiline_i.NomRef()+"CLL",iocondiline_i.NomRef()+"CLL"); string nom_Ref_CLL(iocondiline_i.NomRef()+"CLL"); bool avec_nom_maillage=false; if (iocondiline_i.NomMaillage() != NULL) {candid.nom1 = *(iocondiline_i.NomMaillage());avec_nom_maillage=true; nom_Ref_CLL = *(iocondiline_i.NomMaillage()) +"_"+ nom_Ref_CLL; }; // on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un list ::iterator ili,ilifin=li_nomRef.end(); int it=1; // future position dans le tableau tab_torseurReac for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++) if (*ili == candid) break; if (ili == li_nomRef.end()) {// aucun élément trouvé, on ajoute un nouveau li_nomRef.push_back(candid); li_nomRef_CLL.push_back(nom_Ref_CLL); taille_tors++; taille_tors_CLL++; ttRGCLL(icondli)(1)=taille_tors; } else // on a trouvé un élément identique déjà existant de numéro it {ttRGCLL(icondli)(1)=it; }; }; // fin encapsulage // b) maintenant on regarde les références secondaires for (int ir=1;ir<=tabnomRefTaille;ir++) { Deux_String candid(tabnomRef(ir)+"CLL",tabnomRef(ir)+"CLL"); string nom_Ref_CLL(tabnomRef(ir)+"CLL"); if (iocondiline_i.NomMaillage() != NULL) {candid.nom1 = nom_mail_associe(ir); nom_Ref_CLL = nom_mail_associe(ir) +"_"+ nom_Ref_CLL; }; // on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un list ::iterator ili,ilifin=li_nomRef.end(); int it=1; // future position dans le tableau tab_torseurReac for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++) if (*ili == candid) break; if (ili == li_nomRef.end()) {// aucun élément trouvé, on ajoute un nouveau li_nomRef.push_back(candid); li_nomRef_CLL.push_back(nom_Ref_CLL); taille_tors++;taille_tors_CLL++; ttRGCLL(icondli)(ir+1)=taille_tors; } else // on a trouvé un élément identique déjà existant de numéro it {ttRGCLL(icondli)(ir+1)=it;}; }; // fin boucle sur les références secondaires }; //-- fin du test if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1))) }; //-- fin de la boucle sur les conditions linéaires // maintenant on dimensionne le tableau de torseurs int taille_tors_bloqu = taille_tors - taille_tors_CLL; tab_torseurReac.Change_taille(taille_tors); for (int ia=1;ia<=taille_tors;ia++) {tab_torseurReac(ia).Activation(dima); // on définit si le torseur correspond à un ddl bloqué ou une CLL if (ia > taille_tors_bloqu) {tab_torseurReac(ia).bloque_ou_CLL = false;} else {tab_torseurReac(ia).bloque_ou_CLL = true;} }; // maintenant on dimensionne et rempli ttorBloq ttorBloq.Change_taille(taille_tors_bloqu); for (int ib=1;ib<=taille;ib++) if (ttRG(ib) != 0 ) ttorBloq(ttRG(ib)).push_back(ib); // cas d'une ref qui contient un déplacement // et ensuite on dimensionne et rempli ttorCLL ttorCLL.Change_taille(taille_tors); for (int ib=1;ib<=tabCLLTaille;ib++) { int tai = ttRGCLL(ib).Taille(); for (int j=1;j<=tai;j++) if (ttRGCLL(ib)(j) != 0 ) ttorCLL(ttRGCLL(ib)(j)).push_back(DeuxEntiers(ib,j)); // cas d'une ref qui contient un déplacement }; // on définit les tableaux ttRG_noms_ref et ttRGCLL_noms_ref int nb_RG_noms_ref = li_nomRef_CL.size(); ttRG_noms_ref.Change_taille(nb_RG_noms_ref); {list ::iterator ili,ilifin=li_nomRef_CL.end(); int i=1; for (ili = li_nomRef_CL.begin();ili != ilifin; ili++,i++) ttRG_noms_ref(i)=(*ili); }; ttRGCLL_noms_ref.Change_taille(li_nomRef_CLL.size()); {list ::iterator ili,ilifin=li_nomRef_CLL.end(); int i=1; for (ili = li_nomRef_CLL.begin();ili != ilifin; ili++,i++) ttRGCLL_noms_ref(i)=(*ili); }; // on va maintenant définir des grandeurs globales qui permettront de récupérer les réactions par // exemple via des fonctions nD Ddl_enum_etendu ddl("comp_tors_reaction"); Ddl_etendu v(ddl); int taille_tors_bloquplus1 = taille_tors_bloqu +1; {int il = 1; for (int ia=1;iaGrandeurGlobal(nom_ref) == NULL) ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); } // 2) le moment for (int ic= 1; ic < dimaPlus1; ic++) {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); Grandeur_Ddl_etendu grand_courant(v,nom_ref); // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas // et on récupère un exemplaire TypeQuelconque_enum_etendu enuType = TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE); // on définit le type quelconque associé TypeQuelconque typQ(enuType,X1,grand_courant); // et on ajoute une grandeur globale qui sera indexée par le nom de référence // si celle-ci n'existe pas déjà if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL) ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); } }; }; // maintenant on s'occupe des conditions concernant les CLL {int taille_torsPlusUn = taille_tors+1; int il = 1; for (int ia=taille_tors_bloquplus1;iaGrandeurGlobal(nom_ref) == NULL) ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); } // 2) le moment for (int ic= 1; ic < dimaPlus1; ic++) {string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); Grandeur_Ddl_etendu grand_courant(v,nom_ref); // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas // et on récupère un exemplaire TypeQuelconque_enum_etendu enuType = TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE); // on définit le type quelconque associé TypeQuelconque typQ(enuType,X1,grand_courant); // et on ajoute une grandeur globale qui sera indexée par le nom de référence // si celle-ci n'existe pas déjà if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL) ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); } }; }; //--- débug --- //cout << "\n " << ttorCLL << endl; //--- fin débug --- }; // DdlLim : mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD void LesCondLim::Mise_a_jour_t_minmax_ddlLim(Noeud& noe,DdlLim& ddlLim,LesFonctions_nD* lesFonctionsnD) {// on regarde le temps min string nom_t_min = ddlLim.Nom_fctnD_tmin(); if (nom_t_min != "") { Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_min); // récup de la fonction // récup des valeurs au noeud, pour alimenter la fonction Tableau tab(noe.Valeur_multi_et_Tensorielle (fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue()) ); // appel fonction Tableau & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL); ddlLim.Mise_a_jour_tmin(tab_ret(1)); #ifdef MISE_AU_POINT // on vérifie que la fonction est scalaire if (tab_ret.Taille() != 1) { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min << " qui gere le temps mini " << " elle retourne une grandeur vectorielle " << " ce n'est pas normal !! , on arrete le calcul " << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(nom_t_max); // récup de la fonction // récup des valeurs au noeud, pour alimenter la fonction Tableau tab(noe.Valeur_multi_et_Tensorielle (fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue()) ); // appel fonction Tableau & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL); ddlLim.Mise_a_jour_tmax(tab_ret(1)); #ifdef MISE_AU_POINT // on vérifie que la fonction est scalaire if (tab_ret.Taille() != 1) { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max << " qui gere le temps maxi " << " elle retourne une grandeur vectorielle " << " ce n'est pas normal !! , on arrete le calcul " << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(nom_t_min); // récup de la fonction // appel fonction Tableau & tab_ret = fct->Valeur_pour_variables_globales(); ddlLim.Mise_a_jour_tmin(tab_ret(1)); #ifdef MISE_AU_POINT // on vérifie que la fonction est scalaire if (tab_ret.Taille() != 1) { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min << " qui gere le temps mini " << " elle retourne une grandeur vectorielle " << " ce n'est pas normal !! , on arrete le calcul " << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(nom_t_max); // récup de la fonction // appel fonction Tableau & tab_ret = fct->Valeur_pour_variables_globales(); ddlLim.Mise_a_jour_tmax(tab_ret(1)); #ifdef MISE_AU_POINT // on vérifie que la fonction est scalaire if (tab_ret.Taille() != 1) { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max << " qui gere le temps maxi " << " elle retourne une grandeur vectorielle " << " ce n'est pas normal !! , on arrete le calcul " << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); int nb_n_princ = refp.Taille(); Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli); t_condiAppli.Change_taille(0); // a priori 0 c'est-à-dire qu'il n'y en a pas // on boucle sur les noeuds de la référence principale for (int in=1;in<=nb_n_princ;in++) { // récup du noeud principal Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); if (a_considerer) { bool actif_pour_le_temps = iocondiline_i.Temps_actif(temps); // pour simplifier //debug //cout << "\n LesCondLim::MiseAJour_condilineaire_tdt " // << " actif_pour_le_temps= "<< actif_pour_le_temps << endl; //fin debug if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline)) { if ((!actif_pour_le_temps) && (iocondiline_i.Etat_validation())) // cas du temps non actif, mais qui était actif au pas précédent { ch_statut = true; } else if ((actif_pour_le_temps) && (!iocondiline_i.Etat_validation())) { ch_statut = true; }; }; //-- fin du test si le noeud est à considérer ou pas }; }; // fin de la boucle sur les noeuds de la ref principale // II) ---- un deuxième passage pour le traitement des conditions limites de projection --- // sur un plan ou une droite // ** je ne comprends pas pourquoi il faut l'usine à gaz Pas_a_prendre_en_compte( qui fait que si au // temps précédent c'était actif, alors au temps actuel, même en dehors de l'intervalle c'est également à considérer // cela conduit à des erreurs donc je supprime et met un cas plus restrictif : Pas_a_prendre_en_compte_dans_intervalle( // mais il faudrait également changer dans tous les chargement les fct du même type : Pas_a_prendre_en_compte( // if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte(temps)) if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte_dans_intervalle(temps)) && (iocondiline_i.PlanDroite())) {// construction des données nécessaires // on regarde si l'on utilise un noeud rotation const String_et_entier* mailEtNumCentreNoeud = iocondiline_i.RefNoeudRotation(); if ( mailEtNumCentreNoeud != NULL) // utilisation d'un noeud rotation, on renseigne { if (mailEtNumCentreNoeud->nom == "") // cas par défaut de noeud du premier maillage {iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(1,mailEtNumCentreNoeud->n)));} else // sinon il y a un nom de maillage {int imail = lesMail->NumMaillage(mailEtNumCentreNoeud->nom); iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(imail,mailEtNumCentreNoeud->n)));}; }; // on regarde s'il y a des fonctions de charge si oui on renseigne int nbfct = iocondiline_i.ExisteFonctionChargeCoef(); if (nbfct) {Vecteur valfct(nbfct),deltatvalfct(nbfct); for (int ifct = 1; ifct <= nbfct; ifct++) {Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct)); valfct(ifct)=pt_courbe->Valeur(temps); deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))); }; // on renseigne la condition limite iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct); // on actualise la direction actuelle ou normale pour plan droite iocondiline_i.ActualiseDirectionPlanDroite(); }; 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 posi = Id_nom_ddl("X1") -1; // position du ddl X1 // on boucle sur les noeuds de la référence principale pour appliquer la condition for (int in=1;in<=nb_n_princ;in++) { // récup du noeud principal Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); //si le noeud est par ailleurs bloqué, ce n'est pas possible (sauf cas particulier // non pris en compte car c'est trop spécifique, il faut utiliser une CL classique à la place // d'utiliser ce type de condition linéaire, on test donc pour éviter des déconvenues int indi = 0; switch (dima) { case 3: if (noe.Ddl_fixe(Enum_ddl(posi+3))) { indi=3; if (!iocondiline_i.Coherence_condi_PlanDroite(indi)) {break;} else {indi = 0;}; // on remet à 0 si c'est cohérent } case 2: if (noe.Ddl_fixe(Enum_ddl(posi+2))) { indi=2; if (!iocondiline_i.Coherence_condi_PlanDroite(indi)) {break;} else {indi = 0;}; // on remet à 0 si c'est cohérent } case 1: if (noe.Ddl_fixe(Enum_ddl(posi+1))) { indi=1; if (!iocondiline_i.Coherence_condi_PlanDroite(indi)) {break;} else {indi = 0;}; // on remet à 0 si c'est cohérent } default: break; }; if (indi) { // cas où il existe un blocage sur le noeud, la condition linéaire n'est pas licite cout << "\n erreur concernant une condition lineaire par projection " << ", le noeud : "<& nomRefassocie = iocondiline_i.ReferenceAssociees(); const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); int tailrefasso = nomRefassocie.Taille(); Tableau * > tab_numNoeud_associe(tailrefasso); Tableau tab_numMail_associe(tailrefasso); if (tailrefasso != 0) {for (int k=1;k<=tailrefasso;k++) {const string * nom_maillage=NULL; if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); const ReferenceNE & refasso = ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés tab_numMail_associe(k)= refasso.Nbmaille(); }; }; // -- maintenant que l'est là, il y a de bonnes raisons de penser que les conditions sont effectives // on dimensionne correctement le tableau finale t_condiAppli.Change_taille(nb_n_princ); // mise à jour de la taille au cas où // éventuellement, due à la non activité des ddl, la condition peut néanmoins ne pas être construite // par défaut on met le Iddl() en négatif, histoire de rendre par défaut la condition non exploitable // ceci sera changé durant la construction effective, si elle a lieu. D'autre part au moment de l'utilisation de la condition // le test sur le Iddl() permettra de savoir si la condition est exploitable ou non for (int ijk=1;ijk<=nb_n_princ;ijk++) t_condiAppli(ijk).ChangeIddl()=-1; // on boucles sur les noeuds de la ref principale Tableau t_noe(tailrefasso+1); // tableau de travail // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds // concernés par la condition linéaire. for (int in=1;in<=nb_n_princ;in++) { // récup du noeud principal Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); t_noe(1)= &noe; // on ne continue que si le type de ddl de la condition limite est actif pour le noeud // et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline)) {// récupération des noeuds associés, on utilise le même indice dans les ref associées que // dans la ref principale for (int ia = 1;ia<=tailrefasso;ia++) t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); // on commence par voir s'il y a des fonctions de charge si oui on renseigne int nbfct = iocondiline_i.ExisteFonctionChargeCoef(); if (nbfct) {Vecteur valfct(nbfct),deltatvalfct(nbfct); for (int ifct = 1; ifct <= nbfct; ifct++) {Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct)); valfct(ifct)=pt_courbe->Valeur(temps); deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))); }; // on renseigne la condition limite iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct); }; // on calcul les coefs effectifs de condition limite Condilineaire & condi = t_condiAppli(in); // pour simplifier // on constuit la condition et on impose la valeur c-a-d: // on met en place la condition limite sur le ddl ddl_i du noeud principal // qui correspond au ddl_i' dans le nouveau repèrere qui recevra la condition bloqué // en fait ddl_i sera la seul modification de ddl due à la mise en place de la CLL iocondiline_i.ConstructionCondition(t_noe,condi); construction_effectuee = true; // on enregistre }; // -- fin du cas ou c'est une variable et qu'elle est active }; // -- fin de la boucle sur les noeuds de la ref principal }; // -- fin du test pour savoir s'il faut considérer la condition linéaire ou pas }; //-- fin de la boucle sur l'ensemble des conditions linéaire // 2--- on boucle sur toutes les conditions linéaires effectives, pour imposer les blocages for (int icondli=1;icondli<= tabTaille; icondli++) {Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli); int taille = t_condiAppli.Taille(); for (int i=1;i<=taille;i++) { double Uk_impose = t_condiAppli(i).Val_Uk_impose(); // récup de la valeur a imposer // dans le cas où c'est une condition de projection, la condition a déjà été effectuée // donc il ne faut pas la faire ici: le test de Uk_impose, permet de le savoir if (Uk_impose != ConstMath::tresgrand) { Noeud* noe = t_condiAppli(i).Noe(); // pour simplifier Enum_ddl leEnuAChanger = t_condiAppli(i).Tab_Enum()(1); // le enu a changer noe->Change_val_tdt(leEnuAChanger,Uk_impose); }; }; }; tempsCLL.Arret_du_comptage(); // temps cpu }; // création d'un tableau de condition linéaire, correspondant à toutes les conditions linéaires d'entrées // qu'elles soient actives ou pas (a priori cette méthode est conçu pour donner des infos relativement à la largeur // de bandes en noeuds due aux CLL) // chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, Tableau > LesCondLim::ConnectionCLL (const LesMaillages * lesMail,const LesReferences* lesRef) const { // on boucle sur le tableau et pour chaque element on impose une condition lineaire int tabTaille = tab_iocondiline.Taille(); Tableau > t_connectionCLL(tabTaille); for (int icondli=1;icondli<= tabTaille; icondli++) {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier // recup de la reference principal correspondant au mot cle const ReferenceNE & refp = ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); int nb_n_princ = refp.Taille(); Tableau & connectionCLL = t_connectionCLL(icondli); // pour simplifier connectionCLL.Change_taille(nb_n_princ); // mise à jour de la taille // ---- traitement des conditions limites de projection --- // sur un plan ou une droite if (iocondiline_i.PlanDroite()) {Tableau t_noe(1); // tableau de travail for (int in=1;in<=nb_n_princ;in++) { // récup du noeud principal t_noe(1)= &lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi Enum_ddl enu = enu_condline; // init if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX)) enu = UxyzXi(enu_condline); // on ne continue que si le type de ddl de la condition limite est une variable // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) if (t_noe(1)->UneVariable(enu)) // on renseigne la condition uniquement sur le tableau de noeud { connectionCLL(in).ChangeTabNoeud(t_noe); }; }; // -- fin de la boucle sur les noeuds de la ref principal }// -- fin du test pour savoir si c'est une condition de projection ou non // --- cas des conditions linéaires générales --------- else {// recup du tableau des références secondaires associées si elles existent const Tableau & nomRefassocie = iocondiline_i.ReferenceAssociees(); const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); int tailrefasso = nomRefassocie.Taille(); Tableau * > tab_numNoeud_associe(tailrefasso); Tableau tab_numMail_associe(tailrefasso); if (tailrefasso != 0) {for (int k=1;k<=tailrefasso;k++) {const string * nom_maillage=NULL; if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); const ReferenceNE & refasso = ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés tab_numMail_associe(k)= refasso.Nbmaille(); }; }; // on boucles sur les noeuds de la ref principale Tableau t_noe(tailrefasso+1); // tableau de travail // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds // concernés par la condition linéaire. for (int in=1;in<=nb_n_princ;in++) { // récup du noeud principal Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); t_noe(1)= &noe; Condilineaire& condCLL = connectionCLL(in); // pour simplifier // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi Enum_ddl enu = enu_condline; // init if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX)) enu = UxyzXi(enu_condline); // on ne continue que si le type de ddl de la condition limite est une variable, // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) if (noe.UneVariable(enu) ) {// récupération des noeuds associés, on utilise le même indice dans les ref associées que // dans la ref principale for (int ia = 1;ia<=tailrefasso;ia++) t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); }; // on renseigne la condition uniquement sur le tableau de noeud condCLL.ChangeTabNoeud(t_noe); }; // -- fin du cas ou c'est une variable }; // -- fin de la boucle sur les noeuds de la ref principal }; //-- fin de la boucle sur l'ensemble des conditions linéaire // retour return t_connectionCLL; }; // idem ConnectionCLL avec une liste, mais spécifiquement les conditions de type "stricte_egalite" entre ddl de noeud // correspondant à toutes les conditions linéaires d'entrées actives uniquement // (a priori cette méthode est conçu pour donner des infos pour condenser les pointeurs d'assemblages: // LesMaillages::MiseAJourPointeurAssemblage() ) // chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, et le type enumere de ddl list LesCondLim::ConnectionCLL_stricte_egalite (const LesMaillages * lesMail,const LesReferences* lesRef) const { // def de la liste de retour list list_condi; // on boucle sur le tableau et pour chaque element on analyse la condition lineaire int tabTaille = tab_iocondiline.Taille(); for (int icondli=1;icondli<= tabTaille; icondli++) {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier Tableau tab_enu(1); tab_enu(1) = enu_condline; // servira pour construire les Condilineaires // recup de la reference principal correspondant au mot cle const ReferenceNE & refp = ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); int nb_n_princ = refp.Taille(); // --- on ne continue que s'il s'agit d'une condition stricte_egalite et que la condition // est active pour le temps actuel if ((iocondiline_i.StricteEgalite()) && (iocondiline_i.Temps_actif(ParaGlob::Variables_de_temps().TempsCourant()))) {// recup du tableau des références secondaires associées si elles existent const Tableau & nomRefassocie = iocondiline_i.ReferenceAssociees(); const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); int tailrefasso = nomRefassocie.Taille(); Tableau * > tab_numNoeud_associe(tailrefasso); Tableau tab_numMail_associe(tailrefasso); if (tailrefasso != 0) {for (int k=1;k<=tailrefasso;k++) {const string * nom_maillage=NULL; if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); const ReferenceNE & refasso = ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés tab_numMail_associe(k)= refasso.Nbmaille(); }; }; // on boucles sur les noeuds de la ref principale Tableau t_noe(tailrefasso+1); // tableau de travail // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds // concernés par la condition linéaire. for (int in=1;in<=nb_n_princ;in++) { // récup du noeud principal Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); t_noe(1)= &noe; // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi Enum_ddl enu = enu_condline; // init if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX)) enu = UxyzXi(enu_condline); // on ne continue que si le type de ddl de la condition limite est une variable, // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) if (noe.UneVariable(enu) ) {// récupération des noeuds associés, on utilise le même indice dans les ref associées que // dans la ref principale for (int ia = 1;ia<=tailrefasso;ia++) t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); }; // on renseigne une condition uniquement sur le tableau de noeud Condilineaire condi_stric_egal(tab_enu,t_noe); list_condi.push_back(condi_stric_egal); }; // -- fin du cas ou c'est une variable }; // -- fin de la boucle sur les noeuds de la ref principal }; //-- fin de la boucle sur l'ensemble des conditions linéaire // retour return list_condi; }; // récupération de valeurs à un noeud pour les grandeur enu // ici il s'agit de grandeur scalaires Tableau LesCondLim::Valeur_multi_interpoler_ou_calculer (const Noeud& noe, Enum_dure temps,const List_io& enu) { // recup de l'incrément de temps double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant(); double unSurDeltat=0; if (Abs(deltat) >= ConstMath::trespetit) {unSurDeltat = 1./deltat;} else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb if (unSurDeltat < 0) { cout << "\n le pas de temps est négatif !! "; }; unSurDeltat = ConstMath::tresgrand; }; // le tableau de retour Tableau tab_ret (enu.size()); // on balaie la liste des grandeurs à sortir List_io::const_iterator ie,iefin=enu.end(); int it; // it est l'indice dans le tableau de retour for (it=1,ie=enu.begin(); ie!=iefin;ie++,it++) { if ((Meme_famille((*ie).Enum(),X1)) && ((*ie).Nom_vide())) {switch (temps) {case TEMPS_0 : tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1);break; case TEMPS_t : tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1);break; case TEMPS_tdt : tab_ret(it)= noe.Coord2()((*ie).Enum() - X1 +1);break; default : cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n"; Sortie(1); }; } else if ((Meme_famille((*ie).Enum(),UX)) && ((*ie).Nom_vide())) {int i_cor = (*ie).Enum() - UX +1; // l'indice de coordonnée switch (temps) {case TEMPS_0 : tab_ret(it)= 0.;break; case TEMPS_t : tab_ret(it)= noe.Coord1()(i_cor)-noe.Coord0()(i_cor);break; case TEMPS_tdt : tab_ret(it)= noe.Coord2()(i_cor)-noe.Coord0()(i_cor);break; default : cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n"; Sortie(1); }; } // cas particulier de la position à t, indépendamment du temps else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 123) {tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1); } // cas particulier de la position à t0, indépendamment du temps else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 126) {tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1); } else if ((*ie).Nom_vide()) {// il s'agit d'un ddl pur on le récupère directement switch (temps) {case TEMPS_0 : tab_ret(it)= noe.Valeur_0((*ie).Enum());break; case TEMPS_t : tab_ret(it)= noe.Valeur_t((*ie).Enum());break; case TEMPS_tdt : tab_ret(it)= noe.Valeur_tdt((*ie).Enum());break; default : cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; cout << "LesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n"; Sortie(1); }; } // --- a complèter ---- else { tab_ret(it) = 0.; cout << "\n cas de ddl actuellement non traite " << "\n pas de ddl " << (*ie).Nom() << " au noeud " << noe.Num_noeud() <<" du maillage "<< noe.Num_Mail() << "\n ou cas non implante pour l'instant, on retourne 0" << "\n LesCondLim::Valeur_multi_interpoler_ou_calculer(.. "; }; };// -- fin de la boucle sur la liste de Ddl_enum_etendu // liberation des tenseurs intermediaires LibereTenseur(); return tab_ret; }; // récupération de valeurs à un noeud pour les grandeur enu // ici il s'agit de grandeurs tensorielles void LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer (const Noeud& noe, Enum_dure temps,List_io& enu) { // ----- def de grandeurs de travail int dim_espace = ParaGlob::Dimension(); // on initialise ces variables booléennes et les conteneurs List_io::iterator ipq,ipqfin=enu.end(); for (ipq=enu.begin();ipq!=ipqfin;ipq++) {TypeQuelconque_enum_etendu enuq = (*ipq).EnuTypeQuelconque().EnumTQ(); switch (enuq.Position()) { case POSITION_GEOMETRIQUE : {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); Coordonnee* M = gr.ConteneurCoordonnee(); switch (temps) {case TEMPS_0 : (*M)= noe.Coord0();break; case TEMPS_t : (*M)= noe.Coord1();break; case TEMPS_tdt : (*M)= noe.Coord2();break; default : cout << "\nErreur : valeur incorrecte du temps !\n"; cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); Sortie(1); }; break; } case POSITION_GEOMETRIQUE_t : {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); Coordonnee* M = gr.ConteneurCoordonnee(); (*M)= noe.Coord1(); break; } case POSITION_GEOMETRIQUE_t0 : {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); Coordonnee* M = gr.ConteneurCoordonnee(); (*M)= noe.Coord0(); break; } case DEPLACEMENT : {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); Coordonnee* M = gr.ConteneurCoordonnee(); switch (temps) {case TEMPS_0 : M->Zero();break; case TEMPS_t : (*M)= noe.Coord1()-noe.Coord0();break; case TEMPS_tdt : (*M)= noe.Coord2()-noe.Coord0();break; default : cout << "\nErreur : valeur incorrecte du temps !\n"; cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); Sortie(1); }; break; } case FORCE_GENE_EXT : case FORCE_GENE_INT : case VECT_PRESSION : case VECT_FORCE_VOLUM : case VECT_DIR_FIXE : case VECT_SURF_SUIV : case VECT_HYDRODYNA_Fn : case VECT_HYDRODYNA_Ft : case VECT_HYDRODYNA_T : case VECT_LINE : case VECT_LINE_SUIV : case VECT_REAC : case VECT_REAC_N : case FORCE_CONTACT : case FORCE_GENE_TOT: case RESIDU_GLOBAL: {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); Coordonnee* F = gr.ConteneurCoordonnee(); // on vérifie l'existante #ifdef MISE_AU_POINT if (!(noe.Existe_ici(enuq))) {cout << "\nErreur : " << enuq.Nom() << " n'existe pas au noeud " << noe.Num_noeud() << " du maillage "<< noe.Num_Mail() << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); Sortie(1); }; #endif // récupération de la grandeur quelconque const TypeQuelconque& toto = noe.Grandeur_quelconque(enuq); const Grandeur_coordonnee& titi = *((const Grandeur_coordonnee* ) toto.Const_Grandeur_pointee()); (*F) = titi.ConteneurCoordonnee_const(); // ouf break; } case VITESSE : {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); Coordonnee* V = gr.ConteneurCoordonnee(); // on vérifie l'existante #ifdef MISE_AU_POINT if (!(noe.Existe_ici(V1))) {cout << "\nErreur : la vitesse n'existe pas au noeud " << noe.Num_noeud() << " du maillage "<< noe.Num_Mail() << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); Sortie(1); }; #endif // récupération de la vitesse switch (temps) { case TEMPS_0 : {switch (dim_espace) {case 3: (*V)(3) = noe.Valeur_0(V3); case 2: (*V)(2) = noe.Valeur_0(V2); case 1: (*V)(1) = noe.Valeur_0(V1); break; default: break; }; break; } case TEMPS_t : {switch (dim_espace) {case 3: (*V)(3) = noe.Valeur_t(V3); case 2: (*V)(2) = noe.Valeur_t(V2); case 1: (*V)(1) = noe.Valeur_t(V1); break; default: break; }; break; } case TEMPS_tdt : {switch (dim_espace) {case 3: (*V)(3) = noe.Valeur_tdt(V3); case 2: (*V)(2) = noe.Valeur_tdt(V2); case 1: (*V)(1) = noe.Valeur_tdt(V1); break; default: break; }; break; } default: break; }; break; } case ACCELERATION : {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); Coordonnee* gamma = gr.ConteneurCoordonnee(); // on vérifie l'existante #ifdef MISE_AU_POINT if (!(noe.Existe_ici(GAMMA1))) {cout << "\nErreur : l'acceleration n'existe pas au noeud " << noe.Num_noeud() << " du maillage "<< noe.Num_Mail() << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); Sortie(1); }; #endif // récupération de la vitesse switch (temps) { case TEMPS_0 : {switch (dim_espace) {case 3: (*gamma)(3) = noe.Valeur_0(GAMMA3); case 2: (*gamma)(2) = noe.Valeur_0(GAMMA2); case 1: (*gamma)(1) = noe.Valeur_0(GAMMA1); break; default: break; }; break; } case TEMPS_t : {switch (dim_espace) {case 3: (*gamma)(3) = noe.Valeur_t(GAMMA3); case 2: (*gamma)(2) = noe.Valeur_t(GAMMA2); case 1: (*gamma)(1) = noe.Valeur_t(GAMMA1); break; default: break; }; break; } case TEMPS_tdt : {switch (dim_espace) {case 3: (*gamma)(3) = noe.Valeur_tdt(GAMMA3); case 2: (*gamma)(2) = noe.Valeur_tdt(GAMMA2); case 1: (*gamma)(1) = noe.Valeur_tdt(GAMMA1); break; default: break; }; break; } default: break; }; break; } default : {// on initialise la grandeur pour éviter d'avoir des valeurs aléatoires ((*ipq).Grandeur_pointee())->InitParDefaut(); if (ParaGlob::NiveauImpression() > 0) {cout << "\nWarning : attention cas non traite: " << (*ipq).EnuTypeQuelconque().NomPlein() << "!\n"; // on initialise la grandeur pour éviter d'avoir des valeurs aléatoires if (ParaGlob::NiveauImpression() > 5) cout << "\n LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(...."; }; } }; }; // liberation des tenseurs intermediaires LibereTenseur(); };