// 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-2021 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 "BlocCharge.h" #include "ConstMath.h" #include "CharUtil.h" #include "Util.h" #include //================================================ // cas d'un bloc scalaire type //================================================ // un bloc scalaire type correspond a une reference // un mot cle, et une seule valeur // Constructeur BlocScalVecTypeCharge::BlocScalVecTypeCharge () : // par defaut BlocGeneEtVecMultType(0,1) // 0 vecteur et 1 scalaire ,champ(false) { }; // avec : n: le nombre de vecteurs, m le nombre de scalaires , n le nombre de ptnom BlocScalVecTypeCharge::BlocScalVecTypeCharge(int n,int m) : BlocGeneEtVecMultType(n,m),champ(false) {}; BlocScalVecTypeCharge::BlocScalVecTypeCharge (const BlocScalVecTypeCharge& a) : // de copie BlocGeneEtVecMultType(a),champ(a.champ) { }; // lecture d'un bloc void BlocScalVecTypeCharge::Lecture(UtilLecture & entreePrinc) { // tout d'abord les cas particuliers if (strstr(entreePrinc.tablcar,"champ_de_valeurs:")!=NULL) // on regarde si c'est un champ de valeur c'est-à-dire une valeur par item de la ref // dans ce cas appel de la procédure a doc { BlocGeneEtVecMultType::Lecture_entete(entreePrinc); Lecture_champ_de_valeurs(entreePrinc); champ = 1; } else if (strstr(entreePrinc.tablcar,"champ_de_fonctions:")!=NULL) { BlocGeneEtVecMultType::Lecture_entete(entreePrinc); Lecture_champ_de_fonctions(entreePrinc); champ = 2; } else // sinon cas d'une simple valeur // lecture de la classe mère { BlocGeneEtVecMultType::Lecture(entreePrinc); champ = 0; }; }; //--------------- méthodes protégées ------ // lecture dans le cas particulier d'un champ de valeurs void BlocScalVecTypeCharge::Lecture_champ_de_valeurs(UtilLecture & entreePrinc) {// si initialement on a un vecteur ce sera un champ de vecteur à lire // idem si c'est un scalaire int dima = ParaGlob::Dimension(); if (DimVect() == 0) // cas d'un champ de scalaire { list lili; // une liste de travail // on va lire tant que l'on n'aura pas trouvé le mot clé de fin de champ entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement while (strstr(entreePrinc.tablcar,"fin_champ_de_valeurs:")!=NULL) { double grandeur; *(entreePrinc.entree) >> grandeur; // on contrôle le flux if ((entreePrinc.entree)->rdstate() == 0) // pour mémoire ici on a /* enum io_state { badbit = 1<<0, // -> 1 dans rdstate() eofbit = 1<<1, // -> 2 failbit = 1<<2, // -> 4 goodbit = 0 // -> O };*/ {lili.push_back(grandeur); }// lecture normale #ifdef ENLINUX else if ((entreePrinc.entree)->fail()) // on a atteind la fin de la ligne et on appelle un nouvel enregistrement { entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement *(entreePrinc.entree) >> grandeur; lili.push_back(grandeur); // lecture normale } #else else if ((entreePrinc.entree)->eof()) // la lecture est bonne mais on a atteind la fin de la ligne { lili.push_back(grandeur); // lecture entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement } #endif else // cas d'une erreur de lecture { cout << "\n erreur de lecture inconnue "; entreePrinc.MessageBuffer("** lecture champ de chargement **"); cout << "\n BlocScalVecTypeCharge::Lecture_champ_de_valeurs(..." << endl; Sortie (1); }; }; BlocGeneEtVecMultType::Change_tab_val(lili); } else // cas d'un champ de vecteur { list lico; // une liste de travail // on va lire tant que l'on n'aura pas trouvé le mot clé de fin de champ entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement Coordonnee coo(dima); // variable de travail while (strstr(entreePrinc.tablcar,"fin_champ_de_valeurs:")==NULL) { coo.Lecture(entreePrinc); // on contrôle le flux if ((entreePrinc.entree)->rdstate() == 0) // pour mémoire ici on a /* enum io_state { badbit = 1<<0, // -> 1 dans rdstate() eofbit = 1<<1, // -> 2 failbit = 1<<2, // -> 4 goodbit = 0 // -> O };*/ {lico.push_back(coo); }// lecture normale #ifdef ENLINUX else if ((entreePrinc->entree)->fail()) // on a atteind la fin de la ligne et on appelle un nouvel enregistrement { entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement coo.Lecture(entreePrinc); lico.push_back(coo); // lecture normale } #else else if ((entreePrinc.entree)->eof()) // la lecture est bonne mais on a atteind la fin de la ligne { lico.push_back(coo); // lecture entreePrinc.NouvelleDonnee(); // lecture d'un nouvelle enregistrement } #endif else // cas d'une erreur de lecture { cout << "\n erreur de lecture inconnue "; entreePrinc.MessageBuffer("** lecture champ de chargement **"); cout << "\n BlocScalVecTypeCharge::Lecture_champ_de_valeurs(..." << endl; Sortie (1); }; }; BlocGeneEtVecMultType::Change_vect_coorpt(lico); }; }; // lecture dans le cas particulier d'un champ de fonctions void BlocScalVecTypeCharge::Lecture_champ_de_fonctions(UtilLecture & entreePrinc) { // en attente pour l'instant cout << "\n **** pour l'instant la methode : " << " BlocScalVecTypeCharge::Lecture_champ_de_fonctions(..." << " n'est pas implemente ! "<< endl; }; // affichage des infos void BlocScalVecTypeCharge::Affiche() const { // tout d'abord affichage des infos de la classe mère BlocGeneEtVecMultType::Affiche(); // puis les valeurs propres cout << "\n champ: " << champ << endl; }; BlocScalVecTypeCharge& BlocScalVecTypeCharge::operator = ( const BlocScalVecTypeCharge& a) { // tout d'abord la classe mère // pour être sûr de ne pas utiliser le constructeur const BlocGeneEtVecMultType& b = *((const BlocGeneEtVecMultType*) & a); // une addition de l'opérateur du bloc BlocGeneEtVecMultType // en fait cela marche en remplaçant b par a directement this->BlocGeneEtVecMultType::operator=(b); // puis les valeurs propres champ = a.champ; return *this; }; istream & operator >> (istream & entree, BlocScalVecTypeCharge & coo) { // tout d'abord la classe mère entree >> ((BlocGeneEtVecMultType&)(coo)); // puis les valeurs propres string toto; entree >> toto >> coo.champ ; return entree; }; ostream & operator << ( ostream & sort,const BlocScalVecTypeCharge & coo) { // tout d'abord la classe mère sort << ((BlocGeneEtVecMultType&)(coo)); // puis les valeurs propres sort << "\n champ: " << coo.champ << endl; return sort; }; //------------ cas des torseurs de forces ponctuelles ------------ istream & operator >> (istream & entree, PTorseurPonct & a) { entree >> ((BlocGen&)(a)); string nom;string mot_cle; entree >> nom >> a.Re >> nom >> a.Mo; // lecture éventuelle d'une fonction nD sur la résultante entree >> nom >> mot_cle; if (mot_cle != "_") {a.nom_fnD_Re = mot_cle;} else {a.nom_fnD_Re = "";a.fnD_Re=NULL;} // idem pour le moment entree >> nom >> mot_cle; if (mot_cle != "_") {a.nom_fnD_Mo = mot_cle;} else {a.nom_fnD_Mo = "";a.fnD_Mo=NULL;} // le centre entree >> nom >> a.type_centre; switch (a.type_centre) {case 1: {entree >> nom;a.nom_fnD_Ce = "";a.fnD_Ce=NULL; break;} case 2: {entree >> nom >> a.nom_fnD_Ce; break;} case 3: {entree >> nom >> a.nom_mail_ref_pour_Ce >> nom >> a.num_noeud ; break; } case 4: {entree >> nom >> mot_cle >> a.nom_mail_ref_pour_Ce >> nom >> a.nom_ref_pour_Ce; break; } default: break; }; // fonction poids entree >> nom >> mot_cle; if (mot_cle != "_") {a.nom_fnD_poids = mot_cle;} else {a.nom_fnD_poids = "";a.fnD_poids=NULL;} return entree; }; // surcharge de l'operator d'ecriture ostream & operator << (ostream & sort, const PTorseurPonct & a) { sort << ((const BlocGen&)(a)); sort << "\n TORSEUR_PONCT__Re= " << a.Re << " Mo= " << a.Mo; if (a.nom_fnD_Re.length()) {sort << " nom_fnD_Re= "<< a.nom_fnD_Re << " ";} else {sort << " nom_fnD_Re= _ ";}; // idem pour le moment if (a.nom_fnD_Mo.length()) {sort << " nom_fnD_Mo= " << a.nom_fnD_Mo;} else {sort << " nom_fnD_Mo= _ ";}; // le centre sort << " type_centre= " << a.type_centre; switch (a.type_centre) {case 1: sort << " centre_fixe: "; break; case 2: {sort << " Fonction_nD_centre_: " << " nom_fnD_Ce= " << a.nom_fnD_Ce; break; } case 3: {sort << " centre_noeud:_nom_mail_ref_pour_Ce= " << a.nom_mail_ref_pour_Ce << " num_noeud= " << a.num_noeud ; break; } case 4: {sort << " centre_de_gravite_d'un_groupe_de_noeuds: " << " nom_mail_ref_pour_Ce= " << a.nom_mail_ref_pour_Ce << " nom_ref_pour_Ce= " << a.nom_ref_pour_Ce; break; } default: break; }; if (a.nom_fnD_poids.length()) {sort << " nom_fnD_poids= " << a.nom_fnD_poids;} else {sort << " nom_fnD_poids= _ ";}; return sort; }; //Constructeur par défaut PTorseurPonct::PTorseurPonct() : BlocGen(1,0) // 1 nom = nom de la ref ,Re(ParaGlob::Dimension()),nom_fnD_Re(""),fnD_Re(NULL) ,Mo(ParaGlob::Dimension()),nom_fnD_Mo(""),fnD_Mo(NULL) ,Ce(ParaGlob::Dimension()),fnD_Ce(NULL),nom_fnD_Ce("") ,noe_Ce(NULL),temps_noe_Ce(TEMPS_0),nom_ref_pour_Ce("") ,nom_mail_ref_pour_Ce(""),tab_noe_ref_centre(),type_centre(1) ,nom_fnD_poids(""),fnD_poids(NULL),t_poids(),t_vec() {}; // constructeur de copie PTorseurPonct::PTorseurPonct (const PTorseurPonct & a): BlocGen(a) // 1 nom = nom de la ref ,Re(a.Re),nom_fnD_Re(a.nom_fnD_Re),fnD_Re(a.fnD_Re),Mo(a.Mo),nom_fnD_Mo(a.nom_fnD_Mo) ,fnD_Mo(a.fnD_Mo),Ce(a.Ce),fnD_Ce(a.fnD_Ce),nom_fnD_Ce(a.nom_fnD_Ce) ,noe_Ce(a.noe_Ce),temps_noe_Ce(a.temps_noe_Ce),nom_ref_pour_Ce(a.nom_ref_pour_Ce) ,nom_mail_ref_pour_Ce(a.nom_mail_ref_pour_Ce) ,tab_noe_ref_centre(a.tab_noe_ref_centre),type_centre(a.type_centre) ,nom_fnD_poids(a.nom_fnD_poids),fnD_poids(a.fnD_poids),t_poids(a.t_poids),t_vec() {}; // surcharge d'affectation PTorseurPonct& PTorseurPonct::operator = (const PTorseurPonct& a) { BlocGen* b = ((BlocGen* ) this); // const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3 (*b) = a; // affectation des grandeurs de bloc gen Re = a.Re; nom_fnD_Re = a.nom_fnD_Re; fnD_Re = a.fnD_Re; Mo = a.Mo; nom_fnD_Mo = a.nom_fnD_Mo; fnD_Mo = a.fnD_Mo; Ce = a.Ce; fnD_Ce = a.fnD_Ce; nom_fnD_Ce = a.nom_fnD_Ce; noe_Ce = a.noe_Ce; temps_noe_Ce = a.temps_noe_Ce; nom_ref_pour_Ce = a.nom_ref_pour_Ce; nom_mail_ref_pour_Ce = a.nom_mail_ref_pour_Ce; tab_noe_ref_centre = a.tab_noe_ref_centre; type_centre = a.type_centre; nom_fnD_poids=a.nom_fnD_poids;fnD_poids = a.fnD_poids; t_poids.Change_taille(a.t_poids.Taille()); t_vec.Change_taille(a.t_vec.Taille()); return *this; }; // surcharge de l'operateur d'égalité bool PTorseurPonct::operator == (const PTorseurPonct& a) const { BlocGen* b = ((BlocGen* ) this); if ( ((*b) == a) && (Re == a.Re) && (nom_fnD_Re == a.nom_fnD_Re) && (fnD_Re == a.fnD_Re) && (Mo == a.Mo) && (nom_fnD_Mo == a.nom_fnD_Mo) && (fnD_Mo == a.fnD_Mo) && (Ce == a.Ce) && (fnD_Ce == a.fnD_Ce) && (nom_fnD_Ce == a.nom_fnD_Ce) && (noe_Ce == a.noe_Ce) && (temps_noe_Ce == a.temps_noe_Ce) && (nom_fnD_poids == a.nom_fnD_poids)&&(fnD_poids == a.fnD_poids) && (nom_ref_pour_Ce == a.nom_ref_pour_Ce) && (nom_mail_ref_pour_Ce == a.nom_mail_ref_pour_Ce) && (tab_noe_ref_centre == a.tab_noe_ref_centre) && (type_centre == a.type_centre) ) return true; else return false; }; // lecture d'un bloc void PTorseurPonct::Lecture(UtilLecture & entreePrinc) { BlocGen* b = ((BlocGen* ) this); // on commence par lire le bloc gen, ce qui correspondra à la ref b->Lecture(entreePrinc); // arrivée ici le nom de maillage puis celui de la ref sont lue // lecture du mot clé string nom_charge; string nom_class_methode(" PTorseurPonct::Lecture("); string mot_cle("TORSEUR_PONCT"); // lecture et passage d'un mot clé: il y a simplement vérification que c'est le bon mot clé qui est lue // ramène si oui ou non le mot clé à été lue entreePrinc.Lecture_et_verif_mot_cle(nom_class_methode,mot_cle); //------- lecture de la résultante ---- // idem pour le mot clé R= mot_cle="Re="; entreePrinc.Lecture_et_verif_mot_cle(nom_class_methode,mot_cle); // maintenant on fait le choix entre valeur ou fonction nD if (strstr(entreePrinc.tablcar,"Fonction_nD_Re:")!=NULL) {// cas d'une fonction nD, on se positionne sur le mot clé string titi4; bool bonnefin4=false; while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur (!(entreePrinc.entree->eof()))) { // lecture du prochain mot *(entreePrinc.entree) >> titi4 ; if (titi4 == "Fonction_nD_Re:"){bonnefin4=true; break;}; }; if (!bonnefin4) {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD pour la resultante "; cout << "\n PTorseurPonct::Lecture(.. " << endl ; entreePrinc.MessageBuffer("**erreur**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else //lecture du nom de la fonction nD { *(entreePrinc.entree) >> nom_fnD_Re; }; } //-- fin récup de la fonction de charge else // sinon on lit directement les coordonnées de la résultante { Re.Lecture(entreePrinc);}; //------- lecture du moment ---- // idem pour le mot clé M= mot_cle="Mo="; entreePrinc.Lecture_et_verif_mot_cle(nom_class_methode,mot_cle); // maintenant on fait le choix entre valeur ou fonction nD if (strstr(entreePrinc.tablcar,"Fonction_nD_Mo:")!=NULL) {// cas d'une fonction nD, on se positionne sur le mot clé string titi4; bool bonnefin4=false; while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur (!(entreePrinc.entree->eof()))) { // lecture du prochain mot *(entreePrinc.entree) >> titi4 ; if (titi4 == "Fonction_nD_Mo:"){bonnefin4=true; break;}; }; if (!bonnefin4) {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD pour le moment "; cout << "\n PTorseurPonct::Lecture(.. " << endl ; entreePrinc.MessageBuffer("**erreur**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else //lecture du nom de la fonction nD { *(entreePrinc.entree) >> nom_fnD_Mo; }; } //-- fin récup de la fonction de charge else // sinon on lit directement les coordonnées du moment { Mo.Lecture(entreePrinc);}; //------- lecture du centre ---- // idem pour le mot clé centre_= mot_cle="centre_="; entreePrinc.Lecture_et_verif_mot_cle(nom_class_methode,mot_cle); // maintenant on fait le choix entre valeur, fonction nD, noeud, groupe de noeud // 1) cas d'une fonction nD décrivant le centre if (strstr(entreePrinc.tablcar,"Fonction_nD_centre_:")!=NULL) {// cas d'une fonction nD, on se positionne sur le mot clé string titi4; bool bonnefin4=false; while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur (!(entreePrinc.entree->eof()))) { // lecture du prochain mot *(entreePrinc.entree) >> titi4 ; if (titi4 == "Fonction_nD_centre_:"){bonnefin4=true; break;}; }; if (!bonnefin4) {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD pour le centre d'application du moment "; cout << "\n PTorseurPonct::Lecture(.. " << endl ; entreePrinc.MessageBuffer("**erreur**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else //lecture du nom de la fonction nD { *(entreePrinc.entree) >> nom_fnD_Ce; }; type_centre = 2; } //-- fin récup de la fonction de charge // 2) cas d'un noeud décrivant le centre else if (strstr(entreePrinc.tablcar,"centre_noeud_=")!=NULL) { // cas d'un centre donné par un numero de noeud mot_cle="centre_noeud_="; entreePrinc.Lecture_et_verif_mot_cle(nom_class_methode,mot_cle); string nom_mail; *(entreePrinc.entree) >> nom_mail; if (nom_mail == "nom_mail=") { // cas où il y a un nom de maillage *(entreePrinc.entree) >> nom_mail_ref_pour_Ce; // lecture du nom *(entreePrinc.entree) >> num_noeud; // lecture du numero de noeud } else { // sinon cela veut dire que l'on vient de lire un numéro de noeud du premier maillage nom_mail_ref_pour_Ce = ""; num_noeud = ChangeEntier(nom_mail); }; // puis on lit le temps pour lequel on considère les coordonnées du noeud: string dure; *(entreePrinc.entree) >> dure; temps_noe_Ce = Id_nom_dure (dure); type_centre = 3; } // 3) cas du centre de gravité d'une ref de noeuds else if (strstr(entreePrinc.tablcar,"centre_gravite_ref_=")!=NULL) { // cas d'un centre donné par un centre de gravité d'une ref de noeuds mot_cle="centre_gravite_ref_="; entreePrinc.Lecture_et_verif_mot_cle(nom_class_methode,mot_cle); string nom_mail; *(entreePrinc.entree) >> nom_mail; if (nom_mail == "nom_mail=") { // cas où il y a un nom de maillage *(entreePrinc.entree) >> nom_mail_ref_pour_Ce; // lecture du nom *(entreePrinc.entree) >> nom_ref_pour_Ce; // lecture du nom de la ref de noeud } else { // sinon cela veut dire que l'on vient de lire la référence de noeud du premier maillage nom_mail_ref_pour_Ce = ""; nom_ref_pour_Ce = nom_mail; }; // puis on lit le temps pour lequel on considère les coordonnées du noeud: string dure; *(entreePrinc.entree) >> dure; temps_noe_Ce = Id_nom_dure (dure); type_centre = 4; } // 4) cas du centre de gravité fixe else // on lit directement les coordonnées { Ce.Lecture(entreePrinc); type_centre=1; }; //------- lecture d'une fonction poids éventuelle moment ---- if (strstr(entreePrinc.tablcar,"Fonction_nD_Poids:")!=NULL) {// cas d'une fonction nD, on se positionne sur le mot clé string titi4; bool bonnefin4=false; while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur (!(entreePrinc.entree->eof()))) { // lecture du prochain mot *(entreePrinc.entree) >> titi4 ; if (titi4 == "Fonction_nD_Poids:"){bonnefin4=true; break;}; }; if (!bonnefin4) {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD pour la repartition de poids "; cout << "\n PTorseurPonct::Lecture(.. " << endl ; entreePrinc.MessageBuffer("**erreur**"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); } else //lecture du nom de la fonction nD { *(entreePrinc.entree) >> nom_fnD_poids; }; } //-- fin récup de la fonction de charge else // sinon on vide le nom { nom_fnD_poids="";}; //nom_mail= petit_prisme N_bas_arriere TORSEUR_PONCT Re= 10 0 0 \ // Mo= 0 0 0 centre_= 45 45 1070 }; // mise en place de l'association des fonctions nD, dont ensuite on garde un pointeur // en retour indique si l'association est ok bool PTorseurPonct::Mise_en_place_des_fonction_nD(const LesFonctions_nD& lesFonctionsnD) { bool retour = true; // on regarde et on récupère s'il le faut la fct nD associée avec la résultante du torseur if (nom_fnD_Re.length()) {fnD_Re = lesFonctionsnD.Trouve(nom_fnD_Re); int dima = ParaGlob::Dimension(); if (fnD_Re != NULL) {// on vérifie qu'en retour on a un vecteur de dimension = la dimension de l'espace if (fnD_Re->NbComposante() != dima) {cout << "\n *** erreur dans l'utilisation d'une fonction nD avec grandeur(s) globale(s)" << " cas du calcul de la resultante d'un torseur" << " en retour, le nombre de composante"<< fnD_Re->NbComposante() << " est different de la dimension de l'espace : " << dima << endl; Sortie(1); }; }; }; // idem pour le moment if (nom_fnD_Mo.length()) {fnD_Mo = lesFonctionsnD.Trouve(nom_fnD_Mo); int dima = ParaGlob::Dimension(); if (fnD_Mo != NULL) {// on vérifie qu'en retour on a un vecteur de dimension = la dimension de l'espace if (fnD_Mo->NbComposante() != dima) {cout << "\n *** erreur dans l'utilisation d'une fonction nD avec grandeur(s) globale(s)" << " cas du calcul du moment d'un torseur" << " en retour, le nombre de composante"<< fnD_Mo->NbComposante() << " est different de la dimension de l'espace : " << dima << endl; Sortie(1); }; }; }; // idem pour le centre if (nom_fnD_Ce.length()) {fnD_Ce = lesFonctionsnD.Trouve(nom_fnD_Ce); int dima = ParaGlob::Dimension(); if (fnD_Ce != NULL) {// on vérifie qu'en retour on a un vecteur de dimension = la dimension de l'espace if (fnD_Ce->NbComposante() != dima) {cout << "\n *** erreur dans l'utilisation d'une fonction nD avec grandeur(s) globale(s)" << " cas du calcul du centre d'un torseur" << " en retour, le nombre de composante"<< fnD_Ce->NbComposante() << " est different de la dimension de l'espace : " << dima << endl; Sortie(1); }; }; if ( (type_centre == 1) // 1 c'est la valeur par défaut ||(type_centre == 2) ) {type_centre = 2;} else // cas pb {cout << "\n erreur de definition du centre de calcul du moment (torseur ponctuel) "; cout << " le centre a deja ete defini comme :"; switch (type_centre) {case 3: cout << " centre noeud "; break; case 4: cout << " centre de gravite d'un groupe de noeuds "; break; default: break; }; retour=false; }; }; if (nom_fnD_poids.length()) {fnD_poids = lesFonctionsnD.Trouve(nom_fnD_poids); if (fnD_poids != NULL) {// on vérifie qu'en retour on a un vecteur de dimension = 1 if (fnD_poids->NbComposante() != 1) {cout << "\n *** erreur dans l'utilisation d'une fonction nD avec grandeur(s) globale(s)" << " cas du calcul des poids aux points, pour le centre de gravite d'un torseur" << " en retour, le nombre de composante"<< fnD_poids->NbComposante() << " est different de 1 ! " << endl; Sortie(1); }; }; }; // la méthode de la fonction mère n'existe pas donc rien d'autre à faire return retour; }; // mise en place des infos pour le centre si celui-ci dépend des noeuds // en retour indique si c'est ok bool PTorseurPonct::Def_tab_noeud_pour_centre(const list li_noe_ref_centre) {bool retour = true; // on initialise à partir de la liste tab_noe_ref_centre.Init_from_list(li_noe_ref_centre); int nbn = tab_noe_ref_centre.Taille(); t_poids.Change_taille(nbn); t_vec.Change_taille(nbn); if ((type_centre == 2) && (tab_noe_ref_centre.Taille() != 0)) {cout << "\n erreur de definition du centre de calcul du moment (torseur ponctuel) "; cout << " le centre a deja ete defini comme : fonction nD "; retour=false; } else if (tab_noe_ref_centre.Taille() != 0) {if (tab_noe_ref_centre.Taille()==1) { type_centre = 3; noe_Ce=tab_noe_ref_centre(1); } else { type_centre = 4;}; }; return retour; }; // calcul éventuel et retour de la résultante (qui peut varier) // M: indique un point dont peut dépendre les éléments du torseur Coordonnee& PTorseurPonct::Resultante(const Coordonnee& M ) {int dima = ParaGlob::Dimension(); if (fnD_Re != NULL) {if (fnD_Re->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales { Tableau & tava = fnD_Re->Valeur_pour_variables_globales(); // pour simplifier switch (dima) { case 3 : Re(3) = tava(3); case 2 : Re(2) = tava(2); case 1 : Re(1) = tava(1); }; } else if (fnD_Re->Depend_M() != 0) // signifie qu'il y a une dépendance au point M { if (fnD_Re->Depend_M()<0) {// comme pt_fonct->Depend_M()<0, cela signifie que la fonction dépend que de M // donc dans les paramètres d'appel on ne transmet que M Tableau tab_M(1,M); Tableau & tava = fnD_Re->Val_FnD_Evoluee(NULL,&tab_M,NULL); // pour simplifier switch (dima) { case 3 : Re(3) = tava(3); case 2 : Re(2) = tava(2); case 1 : Re(1) = tava(1); }; } else { if ((fnD_Re->Depend_M()>0)|| fnD_Re->Nom_variables().Taille() != dima) {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD utilisant les coordonnees du point" << " cas du calcul de la resultante d'un torseur" << " actuellement la fonction doit avoir uniquement comme parametres, les coordonnees du point et/ou eventuellement des variables globales "; cout << "\n fonction nD: "; fnD_Re->Affiche();this->Affiche(); Sortie(1); }; }; } }; return Re; }; // calcul éventuel et retour du moment (qui peut varier) // M: indique un point dont peut dépendre les éléments du torseur Coordonnee& PTorseurPonct::Moment(const Coordonnee& M ) {int dima = ParaGlob::Dimension(); if (fnD_Mo != NULL) {if (fnD_Mo->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales { Tableau & tava = fnD_Mo->Valeur_pour_variables_globales(); // pour simplifier switch (dima) { case 3 : Mo(3) = tava(3); case 2 : Mo(2) = tava(2); case 1 : Mo(1) = tava(1); }; } else if (fnD_Mo->Depend_M() != 0) // signifie qu'il y a une dépendance au point M { if (fnD_Mo->Depend_M()<0) {// comme pt_fonct->Depend_M()<0, cela signifie que la fonction dépend que de M // donc dans les paramètres d'appel on ne transmet que M Tableau tab_M(1,M); Tableau & tava = fnD_Mo->Val_FnD_Evoluee(NULL,&tab_M,NULL); // pour simplifier switch (dima) { case 3 : Mo(3) = tava(3); case 2 : Mo(2) = tava(2); case 1 : Mo(1) = tava(1); }; } else { if ((fnD_Mo->Depend_M()>0)|| fnD_Mo->Nom_variables().Taille() != dima) {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD utilisant les coordonnees du point" << " cas du calcul du moment d'un torseur" << " actuellement la fonction doit avoir uniquement comme parametres, les coordonnees du point et eventuellement des variables globales "; cout << "\n fonction nD: "; fnD_Mo->Affiche();this->Affiche(); Sortie(1); }; }; } }; return Mo; }; // calcul éventuel et retour du centre du moment (qui peut varier) // M: indique un point dont peut dépendre les éléments du torseur Coordonnee& PTorseurPonct::Centre( ) { int dima = ParaGlob::Dimension(); switch (type_centre) {case 1: break; // rien n'a faire case 2: // cas d'une fonction nD {if (fnD_Ce->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales { Tableau & tava = fnD_Ce->Valeur_pour_variables_globales(); // pour simplifier switch (dima) { case 3 : Ce(3) = tava(3); case 2 : Ce(2) = tava(2); case 1 : Ce(1) = tava(1); }; } else {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD utilisant les coordonnees du point" << " cas du calcul du centre d'un torseur" << " actuellement la fonction doit avoir uniquement comme parametres des variables globales "; cout << "\n fonction nD: "; fnD_Ce->Affiche();this->Affiche(); Sortie(1); }; break; } case 3: // cas ou il s'agit d'un noeud {switch (temps_noe_Ce) {case TEMPS_0: Ce=noe_Ce->Coord0(); break; case TEMPS_t: Ce=noe_Ce->Coord1(); break; case TEMPS_tdt: Ce=noe_Ce->Coord2(); break; default: break; }; break; } case 4: // cas d'un centre de gravité { // on itère sur les noeuds du tableau Ce.Zero(); // init int nb_noe = tab_noe_ref_centre.Taille(); switch (temps_noe_Ce) {case TEMPS_0: { for (int i=1;i<= nb_noe; i++) Ce += tab_noe_ref_centre(i)->Coord0(); // on moyenne Ce /= nb_noe; break; } case TEMPS_t: { for (int i=1;i<= nb_noe; i++) Ce += tab_noe_ref_centre(i)->Coord1(); // on moyenne Ce /= nb_noe; break; } case TEMPS_tdt: { for (int i=1;i<= nb_noe; i++) Ce += tab_noe_ref_centre(i)->Coord2(); // on moyenne Ce /= nb_noe; break; } default: break; }; break; } default: break; }; // retour return Ce; }; // affichage des informations void PTorseurPonct::Affiche() const { cout << "\n TORSEUR_PONCT Re= " << Re << " Mo= " << Mo; if (ParaGlob::NiveauImpression() > 3) { cout << "\n"; if (nom_fnD_Re.length()) cout << "\n nom_fnD_Re= "<< nom_fnD_Re << " "; // idem pour le moment if (nom_fnD_Mo.length()) cout << " nom_fnD_Mo= " << nom_fnD_Mo; switch (type_centre) {case 1: cout << " centre_fixe: "; break; case 2: {cout << " Fonction_nD_centre_: " << " nom_fnD_Ce= " << nom_fnD_Ce; break; } case 3: {cout << " centre_noeud: nom_mail_ref_pour_Ce= " << nom_mail_ref_pour_Ce << " num_noeud= " << num_noeud ; break; } case 4: {cout << " centre_de_gravite_d'un_groupe_de_noeuds: " << " nom_mail_ref_pour_Ce= " << nom_mail_ref_pour_Ce << " nom_ref_pour_Ce= " << nom_ref_pour_Ce; break; } default: break; }; if (nom_fnD_poids.length()) cout << " nom_fnD_poids= " << nom_fnD_poids; }; }; // calcul de l'effort ponctuelle correspondant au torseur // pour la position passée en paramètres // M: indique un point dont peut dépendre les éléments du torseur // tab_P: tableau des points où sont exprimés les forces équivalentes au torseur // t_force : tableau des forces calculées, équivalentes au torseur void PTorseurPonct::Force(const Tableau & tab_P, Tableau & t_force) { // on commence par calculer le centre du torseur // utile uniquement s'il varie //--- debug //cout << "\n debug PTorseurPonct::Force(.." // << "\n Re= "<< Re << " Mo= "<< Mo // << "\n tab_P= "<< tab_P // << flush; //--- fin debug Centre(); //--- debug //cout << "\n Ce= "<< Ce << flush; //--- fin debug // puis la résultante et le moment qui peuvent dépendre du centre Resultante(Ce); Moment(Ce); // traitement du cas particulier d'un seul point int nb_Pi = tab_P.Taille(); if (nb_Pi==1) {// ici on a qu'un seul point // -> le centre G = le point // par rapport à G, on ne peut pas avoir de moment // la résultante ne peut qu'être transférée telle quelle // la répartition ne sert à rien Coordonnee& G = tab_P(1); // le centre de gravité = le seul point Coordonnee CG (G-Ce); // on transfert le moment en G Coordonnee MG = Mo - Util::ProdVec_coor(CG,Re); // il faut que le moment soit nul double M_G = MG.Norme(); if (M_G > ConstMath::petit) {cout << "\n *** erreur dans le calcul de la repartition du moment d'un torseur d'action," << " ici il n'y a qu'un point, et le moment en se point n'est pas nul, MG= " << MG << " le transfert n'est pas possible!! "; this->Affiche(); Sortie(1); }; // calcul des résultantes individuelles correspondant uniquement à Re t_force(1) = Re; } else // la suite concerne le cas avec plusieurs points {int dima = ParaGlob::Dimension(); Coordonnee G(dima); t_force.Change_taille(nb_Pi); double poids_total = 0.; // init if (fnD_poids == NULL) // si on n'a pas de fonction de répartition, cela signifie que les poids sont tous = 1 {for (int i =1; i<= nb_Pi; i++) {Coordonnee& tab_P_i = tab_P(i); t_force(i) = Re ; // première partie du calcul de force G += tab_P(i) ; poids_total += 1.; }; // d'où double alpha = 1./poids_total; G *= alpha; // le centre de gravité //--- debug //cout << "\n debug PTorseurPonct::Force(.." // << "\n Re= "<< Re << " Mo= "<< Mo // << "\n centre G= "<< G << flush; //--- fin debug Coordonnee CG (G-Ce); // on transfert le moment en G Coordonnee MG = Mo - Util::ProdVec_coor(CG,Re); //--- debug //cout << "\n moment MG= "<< MG << flush; //--- fin debug // calcul des résultantes individuelles correspondant uniquement à Re for (int i =1; i<= nb_Pi; i++) { t_force(i) *= alpha;}; // si le moment n'est pas nul on calcule les moments individuels double M_G = MG.Norme(); t_vec.Change_taille(nb_Pi); if (M_G > ConstMath::petit) { Coordonnee m = MG/M_G; Coordonnee GPi,GPpi; // variables de travail double mom_quad = 0.; for (int i =1; i<= nb_Pi; i++) { Coordonnee& tab_P_i = tab_P(i); GPi = tab_P_i - G; GPpi = GPi - (GPi * m) * m; double GPpi2 = GPpi * GPpi; mom_quad += GPpi2 ; // si la norme de GPpi est trop petite, la force individuelle // ne pourra pas contribuer au moment t_vec(i) = Util::ProdVec_coor(GPpi,m); }; // si le moment quadratique est nul on ne peut pas équilibrer le moment if (mom_quad < ConstMath::petit) {cout << "\n *** erreur dans le calcul de la repartition du moment d'un torseur d'action," << " vers des forces ponctuelles" << " le moment quadratique est nul, on ne peut pas equilibrer le moment actuel MG= " << MG ; this->Affiche(); Sortie(1); }; double beta = M_G / mom_quad ; // si diff de 0. // on calcule la part due au moment, répartie sur les points for (int i =1; i<= nb_Pi; i++) t_force(i) -= (beta ) * t_vec(i); } } // fin du cas où il n'y a pas de fonction de poids else // cas avec une fonction de répartition de poids {int dimPlus1 = 1+ParaGlob::Dimension(); Tableau tab_d(dimPlus1); double& CP_i = tab_d(1); // pour simplifier for (int i =1; i<= nb_Pi; i++) {Coordonnee& tab_P_i = tab_P(i); Coordonnee CPi = tab_P_i - Ce; for (int j=1;j & tava = fnD_poids->Valeur_FnD_tab_scalaire(&tab_d); //Val_FnD_Evoluee(&tab_d,NULL,NULL); // pour simplifier double f_opi = t_poids(i)= Dabs(tava(1)); //--- debug //cout << "\n poids( "<< i << ")= " << f_opi << " r= " << tab_d(1) << flush; //--- fin debug t_force(i) = Re * f_opi; // première partie du calcul de force G += tab_P(i) * f_opi; poids_total += f_opi; }; // d'où double alpha = 1./poids_total; G *= alpha; // le centre de gravité Coordonnee CG (G-Ce); // on transfert le moment en G Coordonnee MG = Mo - Util::ProdVec_coor(CG,Re); // calcul des résultantes individuelles correspondant uniquement à Re for (int i =1; i<= nb_Pi; i++) { t_force(i) *= alpha;}; // si le moment n'est pas nul on calcule les moments individuels double M_G = MG.Norme(); if (M_G > ConstMath::petit) { Coordonnee m = MG/M_G; Coordonnee GPi,GPpi; // variables de travail double mom_quad = 0.; for (int i =1; i<= nb_Pi; i++) { Coordonnee& tab_P_i = tab_P(i); GPi = tab_P_i - G; GPpi = GPi - (GPi * m) * m; double GPpi2 = GPpi * GPpi; mom_quad += GPpi2 * t_poids(i); // si la norme de GPpi est trop petite, la force individuelle // ne pourra pas contribuer au moment t_vec(i) = Util::ProdVec_coor(GPpi,m); }; // si le moment quadratique est nul on ne peut pas équilibrer le moment if (mom_quad < ConstMath::petit) {cout << "\n *** erreur dans le calcul de la repartition du moment d'un torseur d'action," << " vers des forces ponctuelles" << " le moment quadratique est nul, on ne peut pas equilibrer le moment actuel MG= " << MG ; this->Affiche(); Sortie(1); }; double beta = M_G / mom_quad ; // si diff de 0. // on calcule la part due au moment, répartie sur les points for (int i =1; i<= nb_Pi; i++) t_force(i) -= (beta * t_poids(i)) * t_vec(i); }; }; // fin du test sur l'existence ou non d'une fonction de poids }; // fin du cas où il y a plusieurs points: }; // affichage et definition interactive des commandes // plusieurs_maillages : indique s'il y a ou pas // renvoi : true s'il y a effectivement une écriture bool PTorseurPonct::Info_commande_Charges(bool plusieurs_maillages,UtilLecture & entreePrinc) { // ---------- définition des différents paramètres de définition du chargement ---------- ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier string la_sortie(" TORSEUR_PONCT "); // la chaine de caractères qui sera finalement affichée // on passe en revue les différents paramètres qui définissent le torseur bool lecture_ok=true; //------- lecture de la résultante ---- string rep(" "); int dim = ParaGlob::Dimension(); // Résultante: on fait le choix entre valeur ou fonction nD int int_choix=0; while ((int_choix > 3) || (int_choix < 1)) {cout << "\n --- definition de la resultante du torseur --- " << "\n (1) (defaut) valeur fixe: via "<> V(i); std::cin.ignore( std::numeric_limits::max(), '\n' );// purge de cin cout << "\n --> coordonnees lues: "; V.Affiche_1(cout); Re = V; la_sortie += " Re= "; for (int i = 1; i<= dim; i++) la_sortie += ChangeReelSTring(V(i))+" "; } break; case 2: { cout << "\n nom de la fonction nD ? "; nom_fnD_Re = lect_chaine();cout << " nom lu = "<< nom_fnD_Re; la_sortie += " Re= Fonction_nD_Re: " + nom_fnD_Re; }; break; default: {cout << "\n *** mauvais choix, vous devez donner une valeur entre 1 et 2 !" << "\n recommencer "; }; }; }; // Moment: on fait le choix entre valeur ou fonction nD rep =" ";int_choix=0; if (lecture_ok) while ((int_choix > 3) || (int_choix < 1)) {cout << "\n --- definition du moment du torseur --- " << "\n (1) (defaut) valeur fixe: via "<> V(i); std::cin.ignore( std::numeric_limits::max(), '\n' );// purge de cin cout << "\n --> coordonnees lues: "; V.Affiche_1(cout); Mo = V; la_sortie += " Mo= "; for (int i = 1; i<= dim; i++) la_sortie += ChangeReelSTring(V(i))+" "; } break; case 2: { cout << "\n nom de la fonction nD ? "; nom_fnD_Mo = lect_chaine();cout << " nom lu = "<< nom_fnD_Mo; la_sortie += " Mo= Fonction_nD_Mo: " + nom_fnD_Mo; }; break; default: {cout << "\n *** mauvais choix, vous devez donner une valeur entre 1 et 2 !" << "\n recommencer "; }; }; }; // centre: on fait le choix entre les différentes possibilités rep =" ";int_choix=0; if (lecture_ok) while ((int_choix > 5) || (int_choix < 1)) {cout << "\n --- definition du centre du torseur --- " << "\n (1) (defaut) valeur fixe: via "<> V(i); std::cin.ignore( std::numeric_limits::max(), '\n' );// purge de cin cout << "\n --> coordonnees lues: "; V.Affiche_1(cout); Ce = V; type_centre=1; la_sortie += " centre_= "; for (int i = 1; i<= dim; i++) la_sortie += ChangeReelSTring(V(i))+" "; } break; case 2: { cout << "\n nom de la fonction nD de charge ? "; nom_fnD_Ce=lect_chaine();cout << " nom lu = "<< nom_fnD_Ce; la_sortie += " centre_= Fonction_nD_centre_: " + nom_fnD_Ce; type_centre = 2; } break; case 3: { // cas d'un centre donné par un numero de noeud la_sortie += " centre_= centre_noeud_= "; nom_mail_ref_pour_Ce = ""; if (plusieurs_maillages) {cout << "\n nom du maillage contenant le noeud ? "; nom_mail_ref_pour_Ce = lect_chaine(); la_sortie += " nom_mail= "+nom_mail_ref_pour_Ce; }; cout << "\n numero du noeud ? "; num_noeud = (int) lect_double(); la_sortie += " "+ChangeEntierSTring(num_noeud)+" "; string temps(" "); while (!Existe_nom_dure (temps)) {cout << "\n instant auquel on considere le noeud " << "\n TEMPS_0 (ou) TEMPS_t (ou) TEMPS_tdt ? "; temps = lect_chaine(); // on test if (Existe_nom_dure (temps)) {temps_noe_Ce = Id_nom_dure(temps); } else {cout << "\n *** erreur, ce temps n'est pas reconnu, nouvelle valeur ? ";}; }; la_sortie += " "+temps+" "; type_centre = 3; } break; case 4: { // cas d'un centre donné par un centre de gravité d'une ref de noeuds la_sortie += " centre_= centre_gravite_ref_= "; nom_mail_ref_pour_Ce = ""; if (plusieurs_maillages) {string nom_mail; cout << "\n nom du maillage contenant la ref de noeuds ? "; nom_mail_ref_pour_Ce = lect_chaine(); la_sortie += " nom_mail= "+nom_mail_ref_pour_Ce+" "; }; cout << "\n nom de la ref de noeuds ? "; nom_ref_pour_Ce=lect_chaine(); la_sortie += " "+nom_ref_pour_Ce+" "; string temps(" "); while (!Existe_nom_dure (temps)) {cout << "\n instant auquel on considere la ref de noeuds " << "\n TEMPS_0 (ou) TEMPS_t (ou) TEMPS_tdt ? "; temps=lect_chaine(); // on test if (Existe_nom_dure (temps)) {temps_noe_Ce = Id_nom_dure(temps); } else {cout << "\n *** erreur, ce temps n'est pas reconnu, nouvelle valeur ? ";}; }; la_sortie += " "+temps+" "; type_centre = 4; } break; default: {cout << "\n *** mauvais choix, vous devez donner une valeur entre 1 et 4 !" << "\n recommencer "; }; }; }; //------- lecture d'une fonction poids éventuelle moment ---- rep =" ";int_choix=0;nom_fnD_poids=""; if (lecture_ok) while ((int_choix > 3) || (int_choix < 1)) { cout << "\n --- definition eventuelle d'une fonction poids --- " << "\n (1) oui " << "\n (2) (defaut) non " << "\n (3 ou f ) arret " << "\n "; // procédure de lecture avec prise en charge d'un retour chariot rep = lect_return_defaut(false,"2"); Minuscules(rep); int_choix = ChangeEntier(rep); if ((rep == "f")||(int_choix == 5)) {lecture_ok = false; break; }; switch (int_choix) {case 1: { cout << "\n nom de la fonction nD ? "; nom_fnD_poids=lect_chaine();cout << " nom lu = "<< nom_fnD_poids; la_sortie += " Fonction_nD_Poids: "+nom_fnD_poids+" "; }; break; case 2: // on ne fait rien break; default: {cout << "\n *** mauvais choix, vous devez donner une valeur entre 1 et 2 !" << "\n recommencer "; }; }; }; //------- écriture sur le .info de la grandeur ---- if (lecture_ok) sort << la_sortie; return lecture_ok; };