// 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 "I_O_Condilineaire.h" #include "CharUtil.h" #include #include #include #include # include using namespace std; //introduces namespace std // par défaut I_O_Condilineaire::I_O_Condilineaire(): Condilineaire() ,nom_maillage(NULL),refe("") ,t_min(0.),t_max(ConstMath::tresgrand),echelle(1.) ,precedent(false),valeur_precedente_t(0.) ,tab_co_charge(),refs_associe(),enu(NU_DDL) ,nom_mail_associe() ,condition_relative(false) ,fctch(),delta_fctch(),nbddlfamille(0) ,def_auto_par_rotation(false),stricte_egalite(false) ,type_centre(1),mailEtNumCentreNoeud(),centre_noeud(NULL) ,pl(),dr() {}; // de copie I_O_Condilineaire::I_O_Condilineaire(const I_O_Condilineaire& nd): Condilineaire(nd) ,nom_maillage(NULL),refe(nd.refe) ,t_min(nd.t_min),t_max(nd.t_max),echelle(nd.echelle) ,precedent(nd.precedent),valeur_precedente_t(nd.valeur_precedente_t) ,tab_co_charge(nd.tab_co_charge),refs_associe(nd.refs_associe) ,nom_mail_associe(nd.nom_mail_associe),enu(nd.enu) ,condition_relative(nd.condition_relative) ,fctch(nd.fctch),delta_fctch(nd.delta_fctch),nbddlfamille(nd.nbddlfamille) ,def_auto_par_rotation(nd.def_auto_par_rotation),stricte_egalite(nd.stricte_egalite) ,type_centre(nd.type_centre),centre_rotation(nd.centre_rotation) ,mailEtNumCentreNoeud(nd.mailEtNumCentreNoeud),centre_noeud(nd.centre_noeud) ,pl(nd.pl),dr(nd.dr) {if (nd.nom_maillage != NULL) nom_maillage = new string (*(nd.nom_maillage)); }; // DESTRUCTEUR : I_O_Condilineaire::~I_O_Condilineaire() { if (nom_maillage != NULL) delete nom_maillage; }; // examine si la condition passée en argument possède les mêmes cibles que this // mais que les data associés sont différents // ramène true si c'est vrai, false sinon // en fait cette fonction est définit par conformité avec le programme de lecture // LectBloc::Lecture(.. mais ici on peut avoir plusieurs conditions linéaire // sur la même référence, donc on ramène toujours false bool I_O_Condilineaire::MemeCibleMaisDataDifferents(I_O_Condilineaire& ) { return false; }; // Affiche les donnees void I_O_Condilineaire::Affiche () const { // affichage éventuelle du nom de maillage if (nom_maillage != NULL) { cout << "\n nom_mail= " << *nom_maillage;} else cout << "\n"; // puis le reste cout << " ref_princ= " << refe ; if (refs_associe.Taille() != 0) {int tai = refs_associe.Taille(); cout << " ref_associe= "; for (int i=1;i<=tai;i++) if (nom_maillage != NULL) {cout << nom_mail_associe(i) << " " << refs_associe(i) << " ";} else {cout << refs_associe(i) << " ";} }; cout << "\n type_ddl= " << Nom_ddl(enu) ; cout << " def_auto_par_rotation= " << def_auto_par_rotation; cout << " stricte_egalite= " << stricte_egalite; // if (!def_auto_par_rotation) // { cout << " val_condi= " << this->beta << " coefficients= " << val;} // else // {if (type_centre == 1) // { cout << " centre_fixe= " ; // if (ParaGlob::Dimension() == 2) {cout << dr.PointDroite() << " " ;} // else {cout << pl.PointPlan() << " " ;}; // } // else if (type_centre == 2) // { cout << " centre_noeud_t0= " << mailEtNumCentreNoeud << " ";} // else if (type_centre == 3) // { cout << " centre_noeud_t= " << mailEtNumCentreNoeud << " ";}; // if (ParaGlob::Dimension() == 2) // {cout << " dir_droite_now= " << dr.VecDroite() << " dir_droite0= " << val;} // else // cas dimension 3 // {cout << " normal_plan_now= " << pl.Vecplan() << " normal_plan0= " << val;} // }; 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--; if (def_auto_par_rotation) {if (type_centre == 1) { cout << " centre_fixe= " ; if (dima == 2) {cout << dr.PointDroite() << " " ;} else {cout << pl.PointPlan() << " " ;}; } else if (type_centre == 2) { cout << " centre_noeud_t0= " << mailEtNumCentreNoeud << " ";} else if (type_centre == 3) { cout << " centre_noeud_t= " << mailEtNumCentreNoeud << " ";}; if (dima == 2) {cout << " dir_droite_now= " << dr.VecDroite() << " dir_droite0= " << val;} else // cas dimension 3 {cout << " normal_plan_now= " << pl.Vecplan() << " normal_plan0= " << val;} } else if (stricte_egalite) { } else { cout << " val_condi= " << this->beta << " coefficients= " << val;}; cout << " temps_mini= " << t_min << " temps_maxi= " << t_max << " echelle= " << echelle << " activite_actuelle: " << precedent << " condition_relative= " << condition_relative << " "; cout << " courbe_charge= " << tab_co_charge; cout << endl; }; // Realise l'egalite I_O_Condilineaire& I_O_Condilineaire::operator= (const I_O_Condilineaire& d) {// traitement du nom de maillage éventuel if (d.nom_maillage == NULL) {if (nom_maillage != NULL) {delete nom_maillage;nom_maillage=NULL; nom_mail_associe.Change_taille(0);} } else {if (nom_maillage == NULL) {nom_maillage = new string (*(d.nom_maillage)); nom_mail_associe = d.nom_mail_associe; } else {*nom_maillage = *(d.nom_maillage); nom_mail_associe = d.nom_mail_associe; }; }; // nom de la référence refe = d.refe; // tableau de références associé refs_associe = d.refs_associe; // les temps t_min = d.t_min; t_max = d.t_max; echelle = d.echelle; precedent = d.precedent; valeur_precedente_t = d.valeur_precedente_t; // l'énuméré enu = d.enu; nbddlfamille = d.nbddlfamille; // la relativité de la condition condition_relative = d.condition_relative; // les courbes de charge tab_co_charge = d.tab_co_charge; def_auto_par_rotation = d.def_auto_par_rotation; stricte_egalite = d.stricte_egalite; type_centre = d.type_centre; centre_rotation = d.centre_rotation; mailEtNumCentreNoeud = d.mailEtNumCentreNoeud; centre_noeud = d.centre_noeud; pl = d.pl; dr = d.dr; // la condition linéaire this->Condilineaire::operator=(d); // retour return *this; }; //Surcharge d'operateur logique bool I_O_Condilineaire::operator == ( I_O_Condilineaire& a) const { // traitement du nom de maillage éventuel if (nom_maillage == NULL) { if (a.nom_maillage != NULL) return false; } else { if (a.nom_maillage == NULL) return false; // sinon les deux sont non null: on test leur égalité if (*nom_maillage != *(a.nom_maillage)) return false; }; 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 des centres de rotation éventuelles, il peut y avoir des données qui ne servent pas // qui soient différentes, alors que celles qui servent sont identiques ! if (def_auto_par_rotation != a.def_auto_par_rotation) return false; if (stricte_egalite != a.stricte_egalite) return false; if (def_auto_par_rotation) { if (type_centre != a.type_centre) return false; switch (type_centre) { case 1: switch (dima) { case 2: if (dr.PointDroite() != a.dr.PointDroite()) return false; break; case 3: if (pl.PointPlan() != a.pl.PointPlan()) return false; break; }; case 2: case 3: if (centre_noeud != a.centre_noeud) return false; break; }; switch (dima) { case 2: if (dr.VecDroite() != a.dr.VecDroite()) return false; break; case 3: if (pl.Vecplan() != a.pl.Vecplan()) return false; break; }; } else if (stricte_egalite) { } else {if (this->beta != a.beta) return false; if (val != a.val) return false; }; // les autres données if ( (refe==a.refe) && (refs_associe==a.refs_associe) && (nom_mail_associe == a.nom_mail_associe) && (t_min == a.t_min) && (t_max == a.t_max) && (echelle == a.echelle) && (precedent ==a.precedent) && (enu == a.enu) && (tab_co_charge == a.tab_co_charge) && (condition_relative == a.condition_relative) ) {return true;} else {return false; }; } ; // lecture de la condition linéaire sur le fichier d'entree void I_O_Condilineaire::Lecture(UtilLecture & entreePrinc) { // on regarde tout d'abord si il y a un nom de maillage, qui doit être le premier nom 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--; string nom; *(entreePrinc.entree) >> nom; if (nom == "nom_mail=") { // cas où il y a un nom de maillage *(entreePrinc.entree) >> nom; // lecture du nom if (nom_maillage == NULL) { nom_maillage = new string(nom);} else { *nom_maillage = nom;}; // puis on prépare la suite en lisant la référence principale *(entreePrinc.entree) >> nom; }; // lecture de la reference refe = nom; if (refe.length() == 0) { // pas de reference cout << "\n erreur de lecture d'une reference de condition limite lineaire " << " le nom de la reference a une longueur nulle \n"; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // maintenant on lit les autres informations // on lit l'énuméré *(entreePrinc.entree) >> nom; if (nom != "enu=") { // pas d'énuméré cout << "\n erreur de lecture d'une reference de condition limite lineaire " << " on attendait enu= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else { *(entreePrinc.entree) >> nom; if (!ExisteEnum_ddl(nom)) { // énuméré incorrecte cout << "\n erreur de lecture de l'enumere de condition limite lineaire, il n'existe pas " << " dans la liste des enumeres correctes: on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else // on sauvegarde le premier ddl de la famille {enu = PremierDdlFamille(Id_nom_ddl(nom));}; }; // on passe une ligne entreePrinc.NouvelleDonnee(); // on passe un enregistrement bool passer_une_ligne = false; // lecture des références associées éventuellement if (strstr(entreePrinc.tablcar,"refs_associe=")!=NULL) { *(entreePrinc.entree) >> nom; if (nom != "refs_associe=") { // pas de mot clé cout << "\n erreur de lecture des references associees pour un condition limite lineaire " << " on attendait refs_associe= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else { // lecture de la liste demandée int compteur=0; // pour éviter une boucle infinie // il y a deux types de lecture suivant qu'il doit y avoir un nom de maillage ou pas if (nom_maillage == NULL) {list list_inter; while (compteur < 1000) {(*entreePrinc.entree) >> nom; compteur++; // gestion d'erreur if (nom == "nom_mail=") { // cas où il y a un nom de maillage cout << "\n erreur en lecture : on a lue: " << nom << " or la ref " << " principal ne comporte pas de nom de maillage, dans ce cas les ref" << " secondaires ne doivent pas comporter de nom de maillage !! "; entreePrinc.MessageBuffer("*** lecture des references secondaire d'une condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // suite normale if (nom != "fin_list_refs_associe_") {list_inter.push_back(nom);} else break; }; // recopie dans le tableau int taille = list_inter.size(); refs_associe.Change_taille(taille); list ::iterator it,itfin=list_inter.end(); int i=1; for (it = list_inter.begin();it!=itfin;it++,i++) refs_associe(i)=*it; } else // cas où il est possible qu'on lise nom de maillage // de plus il faut attribuer un nom de maillage à chaque ref associé {list list_inter; string nom_mail; while (compteur < 1000) {(*entreePrinc.entree) >> nom; if (nom == "nom_mail=") // cas où il y a un nom de maillage {*(entreePrinc.entree) >> nom_mail; // lecture du nom *(entreePrinc.entree) >> nom; // lecture de la référence } else {nom_mail=*nom_maillage;}; // attribution du nom de maillage générique compteur++; if (nom != "fin_list_refs_associe_") {list_inter.push_back(Deux_String(nom_mail,nom));} else break; }; // recopie dans le tableau int taille = list_inter.size(); refs_associe.Change_taille(taille);nom_mail_associe.Change_taille(taille); list ::iterator it,itfin=list_inter.end(); int i=1; for (it = list_inter.begin();it!=itfin;it++,i++) {nom_mail_associe(i)=(*it).nom1;refs_associe(i)=(*it).nom2;} }; passer_une_ligne = true; }; }; // on récupère l'échelle globale éventuellement if(strstr(entreePrinc.tablcar,"ECHELLE:")!=0) { // cas où il y a un facteur d'échelle *(entreePrinc.entree) >> nom; if (nom != "ECHELLE:") {cout << "\n erreur de syntaxe en lecture du facteur d'echelle " << " on attendait le mot cle ECHELLE: et on a lue " << nom << " "; entreePrinc.MessageBuffer("**erreur lecture d'une reference de condition lineaire **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } // lecture du facteur *(entreePrinc.entree) >> echelle; } else // sinon on met l'échelle à 1 { echelle = 1. ;}; //-- fin récup de l'échelle // lecture d'un tmin et/ou tmax éventuel if (strstr(entreePrinc.tablcar,"TEMPS_MINI=")!=NULL) { *(entreePrinc.entree) >> nom; if (nom != "TEMPS_MINI=") { // pas d'énuméré cout << "\n erreur de lecture: position du TEMPS_MINI= pour un condition limite lineaire " << " on attendait TEMPS_MINI= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else {(*entreePrinc.entree) >> t_min;passer_une_ligne = true;}; }; if (strstr(entreePrinc.tablcar,"TEMPS_MAXI=")!=NULL) { *(entreePrinc.entree) >> nom; if (nom != "TEMPS_MAXI=") { // pas d'énuméré cout << "\n erreur de lecture: position du TEMPS_MAXI= pour un condition limite lineaire " << " on attendait TEMPS_MAXI= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else {(*entreePrinc.entree) >> t_max;passer_une_ligne = true;}; }; // lecture éventuel de l'indicateur de condition relative condition_relative = false; // faux par défaut if (strstr(entreePrinc.tablcar,"CONDITION_RELATIVE=")!=NULL) {*(entreePrinc.entree) >> nom; if (nom != "CONDITION_RELATIVE=") { cout << "\n erreur de lecture: position de CONDITION_RELATIVE= erronee, pour un condition " << " limite lineaire, on attendait CONDITION_RELATIVE= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else {(*entreePrinc.entree) >> condition_relative; passer_une_ligne = true;}; // il y a une vérification concernant la présence de courbe de charge après la lecture de ces dernières }; // on passe une ligne pour lire les coefficients de la condition linéaire if (passer_une_ligne) entreePrinc.NouvelleDonnee(); // on passe éventuellement un enregistrement passer_une_ligne = false; // --- on regarde s'il s'agit d'une définition de linéarité / à une droit ou un plan if (strstr(entreePrinc.tablcar,"def_auto_coef_planOuDroite_")!=NULL) { if (dima == 1) { cout << "\n erreur de lecture: on ne peut pas faire de definition automatique avec la dimension 1 "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; def_auto_par_rotation = true; // on signale une condition automatique *(entreePrinc.entree) >> nom; // on passe le mot clé if (nom != "def_auto_coef_planOuDroite_") { cout << "\n erreur de lecture: position de def_auto_coef_planOuDroite_ erronee, pour un condition " << " limite lineaire, on attendait def_auto_coef_planOuDroite_ , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // on vérifie qu'il n'y a pas de référence associée car ce cas n'est pas prévu (ni possible a priori) if (refs_associe.Taille() != 0) { cout << "\n erreur de lecture: dans le cas du condition lineaire automatique avec ligne ou plan " << " on ne peut pas avoir de reference associe "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // dans le cas où on a lue un enum UX pb, car la projection concerne les positions et non les déplacements // sinon il faut utiliser une condition générale if (enu != X1) { cout << "\n erreur de coherence: dans le cas du condition lineaire automatique avec ligne ou plan " << " on ne peut pas utiliser comme enumere: " << Nom_ddl(enu) ; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // ici l'échelle doit être égale à 1, on vérifie, pour des pb de projection et d'algo d'ensemble if (echelle != 1.) { cout << "\n erreur de coherence: dans le cas du condition lineaire automatique avec ligne ou plan " << " on ne peut pas utiliser une echelle (ici= " << echelle << " ) differente de 1. !! " ; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // ici on ne doit pas avoir de condition relative car ça ne signifie rien pour la projection, on vérifie, if (condition_relative) { cout << "\n erreur de coherence: dans le cas du condition lineaire automatique avec ligne ou plan " << " on ne peut pas utiliser une condition relative (cela ne signifie rien dans le cas d'une projection ) !! " ; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // maintenant on lit le centre *(entreePrinc.entree) >> nom; // on met à jour la dimension des plan droite switch (dima) { case 2: dr.Change_dim(dima);break; case 3: pl.Change_dim(dima);break; }; if (nom == "centre_fixe_") { type_centre = 1; Coordonnee centre_rotation(dima); centre_rotation.Lecture(entreePrinc); switch (dima) { case 2: dr.Change_ptref(centre_rotation); break; case 3: pl.Change_ptref(centre_rotation); break; } } else if ((nom == "centre_noeud_a_t0_") || (nom == "centre_noeud_a_t_")) { if (nom == "centre_noeud_a_t0_") {type_centre = 2;} else if (nom == "centre_noeud_a_t_") {type_centre = 3;}; // cas d'un centre donné par un numero de noeud string nom_mail; *(entreePrinc.entree) >> nom_mail; if (nom_mail == "nom_mail=") { // cas où il y a un nom de maillage *(entreePrinc.entree) >> mailEtNumCentreNoeud.nom; // lecture du nom *(entreePrinc.entree) >> mailEtNumCentreNoeud.n; // lecture du numero de noeud } else { // sinon cela veut dire que l'on vient de lire un numéro de noeud du premier maillage mailEtNumCentreNoeud.nom = ""; mailEtNumCentreNoeud.n = ChangeEntier(nom_mail); }; } else { cout << "\n erreur de lecture: on attendait : centre_fixe_ ou centre_noeud_a_t0_ " << " ou centre_noeud_a_t_ et on a lue: " << nom ; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; // puis on lit la normale ou la direction de la droite qui correspond aux composantes de val ici } else {def_auto_par_rotation = false; }; // -- on regarde s'il s'agit d'une condition de stricte egalité entre noeud pour le type enu if (strstr(entreePrinc.tablcar,"stricte_egalite_")!= NULL) { } else {stricte_egalite = false;}; // dans un cas normal on lit une valeur de la condition linéaire if ((!def_auto_par_rotation)&&(!stricte_egalite)) {// lecture de la valeur de la condition limite *(entreePrinc.entree) >> nom; if (nom != "val_condi_lineaire=") { cout << "\n erreur de lecture: val_condi_lineaire pour un condition limite lineaire " << " on attendait val_condi_lineaire= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else { (*entreePrinc.entree) >> beta;}; }; if (!stricte_egalite) // dans le cas stricte_egalité, la lecture est finie { // lecture des coefficients de la condition linéaire *(entreePrinc.entree) >> nom; if (nom != "coefficients=") { // pas d'énuméré cout << "\n erreur de lecture des coefficients de la condition limite lineaire " << " on attendait coefficients= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else { // lecture de la liste demandée int compteur=0; // pour éviter une boucle infinie list list_inter; while (compteur < 1000) { (*entreePrinc.entree) >> nom; compteur++; if (nom != "fin_list_coefficients_") { list_inter.push_back(ChangeReel(nom));} else break; }; // recopie dans le tableau int taille = list_inter.size(); val.Change_taille(taille); list ::iterator it,itfin=list_inter.end(); int i=1; for (it = list_inter.begin();it!=itfin;it++,i++) val(i)=*it; // on vérifie que le nombre de coefficients est correcte Tableau tab_enu = TableauTypeDdlmobileAvecAxi(enu); nbddlfamille = tab_enu.Taille(); if (taille != nbddlfamille * (1+refs_associe.Taille())) { cout << "\n erreur de lecture des coefficients de la condition lineaire, leur nombre " << taille << " est differente de (1 + le nombre de reference associe)*le nombre de ddl de la famille = " << nbddlfamille * (1+refs_associe.Taille()) << " "; if(ParaGlob::AxiSymetrie()) cout << "(ici en axi) "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; if (def_auto_par_rotation) {// on met à jour la direction ou la normale droite plan switch (dima) { case 2: dr.Change_vect(val.Coordo()); break; case 3: pl.Change_normal(val.Coordo()); break; } }; }; // on regarde s'il faut considérer des fonctions de charge tab_co_charge.Libere(); // par défaut on initialise le tableau à 0 if (strstr(entreePrinc.tablcar,"AvecFonctionsDeCharges_")!=NULL) {entreePrinc.NouvelleDonnee(); // on passe un enregistrement // lecture du mot clé de début (*entreePrinc.entree) >> nom; if (nom != "deb_fonction_de_charge=") { cout << "\n erreur de lecture d'une liste de fonctions de charge " << " pour un condition limite lineaire " << " on attendait deb_fonction_de_charge= , et on a lue: " << nom << " "; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else { // lecture de la liste demandée int compteur=0; // pour éviter une boucle infinie list list_inter; while (compteur < 1000) { (*entreePrinc.entree) >> nom; compteur++; if (nom != "fin_list_fonctions_de_charges_") { list_inter.push_back(nom);} else break; }; // recopie dans le tableau int taille = list_inter.size(); int i=1; // dans le cas plan ou droite, par analogie au cas générale on considère une taille // telle que c'est seulement à partir du second élément que l'on travaille // on double le premier élément, pour permettre aux boucles de fonctionner, mais le premier // élément ne sert pas dans le calcul de la condition !! if (def_auto_par_rotation) {taille++;i=2;}; tab_co_charge.Change_taille(taille); list ::iterator it,itfin=list_inter.end(); for (it = list_inter.begin();it!=itfin;it++,i++) tab_co_charge(i)=*it; if (def_auto_par_rotation) tab_co_charge(1) = tab_co_charge(2); // doublage du premier élément }; // il doit y avoir autant de nom de fonction de charge que de coef + 1 pour la valeur if (tab_co_charge.Taille() != (val.Taille() + 1)) { cout << "\n erreur de lecture d'une liste de fonctions de charge " << " pour un condition limite lineaire " << " le nombre de fonctions de charge lue (ici: " << tab_co_charge.Taille(); if (def_auto_par_rotation) { cout << " ) doit etre egal au nombre de coefficient pour la valeur de condition lineaire de projection " << " ce qui devrait faire : " << (val.Taille()) << " "; } else { cout << " ) doit etre egal au nombre de coefficient + 1 pour la valeur de condition lineaire " << " ce qui devrait faire : " << (val.Taille() + 1) << " "; }; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; } else if (condition_relative) {// cas où il n'y a pas de fonction de charge, mais que l'on a indiqué une condition relative cout << "\n **** Warning !!! les conditions lineaires relatives ne fonctionnent que avec des courbes de charge " << " dans le cas de conditions simples (fixes) on se refere toujours a la situation a t=0 " << endl; condition_relative = false; }; } else {// quelques vérifs au cas où if (echelle != 1.) { cout << "\n erreur de coherence: dans le cas d'une condition stricte_egalite_ " << " on ne peut pas utiliser une echelle (ici= " << echelle << " ) differente de 1. !! " ; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; if ( (strstr(entreePrinc.tablcar,"coefficients=")!= NULL) ||(strstr(entreePrinc.tablcar,"CONDITION_RELATIVE=")!= NULL) ) { cout << "\n erreur de coherence: dans le cas d'une condition stricte_egalite_ " << " on ne peut pas utiliser les mots cles coefficients= , CONDITION_RELATIVE= !! " ; entreePrinc.MessageBuffer("*** lecture d'une reference de condition lineaire ****" ); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; condition_relative = false; tab_co_charge.Libere(); }; // initialisation des grandeurs de travail Initialisation_condil(); }; // affichage des commandes particulières à la définition d'une condition linéaire void I_O_Condilineaire::Info_commande_conditionLineaire(ofstream & sort,bool plusieurs_maillages) { //On va proposer un menu pour choisir entre différents types de conditions linéaires int type_CLL=0; // =0 non défini, =1 -> projection sur un plan ou une droite // =2 -> condition générale {string rep=" "; // tableau des choix possibles Tableau tab_choix(6); tab_choix(1) = "\n (0 ou f) (fin) "; tab_choix(2) = "\n (1) info detaillees dans le fichier .info"; tab_choix(3) = "\n (2 ou ?) informations succinctes a l ecran"; tab_choix(4) = "\n (3) CLL: proj sur plan en 3D (droite en 2D) "; tab_choix(5) = "\n (4) CLL: generale "; tab_choix(6) = "\n (5) CLL: stricte_egalite "; while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { try { for (int i=1;i<=tab_choix.Taille();i++) cout << tab_choix(i); cout << "\n rep : "; rep = lect_return_defaut(false,"f"); cout << " grandeur lue " << rep; int num = 0; // par défaut if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie // on ne fait rien {num = 0;} else { num = ChangeEntier(rep); if (Minuscules(rep) == "?") num = 2; bool choix_valide=false; if ((num >= 0)&&(num<=5)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 5 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; }; switch (num) { case 0: // sortie { break;} case 1: // sortie documentation détaillée sur le fichier .info { sort << "\n# .............................. condition lineaire: mode d'emploi ................................................." << "\n# | NB: de nombreuse grandeurs sont optionelles, par contre l'ordre d'apparition est impose!! |" << "\n# | constituee : d'une reference principal de noeud qui peut etre precedee (eventuellement) d'un nom de maillage, |" << "\n# | ex1: N_avant , ex2: nom_mail= solide1 N_avant |" << "\n# | suivi sur la meme ligne du type de la famille de ddl sur laquelle s'applique la condition lineaire |" << "\n# | ex1: enu= UX , ex2: enu= X1 , ex3 enu= TEMP |" << "\n# | puis sur la ligne qui suit une suite eventuelle de references secondaires, (s'il n'y en a pas, on met rien ) |" << "\n# | sinon on utilise deux mots cle pour encadrer la liste |" << "\n# | ex1: refs_associe= N_arriere N_milieu fin_list_refs_associe_ |" << "\n# | Dans le cas ou la reference principal comporte un nom de maillage, il est possible d'indiquer ou non avant |" << "\n# | chaque reference secondaire, un nom de maillage. Si ce nom de maillage est absent, c'est celui de la reference|" << "\n# | principale qui est retenue a la place. Ainsi, on peut definir une CLL entre des noeuds de maillages |" << "\n# | differents. Par contre, si la reference principale ne contient pas de nom de maillage, les references |" << "\n# | secondaires ne doivent pas en comporer, sinon cela genere une erreur ! |" << "\n# | les references secondaires doivent avoir exactement le meme nombre de noeud que la reference principal |" << "\n# | la condition linaire s'appliquera sur chaque noeud de la reference principal, associe aux noeuds de |" << "\n# | du meme rang des references secondaires: par exemple pour les ex1, la condition lineaire s'applique |" << "\n# | successivement pour tous noeud i de N_avant, sur le groupe (noeud i de N_avant + noeud i de N_arriere |" << "\n# | + noeud i de N_milieu). Comme il s'agit de la famille de ddl de type UX, donc deplacement, en 3D |" << "\n# | on doit donc avoir 3*3 coef + 1 pour la valeur de la condition = 10 coef pour la condition qui s'ecrit |" << "\n# | donc : a1 UX(1) + a2 UY(1) + a3 UZ(1) + a4 UX(2) +..... + a9 UZ(3) = a10 |" << "\n# | UX(1) correspond au deplacement du noeud de la reference de N_avant, UX(2) pour N_arriere, UX(3) pour |" << "\n# | N_milieu, a10 est la condition imposee |" << "\n# | Ensuite toujours sur la meme ligne on peut eventuellement indiquer un temps mini et un temps maxi |" << "\n# | ex1 TEMPS_MINI= 0.1 TEMPS_MAXI= 5. |" << "\n# | Puis toujours sur la meme ligne, on peut eventuellement indiquer que la condition est relative ou non |" << "\n# | par defaut la condition est absolue, cela signifie que l'on se refere a la situation a t=0 |" << "\n# | dans le cas d'une condition relative, on se refere a la situation precedente: cependant, ce mecanisme |" << "\n# | ne fonctionne que si dans le cas de l'utilisation de fonction de charge (cf. suite des infos) |" << "\n# | ex1 CONDITION_RELATIVE= 1 # =0 absolue, =1 relative |" << "\n# | NB: tous la ligne: ref secondaire, temps mini maxi, condition realtive, est optionnelle, cela signifie |" << "\n# | quelle peut ne pas exister du tout, ou comporter quelques elements seulement. |" << "\n# | |" << "\n# | Ensuite sur la ligne suivante et on indique tout d'abord la valeur de la condition lineaire, (correspond à a10|" << "\n# | dans l'exemple 1 ) puis la la liste des coefficients de la conditions lineaire encadre par 2 mots cle |" << "\n# | ex1 val_condi_lineaire= 10 coefficients= 1 2 3 4 5 6 7 8 9 10 fin_list_coefficients_ |" << "\n# | ensuite on indique eventuellement s'il y a des fonctions de charges pour les coefficients avec la presence |" << "\n# | ou non du mot cle AvecFonctionsDeCharges_ |" << "\n# | ex1 val_condi_lineaire= 10 coefficients= 1 2 3 4 5 6 7 8 9 10 fin_list_coefficients_ AvecFonctionsDeCharges_ |" << "\n# | s'il y a des fonctions de charge, il doit y en avoir exactement le meme nombre que de coefficient+1 (pour |" << "\n# | la valeur de la condition limite ) on a donc une liste de nom de fonction de charge encadree par 2 mots cle |" << "\n# | la premiere fonction de charge s'applique sur la condition, la deuxieme sur le coefficient 1, la ieme sur le |" << "\n# | coefficient i-1. La liste des noms des fct de charge s'indique sur la ligne qui suit |" << "\n# | ex1 deb_fonction_de_charge= chc ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch9 fin_list_fonctions_de_charges_ |" << "\n#........................................................................................................................." << "\n# exemple complet" << "\n nom_mail= solide1 N_avant enu= UX " << "\n refs_associe= nom_mail= solide2 N_arriere N_milieu fin_list_refs_associe_ TEMPS_MINI= 0.1 TEMPS_MAXI= 5. " << "\n val_condi_lineaire= 10 coefficients= 1 2 3 4 5 6 7 8 9 fin_list_coefficients_ AvecFonctionsDeCharges_ " << "\n deb_fonction_de_charge= chc ch1 ch2 ch3 ch4 ch5 ch6 ch7 ch8 ch9 fin_list_fonctions_de_charges_ " << "\n#........................................................................................................................." << endl; } case 2: // informations succinctes a l'écran { cout << "\n cas particulier 1 : CLL: proj sur plan en 3D (droite en 2D) " << " --> permet de construire les parametres d'une CLL a partir de la " << " def d'un plan de projection en 3D (ou d'une droite de projection pour le 2D)" << "\n ** warning ** un noeud qui supporte une CLL de projection ne peut pas supporter une autre" << " condition : CL ou CLL !!! "; cout << "\n cas particulier 2 : stricte_egalite_ : c-a-d stricte egalite entre ddl de type enu " << " --> aucune donnee supplementaire n'est necessaire apres le mot cle stricte_egalite_ " << "\n ** warning ** contrairement aux autres cas : un noeud qui supporte une CLL stricte " << "\n egalite peut egalement supporter une autre condition : CL ou CLL !!! "; cout << "\n CLL: generale --> permet de construire une relation lineaire quelconque entre " << " les ddl d'un ou plusieurs noeuds. Contrairement aux CLL de projection, un noeud peut" << " supporter autant de CL et/ou de CLL qu'il a de ddl libres (mais pas plus sinon une " << " erreur est generee ) " << endl; break; } case 3: // CLL: proj sur plan en 3D (droite en 2D) { type_CLL = 1; rep = "f"; break;} case 4: // CLL: generale { type_CLL = 2; rep = "f";break;} case 5: // CLL: stricte_egalite_ { type_CLL = 3; rep = "f";break;} default: cout << "\n le cas "< tab_Co_charges; // tableau des noms de fonctions de charges // tableau des choix possibles Tableau tab_choix(9); tab_choix(1) = "\n (0 ou f) (fin) "; tab_choix(2) = "\n (1) reference des noeuds "; tab_choix(3) = "\n (2) def d'1 pt fixe du plan via coordonnees "; tab_choix(4) = "\n (3) ou def d'1 pt fixe du plan = noeud a t=0 "; tab_choix(5) = "\n (4) ou def d'1 pt mobile du plan = noeud a tdt "; tab_choix(6) = "\n (5) normale au plan "; tab_choix(7) = "\n (6) temps mini "; tab_choix(8) = "\n (7) temps maxi "; tab_choix(9) = "\n (8) def fonctions de charge "; string nom_ref=""; ostringstream flux; while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { try { for (int i=1;i<=tab_choix.Taille();i++) cout << tab_choix(i); cout << "\n >>> il faut obligatoirement definir (1)+{(2)ou(3)ou(4)}+(5) <<< "; cout << "\n rep : "; rep = lect_return_defaut(false,"f"); cout << " grandeur lue " << rep; if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie // c'est à la sortie que ce fait l'écriture donc ici {sort << "\n"; if ((nom_ref == " ")||(type_point==0)||(N.Dimension()==0)) {cout <<"\n ** CLL incomplete, pas d'ecriture "; break; }; if (plusieurs_maillages) { cout << "\n nom du maillage ? "; string nom_mail; nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; sort << "nom_mail= "<< nom_mail << " "; }; sort << nom_ref <<" enu= X1 "; // temps mini et maxi éventuel if ((temps_mini != - ConstMath::trespetit)||(temps_maxi != ConstMath::tresgrand)) {sort << "\n"; if (temps_mini != (- ConstMath::trespetit)) sort << " TEMPS_MINI= "<< temps_mini<<" "; if (temps_maxi != ConstMath::tresgrand) sort << " TEMPS_MAXI= "<< temps_maxi<<" "; }; // la condition sort << "\n def_auto_coef_planOuDroite_ "; switch (type_point) { case 1: sort << " centre_fixe_ "; M.Affiche_1(sort);break; case 2: sort << " centre_noeud_a_t0_ " << nom_mail_centre << numNoeud_0; break; case 3: sort << " centre_noeud_a_t_ " << nom_mail_centre << numNoeud_t; break; }; // les coefficients sort << " coefficients= "; N.Affiche_1(sort); sort << " fin_list_coefficients_ "; // fonctions de charge éventuelles if (tab_Co_charges.Taille() != 0) {sort << " AvecFonctionsDeCharges_ \n deb_fonction_de_charge= "; for (int i=1;i<=tab_Co_charges.Taille();i++) sort << tab_Co_charges(i) << " "; sort << " fin_list_fonctions_de_charges_ "<< endl; }; break; }; int num = ChangeEntier(rep); bool choix_valide=false; if ((num >= 0)&&(num<=8)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 8 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; } switch (num) { case 0: // sortie { break;} case 1: // reference des noeuds { cout << "\n nom de la ref de noeud pour l'application de la condition ? "; nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; if (nom_ref.at(0) != 'N') {cout << "\n *** erreur, la premiere lettre de la ref de noeuds " << " doit etre N et non "<< nom_ref.at(0)<< " !! *** " << " \n ** cette ref n'est pas valide !! ** \n "; nom_ref = " "; // on re init break; }; break; } case 2: // def d'1 pt fixe du plan via coordonnees { if (type_point != 0) cout << "\n ** warning vous definissez un nouveau point du plan " << " qui va donc remplasser votre precedent point "; switch (dim) {case 3: {cout << "\n def d'un pt du plan via la def de ses coordonnees: "; // comme on a plusieurs entrée on va utiliser un cin cout << "\n donner 3 reels "; for (int i=1;i<4;i++) cin >> M(i); type_point=1; cout << " valeurs lue =";M.Affiche(); std::cin.ignore( std::numeric_limits::max(), '\n' );// vide cin break; } case 2: // comme on a plusieurs entrée on va utiliser un cin {cout << "\n donner 2 reels "; for (int i=1;i<3;i++) cin >> M(i); type_point=1; cout << " valeurs lue =";M.Affiche(); std::cin.ignore( std::numeric_limits::max(), '\n' );// vide cin break; } default: choix_valide=false; break; }; break; } case 3: // ou def d'1 pt fixe du plan = noeud a t=0 { if (type_point != 0) cout << "\n (** warning vous definissez un nouveau point du plan " << " qui va donc remplasser votre precedent point) "; cout << "\n def numero du noeud dont la position initiale sera un point du plan" << "\n numero ? : "; numNoeud_0 = (int) lect_double();cout << " valeur lue ="<< numNoeud_0; if (plusieurs_maillages) { cout << "\n nom du maillage associe ? "; string nom_mail_centre; nom_mail_centre= lect_chaine(); cout << " nom lu = "<< nom_mail_centre; }; type_point=2; break; } case 4: //ou def d'1 pt mobile du plan = noeud a tdt { if (type_point != 0) cout << "\n (** warning vous definissez un nouveau point du plan " << " qui va donc remplasser votre precedent point) "; cout << "\n def numero du noeud dont la position finale sera un point du plan " << "\n numero ? : "; numNoeud_t=(int)lect_double();cout << " valeur lue ="<< numNoeud_t; if (plusieurs_maillages) { cout << "\n nom du maillage associe ? "; string nom_mail_centre; nom_mail_centre= lect_chaine(); cout << " nom lu = "<< nom_mail_centre; }; type_point=3; break; } case 5: // def normale au plan { cout << "\n normale au plan (ou droite) ? "; N.Change_dim(dim); switch (dim) {case 3: {cout << "\n donner 3 reels "; for (int i=1;i<4;i++) cin >> N(i); cout << " valeurs lue =";N.Affiche(); std::cin.ignore( std::numeric_limits::max(), '\n' );//on vide cin break; } case 2: {cout << "\n donner 2 reels "; for (int i=1;i<3;i++) cin >> N(i); cout << " valeurs lue =";N.Affiche(); std::cin.ignore( std::numeric_limits::max(), '\n' );//on vide cin break; } default: cout << "\n en 1D les CLL de projection ne sont pas possible "; choix_valide=false; break; }; break; } case 6: // temps mini { cout << "\n valeur du temps mini (un reel) ? "; temps_mini=lect_double();cout << " valeur lue ="<< temps_mini; break; } case 7: // temps maxi { cout << "\n valeur du temps maxi (un reel) ? "; temps_maxi=lect_double();cout << " valeur lue ="<< temps_maxi; break; } case 8: // def des courbes de charges { tab_Co_charges.Change_taille(dim); cout << "\n il faut definir "< list_ref_secondaires; // liste des références secondaires list list_mail_secondaires; // la liste des maillages associées à list_ref_secondaires Tableau tab_coef_CLL; // tableau des coef de la CLL Tableau tab_Co_charges; // tableau des noms de fonctions de charges bool condition_relative = false; // par défaut // tableau des choix possibles Tableau tab_choix(11); tab_choix(1) = "\n (0 ou f) (fin) "; tab_choix(2) = "\n (1) reference principale de noeuds "; tab_choix(3) = "\n (2) references secondaires de noeuds "; tab_choix(4) = "\n (3) type de degre de liberte "; tab_choix(5) = "\n (4) valeur de la CLL "; tab_choix(6) = "\n (5) coefficients de la CLL "; tab_choix(7) = "\n (6) condition relative "; tab_choix(8) = "\n (7) temps mini "; tab_choix(9) = "\n (8) temps maxi "; tab_choix(10) = "\n (9) def fonctions de charge "; tab_choix(11) = "\n (10) test si la CLL est recevable "; string nom_ref=""; ostringstream flux; while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { try { for (int i=1;i<=tab_choix.Taille();i++) cout << tab_choix(i); cout << "\n >>> il faut obligatoirement definir a minima (1)+(3)+(4)+(5) <<< " << "\n et de preference dans l'ordre indique "; cout << "\n rep : "; rep = lect_return_defaut(false,"f"); cout << " grandeur lue " << rep; if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie // c'est à la sortie que ce fait l'écriture donc ici {sort << "\n"; int nb_val = (dim*(list_ref_secondaires.size()+1)); if ((nom_ref == " ")||(tab_coef_CLL.Taille()!=nb_val) ||((tab_Co_charges.Taille()!=0)&&(tab_Co_charges.Taille()!=nb_val)) ) {cout <<"\n ** CLL incomplete, pas d'ecriture "; break; }; if (plusieurs_maillages) { cout << "\n nom du maillage pour la ref principale ? "; string nom_mail; nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; sort << "nom_mail= "<< nom_mail << " "; }; sort << nom_ref <<" enu= " << Nom_ddl(enu); // références secondaires éventuelles et / ou // temps mini et maxi éventuel if ( ((temps_mini != - ConstMath::trespetit)||(temps_maxi != ConstMath::tresgrand)) || (list_ref_secondaires.size() != 0)) {sort << "\n"; // les ref secondaires if (list_ref_secondaires.size() != 0) {list ::iterator ideb = list_ref_secondaires.begin(); list ::iterator idfin = list_ref_secondaires.end(); list ::iterator ill = list_mail_secondaires.begin(); sort << " refs_associe= "; if (plusieurs_maillages) {for (;ideb != idfin;ideb++, ill++) sort << "nom_mail= "<< (*ill) << " " << (*ideb) << " "; } else {for (;ideb != idfin;ideb++, ill++) sort << (*ideb) << " "; }; sort << " fin_list_refs_associe_ "; }; // encadrement en temps if (temps_mini != (- ConstMath::trespetit)) sort << " TEMPS_MINI= "<< temps_mini<<" "; if (temps_maxi != ConstMath::tresgrand) sort << " TEMPS_MAXI= "<< temps_maxi<<" "; // le cas d'une condition relative ou pas if (condition_relative) sort << " CONDITION_RELATIVE= 1 "; }; // la condition sort << "\n val_condi_lineaire= " << val_condi << " coefficients= "; // les coefficients for (int i=1;i<=nb_val;i++) sort << tab_coef_CLL(i) << " "; sort << " fin_list_coefficients_ "; // fonctions de charge éventuelles if (tab_Co_charges.Taille() != 0) {sort << " AvecFonctionsDeCharges_ \n deb_fonction_de_charge= "; for (int i=1;i<=tab_Co_charges.Taille();i++) sort << tab_Co_charges(i) << " "; sort << " fin_list_fonctions_de_charges_ "; }; sort << endl << std::flush; break; }; int num = ChangeEntier(rep); bool choix_valide=false; if ((num >= 0)&&(num<=10)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 8 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; } switch (num) { case 0: // sortie { break;} case 1: // reference principale de noeuds { cout << "\n nom de la ref de noeud pour l'application de la condition ? "; nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; if (nom_ref.at(0) != 'N') {cout << "\n *** erreur, la premiere lettre de la ref de noeuds " << " doit etre N et non "<< nom_ref.at(0)<< " !! *** " << " \n ** cette ref n'est pas valide !! ** \n "; nom_ref = " "; // on re init break; }; break; } case 2: // references secondaires de noeuds { bool fin = false; string nom_ref_inter=" "; while (!fin) { cout << "\n nom d'une ref de noeud secondaire ou f (ou 0 ou o) pour finir ? "; nom_ref_inter= lect_chaine();cout << " nom lu = "<< nom_ref_inter; if ((Minuscules(nom_ref_inter) == "f")||(Minuscules(nom_ref_inter)=="o") ||(Minuscules(nom_ref_inter)=="0")) {break;} else if (nom_ref_inter.at(0) != 'N') {cout << "\n *** erreur, la premiere lettre de la ref de noeuds " << " doit etre N et non "<< nom_ref_inter.at(0)<< " !! *** " << " \n ** cette ref n'est pas valide !! ** \n "; nom_ref_inter = " "; // on re init } else { if (plusieurs_maillages) { cout << "\n nom du maillage associe ? "; string nom_mail_associe; nom_mail_associe= lect_chaine(); cout << " nom lu = "<< nom_mail_associe; list_mail_secondaires.push_back(nom_mail_associe); }; list_ref_secondaires.push_back(nom_ref_inter); }; }; break; } case 3: // type de degre de liberte { cout << "\n type d'un ddl de la condition lineaire: (ex: UX ou UY ou X1 ou V1 ...): "; string enu_essai; enu_essai= lect_chaine();cout << " valeur lue ="<> tab_coef_CLL(i); cout << " ( valeur lue : "<::max(), '\n' );// on vide cin break; } case 6: // condition relative { string reponse; cout << "\n condition relative (rep: o ou n ) ? "; reponse = lect_o_n(false); cout << " (valeurs lue = "< temps_maxi) {cout <<"\n ** CLL complete mais inchoerente car le temps mini ("< list_ref_secondaires; // liste des références secondaires list list_mail_secondaires; // la liste des maillages associées à list_ref_secondaires bool condition_relative = false; // par défaut // tableau des choix possibles Tableau tab_choix(7); tab_choix(1) = "\n (0 ou f) (fin) "; tab_choix(2) = "\n (1) reference principale de noeuds "; tab_choix(3) = "\n (2) references secondaires de noeuds "; tab_choix(4) = "\n (3) type de degre de liberte "; tab_choix(5) = "\n (4) temps mini "; tab_choix(6) = "\n (5) temps maxi "; tab_choix(7) = "\n (6) test si la CLL est recevable "; string nom_ref=""; ostringstream flux; while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) { try { for (int i=1;i<=tab_choix.Taille();i++) cout << tab_choix(i); cout << "\n >>> il faut obligatoirement definir a minima (1)+(2) <<< " << "\n et de preference dans l'ordre indique "; cout << "\n rep : "; rep = lect_return_defaut(false,"f"); cout << " grandeur lue " << rep; if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie // c'est à la sortie que ce fait l'écriture donc ici {sort << "\n"; if ((nom_ref == " ")||(list_ref_secondaires.size()==0) ) {cout <<"\n ** CLL incomplete, pas d'ecriture "; break; }; if (plusieurs_maillages) { cout << "\n nom du maillage pour la ref principale ? "; string nom_mail; nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; sort << "nom_mail= "<< nom_mail << " "; }; sort << nom_ref <<" enu= " << Nom_ddl(enu); // références secondaires éventuelles et / ou // temps mini et maxi éventuel if ( ((temps_mini != - ConstMath::trespetit)||(temps_maxi != ConstMath::tresgrand)) || (list_ref_secondaires.size() != 0)) {sort << "\n"; // les ref secondaires if (list_ref_secondaires.size() != 0) {list ::iterator ideb = list_ref_secondaires.begin(); list ::iterator idfin = list_ref_secondaires.end(); list ::iterator ill = list_mail_secondaires.begin(); sort << " refs_associe= "; if (plusieurs_maillages) {for (;ideb != idfin;ideb++, ill++) sort << "nom_mail= "<< (*ill) << " " << (*ideb) << " "; } else {for (;ideb != idfin;ideb++, ill++) sort << (*ideb) << " "; }; sort << " fin_list_refs_associe_ "; }; // encadrement en temps if (temps_mini != (- ConstMath::trespetit)) sort << " TEMPS_MINI= "<< temps_mini<<" "; if (temps_maxi != ConstMath::tresgrand) sort << " TEMPS_MAXI= "<< temps_maxi<<" "; // le cas d'une condition relative ou pas if (condition_relative) sort << " CONDITION_RELATIVE= 1 "; }; // la condition sort << "\n stricte_egalite_ " ; sort << endl << std::flush; break; }; int num = ChangeEntier(rep); bool choix_valide=false; if ((num >= 0)&&(num<=6)) { choix_valide=true; } else { cout << "\n Erreur on attendait un entier entre 0 et 6 !!, " << "\n redonnez une bonne valeur" << "\n ou taper f ou 0 pour arreter le programme"; choix_valide=false; } switch (num) { case 0: // sortie { break;} case 1: // reference principale de noeuds { cout << "\n nom de la ref de noeud pour l'application de la condition ? "; nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; if (nom_ref.at(0) != 'N') {cout << "\n *** erreur, la premiere lettre de la ref de noeuds " << " doit etre N et non "<< nom_ref.at(0)<< " !! *** " << " \n ** cette ref n'est pas valide !! ** \n "; nom_ref = " "; // on re init break; }; break; } case 2: // references secondaires de noeuds { bool fin = false; string nom_ref_inter=" "; while (!fin) { cout << "\n nom d'une ref de noeud secondaire ou f (ou 0 ou o) pour finir ? "; nom_ref_inter= lect_chaine();cout << " nom lu = "<< nom_ref_inter; if ((Minuscules(nom_ref_inter) == "f")||(Minuscules(nom_ref_inter)=="o") ||(Minuscules(nom_ref_inter)=="0")) {break;} else if (nom_ref_inter.at(0) != 'N') {cout << "\n *** erreur, la premiere lettre de la ref de noeuds " << " doit etre N et non "<< nom_ref_inter.at(0)<< " !! *** " << " \n ** cette ref n'est pas valide !! ** \n "; nom_ref_inter = " "; // on re init } else { if (plusieurs_maillages) { cout << "\n nom du maillage associe ? "; string nom_mail_associe; nom_mail_associe= lect_chaine(); cout << " nom lu = "<< nom_mail_associe; list_mail_secondaires.push_back(nom_mail_associe); }; list_ref_secondaires.push_back(nom_ref_inter); }; }; break; } case 3: // type de degre de liberte { cout << "\n type d'un ddl de la condition lineaire: (ex: UX ou UY ou X1 ou V1 ...): "; string enu_essai; enu_essai= lect_chaine();cout << " valeur lue ="< temps_maxi) {cout <<"\n ** CLL complete mais inchoerente car le temps mini ("< & t_noe,Condilineaire& condi_actuelle) { // tout d'abord on évacue le cas de l'égalité stricte qui implique : rien n'a faire ! if (stricte_egalite) return condi_actuelle; // condi_actuelle inchangée et ne doit servir à rien // on renseigne la condition Noeud * noe = t_noe(1); // le premier noeud est celui où on met la condition condi_actuelle.ChangeTabNoeud(t_noe); // on renseigne la condition // dimensionnement de la condition de retour, car val peut avoir été changé indépendamment condi_actuelle.Change_taille(val.Taille()); Vecteur val_inter(val); // le vecteur qui contient les coeffs, est utiliser car dans le cas // d'une def auto droite plan, les coeffs sont récupéré donc modifié if (def_auto_par_rotation) { // cas d'une définition par rapport à une droite ou un plan // on récupère les valeurs qui ont été calculées au moment des projections 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--; // la valeur de la condition a déjà été calculée au moment de la projection switch (dima) {case 2: // on tourne autour de z { val_inter(1) = -dr.VecDroite()(2); val_inter(2) = dr.VecDroite()(1); break; } case 3: { val_inter = (pl.Vecplan()).Vect(); // pour simplifier break; } }; }; // --- on met la condition ----- if ((tab_co_charge.Taille() == 0) || def_auto_par_rotation) // cas sans fonction de charge, on applique la valeur complète // dans le cas d'une projection plan ou droite, l'échelle est systématiquement = 1. (vérif à la lecture) // et on ne tient pas compte de la première fonction de charge { condi_actuelle.BetaChange() = echelle * beta ;} else // cas avec fonction de charge, que ce soit en relatif ou pas, on applique la valeur à t // (le coté relatif est a appliqué au niveau des ddl des noeuds, qui sont des valeurs issues // du calcul d'équilibre, et non au niveau des valeurs fixés qui elles peuvent être déterminées // à l'avance, donc pour ces dernières aucun intérêts de faire du relatif, par contre pour les ddl // des noeuds, là le coté relatif est important car il permet d'ajouter à un ddl dont la valeur // est issue du précédent calcul, donc pas connue à l'avance) { condi_actuelle.BetaChange() = echelle * beta * fctch(1) ;}; // --- maintenant on s'occupe des pointeurs et des coefficients double valfinalSurddlAbloquer = 0; // on calcul en même temps la valeur à imposer Tableau t_enu(val.Taille()); // tableau des identificateur de ddl de la CLL // $-$ NB: on traite différemment selon qu'il s'agisse de conditions linéaires entre position ou déplacement, // $-$ ou sur des autres ddl, because, le cas déplacement-position est un peu particulier mais cependant // $-$ globalement c'est très ressemblant if (Meme_famille(enu,X1) || Meme_famille(enu,UX)) { // le premier indice correspondra a la direction bloquee, il faut s'assurer qu'il ne // soit pas nul et qu'il ne correspond pas a une direction deja bloquee par les conditions // limites de depart // on boucle sur la dim pour trouver le coef le plus grand correspondant a une direction // non bloquee 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 iti=0;int indi = 0; double maxi = ConstMath::petit; int posi = Id_nom_ddl("X1") -1; // position du ddl X1 // on cherche le numero de ddl libre qui est associé à la valeur maxi différente de 0 if ((!def_auto_par_rotation)&&(tab_co_charge.Taille() != 0)) // dans le cas normal, avec fonction de charge, on tiens compte de ces fonctions {for (iti=1; iti<= dima; iti++) { if (!noe->Ddl_fixe(Enum_ddl(posi+iti))) // cas d'un ddl libre {double coef_reel = Dabs(val_inter(iti) * fctch(iti+1)); if (coef_reel > maxi) // cas d'une valeur de coefficient non nul { maxi = coef_reel; indi = iti; }; } }; } else // autres cas: cas des projections ou cas sans fonction de charge {for (iti=1; iti<= dima; iti++) { if (!noe->Ddl_fixe(Enum_ddl(posi+iti))) // cas d'un ddl libre if (Dabs(val_inter(iti)) > maxi) // cas d'une valeur de coefficient non nul { maxi = Dabs(val_inter(iti)); indi = iti; }; }; }; if (indi ==0) { // cas ou soit les dima ddl sont bloque, soit le vecteur normal = 0 cout << "\n erreur dans une condition limite lineaire , on ne peut pas imposer de condition lineaire" << " car soit les ddl de deplacement du noeud principal de la condition sont deja tous bloque, " << " soit le vecteur condition (les coeffs) est nul \n"; noe->Affiche(); cout << "\n les coeff : " ; val_inter.Affiche(); cout << "Condilineaire& I_O_Condilineaire::ConstructionCondition(.." << endl; Sortie (1); }; // on indique que la nouvelle direction "indi" est bloque, ceci permet // pour une autre condition, de ne pas reprendre cette direction // --> ce marquage est effacer apres resolution, par la fonction efface blocage Enum_ddl leEnuAChanger = Enum_ddl(posi+indi); // le enu du ddl_k de la condition noe->Change_fixe(leEnuAChanger,true); condi_actuelle.ChangeIddl() = indi; // on enregistre la position // on avance dans la constitution de valfinalSurddlAbloquer double unsurcoef1 = 1./val_inter(condi_actuelle.Iddl()); // correspond à 1/alph_k de la condition if ((!def_auto_par_rotation)&&(tab_co_charge.Taille() != 0)) // dans le cas normal, avec fonction de charge, on tiens compte de ces fonctions unsurcoef1 = 1./fctch(indi+1); // constitution de la condition lineaire int itab = 0.; // définit à l'extérieur car va continuer à s'incrémenter sur la deuxième boucle qui suit for (itab=1;itab<= dima;itab++) { // condi_actuelle.val_inter(1) correspond à coef(indi), puis les autres suivent double coefindi =0.; if (!def_auto_par_rotation) { if (tab_co_charge.Taille() == 0) { coefindi = val(indi) ; } else { coefindi = val(indi) * fctch(indi+1) ;}; } else // dans le cas plan droite les coef sont déjà intégrés {coefindi = val_inter(indi);}; t_enu(itab)= Enum_ddl(posi+indi); // sauvegarde de l'enum associé condi_actuelle.Valchange()(itab) = echelle * coefindi; // pour le coefficient //-------------- // suite constitution de valfinalSurddlAbloquer : if (itab == 1) // correspond à beta/alpha_k { valfinalSurddlAbloquer = condi_actuelle.Beta() * unsurcoef1; } else // correspond à -alph_i/alph_k * U_i // il faut distinguer les cas suivant que c'est une condition linéaire entre Xi ou entre Ui // et que l'on est en relatif ou pas { if (condition_relative) // dans le cas d'une projection, par construction (vérif à la lecture), la condition n'est pas relative !! { // que ce soit en Xi ou en Ui, comme on est en relatif il faut considérer l'accroissement valfinalSurddlAbloquer -= echelle * coefindi * unsurcoef1 // **** a priori une erreur : 23 sep 2014 * (noe->Valeur_tdt(Enum_ddl(posi+itab)) - noe->Valeur_t(Enum_ddl(posi+itab)) ) ; * (noe->Valeur_tdt(Enum_ddl(posi+indi)) - noe->Valeur_t(Enum_ddl(posi+indi)) ) ; } else // donc ici il s'agit d'une condition absolue { if (Meme_famille(enu,X1)) // cas d'une CLL entre Xi on y accède directement // **** a priori une erreur : 23 sep 2014 { valfinalSurddlAbloquer -= echelle * coefindi * unsurcoef1 * noe->Valeur_tdt(Enum_ddl(posi+itab)) ;} { valfinalSurddlAbloquer -= echelle * coefindi * unsurcoef1 * noe->Valeur_tdt(Enum_ddl(posi+indi)) ; ////--debug //cout << "\n debug I_O_Condilineaire::ConstructionCondition noe_val= " << noe->Valeur_tdt(Enum_ddl(posi+indi)) // << " valfinalSurddlAbloquer= " << valfinalSurddlAbloquer << " coefindi= " << coefindi << " unsurcoef1= " << unsurcoef1 // << "Enum_ddl(posi+indi)= " << Enum_ddl(posi+indi) << endl ; ////--fin debug } else // cas d'une CLL entre Ui, il faut donc prendre en compte le delta Xi entre 0 et tdt { valfinalSurddlAbloquer -= echelle * coefindi * unsurcoef1 // **** a priori une erreur : 23 sep 2014 * (noe->Valeur_tdt(Enum_ddl(posi+itab)) - noe->Valeur_0(Enum_ddl(posi+itab)) ) ; * (noe->Valeur_tdt(Enum_ddl(posi+indi)) - noe->Valeur_0(Enum_ddl(posi+indi)) ) ; }; }; }; //------------------- indi ++; if (indi > dima) indi = 1; // on fait une rotation circulaire }; // cas des noeuds des références secondaires int nbnsecondaire = refs_associe.Taille(); for (int nn=2; nn<=nbnsecondaire+1; nn++) // le premier noeud secondaire est pour nn=2 { Noeud & noese = *(t_noe(nn)); // récup du pointeur d'assemblage -1 #ifdef MISE_AU_POINT if (def_auto_par_rotation) { cout << "\nErreur : on ne doit pas avoir de ref secondaire avec la def auto " << '\n' << "Condilineaire& I_O_Condilineaire::ConstructionCondition(.. 3\n"; Sortie(1); }; #endif for (int ia=1;ia<= dima;ia++,itab++) { double coefitab =0.; if (tab_co_charge.Taille() == 0) { coefitab = val_inter(itab) ; } else { coefitab = val_inter(itab) * fctch(itab+1) ;}; t_enu(itab)= Enum_ddl(posi+ia); // sauvegarde de l'enum associé condi_actuelle.Valchange()(itab) = echelle * coefitab; // pour le coefficient // suite constitution de valfinalSurddlAbloquer : correspond à -alph_i/alph_k * U_i // il faut distinguer les cas suivant que c'est une condition linéaire entre Xi ou entre Ui // et que l'on est en relatif ou pas if (condition_relative) // dans le cas d'une projection, par construction (vérif à la lecture), la condition n'est pas relative !! { // que ce soit en Xi ou en Ui, comme on est en relatif il faut considérer l'accroissement valfinalSurddlAbloquer -= echelle * coefitab * unsurcoef1 * (noese.Valeur_tdt(Enum_ddl(posi+ia)) - noese.Valeur_t(Enum_ddl(posi+ia)) ) ; } else // donc ici il s'agit d'une condition absolue { if (Meme_famille(enu,X1)) // cas d'une CLL entre Xi on y accède directement { valfinalSurddlAbloquer -= echelle * coefitab * unsurcoef1 * noese.Valeur_tdt(Enum_ddl(posi+ia)) ;} else // cas d'une CLL entre Ui, il faut donc prendre en compte le delta Xi entre 0 et tdt { valfinalSurddlAbloquer -= echelle * coefitab * unsurcoef1 * (noese.Valeur_tdt(Enum_ddl(posi+ia)) - noese.Valeur_0(Enum_ddl(posi+ia)) ) ; }; }; }; }; // on met à jour le tableau d'enum de la condition condi_actuelle.Change_tab_enum(t_enu); // on finit le calcul de la valeur du ddl imposé if (condition_relative) { // que ce soit en Xi ou en Ui, comme on est en relatif // comme le ddl au niveau du noeud est Xi, il faut le rajouter valfinalSurddlAbloquer += noe->Valeur_t(leEnuAChanger); } else // donc ici il s'agit d'une condition absolue { if (Meme_famille(enu,X1)) // cas d'une CLL entre Xi on a rien à faire, valfinalSurddlAbloquer est directement = à // la valeur a imposer { } else // cas d'une CLL entre Ui, il faut donc prendre en compte le delta Xi entre 0 et tdt // comme le ddl au niveau du noeud est Xi, il faut le rajouter { valfinalSurddlAbloquer += noe->Valeur_0(leEnuAChanger);}; }; // et maintenant on sauvegarde la valeur a bloquer sur le noeud dans la condition linéaire // cette condition correspondra au ddl_i' dans le nouveau repèrere qui recevra la condition bloqué // en fait ddl_i sera la seule modification de ddl due à la mise en place de la CLL // !!! par contre ce changement de valeur n'est pas à effectuer dans le cas des projections, // car dans ce cas, d'une part valfinalSurddlAbloquer doit toujours être à 0 et d'autre part // la valeur des coordonnées est fixées lors de la projection et non ici if (!def_auto_par_rotation) { condi_actuelle.ChangeUk_impose(valfinalSurddlAbloquer);} else { condi_actuelle.ChangeUk_impose(ConstMath::tresgrand);}; /* 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 seule modification de ddl due à la mise en place de la CLL // !!! par contre ce changement de valeur n'est pas à effectuer dans le cas des projections, // car dans ce cas, d'une part valfinalSurddlAbloquer doit toujours être à 0 et d'autre part // la valeur des coordonnées est fixées lors de la projection et non ici noe->Change_val_tdt(leEnuAChanger,valfinalSurddlAbloquer); */ } // -- fin du cas d'une condition linéaire sur un déplacement ou position else { // -- cas d'une famille autre que déplacement ou position // (en fait pas de diff mais je préfère pour l'instant séparer les deux ) // le premier indice correspondra a la direction bloquee, il faut s'assurer qu'il ne // soit pas nul et qu'il ne correspond pas a une direction deja bloquee par les conditions // limites de depart // on boucle pour trouver le coef le plus grand correspondant a une direction non bloquee int iti=0;int indi = 0; double maxi = ConstMath::petit; int posi = enu -1; // position du premier ddl de la famille // on cherche le nb de ddl libre qui est associé à la valeur maxi différente de 0 for (iti=1; iti<= nbddlfamille; iti++) { if (!noe->Ddl_noeud_tdt(Enum_ddl(posi+iti)).Fixe()) // cas d'un ddl libre if (Dabs(val(iti)) > maxi) // cas d'une valeur de coefficient non nul { maxi = Dabs(val(iti)); indi = iti; }; }; if (indi ==0) { // cas ou soit les dima ddl sont bloque, soit le vecteur normal = 0 cout << "\n erreur dans une condition limite lineaire , " << " soit les ddl de la famille " << Nom_ddl(enu) << " du noeud principal sont deja tous bloque, " << " soit le vecteur condition (les coeffs) est entierement nul \n"; noe->Affiche(); cout << "\n les coeff : " ; condi_actuelle.Valchange().Affiche(); cout << "Condilineaire& I_O_Condilineaire::ConstructionCondition(.." << endl; Sortie (1); }; // on indique que la nouvelle direction "indi" est bloque, ceci permet // pour une autre condition, de ne pas reprendre cette direction // --> ce marquage est effacer apres resolution, par la fonction efface blocage Enum_ddl leEnuAChanger = Enum_ddl(posi+indi); // le enu du ddl_k de la condition noe->Change_fixe(leEnuAChanger,true); condi_actuelle.ChangeIddl() = indi; // on enregistre la position // on avance dans la constitution de valfinalSurddlAbloquer double unsurcoef1 = 1./val_inter(condi_actuelle.Iddl()); // correspond à 1/alph_k de la condition // constitution de la condition lineaire int itab = 0.; // définit à l'extérieur car va continuer à s'incrémenter sur deuxième boucle qui suit for (itab=1;itab<= nbddlfamille;itab++) { // condi_actuelle.val(1) correspond à coeff(indi), puis les autres suivent double coefindi =0.; if (tab_co_charge.Taille() == 0) { coefindi = val(indi) ; } else { coefindi = val(indi) * fctch(indi+1) ;}; t_enu(itab)= Enum_ddl(posi+indi); // sauvegarde de l'enum associé condi_actuelle.Valchange()(itab) = echelle * coefindi; // pour le coefficient //-------------- // suite constitution de valfinalSurddlAbloquer : if (itab == 1) // correspond à beta/alpha_k { valfinalSurddlAbloquer = condi_actuelle.Beta() * unsurcoef1;} else // correspond à -alph_i/alph_k * U_i // il faut distinguer les cas suivant que c'est une condition linéaire entre Xi ou entre Ui // et que l'on est en relatif ou pas { if (condition_relative) // dans le cas d'une projection, par construction (vérif à la lecture), la condition n'est pas relative !! { // que ce soit en Xi ou en Ui, comme on est en relatif il faut considérer l'accroissement valfinalSurddlAbloquer -= echelle * coefindi * unsurcoef1 // **** a priori une erreur : 23 sep 2014 * (noe->Valeur_tdt(Enum_ddl(posi+itab)) - noe->Valeur_t(Enum_ddl(posi+itab)) ) ; * (noe->Valeur_tdt(Enum_ddl(posi+indi)) - noe->Valeur_t(Enum_ddl(posi+indi)) ) ; } else // donc ici il s'agit d'une condition absolue on y accède directement // **** a priori une erreur : 23 sep 2014 { valfinalSurddlAbloquer -= echelle * coefindi * unsurcoef1 * noe->Valeur_tdt(Enum_ddl(posi+itab)) ; { valfinalSurddlAbloquer -= echelle * coefindi * unsurcoef1 * noe->Valeur_tdt(Enum_ddl(posi+indi)) ; }; } //------------------- indi ++; if (indi > nbddlfamille) indi = 1; // on fait une rotation circulaire }; // cas des noeuds des références secondaires int nbnsecondaire = refs_associe.Taille(); for (int nn=2; nn<=nbnsecondaire+1; nn++) // le premier noeud secondaire est pour nn=2 { Noeud & noese = *(t_noe(nn)); for (int ia=1;ia<= nbddlfamille;ia++,itab++) {double coefitab =0.; if (tab_co_charge.Taille() == 0) { coefitab = val(itab) ; } else { coefitab = val(itab) * fctch(itab+1) ;}; condi_actuelle.Valchange()(itab) = echelle * coefitab; // pour le coefficient t_enu(itab)= Enum_ddl(posi+ia); // sauvegarde de l'enum associé // suite constitution de valfinalSurddlAbloquer : correspond à -alph_i/alph_k * U_i // il faut distinguer les cas suivant que c'est une condition linéaire entre Xi ou entre Ui // et que l'on est en relatif ou pas if (condition_relative) { // comme on est en relatif il faut considérer l'accroissement valfinalSurddlAbloquer -= echelle * coefitab * unsurcoef1 * (noese.Valeur_tdt(Enum_ddl(posi+ia)) - noese.Valeur_t(Enum_ddl(posi+ia)) ) ; } else // donc ici il s'agit d'une condition absolue on y accède directement { valfinalSurddlAbloquer -= echelle * coefitab * unsurcoef1 * noese.Valeur_tdt(Enum_ddl(posi+ia)) ; }; }; }; // on met à jour le tableau d'enum de la condition condi_actuelle.Change_tab_enum(t_enu); // on finit le calcul de la valeur du ddl imposé if (condition_relative) { // comme on est en relatif il faut rajouter la valeur à t valfinalSurddlAbloquer += noe->Valeur_t(leEnuAChanger); }; // sinon il n'y a rien à faire, valfinalSurddlAbloquer est directement = à // la valeur a imposer // et maintenant on sauvegarde la valeur a bloquer sur le noeud dans la condition linéaire // 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 condi_actuelle.ChangeUk_impose(valfinalSurddlAbloquer); /* // et maintenant 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 noe->Change_val_tdt(leEnuAChanger,valfinalSurddlAbloquer); */ }; // -- fin du cas d'une condition linéaire une famille quelconque autre que position et déplacement // retour // //--- debug // cout << "\n la condition lineaire : I_O_Condli "; // this->Affiche(); // cout << "\n la condition resultat "; // condi_actuelle.Affiche(); // // fin debug --- return condi_actuelle; }; // initialisation des grandeurs de travail void I_O_Condilineaire::Initialisation_condil() {Tableau tab_enu = TableauTypeDdlmobileAvecAxi(enu); nbddlfamille = tab_enu.Taille(); if (!stricte_egalite) // dans le cas stricte_egalité il n'y a pas de coef {// on vérifie l'adéquation des dimensions int ndimvec = nbddlfamille * (1+ refs_associe.Taille()); // nombre total de ddl concerné if (ndimvec != val.Taille()) { cout << "\n erreur de dimension: le nombre de coefficient de la condition limite = " << val.Taille() << " est different du nombre de ddl de la famille concernee " << nbddlfamille << " fois le nombre de noeud " << " c'est-a-dire (1 + le nombre de ref secondaire) = " << (1+ refs_associe.Taille()) << " ce qui fait: " << ndimvec << endl; Sortie(1); }; }; }; // definition du noeud: centre rotation void I_O_Condilineaire::ChangeCentreNoeudRotation( Noeud* noe) {centre_noeud = noe; 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--; switch (dima) { case 2: switch(type_centre) {case 2 : dr.Change_ptref(noe->Coord0()); break; case 3 : dr.Change_ptref(noe->Coord2()); break; } break; case 3: switch(type_centre) {case 2 : pl.Change_ptref(noe->Coord0()); break; case 3 : pl.Change_ptref(noe->Coord2()); break; } break; }; // dans le cas ou type_centre = 1, on ne fait rien, donc le centre actuellement enregistré est maintenu }; // indique si le blocage qui existe déjà sur les noeuds à projeter, est cohérent // avec la projection: // typiquement si la direction de blocage est normale au plan de rotation // ramène true si on peut concerver la condition de projection // en entrée: indi qui donne la direction déjà bloquée bool I_O_Condilineaire::Coherence_condi_PlanDroite(int indi)const { bool retour = false; 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--; switch (dima) { case 2: { const Coordonnee& dro = dr.VecDroite(); if (Dabs(dro(indi)) < ConstMath::pasmalpetit) retour = true; break; } case 3: { const Coordonnee& N = pl.Vecplan(); if (Dabs(N(indi)) < ConstMath::pasmalpetit) retour = true; break; } default: break; // pour les autres dimensions on ne fait rien }; // retour return retour; }; // définition de la direction actuelle ou normale pour plan droite void I_O_Condilineaire::ActualiseDirectionPlanDroite() {// exécution en fonction de la présence de fonction de charge ou non Coordonnee dir(val.Coordo()); // val doit avoir la dimension du pb 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--; if (tab_co_charge.Taille() != 0) { for (int i=1;i<=dima;i++) dir(i) *= fctch(i+1) ; }; switch (dima) { case 2: dr.Change_vect(dir); break; // on met à jour la direction case 3: pl.Change_normal(dir); break; // on met à jour la direction }; }; // projection (normale) du point M sur le plan ou droite, ramène le point M à la place du // projeté, et calcul de la condition linéaire correspondant à la projection Coordonnee& I_O_Condilineaire::ProjectionSurPlanDroite_et_calValCondiLin(Coordonnee& M ) {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--; switch (dima) { case 2:{ M = dr.Projete(M); beta = -dr.VecDroite()(2)*M(1)+dr.VecDroite()(1)*M(2); break; } case 3:{ M = pl.Projete(M); beta = pl.Vecplan() * M ; break; } default: break; // pour les autres dimensions on ne fait rien }; // retour return M; }; // surcharge de l'operateur de lecture typée istream & operator >> (istream & entree, I_O_Condilineaire & cLL) { // vérification du type string type; entree >> type; if (type != "I_O_Condilineaire___ref_princ=") {cout << "\n erreur en lecture d'une condition lineaire " << "\n operator >> (istream & entree, I_O_Condilineaire & cLL) "; Sortie (1); return entree; } // lecture d'un nom de maillage éventuel bool existe_nom_maillage; entree >> existe_nom_maillage; string nom; if (existe_nom_maillage) { entree >> nom; if (cLL.nom_maillage == NULL) {cLL.nom_maillage = new string(nom);} else {*(cLL.nom_maillage) = nom;}; }; // maintenant la référence principale entree >> cLL.refe ; // les références associés int tai=0; entree >> nom >> tai; if (tai != 0) {cLL.refs_associe.Change_taille(tai); if (cLL.nom_maillage != NULL) {cLL.nom_mail_associe.Change_taille(tai); for (int i=1;i<=tai;i++) {entree >> cLL.nom_mail_associe(i) >> cLL.refs_associe(i); }; } else {for (int i=1;i<=tai;i++) {entree >> cLL.refs_associe(i); }; }; }; entree >> nom >> cLL.enu ; entree >> nom >> cLL.def_auto_par_rotation; entree >> nom >> cLL.stricte_egalite; 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--; if (cLL.stricte_egalite) { } else {if (cLL.def_auto_par_rotation) {entree >> nom >> cLL.type_centre; if (cLL.type_centre == 1) { entree >> nom; Coordonnee B; entree >> nom >> B; if (dima == 2) {cLL.dr.Change_ptref(B) ;} else {cLL.pl.Change_ptref(B) ;}; } else if ((cLL.type_centre == 2) || (cLL.type_centre == 3)) { entree >> nom >> cLL.mailEtNumCentreNoeud ;} Coordonnee V; entree >> nom >> V >> nom >> cLL.val; if (dima == 2) {cLL.dr.Change_vect(V);} else // cas dimension 3 {cLL.pl.Change_normal(V);}; } else { entree >> nom >> cLL.beta >> nom >> cLL.val;}; entree >> nom >> cLL.condition_relative >> nom >> cLL.echelle; entree >> nom >> cLL.tab_co_charge; }; // if (!cLL.def_auto_par_rotation) // { entree >> nom >> cLL.beta >> nom >> cLL.val;} // else // {entree >> nom >> cLL.type_centre; // if (cLL.type_centre == 1) // { entree >> nom; // Coordonnee B; // entree >> nom >> B; // if (ParaGlob::Dimension() == 2) // {cLL.dr.Change_ptref(B) ;} // else // {cLL.pl.Change_ptref(B) ;}; // } // else if ((cLL.type_centre == 2) || (cLL.type_centre == 3)) // { entree >> nom >> cLL.mailEtNumCentreNoeud ;} // Coordonnee V; // entree >> nom >> V >> nom >> cLL.val; // if (ParaGlob::Dimension() == 2) // {cLL.dr.Change_vect(V);} // else // cas dimension 3 // {cLL.pl.Change_normal(V);}; // }; entree >> nom >> cLL.t_min >> nom >> cLL.t_max >> nom >> cLL.precedent; return entree; }; // surcharge de l'operateur d'ecriture typée ostream & operator << ( ostream & sort,const I_O_Condilineaire & cLL) { // tout d'abord un indicateur donnant le type sort << " I_O_Condilineaire___ref_princ= " ; // puis le maillage éventuelle if (cLL.nom_maillage == NULL) {sort << false << " ";} else {sort << true << " " << *(cLL.nom_maillage) << " ";}; // maintenant la référence principale sort << cLL.refe << " "; // les références associés if (cLL.refs_associe.Taille() != 0) {int tai = cLL.refs_associe.Taille(); sort << " ref_associe___taille= " << tai << " "; for (int i=1;i<=tai;i++) if (cLL.nom_maillage != NULL) {sort << cLL.nom_mail_associe(i) << " " << cLL.refs_associe(i) << " ";} else {sort << cLL.refs_associe(i) << " ";} }; sort << "\n type_ddl= " << Nom_ddl(cLL.enu) ; sort << " def_auto_par_rotation= " << cLL.def_auto_par_rotation; sort << " stricte_egalite= " << cLL.stricte_egalite; 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--; if (cLL.stricte_egalite) { } else {if (cLL.def_auto_par_rotation) {sort << " type_centre= " << cLL.type_centre; if (cLL.type_centre == 1) { sort << " centre_fixe= " ; if (dima == 2) {sort << cLL.dr.PointDroite() << " " ;} else {sort << cLL.pl.PointPlan() << " " ;}; } else if (cLL.type_centre == 2) { sort << " centre_noeud_t0= " << cLL.mailEtNumCentreNoeud << " ";} else if (cLL.type_centre == 3) { sort << " centre_noeud_t= " << cLL.mailEtNumCentreNoeud << " ";}; if (dima == 2) {sort << " dir_droite_now= " << cLL.dr.VecDroite() << " dir_droite0= " << cLL.val;} else // cas dimension 3 {sort << " normal_plan_now= " << cLL.pl.Vecplan() << " normal_plan0= " << cLL.val;} } else { sort << " val_condi= " << cLL.beta << " coefficients= " << cLL.val;}; sort << " condition_relative= " << cLL.condition_relative << " " << " echelle= " << cLL.echelle; sort << "\n courbe_charge= " << cLL.tab_co_charge; }; // if (!cLL.def_auto_par_rotation) // { sort << " val_condi= " << cLL.beta << " coefficients= " << cLL.val;} // else // {sort << " type_centre= " << cLL.type_centre; // if (cLL.type_centre == 1) // { sort << " centre_fixe= " ; // if (ParaGlob::Dimension() == 2) {sort << cLL.dr.PointDroite() << " " ;} // else {sort << cLL.pl.PointPlan() << " " ;}; // } // else if (cLL.type_centre == 2) // { sort << " centre_noeud_t0= " << cLL.mailEtNumCentreNoeud << " ";} // else if (cLL.type_centre == 3) // { sort << " centre_noeud_t= " << cLL.mailEtNumCentreNoeud << " ";}; // if (ParaGlob::Dimension() == 2) // {sort << " dir_droite_now= " << cLL.dr.VecDroite() << " dir_droite0= " << cLL.val;} // else // cas dimension 3 // {sort << " normal_plan_now= " << cLL.pl.Vecplan() << " normal_plan0= " << cLL.val;} // }; sort << "\n tmin= " << cLL.t_min << " tmax= " << cLL.t_max << " prec " << cLL.precedent; return sort; };