diff --git a/Maillage/BlocDdlLim.h b/Maillage/BlocDdlLim.h new file mode 100644 index 0000000..4b93340 --- /dev/null +++ b/Maillage/BlocDdlLim.h @@ -0,0 +1,230 @@ +/*! \file BlocDdlLim.h + \brief def classe et fonctions template pour la lecture de ddl lim. +*/ + +// 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: . + +/************************************************************************ + * DATE: 28/03/2004 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: Gestion de divers bloc courant du fichier de lecture . * + * Cas où ces blocs sont relatif aux conditions limites, * + * et héritent de bloc classiques. * + * par rapport au bloc, l'apport est la gestion d'un nom_de maillage* + * éventuellement en plus du nom de référence. * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ +#ifndef BLOC_DDLLIM_T_H +#define BLOC_DDLLIM_T_H + +#include "Bloc.h" +#include "ConstMath.h" + +/// @addtogroup Les_classes_Ddl_en_tout_genre +/// @{ +/// + +/// +/// +///================================================ +/// cas d'un bloc template avec conditions limites +///================================================ +template +class BlocDdlLim : public Bloc_particulier +{ + // surcharge de l'operator de lecture + friend istream & operator >> (istream & entree, BlocDdlLim & coo) + { // lecture d'un nom de maillage éventuel + bool existe_nom_maillage; entree >> existe_nom_maillage; + if (existe_nom_maillage) + { string nom; entree >> nom; + if (coo.nom_maillage == NULL) + coo.nom_maillage = new string(nom); + else + *(coo.nom_maillage) = nom; + }; + // puis la classe mère + entree >> ((Bloc_particulier&)(coo)); + return entree; + } + + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort, const BlocDdlLim & coo) + { // tout d'abord le maillage éventuelle + if (coo.nom_maillage == NULL) + sort << false << " "; + else + sort << true << " " << *(coo.nom_maillage) << " "; + // puis la classe mère + sort << ((const Bloc_particulier&)(coo)); + return sort; + } + + public : + // VARIABLES PUBLIQUES : + // stockage d'un element + // class conforme a la specif de T de la class LectBloc_T + + // Constructeur + BlocDdlLim () : // par defaut + nom_maillage(NULL),Bloc_particulier() + {}; + // fonction d'une instance de Bloc_particulier + BlocDdlLim (const Bloc_particulier& a) : Bloc_particulier(a),nom_maillage(NULL) {}; + // fonction d'une instance et d'un string + BlocDdlLim (const string& nom_mail,const Bloc_particulier& a) : + Bloc_particulier(a),nom_maillage(new string (nom_mail)) {}; + // fonction d'une instance et d'un pointeur de string + BlocDdlLim (const string* nom_mail,const Bloc_particulier& a) : + Bloc_particulier(a),nom_maillage(NULL) + { if (nom_mail != NULL) nom_maillage = new string (*nom_mail);}; + // de copie + BlocDdlLim (const BlocDdlLim& a) : + nom_maillage(NULL),Bloc_particulier(a) + {if (a.nom_maillage != NULL) nom_maillage = new string (*(a.nom_maillage));}; + // destructeur + ~BlocDdlLim () {if (nom_maillage != NULL) delete nom_maillage;}; + // retourne un pointeur de string donnant le nom du maillage associé + // = NULL si aucun maillage + const string* NomMaillage() const {return nom_maillage;}; + // change le nom de maillage + // ATTENTION : Les modifications liees au changement du nom de maillage + // sont a la charge de l'utilisateur. + // le nouveau nom ne doit pas être vide !! sinon erreur + void Change_nom_maillage(const string& nouveau); + // lecture d'un bloc + void Lecture(UtilLecture & entreePrinc); + // affichage des informations + void Affiche() const ; + // surcharge des operateurs + bool operator == ( const BlocDdlLim& a) const; + BlocDdlLim& operator = (const BlocDdlLim& a); + bool operator != ( const BlocDdlLim& a) const { return !(*this == a);}; + + protected : + string* nom_maillage; // nom d'un maillage +}; +/// @} // end of group + + +/// lecture d'un bloc +template +void BlocDdlLim::Lecture(UtilLecture & entreePrinc) + { // on regarde tout d'abord si il y a un nom de maillage, qui doit être le premier nom + string nom; + if (strstr(entreePrinc.tablcar,"nom_mail=")!=NULL) + { // cas où il y a un nom de maillage + *(entreePrinc.entree) >> nom >> nom; // lecture du mot_clé et du nom + if (nom_maillage == NULL) { nom_maillage = new string(nom);} + else { *nom_maillage = nom;}; + } + // puis lecture de la classe mère + Bloc_particulier::Lecture(entreePrinc); + } + +/// affichage des infos +template +void BlocDdlLim::Affiche() const + { // affichage éventuelle du nom de maillage + if (nom_maillage != NULL) + { cout << "\n nom_mail= " << *nom_maillage;} else cout << "\n"; + // puis affichage des infos de la classe mère + Bloc_particulier::Affiche(); + } + +/// surcharge de l'operateur == +template +bool BlocDdlLim::operator == ( const BlocDdlLim& a) const + { 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; + }; + // puis la classe mère + if (((Bloc_particulier&)(*this)).operator==(a)) + return true; + else + { return false; }; + } + +/// surcharge de l'operateur = +template +BlocDdlLim& BlocDdlLim::operator + = ( const BlocDdlLim& a) + { if (a.nom_maillage == NULL) + { if (nom_maillage != NULL) {delete nom_maillage;nom_maillage=NULL;}} + else + { if (nom_maillage == NULL) nom_maillage = new string(*(a.nom_maillage)); + else *nom_maillage = *(a.nom_maillage); + }; + // puis la classe mère + ((Bloc_particulier&)(*this)).operator=(a); + return *this; + } + +/// change le nom de maillage +/// ATTENTION : Les modifications liees au changement du nom de maillage +/// sont a la charge de l'utilisateur. +/// le nouveau nom ne doit pas être vide !! sinon erreur +template +void BlocDdlLim::Change_nom_maillage(const string& nouveau) + { if (nouveau.length() == 0) + { cout << "\nErreur : reference de nom de maillage non valide car de longueur nulle ! " + << " nom_mail= " << nouveau << "\n"; + cout << "BlocDdlLim::Change_nom_maillage(....) \n"; + Sortie(1); + } + if (nom_maillage == NULL) + { nom_maillage = new string(nouveau);} + else + { *nom_maillage = nouveau;}; + } + +#endif diff --git a/Maillage/Ddl.cc b/Maillage/Ddl.cc new file mode 100644 index 0000000..296470d --- /dev/null +++ b/Maillage/Ddl.cc @@ -0,0 +1,514 @@ +// FICHIER : Ddl.cp +// CLASSE : Ddl + +// 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 "Ddl.h" + + +# include +using namespace std; //introduces namespace std + +#include +#include "Sortie.h" + +#ifndef Ddl_deja_inclus + +#ifndef MISE_AU_POINT + inline +#endif +Ddl::Ddl (Enum_ddl id_nom_ddl,double val,Enum_boolddl val_fixe) : + id_nom(id_nom_ddl),val_ddl(val),fixe(val_fixe) +// Constructeur utile quand l'identificateur de nom du degre de +// liberte sont connus +// ( N.B. : Tous les parametres de ce constructeur ont des valeurs par defaut. +// Ce constructeur peut donc servir de constructeur par defaut. ) +{}; + +#ifndef MISE_AU_POINT + inline +#endif +Ddl::Ddl (char* nom,double val,Enum_boolddl val_fixe) : + val_ddl(val),fixe(val_fixe) +// Constructeur utile quand le nom et la valeur du degre de liberte sont +// connus +// ( N.B. : val et val_fixe ont des valeurs par defaut, il n'est par consequent +// pas obligatoire de leur donner des valeurs a l'appel de ce constructeur ) +{ id_nom=Id_nom_ddl(nom); +}; + +#ifndef MISE_AU_POINT + inline +#endif +Ddl::Ddl (const Ddl& d) +// Constructeur de copie +{ id_nom=d.id_nom; + val_ddl=d.val_ddl; + fixe=d.fixe; +}; + +#ifndef MISE_AU_POINT + inline +#endif +Ddl::~Ddl () +// Destructeur +{ }; + + +#ifndef MISE_AU_POINT + inline +#endif +// Retourne 1 si le degre de liberte a une valeur fixée tout au long du calcul +// Retourne 0 sinon +// ne concerne que les variables (par exemple ne concerne pas les données) +bool Ddl::Fixe() const +{switch (fixe) + { case FIXE : case SURFIXE: case LISIBLE_FIXE: case LISIBLE_SURFIXE: + case HS_LISIBLE_FIXE: case HS_SURFIXE: case HS_LISIBLE_SURFIXE: + case HSFIXE: return true;break; + case LIBRE : case SOUSLIBRE: case LISIBLE_LIBRE: case LISIBLE_SOUSLIBRE: + case HS_LISIBLE_LIBRE: case HS_SOUSLIBRE: case HS_LISIBLE_SOUSLIBRE: + case HSLIBRE: return false;break; + + default : + #ifdef MISE_AU_POINT + cout << "\nErreur : valeur incorrecte du type ddl !\n"; + cout << "Ddl.Fixe(): val= " << fixe; + Sortie(1); + #endif + break; + } + // la ligne suivante ne sert pas mais c'est pour ne pas avoir de Warning + return false ; +}; + +#ifndef MISE_AU_POINT + inline +#endif +// test pour savoir si le ddl est une variable ou une donnée +bool Ddl::UneVariable() const + { switch (fixe) + { case LIBRE: case FIXE : case SOUSLIBRE: case SURFIXE: + case HSLIBRE: case HSFIXE: case HS_SOUSLIBRE: case HS_SURFIXE: + return true; break; + case LISIBLE_LIBRE: case LISIBLE_FIXE : + case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE: + case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE: + case HS_LISIBLE_SOUSLIBRE: case HS_LISIBLE_SURFIXE: + return false;break; + default : + cout << "\nErreur : degre de liberte non defini !\n"; + cout << "\n UneVariable() " << fixe; + Sortie(1); + }; + // la ligne suivante ne sert pas mais c'est pour ne pas avoir de Warning + return false ; + }; + +#ifndef MISE_AU_POINT + inline +#endif +// changement du statut de variable à donnée +void Ddl::ChangeVariable_a_Donnee() + { switch (fixe) + { case LIBRE: fixe = LISIBLE_LIBRE; break; + case FIXE : fixe = LISIBLE_FIXE; break; + case SOUSLIBRE: fixe = LISIBLE_SOUSLIBRE; break; + case SURFIXE: fixe = LISIBLE_SURFIXE; break; + case HSLIBRE: fixe = HS_LISIBLE_LIBRE; break; + case HSFIXE: fixe = HS_LISIBLE_FIXE; break; + case HS_SOUSLIBRE: fixe = HS_LISIBLE_SOUSLIBRE; break; + case HS_SURFIXE: fixe = HS_LISIBLE_SURFIXE; break; + // cas déjà une variable on ne fait rien + case LISIBLE_LIBRE: case LISIBLE_FIXE : + case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE: + case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE: + case HS_LISIBLE_SOUSLIBRE: case HS_LISIBLE_SURFIXE: break; + + default : + cout << "\nErreur : degre de liberte non defini !\n"; + cout << "\n Ddl::ChangeVariable_a_Donnee() " << fixe; + Sortie(1); + } + }; + +#ifndef MISE_AU_POINT + inline +#endif +// changement du statut de donnée à variable +void Ddl::ChangeDonnee_a_Variable() + { switch (fixe) + { case LISIBLE_LIBRE : fixe = LIBRE; break; + case LISIBLE_FIXE : fixe = FIXE; break; + case LISIBLE_SOUSLIBRE : fixe = SOUSLIBRE; break; + case LISIBLE_SURFIXE : fixe = SURFIXE; break; + case HS_LISIBLE_LIBRE : fixe = HSLIBRE; break; + case HS_LISIBLE_FIXE : fixe = HSFIXE; break; + case HS_LISIBLE_SOUSLIBRE: fixe = HS_SOUSLIBRE; break; + case HS_LISIBLE_SURFIXE: fixe = HS_SURFIXE; break; + // cas déjà une variable on ne fait rien + case LIBRE: case FIXE : case SOUSLIBRE: case SURFIXE: + case HSLIBRE: case HSFIXE: + case HS_SOUSLIBRE: case HS_SURFIXE: break; + default : + cout << "\nErreur : degre de liberte non defini !\n"; + cout << "\n ChangeDonnee_a_Variable() " << fixe; + Sortie(1); + } + }; + +#ifndef MISE_AU_POINT + inline +#endif +// Modifie la valeur de fixe, si val est vrai -> blocage , sinon libre +void Ddl::Change_fixe(bool val) +{ if (val) + {switch (fixe) // cas ou on veut fixer + { case SOUSLIBRE : fixe = LIBRE ;break; + case LIBRE : fixe = FIXE ;break; + case FIXE : fixe = SURFIXE ;break; + case HSLIBRE : fixe = HSFIXE;break; + case LISIBLE_SOUSLIBRE : fixe = LISIBLE_LIBRE;break; + case LISIBLE_LIBRE : fixe = LISIBLE_FIXE;break; + case LISIBLE_FIXE : fixe = LISIBLE_SURFIXE;break; + case HS_LISIBLE_LIBRE : fixe = HS_LISIBLE_FIXE;break; + case HS_SOUSLIBRE : fixe = HSLIBRE;break; + case HS_LISIBLE_SOUSLIBRE : fixe = HS_LISIBLE_LIBRE;break; + case HSFIXE : fixe = HS_SURFIXE;break; + case HS_LISIBLE_FIXE : fixe = HS_LISIBLE_SURFIXE;break; + // pour tous les surfixes, on ne fait rien + case SURFIXE: case LISIBLE_SURFIXE: case HS_SURFIXE: case HS_LISIBLE_SURFIXE: + break; + default : + cout << "\nErreur : degre de liberte non defini !\n"; + cout << "\n Ddl::Change_fixe(.. " << fixe; + Sortie(1); + }; + } + else + { switch (fixe) // cas ou on veut rendre libre + { case SURFIXE : fixe = FIXE ;break; + case FIXE : fixe = LIBRE ;break; + case LIBRE : fixe = SOUSLIBRE ;break; + case HSFIXE : fixe = HSLIBRE;break; + case LISIBLE_SURFIXE : fixe = LISIBLE_FIXE;break; + case LISIBLE_FIXE : fixe = LISIBLE_LIBRE;break; + case LISIBLE_LIBRE : fixe = LISIBLE_SOUSLIBRE;break; + case HS_LISIBLE_FIXE : fixe = HS_LISIBLE_LIBRE;break; + case HS_SURFIXE : fixe = HSFIXE;break; + case HS_LISIBLE_SURFIXE : fixe = HS_LISIBLE_FIXE;break; + case HSLIBRE : fixe = HS_SOUSLIBRE;break; + case HS_LISIBLE_LIBRE : fixe = HS_LISIBLE_SOUSLIBRE;break; + // pour tous les sous libre on ne fait rien + case SOUSLIBRE: case LISIBLE_SOUSLIBRE: case HS_SOUSLIBRE: + case HS_LISIBLE_SOUSLIBRE: break; + default : + cout << "\nErreur : degre de liberte non defini !\n"; + cout << "\n Ddl::Change_fixe(.. " << fixe; + Sortie(1); + }; + } + }; + +#ifndef MISE_AU_POINT + inline +#endif +// test si le ddl est SOUSLIBRE ou SURFIXE, ramène true si oui +bool Ddl::SousSurFixe() const +{ switch (fixe) + { case SOUSLIBRE : case SURFIXE : case LISIBLE_SOUSLIBRE : + case LISIBLE_SURFIXE : case HS_SOUSLIBRE : case HS_SURFIXE : + case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE : + return true; break; + // pour les autres retour false + case LIBRE : case FIXE : case HSLIBRE : case HSFIXE : case LISIBLE_LIBRE : + case LISIBLE_FIXE : case HS_LISIBLE_LIBRE : case HS_LISIBLE_FIXE: + return false; break; + default : + cout << "\nErreur : degre de liberte non defini !\n"; + cout << "\n Ddl::SousSurFixe(.. " << fixe; + Sortie(1); + }; +}; + + +#ifndef MISE_AU_POINT + inline +#endif +// remise à normal si le ddl est en souslibre ou surfixe +// s'il est en souslibre il passe en libre et s'il est en surfixe il passe en fixe +// sinon on ne fait rien +void Ddl::Retour_normal_sur_ou_sous_fixe() +{switch (fixe) // cas ou on veut rendre libre + { case SURFIXE : fixe = FIXE ;break; + case LISIBLE_SURFIXE : fixe = LISIBLE_FIXE ;break; + case HS_SURFIXE: fixe = HSFIXE;break; + case HS_LISIBLE_SURFIXE: fixe = HS_LISIBLE_FIXE;break; + case SOUSLIBRE : fixe = LIBRE ;break; + case LISIBLE_SOUSLIBRE : fixe = LISIBLE_LIBRE;break; + case HS_SOUSLIBRE : fixe = HSLIBRE;break; + case HS_LISIBLE_SOUSLIBRE: fixe = HS_LISIBLE_LIBRE;break; + // pour les autres on ne fait rien + case LIBRE : case FIXE : case HSLIBRE : case HSFIXE : + case LISIBLE_LIBRE : case LISIBLE_FIXE : case HS_LISIBLE_LIBRE: + case HS_LISIBLE_FIXE : break; + default : + cout << "\nErreur : degre de liberte non defini !\n"; + cout << "\n Ddl::Retour_normal_sur_ou_sous_fixe(.. " << fixe; + Sortie(1); + }; +}; + +#ifndef MISE_AU_POINT + inline +#endif +void Ddl::Met_hors_service() +// met hors_service le ddl, cela signifie que momentanément il ne sert plus + { switch (fixe) // cas ou on veut rendre libre + { case LIBRE : fixe = HSLIBRE ;break; + case SOUSLIBRE : fixe = HS_SOUSLIBRE ;break; + case FIXE : fixe = HSFIXE ;break; + case SURFIXE : fixe = HS_SURFIXE ;break; + case LISIBLE_LIBRE : fixe = HS_LISIBLE_LIBRE ;break; + case LISIBLE_SOUSLIBRE : fixe = HS_LISIBLE_SOUSLIBRE ;break; + case LISIBLE_FIXE : fixe = HS_LISIBLE_FIXE;break; + case LISIBLE_SURFIXE : fixe = HS_LISIBLE_SURFIXE;break; + case HSLIBRE: case HSFIXE: case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE: + case HS_SOUSLIBRE : case HS_SURFIXE : case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE : + break; // cas déjà HS + default: + cout << "\n erreur cas non prevu pour le ddl "; this->Affiche(); + cout << "\n Ddl::Met_hors_service() "; + Sortie(1); + }; + }; + +#ifndef MISE_AU_POINT + inline +#endif +// met en service le ddl +void Ddl::Met_en_service() + { switch (fixe) // cas ou on veut rendre libre + { case HSLIBRE : fixe = LIBRE ;break; + case HSFIXE : fixe = FIXE ;break; + case HS_LISIBLE_LIBRE : fixe = LISIBLE_LIBRE ;break; + case HS_LISIBLE_FIXE : fixe = LISIBLE_FIXE;break; + case HS_SOUSLIBRE : fixe = SOUSLIBRE;break; + case HS_SURFIXE : fixe = SURFIXE;break; + case HS_LISIBLE_SOUSLIBRE : fixe = LISIBLE_SOUSLIBRE;break; + case HS_LISIBLE_SURFIXE :fixe = LISIBLE_SURFIXE;break; + + case LIBRE: case FIXE: case SOUSLIBRE: case SURFIXE: + case LISIBLE_LIBRE: case LISIBLE_FIXE: + case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE: + break; // cas déjà OK + default: + cout << "\n erreur cas non prevu pour le ddl "; this->Affiche(); + cout << "\n Ddl::Met_hors_service() "; + Sortie(1); + }; + }; + + +#ifndef MISE_AU_POINT + inline +#endif +void Ddl::Met_hors_service_ddl() +// met hors_service le ddl, cela signifie que momentanément il ne sert plus +// ne concerne pas les données + { switch (fixe) // cas ou on veut rendre libre + { case LIBRE : fixe = HSLIBRE ;break; + case SOUSLIBRE : fixe = HS_SOUSLIBRE ;break; + case FIXE : fixe = HSFIXE ;break; + case SURFIXE : fixe = HS_SURFIXE ;break; + // --- cas déjà HS on ne change rien + case HSLIBRE: case HSFIXE: case HS_LISIBLE_LIBRE: case HS_LISIBLE_FIXE: + case HS_SOUSLIBRE : case HS_SURFIXE : case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE : + break; // cas déjà HS + // --- cas des données, on ne fait rien + case LISIBLE_LIBRE : case LISIBLE_SOUSLIBRE : + case LISIBLE_FIXE : case LISIBLE_SURFIXE : + break; // pour les données, on ne change rien + default: + cout << "\n erreur cas non prevu pour le ddl "; this->Affiche(); + cout << "\n Ddl::Met_hors_service_ddl() "; + Sortie(1); + }; + }; + +#ifndef MISE_AU_POINT + inline +#endif +// met en service le ddl, ne concerne pas les données +void Ddl::Met_en_service_ddl() + { switch (fixe) // cas ou on veut rendre libre + { case HSLIBRE : fixe = LIBRE ;break; + case HSFIXE : fixe = FIXE ;break; + case HS_SOUSLIBRE : fixe = SOUSLIBRE;break; + case HS_SURFIXE : fixe = SURFIXE;break; + + // --- déjà libre, on ne change rien + case LIBRE: case FIXE: case SOUSLIBRE: case SURFIXE: + case LISIBLE_LIBRE: case LISIBLE_FIXE: + case LISIBLE_SOUSLIBRE: case LISIBLE_SURFIXE: + break; // cas déjà OK + + // --- on n'intervient pas sur les données + case HS_LISIBLE_SOUSLIBRE : case HS_LISIBLE_SURFIXE : + case HS_LISIBLE_LIBRE : case HS_LISIBLE_FIXE : + break; + + default: + cout << "\n erreur cas non prevu pour le ddl "; this->Affiche(); + cout << "\n Ddl::Met_en_service_ddl() "; + Sortie(1); + }; + }; + +#ifndef MISE_AU_POINT + inline +#endif +// surcharge de l'operateur d'ecriture +ostream & operator << (ostream & sort,const Ddl & a) + { // écriture du type + sort << "Ddl "; + // les données + sort << a.id_nom << " " << a.fixe << " " ; + sort << setprecision(ParaGlob::NbdigdoCA()) << a.val_ddl << " "; + return sort; + }; + +#ifndef MISE_AU_POINT + inline +#endif + // surcharge de l'operator de lecture +istream & operator >> (istream & entree, Ddl& a) + { // vérification du type + string type; + entree >> type; + if (type != "Ddl") + {Sortie (1); + return entree; + } + // entrée des données + entree >> a.id_nom; + entree >> a.fixe; + entree >> a.val_ddl; + + return entree; + }; + + +#ifndef MISE_AU_POINT + inline +#endif +// Affiche les donnees liees au degre de liberte +void Ddl::Affiche () const +{ + cout << " " << Nom_ddl(id_nom) ; + cout << " = " << val_ddl ; + switch (fixe) + { case LIBRE : cout << " val_libre, "; break; + case FIXE : cout << " val_fixe, "; break; + case SOUSLIBRE : cout << " val_sous_libre, "; break; + case SURFIXE : cout << " val_sur_fixe, "; break; + case LISIBLE_LIBRE : cout << " lisible_libre, "; break; + case LISIBLE_FIXE : cout << " lisible_fixe, "; break; + case LISIBLE_SOUSLIBRE : cout << " lisible_sous_libre, "; break; + case LISIBLE_SURFIXE : cout << " lisible_sur_fixe, "; break; + // pour les autres ils sont hors services + case HSLIBRE : + case HSFIXE : + case HS_LISIBLE_LIBRE : + case HS_LISIBLE_FIXE : + case HS_SOUSLIBRE : + case HS_SURFIXE : + case HS_LISIBLE_SOUSLIBRE : + case HS_LISIBLE_SURFIXE : + cout << " hors service, "; break; +/* + case LIBRE : result="LIBRE"; break; + case FIXE : result="FIXE"; break; + case HSLIBRE : result="HSLIBRE"; break; + case HSFIXE : result="HSFIXE"; break; + case SOUSLIBRE : result="SOUSLIBRE"; break; + case SURFIXE : result="SURFIXE"; break; + case LISIBLE_LIBRE : result="LISIBLE_LIBRE"; break; + case LISIBLE_FIXE : result="LISIBLE_FIXE"; break; + case LISIBLE_SOUSLIBRE : result="LISIBLE_SOUSLIBRE"; break; + case LISIBLE_SURFIXE : result="LISIBLE_SURFIXE"; break; + case HS_LISIBLE_LIBRE : result="HS_LISIBLE_LIBRE"; break; + case HS_LISIBLE_FIXE : result="HS_LISIBLE_FIXE"; break; + case HS_SOUSLIBRE : result="HS_SOUSLIBRE"; break; + case HS_SURFIXE : result="HS_SURFIXE"; break; + case HS_LISIBLE_SOUSLIBRE : result="HS_LISIBLE_SOUSLIBRE"; break; + case HS_LISIBLE_SURFIXE : result="HS_LISIBLE_SURFIXE"; break; +*/ + + default: + cout << "\n erreur cas non prevu pour le ddl "; this->Affiche(); + cout << "\n Ddl::Affiche(.. "; + Sortie(1); + }; + }; + +#ifndef MISE_AU_POINT + inline +#endif +//Surcharge d'operateur logique +bool Ddl::operator == (const Ddl& a) const + { if ( (id_nom==a.id_nom) + && (val_ddl == a.val_ddl) && (fixe == a.fixe)) + return true; + else return false; + }; + +#ifndef MISE_AU_POINT + inline +#endif +bool Ddl::operator != (const Ddl& a) const + { return !(*this == a);}; + +#ifndef MISE_AU_POINT + inline +#endif +// test si le degre de liberte est complet +// = 1 tout est ok, =0 element incomplet +int Ddl::TestComplet() const + { if (id_nom == NU_DDL) + { cout << "\n pb !! ddl non defini "; + return false; + } + return true; + }; + + +#endif // fin de l'inclusion totale diff --git a/Maillage/Ddl.h b/Maillage/Ddl.h new file mode 100644 index 0000000..548b073 --- /dev/null +++ b/Maillage/Ddl.h @@ -0,0 +1,279 @@ +// FICHIER : Ddl.h +// CLASSE : Ddl + +// 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: . + +/************************************************************************ +* DATE: 23/01/97 * +* $ * +* AUTEUR: G RIO (mailto:gerardrio56@free.fr) * +* $ * +* PROJET: Herezh++ * +* $ * +************************************************************************ +* La classe Ddl permet de declarer des degres de liberte. +* soit c'est une variable ou soit c'est une données qui peuvent être soit active +* soit hors-service +* ensuite soit il est fixe ou soit il est bloqué +* 1) libre, fixe, ou 2) hors service libre ou hors service fixe ===> une variable +* 3) lisible libre ou fixe ou 4) hors service libre ou fixe ===> une donnée +* 1) c'est pour les ddl qui sont des variables que le calcul va déterminer, +* 2) sont les variables qui sont hors service: on ne les considères pas +* 3) sont des variables que l'on peut utiliser mais que le calcul ne +* cherche pas à déterminer: elle sont en lecture seule en quelque sorte +* 4) se sont des données qui ne sont pas dispon pour la consultation (par exemple hors temps) +* $ * +* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * +* * +* VERIFICATION: * +* * +* ! date ! auteur ! but ! * +* ------------------------------------------------------------ * +* ! ! ! ! * +* $ * +* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * +* MODIFICATIONS: * +* ! date ! auteur ! but ! * +* ------------------------------------------------------------ * +* $ * +************************************************************************/ + +// La classe Ddl permet de declarer des degres de liberte. +// soit c'est une variable ou soit c'est une données qui peuvent être soit active +// soit hors-service +// ensuite soit il est fixe ou soit il est bloqué +// 1) libre, fixe, ou 2) hors service libre ou hors service fixe ===> une variable +// 3) lisible libre ou fixe ou 4) hors service libre ou fixe ===> une donnée +// 1) c'est pour les ddl qui sont des variables que le calcul va déterminer, +// 2) sont les variables qui sont hors service: on ne les considères pas +// 3) sont des variables que l'on peut utiliser mais que le calcul ne +// cherche pas à déterminer: elle sont en lecture seule en quelque sorte +// 4) se sont des données qui ne sont pas dispon pour la consultation (par exemple hors temps) + + +#ifndef DDL_H +#define DDL_H + + +#include "Enum_ddl.h" +#include "Enum_boolddl.h" + + +#include +#include +#include "Sortie.h" +#include +// #include + +/** @defgroup Les_classes_Ddl_en_tout_genre +* +* BUT:def de classes relatives aux ddl en tout genre +* Ddl, Ddl_etendu, DdlElement, DdlLim etc. +* +* \author Gérard Rio +* \version 1.0 +* \date 23/01/97 +* \brief Def de classes relatives aux ddl en tout genre +* +*/ + +/// @addtogroup Les_classes_Ddl_en_tout_genre +/// @{ +/// + + +/// BUT: La classe Ddl permet de declarer des degres de liberte. +/// soit c'est une variable ou soit c'est une données qui peuvent être soit active +/// soit hors-service +/// ensuite soit il est fixe ou soit il est bloqué +/// 1) libre, fixe, ou 2) hors service libre ou hors service fixe ===> une variable +/// 3) lisible libre ou fixe ou 4) hors service libre ou fixe ===> une donnée +/// 1) c'est pour les ddl qui sont des variables que le calcul va déterminer, +/// 2) sont les variables qui sont hors service: on ne les considères pas +/// 3) sont des variables que l'on peut utiliser mais que le calcul ne +/// cherche pas à déterminer: elle sont en lecture seule en quelque sorte +/// 4) se sont des données qui ne sont pas dispon pour la consultation (par exemple hors temps) +/// +/// \author Gérard Rio +/// \version 1.0 +/// \date 23/01/97 +/// +/// + + +class Ddl +{ + // surcharge de l'operator de lecture + friend istream & operator >> (istream & entree, Ddl& a); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort, const Ddl& a); + + public: + + + // CONSTRUCTEURS : + + // Constructeur eventuellement par defaut + Ddl (Enum_ddl id_nom_ddl=NU_DDL,double val=0.0,Enum_boolddl val_fixe=HS_LISIBLE_LIBRE); + + // Constructeur se servant d'un nom + // ( N.B. : val et val_fixe ont des valeurs par defaut, il n'est par consequent + // pas obligatoire de leur donner des valeurs a l'appel de ce constructeur ) + Ddl (char* nom,double val=0.0,Enum_boolddl val_fixe=HS_LISIBLE_LIBRE); + + + // Constructeur de copie + Ddl (const Ddl& d); + + + // DESTRUCTEUR : + + ~Ddl (); + + + // METHODES : + + // Retourne 1 si le degre de liberte a une valeur fixée tout au long du calcul + // Retourne 0 sinon + // ne concerne que les variables (par exemple ne concerne pas les données) + bool Fixe() const; + + // test pour savoir si le ddl est une variable ou une donnée + bool UneVariable() const; + + // changement du statut de variable à donnée + void ChangeVariable_a_Donnee(); + + // changement du statut de donnée à variable + void ChangeDonnee_a_Variable(); + + // Retourne la valeur de fixe en lecture uniquement + inline const Enum_boolddl Retour_Fixe() const { return fixe ; }; + + // Modifie la valeur de fixe, si val est vrai -> blocage , sinon libre + void Change_fixe(bool val); + + // modifie toute les conditions sauf la valeur: c-a-d: + // le fixage, le fait que c'est une variable ou une donnée, le fait + // d'être en service ou non etc.. + void CopieToutesLesConditions( Enum_boolddl en) {fixe = en;}; + + // test pour savoir si le ddl est en service ou pas + inline bool Service() const + { return (!(Est_HS(fixe)));}; + + // test si le ddl est SOUSLIBRE ou SURFIXE, ramène true si oui + bool SousSurFixe() const; + + // remise à normal si le ddl est en souslibre ou surfixe + // s'il est en souslibre il passe en libre et s'il est en surfixe il passe en fixe + // sinon on ne fait rien + void Retour_normal_sur_ou_sous_fixe(); + + // met hors_service le ddl ou la donnée, cela signifie que momentanément il ne sert plus + void Met_hors_service(); + // met en service le ddl ou la donnée + void Met_en_service(); + + // met hors_service le ddl, cela signifie que momentanément il ne sert plus + // ne concerne pas les données + void Met_hors_service_ddl(); + // met en service le ddl, ne concerne pas les données + void Met_en_service_ddl(); + + // Retourne la valeur associee au degre de liberte + inline double& Valeur() { return val_ddl; }; + + // Retourne le nom associe au degre de liberte + inline const string Nom() const { return Nom_ddl(id_nom); }; + + // Retourne la variable de type enumere associee au nom du degre de liberte + inline Enum_ddl Id_nom() const { return id_nom; }; + + // Remplace le nom du degre de liberte par nouveau_nom + // (par l'intermediaire du type enumere associe) + // ATTENTION : Les modifications liees au changement de nom du degre + // de liberte sont a la charge de l'utilisateur. + inline void Change_nom(char* nouveau_nom) + { id_nom=Id_nom_ddl(nouveau_nom); }; + + // Remplace l'identificateur de nom du degre de liberte par + // nouveau_id + // ATTENTION : Les modifications liees au changement de nom du degre + // de liberte sont a la charge de l'utilisateur. + inline void Change_nom(Enum_ddl nouveau_id) + { id_nom=nouveau_id; }; + + // Affiche les donnees liees au degre de liberte + void Affiche() const ; + + inline Ddl& operator= (const Ddl& d) + // Realise l'egalite entre deux degres de liberte + { id_nom=d.id_nom; + val_ddl=d.val_ddl; + fixe=d.fixe; + return (*this); + }; + + //Surcharge d'operateur logique + bool operator == ( const Ddl& a) const ; + + bool operator != ( const Ddl& a) const; + + + // test si le degre de liberte est complet + // = 1 tout est ok, =0 element incomplet + int TestComplet() const; + + + protected : + + Enum_ddl id_nom; // identificateur du nom + + // bool fixe; // booleen pour savoir si la valeur associee au + // degre de liberte est fixe pendant tout le calcul + Enum_boolddl fixe; // 1) libre, fixe, ou 2) hors service libre ou hors service fixe + // ou 3) lisible libre ou fixe + // cf. l'énuméré + + double val_ddl; // valeur associee + + +}; +/// @} // end of group + +// pour faire de l'inline +#ifndef MISE_AU_POINT + #include "Ddl.cc" + #define Ddl_deja_inclus +#endif + + + +#endif diff --git a/Maillage/DdlElement.cc b/Maillage/DdlElement.cc new file mode 100644 index 0000000..5c1fe98 --- /dev/null +++ b/Maillage/DdlElement.cc @@ -0,0 +1,329 @@ + +// 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 "DdlElement.h" + + + // CONSTRUCTEURS : +// par defaut +DdlElement::DdlElement () : + te(),nbddl(0),tab_enum_famille() {}; +// definition du tableau pour n noeuds vide +DdlElement::DdlElement (int n) : + te(n),nbddl(0),tab_enum_famille() + { }; +// definition du tableau pour n noeuds et m ddl par noeud +// utile lorsque tous les noeuds ont le meme nombre de ddl +// par contre ici aucun ddl n'est encore défini +DdlElement::DdlElement (int n, int m) : + te(n),nbddl(n*m),tab_enum_famille() + { for (int i=1; i<= n;i++) + { Tableau & tb=te(i).tb; + tb.Change_taille (m); + for (int j=1;j<=m;j++) + tb(j)=NU_DDL; + }; + // def du nombre des types particuliers de ddl, ici il s'agit de NU_DDL + Calcul_NbDdl_typer(); + }; +// definition du tableau pour n noeuds et un nombre de ddl par noeud +// stocke dans le tableau mddl qui doit avoir la dimension n +// par contre ici aucun ddl n'est encore défini +DdlElement::DdlElement (int n,const Tableau & mddl) : + te(n),tab_enum_famille() + { if (mddl.Taille() == n) + for (int i=1; i<= n;i++) + { Tableau & tb=te(i).tb; + int m = mddl(i); + tb.Change_taille (m); + for (int j=1;j<=m;j++) + tb(j)=NU_DDL; + } + else + { cout << "\n erreur de dimension pour le tableau mddl, il doit avoir la "; + cout << " dimension : " << n << ", alors qu\'il a la dimension : " + << mddl.Taille() << "\nDdlElement (int n, Tableau mddl)" << endl; + Sortie (1); + } + // def du nombre total et des types particuliers de ddl + Calcul_NbDdl(); Calcul_NbDdl_typer(); + }; + +// definition du tableau pour n noeuds et une meme liste de ddl pour chaque +// noeud identique au second argument +DdlElement::DdlElement (int n, DdlNoeudElement d) : + te(n,d),nbddl(n * d.tb.Taille()),tab_enum_famille() + { // def du nombre total et des types particuliers de ddl + Calcul_NbDdl(); Calcul_NbDdl_typer(); + }; + +DdlElement::DdlElement (const DdlElement& a) : + te(a.te),nbddl(a.nbddl),tab_enum_famille(a.tab_enum_famille) + {}; // de copie + // DESTRUCTEUR : +DdlElement::~DdlElement () {}; + +// acces en modification au ddl j du noeud i +void DdlElement::Change_Enum(int i,int j,const Enum_ddl enu) + {tab_enum_famille[PremierDdlFamille((te(i)).tb(j))]--; + (te(i)).tb(j) = enu; + tab_enum_famille[PremierDdlFamille(enu)]++; + }; + +// nombre de ddl du noeudElement i contenu +int DdlElement::NbDdl(int i) const + { return (te(i)).tb.Taille();}; + +// change la dimension du tableau de ddl pour n noeuds et m ddl par noeud +//dans le cas ou tous les noeuds ont le meme nombre de ddl +// si la nouvelle taille est plus petite: suppression +// si la nouvelle dimension est plus grande on met les ddl suplémentaires à NU_DDL +void DdlElement::Change_taille(int n,int m) + { int oldTaille = te.Taille(); + te.Change_taille(n); + int deltataille = n-oldTaille; + if (deltataille > 0) + { // cas où on augmente la taille + // 1) on traite différemment les anciens ddl et les nouveaux + for (int i=1;i<=oldTaille;i++) + { Tableau & tb=te(i).tb; + int otaille = tb.Taille(); + if (m<=otaille) + {// on supprime sans pb + tb.Change_taille(m); + } + else // on augmente avec des ddl NU_DDL + {tb.Change_taille(m); + for (int j=otaille+1;j<=m;j++) + tb(j)=NU_DDL; + }; + }; + // 2) les nouveaux DdlNoeudElement sont mis à NU_DDL + for (int i1=oldTaille+1;i1<= n;i1++) + { Tableau & tb=te(i1).tb; + for (int j1=1;j1<=m;j1++) + tb(j1)=NU_DDL; + }; + } + else // si on diminue + { for (int i=1;i<=oldTaille;i++) + { Tableau & tb=te(i).tb; + int otaille = tb.Taille(); + if (m<=otaille) + {// on supprime sans pb + tb.Change_taille(m); + } + else // on augmente avec des ddl NU_DDL + {tb.Change_taille(m); + for (int j=otaille+1;j<=m;j++) + tb(j)=NU_DDL; + }; + }; + }; + nbddl = n*m; + Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type + }; + +// change la dimension du tableau de ddl pour n noeuds et un nombre de ddl par noeud +// stocke dans le tableau mddl qui doit avoir la dimension n +// si la nouvelle taille est plus petite: suppression +// si la nouvelle dimension est plus grande on met les ddl suplémentaires à NU_DDL +void DdlElement::Change_taille(int n,Tableau mddl) + { int oldTaille = te.Taille(); + te.Change_taille(n); + nbddl = 0; + if (mddl.Taille() == n) + {int deltataille = n-oldTaille; + if (deltataille > 0) + { // cas où on augmente la taille + // 1) on traite différemment les anciens ddl et les nouveaux + for (int i=1;i<=oldTaille;i++) + { Tableau & tb=te(i).tb; + int otaille = tb.Taille(); + int m = mddl(i);nbddl += m; + if (m<=otaille) + {// on supprime sans pb + tb.Change_taille(m); + } + else // on augmente avec des ddl NU_DDL + {tb.Change_taille(m); + for (int j=otaille+1;j<=m;j++) + tb(j)=NU_DDL; + }; + }; + // 2) les nouveaux DdlNoeudElement sont mis à NU_DDL + for (int i1=oldTaille+1;i1<= n;i1++) + { Tableau & tb=te(i1).tb; + int m = mddl(i1);nbddl += m; + for (int j1=1;j1<=m;j1++) + tb(j1)=NU_DDL; + }; + } + else // si on diminue + { for (int i=1;i<=oldTaille;i++) + { Tableau & tb=te(i).tb; + int otaille = tb.Taille(); + int m = mddl(i); nbddl += m; + if (m<=otaille) + {// on supprime sans pb + tb.Change_taille(m); + } + else // on augmente avec des ddl NU_DDL + {tb.Change_taille(m); + for (int j=otaille+1;j<=m;j++) + tb(j)=NU_DDL; + }; + }; + }; + } + else + { cout << "\n erreur de dimension pour le tableau mddl, il doit avoir la "; + cout << " dimension : " << n << ", alors qu\'il a la dimension : " + << mddl.Taille() << "\nChange_taille(int n,Tableau mddl)" << endl; + Sortie (1); + } + Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type + }; + + // met le tableau de ddl a zero +void DdlElement::TailleZero() + { int maxi_elem = te.Taille(); + for (int i=1; i<=maxi_elem;i++) + (te(i)).tb.Change_taille (0); + te.Change_taille(0); + nbddl = 0; + tab_enum_famille.erase(tab_enum_famille.begin(),tab_enum_famille.end()); + }; +// change un des ddlNoeudElements +void DdlElement::Change_un_ddlNoeudElement(int i,const DdlNoeudElement& add) + { int nbdold = te(i).tb.Taille(); + nbddl -= nbdold; + int nbdnew = add.tb.Taille(); + nbddl += nbdnew; + // mise en place de add + te(i)=add; + // mise à jour des ddl par famille + Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type + /*Tableau & tb=te(i).tb; + for (int j=1;j<=nbdold;j++) + (tab_enum_famille[PremierDdlFamille(tb(j))])--; + for (int i=1;i<= nbdnew;i++) + (tab_enum_famille[PremierDdlFamille(add.tb(i))])++;*/ + }; + +// surcharge de l'operateur d'affectation +DdlElement& DdlElement::operator = (const DdlElement & a) + { int nb = a.NbNoeud(); + this->te.Change_taille(nb); + for (int i=1;i<= nb;i++) + this->te(i) = a(i); + // mise à jour du nombre de ddl + nbddl = a.nbddl; tab_enum_famille = a.tab_enum_famille; + return *this; + }; +// surcharge des operator de test +bool DdlElement::operator == (const DdlElement & a) const + { int nb = a.NbNoeud(); + for (int i=1;i<=nb;i++) + if (this->te(i) != a(i)) return false; + return true; + }; +bool DdlElement::operator != (const DdlElement & a) const + { if (*this == a) return false; else return true; + }; + + // surcharge de l'operator de lecture +istream & operator >> (istream & entree, DdlElement& a) + { // vérification du type + string type; + entree >> type; + if (type != "DdlElement") + {Sortie (1); + return entree; + } + // entrée du tableau + entree >> a.te; + // puis def du nombre total de ddl + a.Calcul_NbDdl(); + a.Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type + return entree; + }; + // surcharge de l'operator d'ecriture +ostream & operator << (ostream & sort, const DdlElement& a) + { // tout d'abord un indicateur donnant le type + sort << "DdlElement " ; + // puis le tableau + sort << a.te; + return sort; + }; + +// retour du nombre de ddl d'une famille donnée +int DdlElement::NbDdl_famille(Enum_ddl enu) const + { // pour l'instant on sort la totalité des ddl ce qui est faux mais permet de fonctionner comme avant +// return nbddl; + map < Enum_ddl, Int_initer , std::less >::const_iterator il = tab_enum_famille.find(enu); + if (il == tab_enum_famille.end()) return 0; else return (*il).second.vali; + }; + +//================================= methodes proteges ================== + + // calcul du nb de ddl +void DdlElement::Calcul_NbDdl() + { nbddl = 0; + int tetaille = te.Taille(); + for (int i=1; i<= tetaille;i++) + nbddl += (te(i)).tb.Taille(); + }; + + // calcul du nb de ddl de chaque type contenu +void DdlElement::Calcul_NbDdl_typer() + { // méthode en utilisant "tab_enum_famille" + // qui est un tableau associatif + // on commence par initialiser le tableau + tab_enum_famille.erase(tab_enum_famille.begin(),tab_enum_famille.end()); + // on passe en revue tous les ddl + int tetaille = te.Taille(); + for (int i=1; i<= tetaille;i++) + { Tableau & tb=te(i).tb; + int nbd= tb.Taille(); + for (int j=1;j<=nbd;j++) + (tab_enum_famille[PremierDdlFamille(tb(j))])++; + } + /* // pour vérif + map < Enum_ddl, Int_initer , std::less >::iterator il,ilfin=tab_enum_famille.end(); + for (il=tab_enum_famille.begin();il != ilfin;il++) + cout << "\n ddl= " << (*il).first << " nombre " << (*il).second.vali << endl; + + cout << "toto ?"; + int toto; cin >> toto; */ + }; + + diff --git a/Maillage/DdlElement.h b/Maillage/DdlElement.h new file mode 100644 index 0000000..c059f73 --- /dev/null +++ b/Maillage/DdlElement.h @@ -0,0 +1,171 @@ + +// 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: . + +/************************************************************************ + * DATE: 23/01/97 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: Definition, gestion et stockage des ddl de l'element. * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ +#ifndef DDLELEMENT_H +#define DDLELEMENT_H + +#include "Tableau_T.h" +#include "DdlNoeudElement.h" +//#ifdef SYSTEM_MAC_OS_X +// #include // a priori ce n'est pas portable +//#el +#if defined SYSTEM_MAC_OS_CARBON + #include // a priori ce n'est pas portable +#else + #include // pour le flot en memoire centrale +#endif +#include +#include + +/// @addtogroup Les_classes_Ddl_en_tout_genre +/// @{ +/// + + +/// BUT: Definition, gestion et stockage des ddl de l'element. +/// +/// \author Gérard Rio +/// \version 1.0 +/// \date 23/01/97 +/// +/// + + +class DdlElement +{ // surcharge de l'operator de lecture + friend istream & operator >> (istream & entree, DdlElement& a); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort, const DdlElement& a); + + public : + + // CONSTRUCTEURS : + DdlElement (); // par defaut + // definition du tableau pour n noeuds vide + DdlElement (int n); + // definition du tableau pour n noeuds et m ddl par noeud + // utile lorsque tous les noeuds ont le meme nombre de ddl + // par contre ici aucun ddl n'est encore défini + DdlElement (int n, int m); + // definition du tableau pour n noeuds et un nombre de ddl par noeud + // stocke dans le tableau mddl qui doit avoir la dimension n + // par contre ici aucun ddl n'est encore défini + DdlElement (int n,const Tableau & mddl); + // definition du tableau pour n noeuds et une meme liste de ddl pour chaque + // noeud identique au second argument + DdlElement (int n, DdlNoeudElement d); + // de copie + DdlElement (const DdlElement& a); + // DESTRUCTEUR : + ~DdlElement (); + + // retourne nombre de noeud + int NbNoeud() const { return te.Taille();}; + // acces en modification au ddl j du noeud i + void Change_Enum(int i,int j,const Enum_ddl enu); + // acces en lecture seulement au ddl j du noeud i + Enum_ddl operator() (const int i,const int j) const { return (te(i)).tb(j);}; + // acces en lecture seulement au tableau de ddl du noeud i + const DdlNoeudElement& operator() (int i) const { return (te(i));}; + // nb de ddl total contenu + int NbDdl() const { return nbddl;}; + // nb de ddl du noeudElement i contenu + int NbDdl(int i) const ; + // retour du nombre de ddl d'une famille donnée + int NbDdl_famille(Enum_ddl enu)const; + // change la dimension du tableau de ddl pour n noeuds et m ddl par noeud + //dans le cas ou tous les noeuds ont le meme nombre de ddl + // si la nouvelle taille est plus petite: suppression + // si la nouvelle dimension est plus grande on met les ddl suplémentaires à NU_DDL + void Change_taille(int n,int m); + // change la dimension du tableau de ddl pour n noeuds et un nombre de ddl par noeud + // stocke dans le tableau mddl qui doit avoir la dimension n + // si la nouvelle taille est plus petite: suppression + // si la nouvelle dimension est plus grande on met les ddl suplémentaires à NU_DDL + void Change_taille(int n,Tableau mddl); + // change un des ddlNoeudElements + void Change_un_ddlNoeudElement(int i,const DdlNoeudElement& add); + // mais le tableau de ddl a zero + void TailleZero(); + // surcharge de l'operateur d'affectation + DdlElement& operator = (const DdlElement & a); + // surcharge des operator de test + bool operator == (const DdlElement & a) const ; + bool operator != (const DdlElement & a) const ; + + + // VARIABLES et méthodes protegees : + protected : + Tableau te; + int nbddl; + + // on définit un tableau associatif pour contenir le nombre de ddl de chaque famille + // on redéfini une classe de int dont les éléments sont mis à 0 au début + class Int_initer {public: int vali; Int_initer(): vali(0) {}; + Int_initer(const Int_initer& a): vali(a.vali) {}; + Int_initer& operator =(const Int_initer& a){vali=a.vali;return *this;}; + void operator ++(int){vali++;}; + void operator --(int){vali--;};}; + map < Enum_ddl, Int_initer , std::less > tab_enum_famille; + + // calcul du nb de ddl total contenu + void Calcul_NbDdl() ; + // calcul du nb de ddl de chaque type contenu + void Calcul_NbDdl_typer() ; + + + }; +/// @} // end of group + +#endif + + diff --git a/Maillage/DdlLim.cc b/Maillage/DdlLim.cc new file mode 100644 index 0000000..bb3ef4b --- /dev/null +++ b/Maillage/DdlLim.cc @@ -0,0 +1,1600 @@ + +// 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 "DdlLim.h" +#include +#include +#include + + +# include +using namespace std; //introduces namespace std +#include +#include "Sortie.h" +#include "ConstMath.h" +#include "CharUtil.h" + + + +DdlLim::DdlLim () : // par defaut + tab(),ref(),t_min(0.),t_max(ConstMath::tresgrand),precedent(false) + ,nom_maillage(NULL),champ(false),blocage_relatif(false),mvtsolide(NULL) + ,nom_fnD_t_min(""),nom_fnD_t_max("") + ,typeCL(RIEN_TYPE_CL) +{ +}; + +// de copie +DdlLim::DdlLim (const DdlLim& d) : + t_min(d.t_min),t_max(d.t_max),ref(d.ref),tab(d.tab),precedent(d.precedent) + ,nom_maillage(NULL),champ(d.champ),blocage_relatif(d.blocage_relatif) + ,mvtsolide(NULL),typeCL(d.typeCL) + ,nom_fnD_t_min(d.nom_fnD_t_min) + ,nom_fnD_t_max(d.nom_fnD_t_max) +// Constructeur de copie +{ if (d.nom_maillage != NULL) nom_maillage = new string(*(d.nom_maillage)); + if (d.mvtsolide != NULL) + mvtsolide = new MvtSolide(*(d.mvtsolide)); +}; + +DdlLim::~DdlLim () +// Destructeur +{ if (nom_maillage != NULL) delete nom_maillage; + if (mvtsolide != NULL) delete mvtsolide; +}; + +// Remplace la reference par nouveau +// ATTENTION : Les modifications liees au changement de la reference +// sont a la charge de l'utilisateur. +void DdlLim::Change_ref (string nouveau) + { if (nouveau.length() == 0) + { cout << "\nErreur : reference non valide car de longueur nulle !\n"; + cout << "DdlLim::CHANGE_REF(string ) \n"; + Sortie(1); + } + ref = nouveau; + }; + +// idem pour le changement de nom de maillage +void DdlLim::Change_nom_maillage(const string& nouveau) + { if (nouveau.length() == 0) + { cout << "\nErreur : reference de nom de maillage non valide car de longueur nulle ! " + << " nom_mail= " << nouveau << "\n"; + cout << "DdlLim::Change_nom_maillage(....) \n"; + Sortie(1); + } + if (nom_maillage == NULL) + { nom_maillage = new string(nouveau);} + else + { *nom_maillage = nouveau;}; + }; + +// lecture des degres de liberte +// sur le fichier d'entree +// util pour la lecture de ddl bloque +void DdlLim::Lecture(UtilLecture & entreePrinc) +{ // on regarde tout d'abord si il y a un nom de maillage, qui doit être le premier nom + 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 + *(entreePrinc.entree) >> nom; + } + // lecture de la reference + char tat[250]; char * ta = tat; char tt[100]; char * t = tt; + char ch = '\''; char * pt = & ch; char bl = ' '; char* pbl = &bl; + ref = nom; // *(entreePrinc.entree) >> ref; + if (ref.length() == 0) + { // pas de reference + cout << "\n erreur de lecture d'une reference de ddl bloquee " + << " la chaine a une longueur nulle \n"; + entreePrinc.MessageBuffer("*** lecture d'une reference de ddl bloquee ****" ); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + // def de la liste de ddl + list lili; + // on regarde si un type de condition limite est indiqué + if (strstr(entreePrinc.tablcar,"typeCL_=")!=NULL) + { string mot; + *(entreePrinc.entree) >> mot ; + if (mot != "typeCL_=") + { cout << "\n erreur de lecture d'une reference " + << " on s'attandait a lire le mot cle : typeCL_= et on a lue: " << mot << " \n"; + entreePrinc.MessageBuffer("*** lecture d'une reference de ddl bloquee: mot cle typeCL_= ****" ); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // sinon c'est ok pour le mot cle, on passe au contenu, + *(entreePrinc.entree) >> mot; + if (Existe_typeCL(mot)) + { typeCL = Id_nomTypeCL(mot);} // cas ou le type de cl existe + else + { cout << "\n erreur de lecture d'un type de condition limite " + << " on a lue: " << mot << " \n"; + entreePrinc.MessageBuffer("*** lecture d'une reference de ddl bloquee: type de CL ****" ); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + } + else // sinon on précise qu'il n'y a pas de type de CL particulier + { typeCL = RIEN_TYPE_CL; }; + + // maintenant les cas particulier + if (strstr(entreePrinc.tablcar,"champ_de:")!=NULL) + // on regarde si c'est un champ de valeur c'est-à-dire une valeur par noeud de la ref + // dans ce cas appel de la procédure a doc + { lili = Lecture_champ(entreePrinc); champ = true;} + else if (strstr(entreePrinc.tablcar,MvtSolide::MotCleMvtSolide().c_str())!=NULL) + // on regarde si c'est un mouvement solide, si oui appel de la procédure a doc + { // petite vérif: incompatible avec la condition de tangente imposée + if (typeCL == TANGENTE_CL) + {cout << "\n erreur en lecture, la condition de mouvement solide est incompatible " + << " avec une condition de tangente imposée !!! revoir l'entree de la " + << " condition " ; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + lili = Lecture_mvtSolide(entreePrinc); champ = false ; + } + else + {champ = false; + // --- dans la suite comme il ne s'agit pas d'un champ toutes les données sont sur une seule ligne ----- + //recup de la fin de la ligne + char tout[150] ; char * ptout = tout; + (entreePrinc.entree)->get(ptout,150); + // avant la lecture on remplace toutes les virgules par des espaces + char * ii = strchr(ptout,','); + while (ii != NULL) + { *ii = ' '; + ii = strchr(ptout,','); + } + // def d'un flot intermédiaire + #ifndef ENLINUX_STREAM + istringstream flot(ptout); + #else + istrstream flot(ptout); + #endif + + // lecture tant que le flot est valide + while (flot.rdstate() == 0) + // tout d'abord on passe les espaces qui sont des séparateurs + // lecture du prochain caractère sans modifier le flot + { char car; + flot >> car; + // éventuellement il n'avait pas bien déterminé la fin de l'enregistrement + // au niveau du while, dans ce cas si durant la lecture de car il y a eu un pb + // cela signifie qu'en fait la ligne était terminée donc on s'arrête + if (flot.rdstate() != 0) break; + while ( (car==' ') && (flot.rdstate() == 0 )) + // cas où le prochain caractère est un espace + { flot >> car;}; + flot.putback(car); + bool un_ddl_a_lire=true; + // on démarre une boucle qui se termine lorsqu'il n'y a plus de ddl à lire + while(un_ddl_a_lire) + {// on définit un ddl pour la lecture + Ddlbloque elem; + // deux cas, soit un ddl nulle par defaut, soit une valeur non nulle imposee + // soit le caractère est ' , signifie que c'est un ddl avec une valeur + // imposée + if ( (car=='\'') && (flot.rdstate() == 0 )) + { // on passe le premier ' + flot >> car; + // on lit jusqu'au prochain ' en non formaté + flot.get(ta,150,'\''); + // on passe ce dernier ' + flot >> car; + // on recherche le = pour mettre un blanc a la place + char * ii = strchr(ta,'\'');char * pii=ii; // sauvegarde de l'adresse + ii = strchr(ta,'='); // on recherche le = + if (ii == NULL) + { cout << "\n erreur de syntaxe dans la definition des conditions limites " + << " imposees a une valeur non nulle "; + cout << " le ddl doit etre separe de la valeur par le signe = , caractere non" + << " trouve "; + entreePrinc.MessageBuffer("*** lecture d'une reference de ddl bloquee ****" ); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + *ii = ' '; // supprime le = + // def d'un flux intermediaire + #ifndef ENLINUX_STREAM + istringstream flux (ta); + #else + istrstream flux (ta); + #endif + + flux >> t ; + elem.ddl.Change_nom(t); + // on vérifie que le ddl est compatible avec la dimension + if (!CompatDim(t)) + { cout << "\n erreur de choix de ddl dans la definition des conditions limites " + << " le ddl " << t << " n'est pas compatible avec la dimension du probleme "; + entreePrinc.MessageBuffer("*** lecture d'une reference de ddl bloquee ****" ); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + + // on regarde s'il ne s'agit pas d'une courbe ou fonction de charge imposée + bool sans_courbe_ou_fct_nD=true; // variable locale + // l'ordre d'apparition de la courbe de charge ou de la fonction nD peut être + // quelconque + if ((strstr(ta,"COURBE_CHARGE:")!=0)|| (strstr(ta,"Fonction_nD_CHARGE:")!=0)) + {string nom_fonct;string nom_cle; + flux >> nom_cle >> nom_fonct; + // a) cas d'une courbe + if(nom_cle == "COURBE_CHARGE:") + { // cas d'une courbe de charge +// flux >> toto >> elem.co_charge; + elem.co_charge = nom_fonct; + sans_courbe_ou_fct_nD=false; + // on regarde s'il y a une fct nD qui suit + if(strstr(ta,"Fonction_nD_CHARGE:")!=0) + { // cas d'une fonction nD + string toto; + flux >> toto >> elem.f_charge; + // on vérifie la présence au bon endroit du mot clé Fonction_nD_CHARGE: + if (toto != "Fonction_nD_CHARGE:") + {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD "; + cout << " on attendait Fonction_nD_CHARGE: " + << " et on a lu "<< toto; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + }; + } + else if (nom_cle == "Fonction_nD_CHARGE:") + { elem.f_charge = nom_fonct; + sans_courbe_ou_fct_nD=false; + // on regarde s'il y a une courbe 1D qui suit + if(strstr(ta,"COURBE_CHARGE:")!=0) + { // cas d'une courbe de charge + string toto; + flux >> toto >> elem.co_charge; + elem.co_charge = nom_fonct; + // on vérifie la présence au bon endroit du mot clé Fonction_nD_CHARGE: + if (toto != "COURBE_CHARGE:") + {cout << "\n erreur de syntaxe en lecture du nom de la courbe "; + cout << " on attendait COURBE_CHARGE: " + << " et on a lu "<< toto; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + }; + } + else + {cout << "\n erreur de syntaxe en lecture du nom de la courbe ou du nom d'une fonction nD"; + cout << " on attendait COURBE_CHARGE: ou Fonction_nD_CHARGE: " + << " et on a lu "<< nom_cle; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // on récupère l'échelle éventuellement + if(strstr(ta,"ECHELLE:")!=0) + { // cas où il y a un facteur d'échelle + string toto; + flux >> toto; + if (toto != "ECHELLE:") + {cout << "\n erreur de syntaxe en lecture du facteur d'échelle "; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // lecture du facteur + flux >> elem.echelle; + }; + }; +// // b) cas d'une fonction nD +// if(strstr(ta,"Fonction_nD_CHARGE:")!=0) +// { // cas d'une fonction nD +// string toto; +// flux >> toto >> elem.f_charge; +// sans_courbe_ou_fct_nD=false; +// // on vérifie la présence au bon endroit du mot clé Fonction_nD_CHARGE: +// if (toto != "Fonction_nD_CHARGE:") +// {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD "; +// cout << "\n DdlLim::Lecture(.. " << endl ; +// entreePrinc.MessageBuffer("**erreur**"); +// throw (UtilLecture::ErrNouvelleDonnee(-1)); +// Sortie(1); +// }; +// }; + + // si aucune courbe ou fct nD + if (sans_courbe_ou_fct_nD) + // cas où c'est une valeur fixe + { + flux >> elem.ddl.Valeur(); + } + elem.ddl.Change_fixe (true); + } + else if (flot.rdstate() == 0 ) // il s'agit d'un ddl à 0 + { //un ddl nulle par defaut + flot >> t; + // on vérifie que c'est bien un ddl + if (!ExisteEnum_ddl(t)) + { cout << "\n erreur , on s'attendait a lire un ddl et on a lue: " << t + << " !!, partie de condition actuellement lue: "; + this->Affiche(); + cout << " DdlLim::Lecture(UtilLecture & entreePrinc)" << endl; + entreePrinc.MessageBuffer("** erreur en lecture des conditions limites**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie (1); + }; + elem.ddl.Change_nom(t); + elem.ddl.Valeur() = 0; + elem.ddl.Change_fixe (true); + }; + // on verifie que l'on n'utilise pas deux fois le meme identificateur de ddl + // avec deux valeurs differentes + list ::iterator imi; + for (imi=lili.begin() ; imi != lili.end(); imi++) + if (((*imi).ddl.Id_nom() == elem.ddl.Id_nom()) && ((*imi).ddl.Valeur() != elem.ddl.Valeur())) + { cout << "\n erreur , un meme identificateur de ddl est utilisee avec" + << " deux valeurs differentes \n"; + cout << " premiere Ddl : "; (*imi).ddl.Affiche(); + cout << " seconde Ddl : "; elem.ddl.Affiche(); + cout << " DdlLim::Lecture(UtilLecture & entreePrinc)" << endl; + entreePrinc.MessageBuffer("** erreur en lecture des conditions limites**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie (1); + } + // stockage du ddl bloque + lili.push_back(elem); + // --- maintenant on regarde si on a encore d'autre ddl à lire + // 1- on passe les blancs + flot >> car; + while ( (car==' ') && (flot.rdstate() == 0 )) + // cas où le prochain caractère est un espace + { flot >> car;} + flot.putback(car); + // on enregistre la position actuelle dans le flot au premier caractère non nul + streampos posi=flot.tellg(); + // maintenant on regarde s'il reste un ddl à lire + // en ayant passé éventuellement le caractère ', on regarde s'il s'agit + // d'un énum de ddl + // manip pour passer le caractère ' + flot >> car; // lecture du prochain caractère + if (flot.rdstate() == 0 ) + { // s'il ne s'agit pas de ' on le remet dans le flot + if (!(car=='\'')) flot.putback(car); + // maintenant on lit la chaine + string ddnom; + flot >> ddnom; // lecture de la chaine + // on cherche s'il y a éventuellement un signe =, si oui + // on supprime le signe = et tout ce qui suit + string::iterator ala,alafin=ddnom.end(); + for (ala=ddnom.begin();ala!=alafin;ala++) + if (*ala == '=') + { ddnom.erase(ala,alafin); + break; + }; + // est-ce que c'est un enum de ddl + if (ExisteEnum_ddl(ddnom)) + {un_ddl_a_lire=true; + flot.clear(); // on remet ok le flot au cas où on avait été jusqu'au bout à la + } // dernière lecture par exemple, car de toute manière on va relire + else {un_ddl_a_lire=false;}; + } + else {un_ddl_a_lire=false;}; // sinon fin + // retour avant la lecture du futur ddl éventuel + flot.seekg(posi, ios::beg); + // on prépare le prochain caractère + flot >> car; + flot.putback(car); + + }; //-- fin de while(un_ddl_a_lire) + + // --- lecture éventuelle des temp mini et maxi --- + if (((!flot.rdstate())&& (!(flot.eof())))) // lecture s'il n'y a pas d'erreur + {if(strstr(ptout,"TEMPS_MINI=") != 0) + { // cas d'un temps mini + string toto; + flot >> toto; + // on vérifie la présence au bon endroit du mot clé TEMPS_MINI= + if (toto != "TEMPS_MINI=") + {cout << "\n erreur de syntaxe en lecture du temps mini, info lue: " << toto; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + //lecture du temps mini + string nomOuNombre; + flot >> nomOuNombre; + if (nomOuNombre != "fct_nD:") + {t_min = ChangeReel(nomOuNombre); + nom_fnD_t_min = ""; + } + else + {flot >> nom_fnD_t_min;}; + } + }; + if (((!flot.rdstate())&& (!(flot.eof())))) // lecture s'il n'y a pas d'erreur + {if(strstr(ptout,"TEMPS_MAXI=") != 0) + { // cas d'un temps maxi + string toto; + flot >> toto; + // on vérifie la présence au bon endroit du mot clé TEMPS_MAXI= + if (toto != "TEMPS_MAXI=") + {cout << "\n erreur de syntaxe en lecture du temps maxi "; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + //lecture du temps maxi + string nomOuNombre; + flot >> nomOuNombre; + if (nomOuNombre != "fct_nD:") + {t_max = ChangeReel(nomOuNombre); + nom_fnD_t_max = ""; + } + else + {flot >> nom_fnD_t_max;}; + } + }; + // lecture éventuel de l'indicateur de blocage "relatif" + if (((!flot.rdstate())&& (!(flot.eof())))) // lecture s'il n'y a pas d'erreur + if(strstr(ptout,"BLOCAGE_RELATIF_") != 0) + { string toto; flot >> toto; // on passe le mot clé + blocage_relatif = true; + // message d'avertissement éventuel + int taille_tab = tab.Taille(); + bool queDesCourbesDeCharge = true; + for (int i=1; i<= taille_tab; i++) // on regarde s'il y n'y a que des courbes de charge + if (tab(i).co_charge == "") + { queDesCourbesDeCharge = false;} ; + if (!queDesCourbesDeCharge) + { // cas où il n'y a au moins un ddl sans courbe de charge + cout << "\n **** Warning !!! le blocage relatif ne fonctionne pas avec des blocages simples " + << " le blocage relatif ne fonctionne qu'avec les ddls soumis a une courbe de charge "; + }; + }; + + } // -- fin de lecture tant que le flot est valide + }//-- fin du test sur existence de champ ou pas + // enregistrement des infos + tab.Change_taille((int) lili.size()); + list ::iterator i; + int j; + for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++) + tab(j) = *i; + // dans le cas où il s'agit d'une condition de tangente imposée, il faut que + // le nombre de ddl = la dimension de l'espace, car la condition représente un vecteur + if (typeCL == TANGENTE_CL) + if (tab.Taille() != ParaGlob::Dimension()) + {cout << "\n erreur en lecture d'une condition de tangente imposée, " + << " le nombre de dd (ici = " << tab.Taille() << ") doit etre egale a la dimension" + << " de l'espace (ici = " << ParaGlob::Dimension()<<") "; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // verification en fonction de la dimension du pb +// VerifDimDdl(); + +}; + +// examine si le ddlmin passé en argument possède les mêmes cibles que this +// c'est-à-dire s'il y a une intersection incohérente entre les deux tableaux de ddl de base +// ramène true s'il y a une intersection incohérente non nulle, false sinon +bool DdlLim::MemeCibleMaisDataDifferents(const DdlLim& d) const + { // l'opération est malheureusement combinatoire (en N^2) à moins de classer les ddlm + // mais pour l'instant ce n'est pas fait, je ne suis pas sûr que ici le temps soit un pb + bool incoherence = false; + + int tailtab = tab.Taille(); + int tailtabex = d.Taille(); + for (int i=1; i<= tailtab; i++) + for (int j=1; j<= tailtabex; j++) + if (tab(i).ddl.Id_nom() == d.ElemLim_const(j).Id_nom()) + if (tab(i).ddl != d.ElemLim_const(j)) + // si on a deux même noms de ddl et le reste qui n'est pas identique --> incohérence + incoherence = true; + // retour + return incoherence; + }; + +// ramène true si le DdlLim contient l'enum_ddl passé en argument, false sinon +bool DdlLim::Existe_ici_leDdl(Enum_ddl enu) const + { // on passe en revue le tableau de ddl + int taille = tab.Taille(); + for (int i=1;i<=taille;i++) + if (tab(i).ddl.Id_nom() == enu) + return true; + // si on arrive ici, c'est que l'on n'a rien trouvé ! + return false; + }; + +// ramène true si le DdlLim contient au moins un déplacement, false sinon +bool DdlLim::Existe_ici_un_deplacement() const + { // on passe en revue le tableau de ddl + int taille = tab.Taille(); + for (int i=1;i<=taille;i++) + {switch (ParaGlob::Dimension()) + {case 3: if (tab(i).ddl.Id_nom() == UZ) + return true; + case 2: if (tab(i).ddl.Id_nom() == UY) + return true; + case 1: if (tab(i).ddl.Id_nom() == UX) + return true; + }; + }; + // si on arrive ici, c'est que l'on n'a rien trouvé ! + return false; + }; + +// Affiche les donnees liees au degre de liberte +void DdlLim::Affiche () const + { // affichage éventuelle du nom de maillage + if (nom_maillage != NULL) + { cout << "\n nom_mail= " << *nom_maillage;} else cout << "\n"; + // affichage éventuelle du type de CL + if (typeCL != RIEN_TYPE_CL) + { cout << "type_de_CL= " << NomTypeCL(typeCL);}; + // puis le reste + if (champ) + {cout << " ref_de_champ= " << ref << ':';} + else if (mvtsolide != NULL) + {mvtsolide->Affiche();} + else + {cout << " ref= " << ref << ':';}; + for (int i=1; i<= tab.Taille();i++) + { (tab(i).ddl).Affiche(); + if (tab(i).co_charge != "") + cout << " courbe_de_charge= " << (tab(i)).co_charge << " echelle= " << (tab(i)).echelle; + if (tab(i).f_charge != "") + cout << " fonction_nD_de_charge= " << (tab(i)).f_charge << " "; + cout << " temps_mini= "; + if (nom_fnD_t_min == "") + {cout << t_min;} + else {cout << " fct_nD: " << nom_fnD_t_min ;}; + cout << " temps_maxi= "; + if (nom_fnD_t_max == "") + {cout << t_max;} + else {cout << " fct_nD: " << nom_fnD_t_max ;}; + cout << " activité_actuelle: " << precedent; + cout << " blocage_relatif_ " << blocage_relatif << " "; + }; + cout << endl; + }; + + +// Realise l'egalite entre deux degres de liberte + DdlLim& DdlLim::operator= (const DdlLim& d) + { if (d.nom_maillage == NULL) + { if (nom_maillage != NULL) {delete nom_maillage;nom_maillage = NULL;}} + else + { if (nom_maillage == NULL) nom_maillage = new string(*(d.nom_maillage)); + else *nom_maillage = *(d.nom_maillage); + }; + typeCL = d.typeCL; + ref=d.ref; + tab = d.tab; + nom_fnD_t_min = d.nom_fnD_t_min ; + nom_fnD_t_max = d.nom_fnD_t_max ; + t_min = d.t_min; + t_max = d.t_max; + precedent = d.precedent; + champ = d.champ; + blocage_relatif = d.blocage_relatif; + if (d.mvtsolide != NULL) + { if (mvtsolide == NULL) + { mvtsolide = new MvtSolide(*(d.mvtsolide));} + else + { (*mvtsolide) = *(d.mvtsolide);}; + } + else // cas où d.mvtsolide est null + { if (mvtsolide != NULL) + {delete mvtsolide;mvtsolide = NULL;}; + }; + return (*this); + }; + +//Surcharge d'operateur logique +bool DdlLim::operator == (const DdlLim& a) const + { 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; + }; + // maintenant on regarde les autres données + if (typeCL != a.typeCL) return false; + // 1) traitement du cas des mouvements solides + bool apriorivrai = true; + if (a.mvtsolide != NULL) + { if (mvtsolide == NULL) + { //apriorivrai = false; + return false; } // on arrete tout de suite + else + { apriorivrai = ((*mvtsolide) == *(a.mvtsolide));}; + }; + // 2) traitement du rest + if (( ref==a.ref) && (tab==a.tab) + && (t_min == a.t_min) && (t_max == a.t_max) + && (nom_fnD_t_min == a.nom_fnD_t_min) + && (nom_fnD_t_max == a.nom_fnD_t_max) + && (precedent == a.precedent) + && (champ == a.champ) && (blocage_relatif == a.blocage_relatif) + && apriorivrai) + return true; + else return false; + }; + +// surcharge de l'operateur de lecture typée +istream & operator >> (istream & entree, DdlLim & dlim) + { // vérification du type + string type; + entree >> type; + if (type == "DdlLim") {dlim.champ = false;} + else if (type == "DdlLim_de_champ") {dlim.champ = true;} + else + {cout << "\n erreur en lecture d'un DdlLim "; + 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 (dlim.nom_maillage == NULL) + dlim.nom_maillage = new string(nom); + else + *(dlim.nom_maillage) = nom; + }; + // passage du nom de la référence puis le type de cl puis du tableau + entree >> dlim.ref >> nom; + dlim.typeCL = Id_nomTypeCL(nom); + entree >> dlim.tab >> nom >> dlim.t_min >> nom >> dlim.t_max >> nom >> dlim.precedent; + entree >> nom >> dlim.blocage_relatif; + // mouvement solide éventuel + int iii=0; + entree >> iii; + if (iii == 0) // indique qu'il n'y a pas de mouvement solide + {if (dlim.mvtsolide != NULL) // on supprime le mouvement solide s'il en existait un + {delete dlim.mvtsolide;dlim.mvtsolide=NULL;}; + } + else // cas d'un mouvement solide + { if (dlim.mvtsolide != NULL) // création s'il n'y en avait pas + dlim.mvtsolide = new MvtSolide(); + entree >> *(dlim.mvtsolide); // lecture du mouvement solide + }; + + return entree; + }; + +// surcharge de l'operateur d'ecriture typée +ostream & operator << ( ostream & sort,const DdlLim & dlim) + { // tout d'abord un indicateur donnant le type + if (dlim.champ) + {sort << "DdlLim_de_champ ";} + else + {sort << "DdlLim ";}; + // puis le maillage éventuelle + if (dlim.nom_maillage == NULL) + sort << false << " "; + else + sort << true << " " << *(dlim.nom_maillage) << " "; + // maintenant la référence + sort << dlim.ref << " "; + // le type de condition limite + sort << NomTypeCL(dlim.typeCL) << " "; + // puis les data + sort << dlim.tab; + sort << " tmin= " << dlim.t_min << " tmax= " << dlim.t_max << " prec " << dlim.precedent; + sort << " blocage_relatif= " << dlim.blocage_relatif; + // mouvement solide éventuel + if (dlim.mvtsolide == NULL) + { sort << " 0 ";} + else + { sort << " 1 " << (*(dlim.mvtsolide)) << " ";}; + sort << "\n"; + return sort; + }; + +// affichage et definition interactive des commandes +void DdlLim::Info_commande_DdlLim(ofstream & sort,bool plusieurs_maillages) +{ //On va proposer un menu + string rep=" "; + string nom_courbe="_"; + string nom_fonction_nD="_"; + double echelle = ConstMath::trespetit; + double temps_mini = - ConstMath::trespetit; + double temps_maxi = ConstMath::tresgrand; + // tableau des choix possibles + Tableau tab_choix(16); + tab_choix(1) = "\n (0 ou f) (defaut) (fin) "; + tab_choix(2) = "\n (1) choix d'un deplacement impose "; + tab_choix(3) = "\n (2) ou autre ddl impose "; + tab_choix(4) = "\n (3) valeur du ddl ? "; + tab_choix(5) = "\n (4) ou utilisation d'une courbe de charge "; + tab_choix(6) = "\n (5) echelle "; + tab_choix(7) = "\n (6) temps mini "; + tab_choix(8) = "\n (7) temps maxi "; + tab_choix(9) = "\n (8) blocage relatif "; + tab_choix(10) = "\n (9) condition de tangence "; + tab_choix(11) = "\n (10) mouvement solide impose "; + tab_choix(12) = "\n (11) champ de valeurs "; + tab_choix(13) = "\n (12) liste de ddl existant "; + tab_choix(14) = "\n (13 ou ? ) information "; + tab_choix(15) = "\n (14) plusieurs ddl de deplacement, nuls "; + tab_choix(16) = "\n (15) utilisation d'une fonction nD de charge "; + // tableau d'indexage pour limiter les choix + int choix=1; // type de choix: ici le cas choix d'un ddl de depart + Tableau index(9); + index(1) = 1; index(2) = 2; index(3) = 3;index(4) = 10;index(5) = 11; + index(6) = 12; index(7) = 13; index(8) =14;index(9) =15; + string nom_des_ddl=""; + bool blocage_relatif =false; // par défaut + double valeur_du_ddl = 0.; + bool plusieurs_ddl_deplacement_nul = false; + string nom_ref=""; + string condition_tangence=""; + bool condition_mvt_solide=false; + ostringstream flux; + bool champ_valeurs=false; + string str_champ_valeurs=""; + + + while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) + { + try + { for (int i=1;i<=index.Taille();i++) + cout << tab_choix(index(i)); + cout << "\n reponse ? "; + rep = lect_return_defaut(false,"0"); 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_des_ddl=="")&&(condition_tangence =="")&&(!condition_mvt_solide) + &&(!champ_valeurs)) + break; // arrêt s'il n'y a pas eu de choix + 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 <<" "; + // ici plusieurs cas + if ((condition_tangence =="")&&(!condition_mvt_solide)&&(!champ_valeurs)) + { // cas normal + bool sortie_cote=false; + if (((valeur_du_ddl != 0.)||(nom_courbe != "_") + || (nom_fonction_nD != "_")) + && (!plusieurs_ddl_deplacement_nul)) + {sort << " ' ";sortie_cote=true;}; + sort << nom_des_ddl ; + if (sortie_cote) sort <<"= "; + if (!plusieurs_ddl_deplacement_nul) + {if (nom_courbe != "_") + {sort << " COURBE_CHARGE: "<= 0)&&(num<=16)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 16 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + } + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: // déplacement imposé + { string repi=" "; + cout << "\n -- choix du ddl -- "; + switch (ParaGlob::Dimension()) + {case 1: cout << "\n (1) UX "; break; + case 2: cout << "\n (1) UX " + << "\n (2) UY "; break; + case 3: cout << "\n (1) UX " + << "\n (2) UY " + << "\n (3) UZ "; break; + default: cout << " "; + }; cout << "\n"; + repi=lect_chaine(); + cout << " valeur lue "< le blocage est mis en relatif "; + blocage_relatif = true; + index.Change_taille(5); + index(1) = 1;index(2) = 7; index(3) = 8; index(4) = 9;index(5) = 14; + break; + } + case 9: // condition de tangence + {cout << "\n --> condition de tangence "; + if (ParaGlob::Dimension() != 3) + { cout << "\n **** erreur il faut etre en dimension 3 pour cette condition !!"; + break; + }; + cout << "\n nom de la ref d'arete pour l'application de la condition ? "; + nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; + if (nom_ref.at(0) != 'A') + {cout << "\n *** erreur, la premiere lettre de la ref d'aretes " + << " doit etre A et non "<< nom_ref.at(0)<< " !!"; + break; + }; + cout << "\n def du vecteur tangent "; + condition_tangence += " typeCL_= TANGENTE_CL "; + + for (int i=1;i<=3;i++) // i représente la dimention + { string compo; // on defini la composante + switch (i){ case 1: compo="UX";break; case 2:compo="UY";break; + case 3: compo="UZ";break;}; + string repi=" "; + bool choix_valide=false; + while (!choix_valide) + { cout << "\n cas de "< mouvement solide impose "; + cout << "\n nom de la reference de noeuds associee? "; + 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 noeud " + << " doit etre N et non "<< nom_ref.at(0)<< " !!"; + break; + }; + // ici on utilise un string intermédiaire pour capter le flux + MvtSolide mvt; // un mouvement par défaut + mvt.Info_commande_MvtSolide(flux); + condition_mvt_solide=true; + + index.Change_taille(8); + index(1) = 1;index(2) = 5; index(3) = 6; index(4) = 7;index(5) = 8; + index(6) = 9;index(7) = 14;index(8) = 16; + break; + } + case 11: // champ de valeurs + {cout << "\n --> champ de valeurs impose "; + cout << "\n nom de la reference de noeuds associee? "; + 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 noeud " + << " doit etre N et non "<< nom_ref.at(0)<< " !!"; + break; + }; + int nb_valeur=0; + cout <<"\n nombre d'elements dans la reference ? "; + nb_valeur=(int) lect_double(); cout << " nombre lu ="<< nb_valeur; + string repa; + str_champ_valeurs += " champ_de:\n"; + bool erreur=false; + for (int i=1;i<=nb_valeur;i++) + { string nom_ddl=""; + cout << "\n nom du ddl "< liste des ddl existants "; + int nb_ddl = nombre_maxi_de_type_de_ddl; + cout << "\n"; + for (int i=1;i<= nombre_maxi_de_type_de_ddl;i++) + cout << Nom_ddl(Enum_ddl(i)) << " "; + cout << "\n"; + break; + } + case 13: // informations + {cout << "\n Il faut se reporter a la document pour avoir une explication detaille de chaque " + << "\n conditions. Globalement les conditions possibles sont les suivantes: " + << "\n (1) choix d'un deplacement impose --> UX ou UY ou UZ " + << "\n (2) autre ddl impose --> a choisir dans la liste des ddl diponibles " + << "\n (3) valeur du ddl --> on definit une valeur numerique " + << "\n (4) utilisation d'une courbe de charge --> la valeur du ddl = la valeur d'une courbe de charge " + << "\n (5) echelle --> facteur multiplicatif de la valeur du ddl (fixe ou dependant d'une fct f(t)" + << "\n (6) temps mini --> en dessous du temps mini, la condition n'existe pas " + << "\n (7) temps maxi --> au dessus du temps maxi la condition n'existe pas " + << "\n (8) blocage relatif --> a partir de temps mini, la condition est ajoute a la valeur existante du ddl " + << "\n (9) condition de tangence --> permet de definir des conditions limites pour les elements SFE " + << "\n (10) mouvement solide impose --> permet de definir des mouvements d'ensemble pour un groupe de noeuds " + << "\n (11) champ de valeurs --> permet de definir de maniere concise un ensemble de conditions non identiques " + << "\n (12) liste de ddl existant --> donne la liste des ddl possibles " + << "\n (13 ou ? ) information --> ce message " + << "\n (14) plusieurs ddl de deplacement, nuls --> forme concise pour mettre des deplacements a 0 " + << "\n (15) une fonction nD --> la valeur du ddl = la valeur de la fonction, eventuellement x Co charge "; + break; + } + case 14: // plusieurs ddl de deplacement, nuls + { string repi=" "; + nom_des_ddl = ""; + while (repi != "f") + { cout << "\n -- choix du ddl -- "; + switch (ParaGlob::Dimension()) + {case 1: cout << "\n (1) UX " + << "\n (f) (defaut) fin"; break; + case 2: cout << "\n (1) UX " + << "\n (2) UY " + << "\n (f) (defaut) fin" ; break; + case 3: cout << "\n (1) UX " + << "\n (2) UY " + << "\n (3) UZ " + << "\n (f) (defaut) fin" ; break; + default: cout << " "; + }; cout << "\n"; + repi= lect_return_defaut(false,"f");; cout << " valeur lue "<> (istream & entree, DdlLim::Ddlbloque& a) + { // vérification du type + string type; + entree >> type; + if (type != "Ddlbloque") + {Sortie (1); + return entree; + } + // entrée des données + entree >> a.ddl; + entree >> a.co_charge >> a.echelle >> a.f_charge; + return entree; + }; + + // surcharge de l'opérateur d'affectation +DdlLim::Ddlbloque& DdlLim::Ddlbloque::operator= (const DdlLim::Ddlbloque& d) + { ddl=d.ddl; + co_charge=d.co_charge; + echelle = d.echelle; + f_charge = d.f_charge; + return (*this); + }; + + //Surcharge d'operateur logique +bool DdlLim::Ddlbloque::operator == ( DdlLim::Ddlbloque& a) + { if ( (ddl==a.ddl) + && (co_charge == a.co_charge) && (echelle == a.echelle) + && (f_charge == a.f_charge) + ) + return true; + else return false; + }; + +bool DdlLim::Ddlbloque::operator != ( DdlLim::Ddlbloque& a) + { return !(*this == a);}; + +// lecture dans le cas particulier d'un champ +list DdlLim::Lecture_champ(UtilLecture & entreePrinc) + { // def de variables inter + char tat[250]; char * ta = tat; char tt[100]; char * t = tt; + // def de la liste de ddl qui sera retournée + list lili; + // le traitement qui suit s'effectue soit une fois si ce n'est pas un champ, soit n fois jusqu'a + // ce que la ligne contienne le mot clé fin_champ_de_ qui doit être le premier enregistrement de la ligne + bool derniere_ligne = true; // le cas courant c'est qu'il y a une seule ligne a exploiter + do ///__________ la grande boucle + { // dans ce cas dans le fichier d'entrée les infos se trouvent sur les lignes qui suivent + // via normalement un fichier (mais ce n'est pas obligatoire) donc on passe + // une ligne à chaque passage jusqu'à trouver le mot clé fin_champ_de_ + entreePrinc.NouvelleDonnee(); // lecture d'une nouvelle ligne + // on lira jusqu'à la ligne qui contiend le mot clé: fin_champ_de_ en début d'enregistrement + if (strstr(entreePrinc.tablcar,"fin_champ_de_")!=NULL) + {derniere_ligne= true; string toto; *(entreePrinc.entree) >> toto; + if (toto != "fin_champ_de_") + { cout << "\n erreur de lecture d'un champ de valeurs " + << " le premier mot de la derniere ligne devait etre fin_champ_de_ \n"; + entreePrinc.MessageBuffer("*** lecture champ de valeurs ****" ); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + } + else + {derniere_ligne = false;}; + + //recup de la fin de la ligne + char tout[150] ; char * ptout = tout; (entreePrinc.entree)->get(ptout,150); + // avant la lecture on remplace toutes les virgules par des espaces + char * ii = strchr(ptout,','); + while (ii != NULL) { *ii = ' '; ii = strchr(ptout,',');} + // def du flot intermédiaire + #ifndef ENLINUX_STREAM + istringstream flot(ptout); + #else + istrstream flot(ptout); + #endif + // lecture tant que le flot est valide + while (flot.rdstate() == 0) + // tout d'abord on passe les espaces qui sont des séparateurs + // lecture du prochain caractère sans modifier le flot + {char car; // = flot.peek(); +//---- debug +//cout << "\n debug DdlLim::Lecture_champ( flot.rdstate()= " << flot.rdstate()<< endl; +//--- fin debug + + flot >> car; + // éventuellement il n'avait pas bien déterminé la fin de l'enregistrement + // au niveau du while, dans ce cas si durant la lecture de car il y a eu un pb + // cela signifie qu'en fait la ligne était terminée donc on s'arrête + if (flot.rdstate() != 0) break; + while ( (car==' ') && (flot.rdstate() == 0 )) + // cas où le prochain caractère est un espace + { flot >> car; } + flot.putback(car); + + if (!derniere_ligne) + {// on définit un ddl pour la lecture + Ddlbloque elem; + // deux cas, soit un ddl nulle par defaut, soit une valeur non nulle imposee + // soit le caractère est ' , signifie que c'est un ddl avec une valeur + // imposée + if ( (car=='\'') && (flot.rdstate() == 0 )) + {// on passe le premier ' + flot >> car; + // on lit jusqu'au prochain ' en non formaté + flot.get(ta,150,'\''); + // on passe ce dernier ' + flot >> car; + // on recherche le = pour mettre un blanc a la place + char * ii = strchr(ta,'\'');char * pii=ii; // sauvegarde de l'adresse + ii = strchr(ta,'='); // on recherche le = + if (ii == NULL) + { cout << "\n erreur de syntaxe dans la definition des conditions limites " + << " imposees a une valeur non nulle "; + cout << " le ddl doit etre separe de la valeur par le signe = , caractere non" + << " trouve "; + entreePrinc.MessageBuffer("*** lecture d'une reference de ddl bloquee ****" ); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + *ii = ' '; // supprime le = + + // def du flux intermediaire + #ifndef ENLINUX_STREAM + istringstream flux (ta); + #else + istrstream flux (ta); + #endif + + flux >> t ; + elem.ddl.Change_nom(t); + // on regarde s'il ne s'agit pas d'une courbe de charge imposée + bool sans_courbe_ou_fct_nD=true; // variable locale + // a) cas d'une courbe + if(strstr(ta,"COURBE_CHARGE:")!=0) + { // cas d'une courbe de charge + string toto; + flux >> toto >> elem.co_charge; + // on vérifie la présence au bon endroit du mot clé COURBE_CHARGE= + if (toto != "COURBE_CHARGE:") + {cout << "\n erreur de syntaxe en lecture du nom de la courbe "; + cout << "\n DdlLim::Lecture_champ(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // on récupère l'échelle éventuellement + if(strstr(ta,"ECHELLE:")!=0) + { // cas où il y a un facteur d'échelle + flux >> toto; + if (toto != "ECHELLE:") + {cout << "\n erreur de syntaxe en lecture du facteur d'échelle "; + cout << "\n DdlLim::Lecture_champ(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // lecture du facteur + flux >> elem.echelle; + }; + }; + // b) cas d'une fonction nD + if(strstr(ta,"Fonction_nD_CHARGE:")!=0) + { // cas d'une fonction nD + string toto; + flux >> toto >> elem.f_charge; + sans_courbe_ou_fct_nD=false; + // on vérifie la présence au bon endroit du mot clé Fonction_nD_CHARGE: + if (toto != "Fonction_nD_CHARGE:") + {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD "; + cout << "\n DdlLim::Lecture_champ(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + }; + + // si aucune courbe ou fct nD + if (sans_courbe_ou_fct_nD) + // cas où c'est une valeur fixe + { flux >> elem.ddl.Valeur();} + elem.ddl.Change_fixe (true); + } + else if (flot.rdstate() == 0 ) // il s'agit d'un ddl à 0 + {//un ddl nulle par defaut + flot >> t; + elem.ddl.Change_nom(t); + elem.ddl.Valeur() = 0; + elem.ddl.Change_fixe (true); + } + // on ne verifie pas que l'on n'utilise pas deux fois le meme identificateur de ddl + // avec deux valeurs differentes car dans le cas d'un champ il y a obligatoirement plusieurs fois le même ddl + // stockage + lili.push_back(elem); + } + else // cas de la dernière ligne + {// lecture éventuelle des temp mini et maxi + if (((!flot.rdstate())&& (!(flot.eof())))) // lecture s'il n'y a pas d'erreur + {if(strstr(ptout,"TEMPS_MINI=") != 0) + {// cas d'un temps mini + string toto; + flot >> toto; + // on vérifie la présence au bon endroit du mot clé TEMPS_MINI= + if (toto != "TEMPS_MINI=") + {cout << "\n erreur de syntaxe en lecture du temps mini, info lue: " << toto; + cout << "\n DdlLim::Lecture_champ(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + //lecture du temps mini + flot >> t_min; + } + } + if (((!flot.rdstate())&& (!(flot.eof())))) // lecture s'il n'y a pas d'erreur + {if(strstr(ptout,"TEMPS_MAXI=") != 0) + {// cas d'un temps maxi + string toto; + flot >> toto; + // on vérifie la présence au bon endroit du mot clé TEMPS_MAXI= + if (toto != "TEMPS_MAXI=") + {cout << "\n erreur de syntaxe en lecture du temps maxi "; + cout << "\n DdlLim::Lecture_champ(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + //lecture du temps maxi + flot >> t_max; + } + }; + // à la fin on considère que c'est fini, il n'y a plus d'info spécifique à lire + // donc on sort de la boucle + break; + } //-- fin du cas de la dernière ligne + + } //-- fin du while (flot.rdstate() == 0) + } ///__________ fin de la grande boucle + while(! derniere_ligne); + + // dans le cas où il s'agit d'un champ de conditions de tangente imposée, il faut que + // la condition soit un multiple de la dimension de l'espace, car chaque condition représente un + // vecteur + if (typeCL == TANGENTE_CL) + {if ((tab.Taille() % ParaGlob::Dimension()) != 0) + {cout << "\n erreur en lecture d'un champ de condition de tangente imposée, " + << " le nombre de dd (ici = " << tab.Taille() << ") doit etre multiple de la dimension" + << " de l'espace (ici = " << ParaGlob::Dimension()<<") "; + cout << "\n DdlLim::Lecture_champ(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + }; + + return lili; + }; + +// lecture dans le cas particulier d'un mouvement solide +list DdlLim::Lecture_mvtSolide(UtilLecture & entreePrinc) + { // on commence par lire les mouvements solides + if (mvtsolide == NULL) + mvtsolide = new MvtSolide(); // création s'il n'existe pas + mvtsolide->Lecture_mouvements_solides(&entreePrinc); + // def de la liste de ddl qui sera retournée + list lili; + // on définit les ddl bloque associés + int dima = ParaGlob::Dimension(); + Ddlbloque elem; // def d'un ddl courant + elem.ddl.Change_fixe (true); + switch (dima) + { case 3: {elem.ddl.Change_nom(UZ); lili.push_front(elem);} + case 2: {elem.ddl.Change_nom(UY); lili.push_front(elem);} + case 1: {elem.ddl.Change_nom(UX); lili.push_front(elem);} + }; + // def d'un string pour les lectures de chaine + string nom; + // maintenant on regarde s'il y a une courbe de charge + // on regarde s'il ne s'agit pas d'une courbe de charge imposée + if (strstr(entreePrinc.tablcar,"COURBE_CHARGE:")!=NULL) + { // cas d'une courbe de charge + *(entreePrinc.entree) >> nom; + // on vérifie la présence au bon endroit du mot clé COURBE_CHARGE= + if (nom != "COURBE_CHARGE:") + {cout << "\n erreur de syntaxe en lecture du nom de la courbe " + << " on a lue " << nom << " alors que l'on attendait : COURBE_CHARGE: "; + cout << "\n DdlLim::Lecture_mvtSolide(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // on se sert du premier ddlbloqué pour stocker la courbe de charge + Ddlbloque & elem = *(lili.begin()); + // lecture de la courbe + *(entreePrinc.entree) >> elem.co_charge; + // on récupère l'échelle éventuellement + if (strstr(entreePrinc.tablcar,"ECHELLE:")!=NULL) + { // 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 a lue " << nom << " alors que l'on attendait ECHELLE: "; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + // lecture du facteur + *(entreePrinc.entree) >> elem.echelle; + }; + }; + if (strstr(entreePrinc.tablcar,"Fonction_nD_CHARGE:")!=NULL) + { // cas d'une fonction nD de charge + *(entreePrinc.entree) >> nom; + // on vérifie la présence au bon endroit du mot clé Fonction_nD_CHARGE: + if (nom != "Fonction_nD_CHARGE:") + {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD " + << " on a lue " << nom << " alors que l'on attendait : Fonction_nD_CHARGE: "; + cout << "\n DdlLim::Lecture_mvtSolide(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + // on se sert du premier ddlbloqué pour stocker la courbe de charge + Ddlbloque & elem = *(lili.begin()); + // lecture de la courbe + *(entreePrinc.entree) >> elem.f_charge; + }; + // lecture éventuelle des temp mini et maxi + if (strstr(entreePrinc.tablcar,"TEMPS_MINI=")!=NULL) + { // cas d'un temps mini + *(entreePrinc.entree) >> nom; + // on vérifie la présence au bon endroit du mot clé TEMPS_MINI= + if (nom != "TEMPS_MINI=") + {cout << "\n erreur de syntaxe en lecture du temps mini, info lue: " << nom + << " alors que l'on attendait : TEMPS_MINI="; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + //lecture du temps mini + *(entreePrinc.entree) >> t_min; + }; + if (strstr(entreePrinc.tablcar,"TEMPS_MAXI=")!=NULL) + { // cas d'un temps maxi + *(entreePrinc.entree) >> nom; + // on vérifie la présence au bon endroit du mot clé TEMPS_MAXI= + if (nom != "TEMPS_MAXI=") + {cout << "\n erreur de syntaxe en lecture du temps maxi, info lue: " << nom + << " alors que l'on attendait : TEMPS_MAXI="; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + //lecture du temps maxi + *(entreePrinc.entree) >> t_max; + }; + // lecture éventuel de l'indicateur de blocage "relatif" + if (strstr(entreePrinc.tablcar,"BLOCAGE_RELATIF_")!=NULL) + { *(entreePrinc.entree) >> nom; + // on vérifie la présence au bon endroit du mot clé BLOCAGE_RELATIF_ + if (nom != "BLOCAGE_RELATIF_") + {cout << "\n erreur de syntaxe en lecture de l'indicateur de blocage relatif, info lue: " << nom + << " alors que l'on attendait : BLOCAGE_RELATIF_"; + cout << "\n DdlLim::Lecture(.. " << endl ; + entreePrinc.MessageBuffer("**erreur**"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + blocage_relatif = true; + }; + + return lili; + }; diff --git a/Maillage/DdlLim.h b/Maillage/DdlLim.h new file mode 100644 index 0000000..37762ee --- /dev/null +++ b/Maillage/DdlLim.h @@ -0,0 +1,331 @@ +// FICHIER : DdlLim.h +// CLASSES : DdlLim + +// 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: . + +/************************************************************************ + * DATE: 15/04/1997 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: La classe DdlLim permet de declarer un ensemble de ddl coiffe * + * par une reference utilise pour les conditions limites. $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ + + +#ifndef DDLLIM_H +#define DDLLIM_H + + +#include "Ddl.h" +#include "Tableau_T.h" +#include +#include +#include "Sortie.h" +#include "UtilLecture.h" +#include "string.h" +#include "string" +#include +#include "MvtSolide.h" +#include "EnuTypeCL.h" + +/// @addtogroup Les_classes_Ddl_en_tout_genre +/// @{ +/// + + +/// BUT: La classe DdlLim permet de declarer un ensemble de ddl coiffe par une reference utilise pour les conditions limites. +/// +/// \author Gérard Rio +/// \version 1.0 +/// \date 15/04/1997 +/// +/// + + +class DdlLim +{ // surcharge de l'operator de lecture + // les informations sont typées + friend istream & operator >> (istream &, DdlLim &); + // surcharge de l'operator d'ecriture typée + friend ostream & operator << (ostream &, const DdlLim &); + + public: + + + // CONSTRUCTEURS : + + // Constructeur defaut + DdlLim (); + + // Constructeur de copie + DdlLim (const DdlLim& d); + + + // DESTRUCTEUR : + ~DdlLim (); + + + // METHODES : + + // Retourne la reference attache au degre de liberte + const string& NomRef () const { return ref; }; + // retourne un pointeur de string donnant le nom du maillage associé + // = NULL si aucun maillage + const string* NomMaillage() const {return nom_maillage;}; + // retourne le type de condition limite associé + EnuTypeCL TypeDeCL() const {return typeCL;}; + + // retourne la taille du tableau de ddl + int Taille() const { return tab.Taille();}; + + // retourne le ddl nb i en lecture/écriture + Ddl& ElemLim(int i) { return tab(i).ddl;}; + // idem en constant + const Ddl& ElemLim_const(int i) const { return tab(i).ddl;}; + + // retourne le nom de la courbe i ou "" s'il n'y en n'a pas + // dans le cas d'un mouvement solide, c'est uniquement le premier ddl + // qui contient la courbe de charge éventuelle + const string& Nom_courbe(int i) const { return tab(i).co_charge;}; + + // retourne le nom de la fonctionnD i ou "" s'il n'y en n'a pas + // dans le cas d'un mouvement solide, c'est uniquement le premier ddl + // qui contient la courbe de charge éventuelle + const string & NomF_charge(int i) const {return tab(i).f_charge;}; + + // retourne si la référence est celle d'un champ ou pas + bool Champ() const {return champ;}; + + // retourne si le blocage est relatif ou pas + // un blocage relatif signifie que le blocage s'effectue par rapport au pas de temps + // précédent i.e. t=t + // un blocage non relatif, donc absolue signifie que le blocage s'effectue par rapport à + // t = 0 + bool BlocageRelatif() const {return blocage_relatif;}; + + // indique si c'est un mouvement solide ou pas + bool Mouvement_Solide() const {return (mvtsolide!=NULL);}; + // récupération du mouvement solide + const MvtSolide* Const_MouvementSolide() const {return mvtsolide;}; + // récupération du mouvement solide + MvtSolide* MouvementSolide() const {return mvtsolide;}; + + // retourne l'échelle pour le ddl nb i + // dans le cas d'un mouvement solide, c'est uniquement le premier ddl + // qui contient la courbe de charge éventuelle + double Echelle_courbe(int i) const {return tab(i).echelle;}; + + // indique si le temps mini et/ou le temps maxi dépend d'une fonction nD + // retour: + // 0 : pas de dépendance + // 1 : tmin uniquement + // 2 : tmax uniquement + // 3 : tmin et tmax + + int Temps_depend_nD() const + {int retour = 0; if (nom_fnD_t_min != "") {if (nom_fnD_t_max != "") return 3;else return 1;} + else {if (nom_fnD_t_max != "") return 2;else return 0;}; + }; + + // retour du nom de la fonction nD qui pilote tmin + // si == "", pas de fonction + string Nom_fctnD_tmin() const {return nom_fnD_t_min;}; + // idem pour tmax + string Nom_fctnD_tmax() const {return nom_fnD_t_max;}; + + // mise à jour de tmin et/ou tmax + // uniquement s'ils dépendent d'une fct nD + void Mise_a_jour_tmin_tmax(double tmin, double tmax) + { if (nom_fnD_t_min != "") t_min = tmin; + if (nom_fnD_t_max != "") t_max = tmax; + }; + // mise à jour de tmin + // uniquement s'il dépend d'une fct nD + void Mise_a_jour_tmin(double tmin) + { if (nom_fnD_t_min != "") t_min = tmin; + }; + // mise à jour de tmax + // uniquement s'il dépend d'une fct nD + void Mise_a_jour_tmax(double tmax) + { if (nom_fnD_t_max != "") t_max = tmax; + }; + + // retourne un booléen qui indique si oui ou non le temps passé en paramètre + // est situé entre le temps min et maxi du ddllim + bool Temps_actif(const double& temps) const + {if ((t_min < temps) && (temps <= t_max)) + return true; + else return false; + }; + + // ramène vrai si le temps est inférieur au temps actif + // ou si d'une part le temps n'est pas actif et qu'au pas précédent + // il n'était pas également actif + bool Pas_a_prendre_en_compte(const double& temps) const + {if ((temps <= t_min) || ((temps > t_max) && !precedent)) + return true; + else return false; + }; + // ramène vrai si le temps est inférieur ou égale au temps actif, ou supérieur au temps max + bool Pas_a_prendre_en_compte_dans_intervalle(const double& temps) const + {if ((temps <= t_min) || (temps > t_max)) + return true; + else return false; + }; + + // affichage et definition interactive des commandes + // plusieurs_maillages : indique si oui ou non, il y a plusieurs maillage + void Info_commande_DdlLim(ofstream & sort,bool plusieurs_maillages); + + // Validation on non de l'activité du ddlLim + void Validation(const double& temps) {precedent = Temps_actif(temps);}; + // retour du statut de validation + // vrai signifie que l'état enregistré est actif + bool Etat_validation() const {return precedent;}; + + + // lecture des degres de liberte + // sur le fichier d'entree + // util pour la lecture de ddl bloque + void Lecture(UtilLecture & entreePrinc); + + // examine si le ddlmin passé 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 + bool MemeCibleMaisDataDifferents(const DdlLim& d) const; + + // ramène true si le DdlLim contient l'enum_ddl passé en argument, false sinon + bool Existe_ici_leDdl(Enum_ddl enu) const; + // ramène true si le DdlLim contient au moins un déplacement, false sinon + bool Existe_ici_un_deplacement() const; + + // Affiche les donnees liees aux degres de liberte + void Affiche () const ; + + // Realise l'egalite + DdlLim& operator= (const DdlLim& d); + + //Surcharge d'operateur logique + bool operator == ( const DdlLim& a) const ; + + bool operator != ( const DdlLim& a) const { return !(*this == a);}; + +// ----------- définition de conteneurs à usage interne ----------- + // cependant elles ne peuvent pas être déclaré en protégé ?? +// protected : + + // le conteneur des ddl bloqués + class Ddlbloque + { public: + // surcharge de l'operator de lecture + friend istream & operator >> (istream & entree, Ddlbloque& d); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort, const Ddlbloque& d); + // constructeur + Ddlbloque() : co_charge(""),f_charge(""),ddl(),echelle(1.) {}; + Ddlbloque(const Ddlbloque& d): co_charge(d.co_charge) + ,f_charge(d.f_charge),ddl(d.ddl),echelle(d.echelle) {}; + Ddlbloque(Ddl ddl_): co_charge(""),f_charge(""),ddl(ddl_),echelle(1.) {}; + // destructeur + ~Ddlbloque() {}; + // surcharge de l'opérateur d'affectation + Ddlbloque& operator= (const Ddlbloque& d); + //Surcharge d'operateur logique + bool operator == ( Ddlbloque& a); + bool operator != ( Ddlbloque& a); + public: + Ddl ddl; // ddl bloqué + string co_charge; // nom d'une courbe de charge éventuelle + string f_charge; // nom d'une fonction nD utilisant des variables globales et autres + double echelle; + }; + + protected : + + // données + string* nom_maillage; // nom de maillage associé, éventuellement! + string ref; // reference attachee aux ddl + EnuTypeCL typeCL; // indique éventuellement un type de condition limite associé + // = RIEN_TYPE_CL par exemple pour les noeuds (donc ne sert à rien dans ce cas) + // = TANGENTE_CL par exemple pour une arête, indique une condition de tangente imposée + Tableau tab; // tableau des ddl + double t_min,t_max; // temps mini et maxi de durée des ddl imposés + string nom_fnD_t_min; // nom éventuelle de la fonction associée + string nom_fnD_t_max; // nom éventuelle de la fonction associée + int precedent; // pour la description de l'évolution du ddlLim + bool champ; // indique si c'est une référence de champ ou pas + bool blocage_relatif; // indique si oui ou non le blocage à t+dt s'effectue + // par rapport à t ou par rapport à 0 + MvtSolide* mvtsolide; // indique si diff de NULL qu'il s'agit d'un mouvement solide appliqué + // si oui, tab contient les 3 ddl de position, dont le premier contient éventuellement + // une courbe de charge si on veut un pilotage du mvt solide par courbe de charge, + // ainsi qu'une échelle éventuelle globale + + + // FONCTIONS PROTEGEES + // verification en fonction de la dimension du pb + // par exemple en dim 2 d'existance des UZ ou des X3 etc.. + void VerifDimDdl(); + // lecture dans le cas particulier d'un champ + list Lecture_champ(UtilLecture & entreePrinc); + // lecture dans le cas particulier d'un mouvement solide + list Lecture_mvtSolide(UtilLecture & entreePrinc); + + // Remplace la reference du degre de + // liberte par nouveau + // ATTENTION : Les modifications liees au changement de la reference du degre + // de liberte sont a la charge de l'utilisateur, en particulier il n'y a pas + // de vérification par exemple du fait que c'est un champ ou pas . + void Change_ref (string nouveau); + // idem pour le changement de nom de maillage + // le nouveau nom ne doit pas être vide !! sinon erreur + void Change_nom_maillage(const string& nouveau); + +}; +/// @} // end of group + + + +#endif diff --git a/Maillage/DdlNoeudElement.cc b/Maillage/DdlNoeudElement.cc new file mode 100644 index 0000000..f0eb872 --- /dev/null +++ b/Maillage/DdlNoeudElement.cc @@ -0,0 +1,96 @@ + +// 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 "DdlNoeudElement.h" + + // CONSTRUCTEURS : +DdlNoeudElement::DdlNoeudElement () : // par defaut + tb() + { /*pt = NULL;*/}; +DdlNoeudElement::DdlNoeudElement (int n) : + tb(n) + { /* pt = new int [n];*/}; +// de copie +DdlNoeudElement::DdlNoeudElement (const DdlNoeudElement& a) : + tb(a.tb) + { // int nbddl = a.tb.Taille(); + /* pt = new int[nbddl]; + for (int i=0;i<= nbddl-1; i++) + pt[i] = a.pt[i];*/ + }; + + // DESTRUCTEUR : +DdlNoeudElement::~DdlNoeudElement () + {/*if (pt != NULL) delete [] pt;*/}; + + // Methodes +// surcharge de l'affectation +DdlNoeudElement& DdlNoeudElement::operator = (const DdlNoeudElement & a) + { this->tb = a.tb; + /*if (pt != NULL) delete [] pt;*/ + //int nbddl = a.tb.Taille(); + /* pt = new int[nbddl]; + for (int i=0;i<= nbddl-1; i++) + this->pt[i] = a.pt[i];*/ + return *this; + }; +// surcharge des tests +bool DdlNoeudElement::operator == (const DdlNoeudElement & a) const + { if (this->tb != a.tb) return false; + /*for (int i=1;i<=(this->tb).Taille();i++) + if (this->pt[i-1] != a.pt[i-1]) return false;*/ + return true; + }; +bool DdlNoeudElement::operator != ( const DdlNoeudElement & a) const + { if (*this == a) return false; + else return true; + }; + + // surcharge de l'operator de lecture +istream & operator >> (istream & entree, DdlNoeudElement& a) + { // vérification du type + string type; + entree >> type; + if (type != "DdlNoeudElement") + {Sortie (1); + return entree; + } + // entrée du tableau d'enum de ddl + entree >> a.tb; + return entree; + }; + + // surcharge de l'operator d'ecriture +ostream & operator << (ostream & sort, const DdlNoeudElement& a) + { // tout d'abord un indicateur donnant le type + sort << "DdlNoeudElement " ; + // puis le tableau d'enum_ddl + sort << a.tb; + return sort; + }; diff --git a/Maillage/DdlNoeudElement.h b/Maillage/DdlNoeudElement.h new file mode 100644 index 0000000..6962112 --- /dev/null +++ b/Maillage/DdlNoeudElement.h @@ -0,0 +1,120 @@ + +// 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: . + +/************************************************************************ + * DATE: 23/01/97 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: Def des ddl lie a un noeud d'un element ( different des ddl* + * lies aux noeuds globaux). * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ +#ifndef DDLNOEUDELEMENT_T +#define DDLNOEUDELEMENT_T +#include "Enum_ddl.h" +#include "Tableau_T.h" +//#ifdef SYSTEM_MAC_OS_X +// #include // a priori ce n'est pas portable +//#el +#if defined SYSTEM_MAC_OS_CARBON + #include // a priori ce n'est pas portable +#else + #include // pour le flot en memoire centrale +#endif +#include + + +/// @addtogroup Les_classes_Ddl_en_tout_genre +/// @{ +/// + + +/// BUT: Def des ddl lie a un noeud d'un element ( different des ddl lies aux noeuds globaux) +/// +/// \author Gérard Rio +/// \version 1.0 +/// \date 23/01/97 +/// +/// + +class DdlNoeudElement +{ + // surcharge de l'operator de lecture + friend istream & operator >> (istream & entree, DdlNoeudElement& a); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort, const DdlNoeudElement& a); + + public : + // VARIABLES PUBLIQUES : + + // CONSTRUCTEURS : + DdlNoeudElement (); // par defaut + // def en fonction dunombre de ddl a stocker + DdlNoeudElement (int n); + // cas où il y a un seul identificateur de ddl a stocker + DdlNoeudElement (Enum_ddl e) : + tb(1,e) + {} ; + // de copie + DdlNoeudElement (const DdlNoeudElement& a); + // DESTRUCTEUR : + ~DdlNoeudElement (); + // Methodes + // surcharge de l'affectation + DdlNoeudElement& operator = (const DdlNoeudElement & a); + // surcharge des tests + bool operator == (const DdlNoeudElement & a) const ; + bool operator != (const DdlNoeudElement & a) const ; + + // le tableau des identificateurs de ddl + Tableau tb; + // pointeur du tableau de connection ddl noeud element/ ddl noeud global + // pour l'instant ne sert à rien donc en commentaire + protected : + // int * pt; + }; + /// @} // end of group + +#endif diff --git a/Maillage/Ddl_etendu.cc b/Maillage/Ddl_etendu.cc new file mode 100644 index 0000000..1af1975 --- /dev/null +++ b/Maillage/Ddl_etendu.cc @@ -0,0 +1,111 @@ +// FICHIER : Ddl_etendu.cp +// CLASSE : Ddl_etendu + + +// 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 "Ddl_etendu.h" + + +# include +using namespace std; //introduces namespace std + +#include +#include "Sortie.h" + +#ifndef Ddl_etendu_deja_inclus + +#ifndef MISE_AU_POINT + inline +#endif +// Constructeur par défaut +Ddl_etendu::Ddl_etendu () : + ddl_enum_etendu(), val_ddl(0.0) + {}; + +#ifndef MISE_AU_POINT + inline +#endif +// Constructeur fonction des variables +Ddl_etendu::Ddl_etendu (const Ddl_enum_etendu& ddl,double vale) : + ddl_enum_etendu(ddl), val_ddl(vale) + {}; + +#ifndef MISE_AU_POINT + inline +#endif +// Constructeur de copie +Ddl_etendu::Ddl_etendu (const Ddl_etendu& d): + ddl_enum_etendu(d.ddl_enum_etendu),val_ddl(d.val_ddl) + {}; + +#ifndef MISE_AU_POINT + inline +#endif +Ddl_etendu::~Ddl_etendu () +// Destructeur +{ }; + + +#ifndef MISE_AU_POINT + inline +#endif +// surcharge de l'operateur d'ecriture +ostream & operator << (ostream & sort,const Ddl_etendu & a) + { // écriture du type + sort << " Ddl_etendu "; + // les données + sort << a.ddl_enum_etendu << " " << setprecision(ParaGlob::NbdigdoCA()) << a.val_ddl << " "; + return sort; + }; + +#ifndef MISE_AU_POINT + inline +#endif + // surcharge de l'operator de lecture +istream & operator >> (istream & entree, Ddl_etendu& a) + { // vérification du type + string type; + entree >> type; + if (type != "Ddl_etendu") + {cout << "\n **** erreur en lecture d'une grandeur type Ddl_etendu "; + Sortie (1); + return entree; + } + // entrée des données + entree >> a.ddl_enum_etendu; + entree >> a.val_ddl; + + return entree; + }; + + + +#endif // fin de l'inclusion totale diff --git a/Maillage/Ddl_etendu.h b/Maillage/Ddl_etendu.h new file mode 100644 index 0000000..ef0582a --- /dev/null +++ b/Maillage/Ddl_etendu.h @@ -0,0 +1,196 @@ + +// 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: . + +/************************************************************************ + * DATE: 19/01/2006 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: class de stockage d'un ddl étendue, associé au type * + * Ddl_enum_etendu. En fait il s'agit du pendant des types * + * Ddl associé au type enum_ddl * + * Noter que la grandeur stockée est un scalaire !! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ + +#ifndef DDL_ETENDU_H +#define DDL_ETENDU_H + + +#include "Ddl_enum_etendu.h" +#include "Enum_boolddl.h" + + +#include +#include +#include "Sortie.h" +#include + +/// @addtogroup Les_classes_Ddl_en_tout_genre +/// @{ +/// + + +/// BUT: class de stockage d'un ddl étendue, associé au type +/// Ddl_enum_etendu. En fait il s'agit du pendant des types +/// Ddl associé au type enum_ddl +/// Noter que la grandeur stockée est un scalaire !! +/// +/// \author Gérard Rio +/// \version 1.0 +/// \date 19/01/2006 +/// +/// + +class Ddl_etendu +{ + // surcharge de l'operator de lecture + friend istream & operator >> (istream & entree, Ddl_etendu& a); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort, const Ddl_etendu& a); + + public: + + + // CONSTRUCTEURS : + + // Constructeur par défaut + Ddl_etendu (); + + // Constructeur fonction des variables, la seconde est facultative + Ddl_etendu (const Ddl_enum_etendu& ddl,double vale=0.0) ; + + // Constructeur de copie + Ddl_etendu (const Ddl_etendu& d); + + + // DESTRUCTEUR : + + ~Ddl_etendu (); + + + // METHODES : + + // Retourne la valeur associee au degre de liberte + // en lecture écriture + inline double& Valeur() { return val_ddl; }; + // idem en lecture seulement + inline const double& ConstValeur() const { return val_ddl; }; + + // Retourne le Ddl_enum_etendu associé + // en lecture écriture + inline Ddl_enum_etendu& DdlEnumEtendu() { return ddl_enum_etendu; }; + // idem mais en constant + inline const Ddl_enum_etendu& Const_DdlEnumEtendu() const { return ddl_enum_etendu; }; + + // Affiche les donnees liees au degre de liberte + void Affiche() const { cout << *this; }; + void Affiche(ostream& sort) const { sort << *this; }; + void Affiche(ostream& sort,int nb) const { sort << setprecision(nb) << *this; }; + + inline Ddl_etendu& operator= (const Ddl_etendu& d) + // Realise l'egalite entre deux degres de liberte étendus + { ddl_enum_etendu=d.ddl_enum_etendu; + val_ddl=d.val_ddl; + return (*this); + }; + // Surcharge de l'operateur += + inline void operator+= (const Ddl_etendu& c) + {if (c.ddl_enum_etendu == ddl_enum_etendu) + {val_ddl += c.val_ddl;} + else + {cout << "\n *** erreur d'affectation void operator+= (const Ddl_enum_etendu& c)"; + cout << "\n this: "; this->Affiche(); + cout << "\n c: "; c.Affiche(); + Sortie(1); + }; + }; + // Surcharge de l'operateur -= + inline void operator-= (const Ddl_etendu& c) + {if (c.ddl_enum_etendu == ddl_enum_etendu) + {val_ddl -= c.val_ddl;} + else + {cout << "\n *** erreur d'affectation void operator-= (const Ddl_enum_etendu& c)"; + cout << "\n this: "; this->Affiche(); + cout << "\n c: "; c.Affiche(); + Sortie(1); + }; + }; + + // Surcharge de l'operateur *= + inline void operator*= (double val) {val_ddl *= val;}; + // Surcharge de l'operateur /= : division par un scalaire + inline void operator/= (double val) {val_ddl /= val;}; + + //Surcharge d'operateur logique + // ne concerne que le type et non la valeur + bool operator == ( Ddl_etendu& a) const + {return (ddl_enum_etendu == a.ddl_enum_etendu);}; + + bool operator != ( Ddl_etendu& a) const + {return (ddl_enum_etendu != a.ddl_enum_etendu);}; + + // test du type et de la valeur + bool Identique(Ddl_etendu& a) + { return ((*this == a)&&(val_ddl == a.val_ddl));}; + + + protected : + + Ddl_enum_etendu ddl_enum_etendu; // identificateur du nom + double val_ddl; // valeur associee + + +}; +/// @} // end of group + +// pour faire de l'inline +#ifndef MISE_AU_POINT + #include "Ddl_etendu.cc" + #define Ddl_etendu_deja_inclus +#endif + + + +#endif diff --git a/Maillage/DiversStockage.cc b/Maillage/DiversStockage.cc new file mode 100644 index 0000000..7ea740c --- /dev/null +++ b/Maillage/DiversStockage.cc @@ -0,0 +1,1210 @@ + +// 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 "DiversStockage.h" +#include "CharUtil.h" +#include "Ddl_enum_etendu.h" + + +DiversStockage::DiversStockage () : // constructeur par defaut + tabEpaiss(),tabLargeurs(),tabSection(),tabMasseAddi(),tabMasseVolu(),tabCoefDila() + ,tabGesHourglass(),tabIntegVol(),tabIntegVol_et_temps(),tabStabMembraneBiel() + ,tabRepAnisotrope(),tabStatistique(),tabStatistique_et_temps() + { + } + +// affichage des infos + void DiversStockage::Affiche () const // affichage de tous les infos + { Affiche1(); + Affiche2(); + } + + void DiversStockage::Affiche1 () const + { bool te = false; + if (tabEpaiss.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabEpaiss.Taille() << " reference(s) d epaisseur lue \n"; + for (int i=1; i<=tabEpaiss.Taille(); i++) + tabEpaiss(i).Affiche(); + cout << "\n\n"; + } + if (tabLargeurs.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabLargeurs.Taille() << " reference(s) de largeur lue \n"; + for (int i=1; i<=tabLargeurs.Taille(); i++) + tabLargeurs(i).Affiche(); + cout << "\n\n"; + } + if (tabSection.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabSection.Taille() << " reference(s) de section lue \n"; + for (int i=1; i<=tabSection.Taille(); i++) + tabSection(i).Affiche(); + cout << "\n\n"; + } + if (tabVarSection.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabVarSection.Taille() << " reference(s) de variation de section lue \n"; + for (int i=1; i<=tabVarSection.Taille(); i++) + tabVarSection(i).Affiche(); + cout << "\n\n"; + } + if (tabMasseVolu.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabMasseVolu.Taille() << " reference(s) de masse volumique lue \n"; + for (int i=1; i<=tabMasseVolu.Taille(); i++) + tabMasseVolu(i).Affiche(); + cout << "\n\n"; + } + if (tabCoefDila.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabCoefDila.Taille() << " reference(s) de coefficient de dilatation thermique lue \n"; + for (int i=1; i<=tabCoefDila.Taille(); i++) + tabCoefDila(i).Affiche(); + cout << "\n\n"; + } + if (tabGesHourglass.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabGesHourglass.Taille() << " reference(s) de blocage d'hourglass lue \n"; + for (int i=1; i<=tabGesHourglass.Taille(); i++) + tabGesHourglass(i).Affiche(); + cout << "\n\n"; + } + if (tabIntegVol.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabIntegVol.Taille() << " reference(s) de grandeur a integrer sur le volume \n"; + for (int i=1; i<=tabIntegVol.Taille(); i++) + tabIntegVol(i).Affiche(); + cout << "\n\n"; + }; + if (tabIntegVol_et_temps.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabIntegVol_et_temps.Taille() << " reference(s) de grandeur a integrer sur le volume et dans le temps \n"; + for (int i=1; i<=tabIntegVol_et_temps.Taille(); i++) + tabIntegVol_et_temps(i).Affiche(); + cout << "\n\n"; + }; + if (tabStabMembraneBiel.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabStabMembraneBiel.Taille() << " reference(s) de stabilisation transversale \n"; + for (int i=1; i<=tabStabMembraneBiel.Taille(); i++) + tabStabMembraneBiel(i).Affiche(); + cout << "\n\n"; + }; + if (tabRepAnisotrope.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabRepAnisotrope.Taille() << " reference(s) de def de repere d'anisotropie \n"; + for (int i=1; i<=tabRepAnisotrope.Taille(); i++) + tabRepAnisotrope(i).Affiche(); + cout << "\n\n"; + }; + if (tabStatistique.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabStatistique.Taille() + << " reference(s) d'une statistique d'une ref de noeuds pour une grandeur quelconque \n"; + for (int i=1; i<=tabStatistique.Taille(); i++) + tabStatistique(i).Affiche(); + cout << "\n\n"; + }; + if (tabStatistique_et_temps.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 1er lecture ******** \n";te = true;} + cout << tabStatistique_et_temps.Taille() + << " reference(s) d'une statistique d'une ref de noeuds cumulee en temps pour une grandeur queconque \n"; + for (int i=1; i<=tabStatistique_et_temps.Taille(); i++) + tabStatistique_et_temps(i).Affiche(); + cout << "\n\n"; + }; + + cout << endl; + }; + + void DiversStockage::Affiche2 () const + { bool te = false; + if (tabMasseAddi.Taille() != 0) + {if (!te) + {cout << "\n ******** DiversStockages 2ieme lecture ******** \n"; te = true;} + cout << tabMasseAddi.Taille() << " reference(s) de masse additionnelle lue \n"; + for (int i=1; i<=tabMasseAddi.Taille(); i++) + tabMasseAddi(i).Affiche(); + cout << "\n\n"; + } + + cout << endl; + }; + +// lecture des infos +void DiversStockage::Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef) + { MotCle motCle; // ref aux mots cle + // on se positionne sur un mot cle + while ( !motCle.SimotCle(entreePrinc.tablcar)) + entreePrinc.NouvelleDonnee(); + bool sortie_info = false; + if ( (strstr(entreePrinc.tablcar,"epaisseurs")!=NULL) || + (strstr(entreePrinc.tablcar,"largeurs")!=NULL) || + (strstr(entreePrinc.tablcar,"masse_volumique")!=NULL) || + (strstr(entreePrinc.tablcar,"dilatation_thermique")!=NULL) || + (strstr(entreePrinc.tablcar,"hourglass_gestion_")!=NULL) || + (strstr(entreePrinc.tablcar,"sections")!=NULL) || + (strstr(entreePrinc.tablcar,"variation_section")!=NULL) || + (strstr(entreePrinc.tablcar,"integrale_sur_volume_")!=NULL) || + (strstr(entreePrinc.tablcar,"integrale_sur_vol_et_temps_")!=NULL) || + (strstr(entreePrinc.tablcar,"stabilisation_transvers_membrane_biel_")!=NULL) || + (strstr(entreePrinc.tablcar,"repere_anisotropie_")!=NULL) || + (strstr(entreePrinc.tablcar,"statistique_sur_RefNoeuds_")!=NULL) || + (strstr(entreePrinc.tablcar,"statistique_sur_RefNoeuds_et_temps_")!=NULL) + ) + {if (ParaGlob::NiveauImpression() >= 4) + cout << " debut de la lecture des divers stockages 1 " << endl; + sortie_info = true; + }; + // def d'une classe de lecture de bloc scalaire + LectBloc < BlocDdlLim > lecScal; + // def d'une classe de lecture de bloc BlocScal_ou_fctnD + LectBloc < BlocDdlLim > lecBlocScal_ou_fctnD; + // def d'une classe de lecture de bloc généraux + LectBloc < BlocDdlLim > lecGen; + // def d'une classe de lecture de bloc généraux pour les intégrales + LectBloc < BlocDdlLim > lecGen3_0; + // def d'une classe de lecture de bloc généraux pour la stabilisation membrane et/ou biel + // ici par défaut c'est un bloc 4,0 mais peut s'agrandir en fonction de la lecture + // cependant on garde le type BlocGen_4_0 car on ne peut pas faire de BlocDdlLim + // d'un bloc gen (4,0) + LectBloc < BlocDdlLim > lecGen4_0; + // def d'une classe de lecture de bloc généraux pour la définition de repère d'anisotropie + LectBloc < BlocDdlLim > lecGen6_0; + // maintenant il faut gérer le fait que l'on peut avoir les infos dans le désordre + // c'est à dire par exemple épaisseurs puis largeur, ou encore l'inverse etc.. + // on doit arrêter la procédure de lecture lorqu'il n'y a plus a lire + while ( (strstr(entreePrinc.tablcar,"epaisseurs")!=NULL) || + (strstr(entreePrinc.tablcar,"largeurs")!=NULL) || + (strstr(entreePrinc.tablcar,"masse_volumique")!=NULL) || + (strstr(entreePrinc.tablcar,"dilatation_thermique")!=NULL) || + (strstr(entreePrinc.tablcar,"hourglass_gestion_")!=NULL) || + (strstr(entreePrinc.tablcar,"sections")!=NULL) || + (strstr(entreePrinc.tablcar,"variation_section")!=NULL) || + (strstr(entreePrinc.tablcar,"integrale_sur_volume_")!=NULL) || + (strstr(entreePrinc.tablcar,"integrale_sur_vol_et_temps_")!=NULL) || + (strstr(entreePrinc.tablcar,"stabilisation_transvers_membrane_biel_")!=NULL) || + (strstr(entreePrinc.tablcar,"repere_anisotropie_")!=NULL) || + (strstr(entreePrinc.tablcar,"statistique_sur_RefNoeuds_")!=NULL) || + (strstr(entreePrinc.tablcar,"statistique_sur_RefNoeuds_et_temps_")!=NULL) + ) + + { + // lecture eventuelle des epaisseurs + lecBlocScal_ou_fctnD.Lecture(entreePrinc,lesRef,"epaisseurs", + " lecture des epaisseurs ",tabEpaiss); + // lecture eventuelle des largeurs + lecBlocScal_ou_fctnD.Lecture(entreePrinc,lesRef,"largeurs", + " lecture des largeurs ",tabLargeurs); + // lecture eventuelle des sections + lecBlocScal_ou_fctnD.Lecture(entreePrinc,lesRef,"sections", + " lecture des sections ",tabSection); + // lecture eventuelle des variations de section + lecScal.Lecture(entreePrinc,lesRef,"variation_section", + " lecture des sections ",tabVarSection); + // lecture eventuelle des masse_volumiques + lecBlocScal_ou_fctnD.Lecture(entreePrinc,lesRef,"masse_volumique", + " lecture des masse_volumique ",tabMasseVolu); + // lecture eventuelle des coefficients de dilatation thermique + lecBlocScal_ou_fctnD.Lecture(entreePrinc,lesRef,"dilatation_thermique", + " lecture des coefficients de dilatation thermique ",tabCoefDila); + // lecture eventuelle de la gestion des modes d'hourglass + lecGen.Lecture(entreePrinc,lesRef,"hourglass_gestion_", + " lecture de la gestion des modes d'hourglass ",tabGesHourglass); + // lecture eventuelle des intégrales sur le volume + lecGen3_0.Lecture(entreePrinc,lesRef,"integrale_sur_volume_", + " lecture des integrales sur le volume ",tabIntegVol); + // lecture eventuelle des intégrales sur le volume et sur le temps + lecGen3_0.Lecture(entreePrinc,lesRef,"integrale_sur_vol_et_temps_", + " lecture des integrales sur le volume et le temps ",tabIntegVol_et_temps); + + // lecture eventuelle d'une stabilisation transversale de membrane ou biel + lecGen4_0.Lecture(entreePrinc,lesRef,"stabilisation_transvers_membrane_biel_", + " lecture des stabilisations transversales ",tabStabMembraneBiel); + + // lecture eventuelle de repère d'anisotropie à des éléments + lecGen6_0.Lecture(entreePrinc,lesRef,"repere_anisotropie_", + " lecture d'un repere d'anisotropie ",tabRepAnisotrope); + // lecture eventuelle des statistiques de ref de noeuds pour une grandeur quelconque + lecGen3_0.Lecture(entreePrinc,lesRef,"statistique_sur_RefNoeuds_", + " lecture des statistique_sur_RefNoeuds_ ",tabStatistique); + // lecture eventuelle des statistiques de ref de noeuds pour une grandeur + // quelconque avec cumul sur le temps + lecGen3_0.Lecture(entreePrinc,lesRef,"statistique_sur_RefNoeuds_et_temps_", + " lecture des statistique_sur_RefNoeuds_et_temps_",tabStatistique_et_temps); + + + }; + +////----- debug --- +//cout << "\n debug DiversStockage::Lecture1( " +// << "\n tabRepAnisotrope= "<< tabRepAnisotrope << endl; +////---- fin debug --- + + // on vérifie qu'il n'y a pas 2 fois exactements les mêmes intégrales a effectuer, si oui on couine + // car cela va poser des pb + {int taille = tabIntegVol.Taille(); + for (int i=1;i<= taille-1;i++) + for (int j=i+1;j<= taille;j++) + if (tabIntegVol(i) == tabIntegVol(j)) + {cout << "\n erreur*** il y a deux integrales de volume qui sont strictement identiques " + << " cela va poser des problemes de referencement a l'execution, il faut en supprimer une !! " + << "\n integrale: "<< tabIntegVol(i) + << endl; + Sortie(1); + }; + }; + {int taille = tabIntegVol_et_temps.Taille(); + for (int i=1;i<= taille-1;i++) + for (int j=i+1;j<= taille;j++) + if (tabIntegVol_et_temps(i) == tabIntegVol_et_temps(j)) + {cout << "\n erreur*** il y a deux integrales de volume et en temps qui sont strictement identiques " + << " cela va poser des problemes de referencement a l'execution, il faut en supprimer une !! " + << "\n integrale: "<< tabIntegVol_et_temps(i) + << endl; + Sortie(1); + }; + }; + + // on vérifie qu'il n'y a pas 2 fois exactements les mêmes statistique a effectuer, si oui on couine + // car cela va poser des pb + {int taille = tabStatistique.Taille(); + for (int i=1;i<= taille-1;i++) + for (int j=i+1;j<= taille;j++) + if (tabStatistique(i) == tabStatistique(j)) + {cout << "\n erreur*** il y a deux statistiques qui sont strictement identiques " + << " cela va poser des problemes de referencement a l'execution, il faut en supprimer une !! " + << "\n statistique: "<< tabStatistique(i) + << endl; + Sortie(1); + }; + }; + {int taille = tabStatistique_et_temps.Taille(); + for (int i=1;i<= taille-1;i++) + for (int j=i+1;j<= taille;j++) + if (tabStatistique_et_temps(i) == tabStatistique_et_temps(j)) + {cout << "\n erreur*** il y a deux statistiques avec cumul en temps qui sont strictement identiques " + << " cela va poser des problemes de referencement a l'execution, il faut en supprimer une !! " + << "\n statistiques: "<< tabStatistique_et_temps(i) + << endl; + Sortie(1); + }; + }; + + + if ((ParaGlob::NiveauImpression() >= 4) && sortie_info) + cout << " fin de la lecture des divers stockages 1 " << endl; + }; + +// dans la seconde lecture il s'agit des masses additionnelles + void DiversStockage::Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef) + { MotCle motCle; // ref aux mots cle + // on se positionne sur un mot cle + while ( !motCle.SimotCle(entreePrinc.tablcar)) + entreePrinc.NouvelleDonnee(); + bool sortie_info = false; + if ( (strstr(entreePrinc.tablcar,"masse_addi")!=NULL) ) + {if (ParaGlob::NiveauImpression() >= 4) + cout << " debut de la lecture des divers stockages 2 " << endl; + sortie_info = true; + } + // def d'une classe de lecture de bloc scalaire + LectBloc < BlocDdlLim > lecScal; + + // lecture eventuelle des masses + lecScal.Lecture(entreePrinc,lesRef,"masse_addi", + " lecture des masses additionnelles ",tabMasseAddi); + if ((ParaGlob::NiveauImpression() >= 4) && sortie_info) + cout << " fin de la lecture des divers stockages 2 " << endl; + }; + +// affichage et definition interactive des commandes +void DiversStockage::Info_commande_DiversStockage1(UtilLecture & entreePrinc) +{ ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier + //On va proposer un menu + string rep=" "; + bool plusieurs_maillages = false; + sort << "\n# --- divers stockages (1) ------- "; + cout << "\n cas d'un seul maillage (par defaut) : rep o " + << "\n cas de plusieurs maillages : rep n "; + // procédure de lecture avec prise en charge d'un retour chariot + rep = lect_return_defaut(true,"o"); + if (rep == "n") + { plusieurs_maillages = true;}; + rep="_"; // init + while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) + { + try + { + cout << "\n -- definition de : --- " + << "\n (0 ou f) (fin) " + << "\n (1) epaisseurs " + << "\n (2) largeurs " + << "\n (3) sections " + << "\n (4) variation de section " + << "\n (5) masse volumique (obligatoire)" + << "\n (6) dilatation_thermique " + << "\n (7) gestion hourglass " + << "\n (8) integrale sur volume " + << "\n (9) integrale sur volume et temps " + << "\n (10) stabilisation transversale " + << "\n (11) repere d'anisotropie " + << "\n (12) statistique sur ref de noeuds " + << "\n (13) statistique sur ref de noeuds et temps " + << "\n (14 ou ? ) informations " + << "\n "; + rep = lect_return_defaut(false,"f"); + if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe + break; + int num = ChangeEntier(rep); + if (Minuscules(rep) == "?") + num = 14; + bool choix_valide=false; + if ((num >= 0)&&(num< 15)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 14 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + } + string grandeur=" "; // init + // cas d'une grandeur simple + switch (num) + { case 1: grandeur = "epaisseurs";break; + case 2: grandeur = "largeurs";break; + case 3: grandeur = "sections";break; + case 4: grandeur = "variation_section";break; + case 5: grandeur = "masse_volumique";break; + case 6: grandeur = "dilatation_thermique";break; + case 7: grandeur = "hourglass_gestion_";break; + case 8: grandeur = "integrale_sur_volume_";break; + case 9: grandeur = "integrale_sur_vol_et_temps_";break; + case 10: grandeur = "stabilisation_transvers_membrane_biel_";break; + case 11: grandeur = "repere_anisotropie_";break; + case 12: grandeur = "statistique_sur_RefNoeuds_";break; + case 13: grandeur = "statistique_sur_RefNoeuds_et_temps_";break; + }; + + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: case 2: case 3: case 5: case 6: + { cout << "\n def de la ref associee : "; + bool lecture_ok=true; // init a priori + string sortie = "\n " + grandeur + " #--------# \n";; + //sort << "\n "<< grandeur<<" #--------# \n"; + if (plusieurs_maillages) + { string nom_mail=" "; + cout << "\n nom du maillage ? "; + nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; + sortie += " nom_mail= " + nom_mail + " "; + // sort << " nom_mail= "<< nom_mail<< " "; + }; + cout << "\n nom de la reference ? "; + string nom_ref=" "; + nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; + if (nom_ref.at(0) != 'E') + {cout << "\n *** erreur, la premiere lettre de la ref d'element " + << " doit etre E et non "<< nom_ref.at(0)<< " !!"; + lecture_ok = false; + break; + } + else {sortie += " " + nom_ref+" ";} ; + + int int_choix_loc=0;string rep_loc(""); + while ((int_choix_loc > 3) || (int_choix_loc < 1)) + {cout << "\n --- definition de la valeur --- " + << "\n (1) valeur fixe -> un reel " + << "\n (2) valeur via une fonction nD " + << "\n (3 ou f ) arret " + << "\n "; + rep_loc = lect_return_defaut(false,"f"); Minuscules(rep_loc); + int_choix_loc = ChangeEntier(rep_loc); + if ((rep_loc == "f")||(int_choix_loc == 3)) + {lecture_ok = false; break; + }; + switch (int_choix_loc) + {case 1: + {double d=0.;// init + cout << "\n un reel ? "; + d=lect_double();cout << " valeur lue = "<< d; + sortie += ChangeReelSTring(d)+" "; + } + break; + case 2: + { cout << "\n nom de la fonction nD ? "; + string nom_fnD(""); + nom_fnD= lect_chaine();cout << " nom lu = "<< nom_fnD; + sortie += " une_fonction_nD_ " + nom_fnD; + }; + break; + default: + {cout << "\n *** mauvais choix, vous devez donner une valeur entre 1 et 3 !" + << "\n recommencer "; + }; + }; + }; + if(lecture_ok) + sort << sortie; + break; + } + case 4: + { cout << "\n def de la ref associee : "; + string sortie = "\n " + grandeur + " #--------# \n";; + //sort << "\n "<< grandeur<<" #--------# \n"; + if (plusieurs_maillages) + { string nom_mail=" "; + cout << "\n nom du maillage ? "; + nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; + sortie += " nom_mail= " + nom_mail + " "; + // sort << " nom_mail= "<< nom_mail<< " "; + }; + cout << "\n nom de la reference ? "; + string nom_ref=" "; + nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; + if (nom_ref.at(0) != 'E') + {cout << "\n *** erreur, la premiere lettre de la ref d'element " + << " doit etre E et non "<< nom_ref.at(0)<< " !!"; + break; + }; + cout << "\n valeur de: " << grandeur<<" (un entier) ? "; + int a = 0.; + a=(int) lect_double();cout << " valeur lue ="<< a; + sort << sortie; + sort << nom_ref << " " << a << " "; + break; + } + case 7: + { cout << "\n def de la ref associee : "; + string sortie = "\n\n " + grandeur + " #--------# "; + //sort << "\n\n "<< grandeur<<" #--------# "; + //sort << "\n#----------------------------------------------------\n"; + sortie += "\n#----------------------------------------------------\n"; + if (plusieurs_maillages) + { string nom_mail=" "; + cout << "\n nom du maillage ? "; + nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; + //sort << " nom_mail= "<< nom_mail<< " "; + sortie += " nom_mail= " + nom_mail + " "; + }; + cout << "\n nom de la reference d'element ? "; + string nom_ref=" "; + nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; + // choix du type de stabilisation + int choix_type_stabilistion = 0; + string type_stabilistion_lu=""; + while (choix_type_stabilistion == 0) + { cout << "\n -- choix du type de stabilisation --- " + << "\n (1) STABHOURGLASS_PAR_COMPORTEMENT " + << "\n (2) STABHOURGLASS_PAR_COMPORTEMENT_REDUIT (par defaut)" + << "\n "; + type_stabilistion_lu= lect_chaine(); cout << " valeur lue ="<< type_stabilistion_lu; + if (type_stabilistion_lu == "1" ) + {type_stabilistion_lu = " STABHOURGLASS_PAR_COMPORTEMENT ";choix_type_stabilistion=1;} + else if (type_stabilistion_lu == "2" ) + {type_stabilistion_lu = " STABHOURGLASS_PAR_COMPORTEMENT_REDUIT ";choix_type_stabilistion=2;}; + }; + cout << "\n stabilisation par comportement: " + << " nom associe a la loi ? "; + string nom_loi="_"; + nom_loi= lect_chaine();cout << " nom lu = "<< nom_loi; + cout << "\n valeur de alpha (un reel) ? "; + double alpha= 0.; + alpha=lect_double();cout << " valeur lu = "<< alpha; + sort << sortie; + sort << nom_ref << type_stabilistion_lu + << nom_loi << " " << alpha << " "; + break; + } + case 8: case 9: + { string type_integrale; + if (num == 8) type_integrale="integrale_sur_volume_"; + else type_integrale="integrale_sur_vol_et_temps_"; + + cout << "\n def de la ref associee : "; + string sortie = "\n\n " + grandeur + " #--------# "; + //sort << "\n\n "<< grandeur<<" #--------# "; + //sort << "\n#----------------------------------------------------\n"; + sortie += "\n#----------------------------------------------------\n"; + if (plusieurs_maillages) + { string nom_mail=" "; + cout << "\n nom du maillage ? "; + nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; + //sort << " nom_mail= "<< nom_mail<< " "; + sortie += " nom_mail= " + nom_mail + " "; + }; + cout << "\n nom de la reference d'element ? "; + string nom_ref=" "; + nom_ref= lect_chaine();cout << " nom lu = "<< nom_ref; + // maintenant choix de la grandeur à intégrer + int choix_type_grandeur = 0; + string type_grandeur_lu=""; + while (choix_type_grandeur == 0) + { cout << "\n -- choix du type de grandeur a integrer sur le volume --- " + << "\n (1) un ddl etendu " + << "\n (2) une fonction nD " + << "\n (f) fin sans sauvegarde (defaut) "; + type_grandeur_lu=lect_return_defaut(false,"f"); + cout << " valeur lue ="<< type_grandeur_lu; + if (type_grandeur_lu == "1" ) + { string nom_ddl(""); + Ddl_enum_etendu ddl; + cout << "\n nom du ddl "; nom_ddl= lect_chaine(); + cout << " valeur lue = "<< nom_ddl; + if (!(ddl.VerifExistence(nom_ddl))) + { cout << "\n *** "< un resultat pour chaque element et un resultat global " + << "\n pour les statistiques: il s'agit de definir une grandeur dont on va calculer " + << "\n sur les noeuds d'une ref: la somme, le mini, le maxi etc. " + << "\n "; + } + default: + cout << "\n le cas "<= 0)&&(num<=7)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 2 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + } + string grandeur=" "; // init + // cas d'une grandeur simple + switch (num) + { case 1: grandeur = "masse_addi";break; + }; + + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: + { string sortie = "\n def de la ref associee : "; + bool lecture_ok=true; // init a priori + //cout << "\n def de la ref associee : "; + sortie += "\n "+ grandeur +" #--------# \n"; + //sort << "\n "<< grandeur <<" #--------# \n"; + if (plusieurs_maillages) + { string nom_mail=" "; + cout << "\n nom du maillage ? "; + nom_mail= lect_chaine(); cout << " nom lu = "<< nom_mail; + sortie += " nom_mail= "+ nom_mail+ " "; + //sort << " nom_mail= "<< nom_mail<< " "; + }; + cout << "\n nom de la reference ? "; + string nom_ref=" "; + 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 noeud " + << " doit etre N et non "<< nom_ref.at(0)<< " !!"; + lecture_ok = false; + break; + } + else {sortie += " " + nom_ref+" ";} ; + + int int_choix_loc=0;string rep_loc(""); + while ((int_choix_loc > 3) || (int_choix_loc < 1)) + {cout << "\n --- definition de la valeur --- " + << "\n (1) valeur fixe -> un reel " + << "\n (2) valeur via une fonction nD " + << "\n (3 ou f ) arret " + << "\n "; + rep_loc = lect_return_defaut(false,"f"); Minuscules(rep_loc); + int_choix_loc = ChangeEntier(rep_loc); + if ((rep_loc == "f")||(int_choix_loc == 3)) + {lecture_ok = false; break; + }; + switch (int_choix_loc) + {case 1: + {double d=0.;// init + d=lect_double();cout << " valeur lue = "<< d; + sortie += ChangeReelSTring(d)+" "; + } + break; + case 2: + { cout << "\n nom de la fonction nD ? "; + string nom_fnD(""); + nom_fnD= lect_chaine();cout << " nom lu = "<< nom_fnD; + sortie += " Fonction_nD_: " + nom_fnD; + }; + break; + default: + {cout << "\n *** mauvais choix, vous devez donner une valeur entre 1 et 3 !" + << "\n recommencer "; + }; + }; + }; + if(lecture_ok) + sort << sortie << flush; + break; + } + case 2: // information + { cout << "\n Au niveau des noeuds il est possible d'imposer une masse supplementaire ponctuelle " + << "\n pour cela on indique une reference de noeud puis une valeur correspondant a la masse ponctuelle " + << "\n on se reportera a la documentation pour plus d'info" + << "\n sinon il suffit de repondre aux questions" + << "\n "; + break; + } + default: + cout << "\n le cas "<> toto ; + + // cas du tableau des épaisseurs + int tabEpaissTaille ; + entr >> toto >> tabEpaissTaille ; + tabEpaiss.Change_taille(tabEpaissTaille); + for (int i=1; i<= tabEpaissTaille; i++) + entr >> tabEpaiss(i) ; + + // cas du tableau des largeurs + int tabLargeursTaille = tabLargeurs.Taille(); + entr >> toto >> tabLargeursTaille ; + tabLargeurs.Change_taille(tabLargeursTaille); + for (int i=1; i<= tabLargeursTaille; i++) + entr >> tabLargeurs(i) ; + + // cas du tableau des sections + int tabSectionTaille = tabSection.Taille(); + entr >> toto >> tabSectionTaille ; + tabSection.Change_taille(tabSectionTaille); + for (int i=1; i<= tabSectionTaille; i++) + entr >> tabSection(i) ; + + // cas du tableau des variation de section + int tabVarSectionTaille = tabVarSection.Taille(); + entr >> toto >> tabVarSectionTaille ; + tabVarSection.Change_taille(tabVarSectionTaille); + for (int i=1; i<= tabVarSectionTaille; i++) + entr >> tabVarSection(i) ; + + // cas du tableau des masses volumique + int tabMasseVoluTaille = tabMasseVolu.Taille(); + entr >> toto >> tabMasseVoluTaille ; + tabMasseVolu.Change_taille(tabMasseVoluTaille); + for (int i=1; i<= tabMasseVoluTaille; i++) + entr >> tabMasseVolu(i) ; + + // cas du tableau des coefficients de dilatation thermique + int tabCoefDilaTaille = tabCoefDila.Taille(); + entr >> toto >> tabCoefDilaTaille ; + tabCoefDila.Change_taille(tabCoefDilaTaille); + for (int i=1; i<= tabCoefDilaTaille; i++) + entr >> tabCoefDila(i) ; + + // cas du tableau des gestions d'hourglass + int tabGesHourglassTaille = tabGesHourglass.Taille(); + entr >> toto >> tabGesHourglassTaille ; + tabGesHourglass.Change_taille(tabGesHourglassTaille); + for (int i=1; i<= tabGesHourglassTaille; i++) + entr >> tabGesHourglass(i) ; + + // cas du tableau des intégrales sur volume + int tabIntegVolTaille = tabIntegVol.Taille(); + entr >> toto >> tabIntegVolTaille ; + tabIntegVol.Change_taille(tabIntegVolTaille); + for (int i=1; i<= tabIntegVolTaille; i++) + entr >> tabIntegVol(i) ; + + // cas du tableau des intégrales sur volume et temps + int tabIntegVol_et_tempsTaille = tabIntegVol_et_temps.Taille(); + entr >> toto >> tabIntegVol_et_tempsTaille ; + tabIntegVol_et_temps.Change_taille(tabIntegVol_et_tempsTaille); + for (int i=1; i<= tabIntegVol_et_tempsTaille; i++) + entr >> tabIntegVol_et_temps(i) ; + + // cas du tableau des stabilisations transversales de membrane ou biel + int tabStabMembraneBielTaille = tabStabMembraneBiel.Taille(); + entr >> toto >> tabStabMembraneBielTaille ; + tabStabMembraneBiel.Change_taille(tabStabMembraneBielTaille); + for (int i=1; i<= tabStabMembraneBielTaille; i++) + entr >> tabStabMembraneBiel(i) ; + + // cas du tableau des masses additionnelles + int tabMasseAddiTaille = tabMasseAddi.Taille(); + entr >> toto >> tabMasseAddiTaille ; + tabMasseAddi.Change_taille(tabMasseAddiTaille); + for (int i=1; i<= tabMasseAddiTaille; i++) + entr >> tabMasseAddi(i) ; + + // cas du tableau des repères d'anisotropie + int tabRepAnisotropeTaille = tabRepAnisotrope.Taille(); + entr >> toto >> tabRepAnisotropeTaille ; + tabRepAnisotrope.Change_taille(tabRepAnisotropeTaille); + for (int i=1; i<= tabRepAnisotropeTaille; i++) + entr >> tabRepAnisotrope(i) ; + + + // cas du tableau des statistiques + int tabStatistiqueTaille = tabStatistique.Taille(); + entr >> toto >> tabStatistiqueTaille ; + tabStatistique.Change_taille(tabStatistiqueTaille); + for (int i=1; i<= tabStatistiqueTaille; i++) + entr >> tabStatistique(i) ; + + // cas du tableau des statistiques avec cumul en temps + int tabStatistique_et_tempsTaille = tabStatistique_et_temps.Taille(); + entr >> toto >> tabStatistique_et_tempsTaille ; + tabStatistique_et_temps.Change_taille(tabStatistique_et_tempsTaille); + for (int i=1; i<= tabStatistique_et_tempsTaille; i++) + entr >> tabStatistique_et_temps(i) ; + + } + }; + + +// écriture base info +// = 1 : on sauvegarde tout +// = 2 : on sauvegarde uniquement les données variables (supposées comme telles) +void DiversStockage::Ecriture_base_info(ofstream& sort,const int cas) + { // a priori les données stockées ne sont pas variables d'où seule le cas = 1 + // est utilisé + if (cas == 1 ) + { sort << "\n ****divers_stockages \n" ; + + // cas du tableau des épaisseurs + int tabEpaissTaille = tabEpaiss.Taille(); + sort << "epaisseurs " << tabEpaissTaille << " " ; + for (int i=1; i<= tabEpaissTaille; i++) + sort << tabEpaiss(i) << " "; + + // cas du tableau des largeurs + int tabLargeursTaille = tabLargeurs.Taille(); + sort << "\n largeurs " << tabLargeursTaille << " " ; + for (int i=1; i<= tabLargeursTaille; i++) + sort << tabLargeurs(i) << " "; + + // cas du tableau des sections + int tabSectionTaille = tabSection.Taille(); + sort << "\n sections " << tabSectionTaille << " " ; + for (int i=1; i<= tabSectionTaille; i++) + sort << tabSection(i) << " "; + + // cas du tableau des variations d sections + int tabVarSectionTaille = tabVarSection.Taille(); + sort << "\n variation de section " << tabVarSectionTaille << " " ; + for (int i=1; i<= tabVarSectionTaille; i++) + sort << tabVarSection(i) << " "; + + // cas du tableau des masses volumiques + int tabMasseVoluTaille = tabMasseVolu.Taille(); + sort << "\n masse_volumique " << tabMasseVoluTaille << " " ; + for (int i=1; i<= tabMasseVoluTaille; i++) + sort << tabMasseVolu(i) << " "; + + // cas du tableau des coefficients de dilatation thermique + int tabCoefDilaTaille = tabCoefDila.Taille(); + sort << "\n dilatation_thermique " << tabCoefDilaTaille << " " ; + for (int i=1; i<= tabCoefDilaTaille; i++) + sort << tabCoefDila(i) << " "; + + // cas du tableau des gestions d'hourglass + int tabGesHourglassTaille = tabGesHourglass.Taille(); + sort << "\n hourglass_gestion_ " << tabGesHourglassTaille << " " ; + for (int i=1; i<= tabGesHourglassTaille; i++) + sort << tabGesHourglass(i) << " "; + + // cas du tableau des intégrales de volume + int tabIntegVolTaille = tabIntegVol.Taille(); + sort << "\n integrale_sur_volume_ " << tabIntegVolTaille << " " ; + for (int i=1; i<= tabIntegVolTaille; i++) + sort << tabIntegVol(i) << " "; + + // cas du tableau des intégrales de volume et sur le temps + int tabIntegVol_et_tempsTaille = tabIntegVol_et_temps.Taille(); + sort << "\n integrale_sur_vol_et_temps_ " << tabIntegVol_et_tempsTaille << " " ; + for (int i=1; i<= tabIntegVol_et_tempsTaille; i++) + sort << tabIntegVol_et_temps(i) << " "; + + // cas du tableau des stabilisations transversales de membrane ou biel + int tabStabMembraneBielTaille = tabStabMembraneBiel.Taille(); + sort << "\n stabilisation_transvers_membrane_biel_ " << tabStabMembraneBielTaille << " " ; + for (int i=1; i<= tabStabMembraneBielTaille; i++) + sort << tabStabMembraneBiel(i) << " "; + + // cas du tableau des masses additionnelles + int tabMasseAddiTaille = tabMasseAddi.Taille(); + sort << "\n masses_additionnelles " << tabMasseAddiTaille << " " ; + for (int i=1; i<= tabMasseAddiTaille; i++) + sort << tabMasseAddi(i) << " "; + + // cas du tableau des repères d'anisotropie + int tabRepAnisotropeTaille = tabRepAnisotrope.Taille(); + sort << "\n repere_anisotropie_ " << tabRepAnisotropeTaille << " " ; + for (int i=1; i<= tabRepAnisotropeTaille; i++) + sort << tabRepAnisotrope(i) << " "; + + // cas du tableau des statistiques + int tabStatistiqueTaille = tabStatistique.Taille(); + sort << "\n statistique_sur_RefNoeuds_ " << tabStatistiqueTaille << " " ; + for (int i=1; i<= tabStatistiqueTaille; i++) + sort << tabStatistique(i) << " "; + + // cas du tableau des statistiques avec cumul en temps + int tabStatistique_et_tempsTaille = tabStatistique_et_temps.Taille(); + sort << "\n statistique_sur_RefNoeuds_et_temps_ " << tabStatistique_et_tempsTaille << " " ; + for (int i=1; i<= tabStatistique_et_tempsTaille; i++) + sort << tabStatistique_et_temps(i) << " "; + + + + } + }; + diff --git a/Maillage/DiversStockage.h b/Maillage/DiversStockage.h new file mode 100644 index 0000000..5111f33 --- /dev/null +++ b/Maillage/DiversStockage.h @@ -0,0 +1,211 @@ + +// 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: . + +/************************************************************************ + * DATE: 23/01/97 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: Classe servant a stocker des informations intermediaires.* + * * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ +#ifndef DIVERSSTOCKAGE_H +#define DIVERSSTOCKAGE_H + +#include +#include +#include +#include "Tableau_T.h" +#include "UtilLecture.h" +#include "LesReferences.h" +#include "MotCle.h" +#include "LectBloc_T.h" +#include "Bloc.h" +#include "BlocDdlLim.h" + +/** +* +* BUT:Classe servant a stocker des informations intermediaires. +* +* \author Gérard Rio +* \version 1.0 +* \date 23/01/97 +* \brief Classe servant a stocker des informations intermediaires. +* +*/ + +class DiversStockage +{ + public : + // VARIABLES PUBLIQUES : + // CONSTRUCTEURS : + + DiversStockage (); + // DESTRUCTEUR : + ~DiversStockage () {}; + + // METHODES PUBLIQUES : + // affichage des infos + void Affiche () const ; // affichage de tous les infos + void Affiche1 () const ; // affichage des infos de la premiere lecture + void Affiche2 () const ; // affichage des infos de la seconde lecture + + + // lecture des infos + // dans la premiere lecture il s'agit actuellement des epaisseurs, des sections + void Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef); + + // dans la seconde lecture il s'agit des masses additionnelles + void Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef); + + // retourne le tableau des epaisseurs + const Tableau < BlocDdlLim > & TabEpaiss() const { return tabEpaiss;}; + + // retourne le tableau des largeurs + const Tableau < BlocDdlLim > & TabLargeurs() const { return tabLargeurs;}; + + // retourne le tableau des section + const Tableau < BlocDdlLim > & TabSect() const { return tabSection;}; + + // retourne le tableau des variations de section + const Tableau < BlocDdlLim > & TabVarSect() const { return tabVarSection;}; + + // retourne le tableau des masses volumiques + const Tableau < BlocDdlLim > & TabMasseVolu() const { return tabMasseVolu;}; + + // retourne le tableau des masses additionnelles + const Tableau < BlocDdlLim > & TabMasseAddi() const { return tabMasseAddi;}; + + // retourne le tableau des dilatations thermique + const Tableau < BlocDdlLim > & TabCoefDila() const { return tabCoefDila;}; + + // retourne le tableau des gestions d'hourglass + const Tableau < BlocDdlLim > & TabGesHourglass() const { return tabGesHourglass;}; + + // retourne le tableau d'intégration de volume d'une grandeur + const Tableau < BlocDdlLim >& TabIntegVol() const {return tabIntegVol;}; + + // retourne le tableau d'intégration de volume et en temps d'une grandeur + const Tableau < BlocDdlLim >& TtabIntegVol_et_temps() const {return tabIntegVol_et_temps;}; + + // retourne le tableau sur la stabilisation transversale de membrane ou biel + const Tableau < BlocDdlLim >& TabStabMembBiel() const {return tabStabMembraneBiel;}; + + // retourne le tableau sur la définition d'un repère d'anisotropie aux éléments + const Tableau < BlocDdlLim >& TabRepAnisotrope() const {return tabRepAnisotrope;}; + + // lecture de donnée en fonction d'un indicateur : int type + // pour l'instant ne fait rien + void LectureDonneesExternes(UtilLecture& ,LesReferences& ,const int ,const string& ) {}; + + // retourne le tableau sur statistique d'une ref de noeuds pour une grandeur quelconque + const Tableau < BlocDdlLim >& TabStatistique() const {return tabStatistique;}; + + // retourne le tableau sur statistique d'une ref de noeuds cumulée en temps pour une grandeur queconque + const Tableau < BlocDdlLim >& TabStatistique_et_temps() const {return tabStatistique_et_temps;}; + + // affichage et definition interactive des commandes + void Info_commande_DiversStockage1(UtilLecture & entreePrinc); + void Info_commande_DiversStockage2(UtilLecture & entreePrinc); + + + //----- lecture écriture dans base info ----- + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) + void Lecture_base_info(ifstream& ent,const int cas); + // cas donne le niveau de sauvegarde + // = 1 : on sauvegarde tout + // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) + void Ecriture_base_info(ofstream& sort,const int cas); + + private : + // VARIABLES PROTEGEES : + + // infos sur les epaisseurs + Tableau < BlocDdlLim > tabEpaiss; + // infos sur les largeurs + Tableau < BlocDdlLim > tabLargeurs; + + // infos sur les sections de biellette + Tableau < BlocDdlLim > tabSection; + + // infos sur les variations de sections de biellette + Tableau < BlocDdlLim > tabVarSection; + + // infos sur les masses volumique + Tableau < BlocDdlLim > tabMasseVolu; + + // infos sur les masses additionnelles + Tableau < BlocDdlLim > tabMasseAddi; + + // infos sur les coefficients de dilatation + Tableau < BlocDdlLim > tabCoefDila; + + // infos sur la gestion d'hourglass + Tableau < BlocDdlLim > tabGesHourglass; + + // infos sur intégration de volume d'une grandeur queconque + Tableau < BlocDdlLim > tabIntegVol; + + // infos sur intégration de volume et en temps d'une grandeur queconque + Tableau < BlocDdlLim > tabIntegVol_et_temps; + + // infos sur la stabilisation transversale de membrane ou biel + // a priori de type 4,0 mais peut s'agrandir si nécessaire à la lecture !! + Tableau < BlocDdlLim > tabStabMembraneBiel; + + // infos sur la définition d'un repère d'anisotropie aux éléments + Tableau < BlocDdlLim > tabRepAnisotrope; + + // infos sur statistique d'une ref de noeuds pour une grandeur quelconque + Tableau < BlocDdlLim > tabStatistique; + + // infos sur statistique d'une ref de noeuds cumulée en temps pour une grandeur queconque + Tableau < BlocDdlLim > tabStatistique_et_temps; + + }; + +#endif diff --git a/Maillage/I_O_Condilineaire.cc b/Maillage/I_O_Condilineaire.cc new file mode 100644 index 0000000..f296b3b --- /dev/null +++ b/Maillage/I_O_Condilineaire.cc @@ -0,0 +1,2216 @@ + +// 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 "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; + }; + + + diff --git a/Maillage/I_O_Condilineaire.h b/Maillage/I_O_Condilineaire.h new file mode 100644 index 0000000..9bb0a6e --- /dev/null +++ b/Maillage/I_O_Condilineaire.h @@ -0,0 +1,273 @@ + +// 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: . + +/************************************************************************ + * DATE: 19/01/2007 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: gérer les conditions limites linéaires en I/O * + * en particulier comme conteneur. * + * informations: pour l'instant on considère une conditions * + * linéaires entre les ddl d'une même famille d'un noeud. * + * Une instance de I_O_Condilineaire peut générer un grand nombres * + * de conditions linéaires particulières, en fait autant que de * + * noeuds appartenant à la référence principal. Ces conditions * + * particulières ne sont pas stockées dans I_O_Condilineaire !! * + * par contre, elles peuvent être générées par I_O_Condilineaire. * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ +#ifndef I_O_CONDILINEAIRE_H +#define I_O_CONDILINEAIRE_H + +#include "Condilineaire.h" +#include "Plan.h" +#include "Droite.h" + +/// @addtogroup Les_classes_relatives_aux_conditions_limites +/// @{ +/// +class I_O_Condilineaire : public Condilineaire +{ // surcharge de l'operator de lecture + // les informations sont typées + friend istream & operator >> (istream &, I_O_Condilineaire &); + // surcharge de l'operator d'ecriture typée + friend ostream & operator << (ostream &, const I_O_Condilineaire &); + + public : + // CONSTRUCTEURS : + + // par défaut + I_O_Condilineaire(); + // de copie + I_O_Condilineaire(const I_O_Condilineaire& nd); + // DESTRUCTEUR : + ~I_O_Condilineaire(); + + + // METHODES PUBLIQUES : + + // Retourne la reference attache à la condition linéaire + const string& NomRef () const { return refe; }; + // retourne un pointeur de string donnant le nom du maillage associé + // = NULL si aucun maillage + const string* NomMaillage() const {return nom_maillage;}; + + // retourne le tableau des références associées (peut-être vide !) + const Tableau & ReferenceAssociees() const {return refs_associe;}; + // retourne le tableau des nom de maillage associées aux noms de ref (peut être = 0) + // tail = 0 si il n'y a pas de nom de maillage sur la ref principale + const Tableau & NomMaillageAssociees() const {return nom_mail_associe;}; + + // 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 + bool MemeCibleMaisDataDifferents(I_O_Condilineaire& d); + + // Affiche les donnees + void Affiche () const ; + // Realise l'egalite + I_O_Condilineaire& operator= (const I_O_Condilineaire& d); + + //Surcharge d'operateur logique: ne concerne que la condition initiale (pas la condition actuelle, + // c-a-d les coeff actuelles et les noeuds actuellement en cause etc.) + bool operator == ( I_O_Condilineaire& a) const ; + + bool operator != ( I_O_Condilineaire& a) const { return !(*this == a);}; + + // lecture de la condition linéaire sur le fichier d'entree + void Lecture(UtilLecture & entreePrinc); + + // retourne si la condition est relative ou pas + // une condition relative signifie que la condition s'effectue par rapport au pas de temps + // précédent i.e. t=t + // une condition non relative, donc absolue signifie que la condition s'effectue par rapport à + // t = 0 + bool ConditionRelative() const {return condition_relative;}; + + //--- cas des conditions linéaires type plan ou droite --------------------------------------------- + + // ramène true si on a effectivement une condi linéaire type plan ou droite + bool PlanDroite() const {return def_auto_par_rotation;}; + + // 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 Coherence_condi_PlanDroite(int indi)const; + + // ramène true si on a effectivement une condi linéaire type stricte_egalite + bool StricteEgalite() const {return stricte_egalite;}; + + // le nom du maillage éventuellement et le numéro du noeud s'il y a un noeud rotation + // sinon ramène un pointeur null + const String_et_entier* RefNoeudRotation() const {if (type_centre==1){return NULL;} + else {return &mailEtNumCentreNoeud;};}; + // definition du noeud: centre rotation + void ChangeCentreNoeudRotation( Noeud* noe); + // définition de la direction actuelle ou normale pour plan droite + void ActualiseDirectionPlanDroite(); + // 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& ProjectionSurPlanDroite_et_calValCondiLin(Coordonnee& M ); + + + + // --- fin des condi linéaires types plan droite --------------------------------------------------- + + // Construction de la condition : en particulier les pointeurs de ddl permettant d'imposer la condition + // et def des coefficients en fonction éventuellement du temps ou de l'incrément du temps selon + // le paramètre condition_relative + // pour cela + // 1) on doit renseigner les fonctions de charge si elles existent + // a) retour du nombre de fonction de charge + int ExisteFonctionChargeCoef()const {return tab_co_charge.Taille();}; + // b) le nom de la courbe + const string & NomFctch(int i) const {return tab_co_charge(i);}; + // b) on renseigne les valeurs des fonctions de charge + void Valeur_fonctionChargeCoef(const Vecteur & fctch_,const Vecteur & delta_fctch_) + {fctch = fctch_;delta_fctch = delta_fctch_;}; + // 2) + // Construction de la condition : 1) mise en place d'une valeur imposée due à la condition linéaire + // def des coefficients en fonction éventuellement des fonctions de charges et du paramètre condition_relative + // NB: pour les conditions correspondant à une projection sur un plan ou une droite, il faut que la direction du plan + // ou de la droite ait déjà été affecté auparavant + // !! la condition sur le ddl n'est pas imposée à ce niveau, par contre elle est stockée dans Condilineaire + Condilineaire& ConstructionCondition(Tableau & t_noe,Condilineaire& condi_actuelle); + + // affichage des commandes particulières à la définition d'une condition linéaire + void Info_commande_conditionLineaire(ofstream & sort,bool plusieurs_maillages); + + // récupération de l'énuméré du type de ddl considéré par la condition limite linéaire + Enum_ddl TypeEnu() const {return enu;}; + + // retourne un booléen qui indique si oui ou non le temps passé en paramètre + // est situé entre le temps min et maxi de la condition linéaire + bool Temps_actif(const double& temps) const + {if ((t_min < temps) && (temps <= t_max)) return true; + else return false; }; + // ramène vrai si le temps est inférieur au temps actif, ou supérieur au temps max + // ou si d'une part le temps n'est pas actif et qu'au pas précédent + // il n'était pas également actif + bool Pas_a_prendre_en_compte(const double& temps) const + {if ((temps <= t_min) || ((temps > t_max) && !precedent)) + return true; + else return false; + }; + // ramène vrai si le temps est inférieur ou égale au temps actif, ou supérieur au temps max + bool Pas_a_prendre_en_compte_dans_intervalle(const double& temps) const + {if ((temps <= t_min) || (temps > t_max)) + return true; + else return false; + }; + // Validation on non de l'activité de la charge + void Validation(const double& temps) {precedent = Temps_actif(temps); + valeur_precedente_t = beta;}; + // retour du statut de validation + // vrai signifie que l'état enregistré est actif + bool Etat_validation() const {return precedent;}; + + // initialisation des grandeurs de travail + void Initialisation_condil(); + + protected : + // informations: pour l'instant on considère une conditions linéaires entre les ddl d'une même + // famille d'un noeud. + + // données + string* nom_maillage; // nom de maillage associé, éventuellement! + string refe; // reference principale attachee aux ddl + Tableau refs_associe; + // dans le cas où il y a une condition linéaire entre plusieurs + // noeuds, la méthode retenue est la suivante: à chaque noeud de refe on associe un noeuds + // de chaque référence du tableau refs_associe, et on prend les ddl de type enu de chaque ref + // et on a une combinaison linéaire entre chacun. Dans ce cas, il faut donc que toutes les + // référence aient le même nombre de noeuds + Tableau nom_mail_associe; // dans le cas où nom_maillage est non null + // il faut que toutes les références associées aient un nom de maillage associé + double t_min,t_max; // temps mini et maxi de durée des ddl imposés + double echelle; // échelle globale éventuelle + Enum_ddl enu; // identificateur du premier ddl de la famille pour laquelle on a une condition linéaire + // les ddl s'appliques d'abord à suivre à chaque noeud + int nbddlfamille; // nombre de ddl de la famille associée à enu + int condition_relative; // indique si oui ou non la condition à t+dt s'effectue + // par rapport à t ou par rapport à 0 + int precedent; // pour la description de l'évolution d'un temps à l'autre + double valeur_precedente_t; // valeur à t + + Tableau tab_co_charge; // même dimension que (le nombre de ddl de type enu) * (1+le nombre + // de ref associé) s'il y a des courbes de charge + // Permet d'avoir des coefficients qui varient. S'il y a une courbe de charge + // alors toutes existent sinon aucune + Vecteur fctch,delta_fctch; // vecteur de travail qui contient les valeurs des fonctions de charge + // et leur acroissment entre t et t+deltat + + //--- variables particulières pour la définition automatique d'une condition linéaire sur plan ou droite + bool def_auto_par_rotation;// signale le cas particulier du condition linéaire automatique + int type_centre; // = 1 on a un centre fixe c-a-d: centre_rotation, =2 le centre est centre_noeud à t=0 + // =3 le centre est centre_noeud à t + Coordonnee centre_rotation; // position du centre de rotation fixe + String_et_entier mailEtNumCentreNoeud; // maillage et numéro du centre noeud s'il existe + Noeud* centre_noeud; + Plan pl; + Droite dr; + + //--- variables particulières pour la condition particulière d'égalité exacte, pour tous les ddl + // du type enu, -> traitement particulier + bool stricte_egalite; + + // 1) cas simple: pas de ref associe cela signifie que la condition linéaire concerne uniquement + // des ddl de chaque noeud de la ref principal. Pour chaque noeud on applique la même condition (au + // mvt solide près). La taille de val + // 1) cas où l'on a des références secondaire, celle-ci doivent avoir tous le même nombre de noeud, + // identique à la ref principal. Supposons qu'il y a na liste associé. La condition linéaire relie + // les ddl de na+1 noeud, chacun étant pris dans une ref associé + 1 sur la ref principal. Pour chaque + // noeud la liste des enu_ddl du même type que enu est parcouru: soit t_enu leur nombre. Donc au final, + // la taille de val (qui contient les coeff de la condition linéaire = (na+1)*t_enu + }; + /// @} // end of group + + +#endif diff --git a/Maillage/LesCondLim.cc b/Maillage/LesCondLim.cc new file mode 100644 index 0000000..1674df4 --- /dev/null +++ b/Maillage/LesCondLim.cc @@ -0,0 +1,2986 @@ + + // 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 "LesCondLim.h" +#include "CharUtil.h" +#include "SfeMembT.h" +#include "TypeQuelconqueParticulier.h" + + +// --- conteneur pour les réactions ----- + // surcharge de l'operator de lecture typée +istream & operator >> (istream & ent , LesCondLim::ReactStoc & a) + { // lecture du type et vérification + string nom_type; + ent >> nom_type; + if (nom_type != "ReactStoc") + Sortie(1); + // lecture des infos + ent >> a.numMail >> a.numNoeud >> a.ddl >> a.casAss; + return ent; + }; + // surcharge de l'operator d'ecriture typée +ostream & operator << (ostream & sort , const LesCondLim::ReactStoc & a) + { // écriture du type + sort << "ReactStoc "; + // les données + sort << a.numMail << " " << a.numNoeud << " " << a.ddl <<" "<< a.casAss; + return sort; + }; + + // surcharge de l'operator de lecture typée +istream & operator >> (istream & ent , LesCondLim::TorseurReac & a) + { // lecture du type et vérification + string nom_type; + ent >> nom_type; + if (nom_type != "TorseurReac") + Sortie(1); + // lecture des infos + ent >> a.existe_torseur_reac >> a.resultante >> a.moment ; + return ent; + }; + // surcharge de l'operator d'ecriture typée +ostream & operator << (ostream & sort , const LesCondLim::TorseurReac & a) + { // écriture du type + sort << " TorseurReac "; + // les données + sort << a.existe_torseur_reac << " " << a.resultante << " " << a.moment <<" "; + return sort; + }; + +// --- fin conteneur pour les réactions ----- + +// CONSTRUCTEURS : +LesCondLim::LesCondLim () : // par defaut + tabBloq(),tabInit(),condlim() + ,reaction(),reaction_CLin(),reactionApresCHrepere() + ,tab_torseurReac(),ttRG(),ttorBloq() + ,tab_iocondiline(),tab_CLinApplique(),ttRGCLL(),ttorCLL() + ,ttRG_noms_ref(),ttRGCLL_noms_ref() +// ,map_reaction() + ,nb_maillage(0) + ,tempsCL(),tempsCLL() + { }; + + // DESTRUCTEUR : +LesCondLim::~LesCondLim () + { }; + + // METHODES PUBLIQUES : + // lecture des conditions limites : ddl bloque +void LesCondLim::Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef) + { MotCle motCle; // ref aux mots cle + // on se positionne sur un mot cle + while ( !motCle.SimotCle(entreePrinc.tablcar)) + entreePrinc.NouvelleDonnee(); + bool sortie_info = false; + if ( (strstr(entreePrinc.tablcar,"blocages")!=NULL) ) // à rajouter tous les cas de lectures éventuelles + {if (ParaGlob::NiveauImpression() >= 4) + cout << " debut de la lecture des conditions limites ddl bloque " << endl; + sortie_info = true; + }; + + // def d'une instance de classe de lecture de Ddl + LectBloc lecDdl; + + // lecture eventuelle des blocages en condition limite + lecDdl.Lecture(entreePrinc,lesRef,"blocages", + "lecture des blocages de ddl en condition limite",tabBloq); + // dimensionnement du tableau des torseurs résultants + LesCondLim::DimensionneTorseurs(); + + + if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info) + cout << " fin de la lecture des conditions limites ddl bloque " << endl; + }; + + // lecture des conditions limites linéaire +void LesCondLim::Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef) + { MotCle motCle; // ref aux mots cle + // on se positionne sur un mot cle + while ( !motCle.SimotCle(entreePrinc.tablcar)) + entreePrinc.NouvelleDonnee(); + bool sortie_info = false; + if ( (strstr(entreePrinc.tablcar,"condition_limite_lineaire_")!=NULL) ) // à rajouter tous les cas de lectures éventuelles + {if (ParaGlob::NiveauImpression() >= 4) + cout << " debut de la lecture des conditions limites lineaires " << endl; + sortie_info = true; + }; + + // def d'une instance de classe de lecture de Ddl + LectBloc lecI_O_Condli; + + // lecture eventuelle des conditions linéaire en condition limite + lecI_O_Condli.Lecture(entreePrinc,lesRef,"condition_limite_lineaire_", + "lecture des conditions limites lineaires ",tab_iocondiline); + // mise à jour de la dimension du tableau associé: tab_CLinApplique + tab_CLinApplique.Change_taille(tab_iocondiline.Taille()); + + // dimensionnement du tableau des torseurs résultants + LesCondLim::DimensionneTorseurs(); + + if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info) + cout << " fin de la lecture des conditions limites lineaire " << endl; + }; + +// lecture des conditions limites : initialisation +void LesCondLim::Lecture3(UtilLecture & entreePrinc,LesReferences& lesRef) + { MotCle motCle; // ref aux mots cle + // on se positionne sur un mot cle + while ( !motCle.SimotCle(entreePrinc.tablcar)) + entreePrinc.NouvelleDonnee(); + + bool sortie_info = false; + if ( (strstr(entreePrinc.tablcar,"initialisation")!=NULL) ) // à rajouter tous les cas de lectures éventuelles + {if (ParaGlob::NiveauImpression() >= 4) + cout << " debut de la lecture des conditions d'initialisation " << endl; + sortie_info = true; + }; + // def d'une instance de classe de lecture de Ddl + LectBloc lecDdl; + + // lecture eventuelle des conditions limites d'initialisation + lecDdl.Lecture(entreePrinc,lesRef,"initialisation", + "lecture des conditions limites d\'initialisation",tabInit); + if ((ParaGlob::NiveauImpression() >= 4) && sortie_info) + cout << " fin de la lecture des conditions d'initialisation " << endl; + +//debug +//Affiche(); +//fin debug + + }; + + // affichage des informations concernant les conditions limites +void LesCondLim::Affiche() const // affichage de tous les infos + { Affiche1(); + Affiche2(); + Affiche3(); + }; + +void LesCondLim::Affiche1() const + { if (tabBloq.Taille() != 0) + {cout << "\n ******** conditions limites : ddl bloque ******** \n"; + cout << tabBloq.Taille() << " reference de conditions limites lue \n"; + int tabBloqTaille = tabBloq.Taille(); + for (int i=1; i<=tabBloqTaille; i++) + tabBloq(i).Affiche(); + cout << "\n\n"; + } + }; +void LesCondLim::Affiche2() const + { + if (tabInit.Taille() != 0) + {cout << "\n ******** conditions limites : lineaire ******** \n"; + cout << tab_iocondiline.Taille() << " reference de conditions limites lue \n"; + int tabInitTaille = tabInit.Taille(); + for (int i=1; i<=tabInitTaille; i++) + tabInit(i).Affiche(); + cout << "\n\n"; + } + }; +void LesCondLim::Affiche3() const + { + if (tabInit.Taille() != 0) + {cout << "\n ******** conditions limites : initialisation ******** \n"; + cout << tabInit.Taille() << " reference de conditions limites lue \n"; + int tabInitTaille = tabInit.Taille(); + for (int i=1; i<=tabInitTaille; i++) + tabInit(i).Affiche(); + cout << "\n\n"; + } + }; + +// introduction des données et variables pour leurs emplois futures, avec init par défaut +void LesCondLim::IntroductionDonnees(LesMaillages * lesMail,LesReferences* lesRef + ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD) + { + tempsCL.Mise_en_route_du_comptage(); // temps cpu + // 1) on parcours le tableau de ddl d'initialisation + int tabInitTaille = tabInit.Taille(); + for (int i=1;i<= tabInitTaille;i++) + { DdlLim& tabInit_i = tabInit(i); + // recup de la reference correspondant au mot cle + const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage()); + if ((refinitial.Indic() == 4) && + (tabInit_i.TypeDeCL()==TANGENTE_CL)) + {// cas des références d'arêtes, avec des conditions initiales de tangente imposée + // ici on vérifie que les données d'entrées sont cohérentes, c'est tout + const ReferenceAF & ref = ((ReferenceAF &) refinitial); + // on renseigne les éléments ad hoc + int refTaille = ref.Taille(); + for (int ne =1; ne<= refTaille;ne++) + {int tabInitiTaille = tabInit_i.Taille(); + // dans le cas d'une référence de champ on vérifie le nombre de ddlLim + if ((tabInit_i.Champ()) && (tabInitiTaille != ref.Taille())) + {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" + << " que le nombre d'element de la reference associee !! " + << "\n void LesCondLim::IntroductionDonnees(... "; + cout << " condition limite : "; tabInit_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer + // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabInitiTaille;// début normale + if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;}; + for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 + // affectation de la valeur d'initialisation + { Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl + Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl + Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl + + // on vérifie qu'il s'agit bien de 3 coordonnées + if (ddl1.Id_nom()!=X1) + {cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 " + << "\n void LesCondLim::IntroductionDonnees(... "; + cout << " condition limite : "; tabInit_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + if (ddl2.Id_nom()!=X2) + {cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 " + << "\n void LesCondLim::IntroductionDonnees(... "; + cout << " condition limite : "; tabInit_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + if (ddl3.Id_nom()!=X3) + {cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 " + << "\n void LesCondLim::IntroductionDonnees(... "; + cout << " condition limite : "; tabInit_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + // on vérifie que le numéro de l'arête existe bien + int num_elem = ref.NumeroElem(ne); + int num_ar = ref.NumeroFA(ne); + // récup de l'élément + Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem); + if (!(el.AreteExiste(num_ar))) + {cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar + << " pour l'element " << num_elem << " n'existe pas !! " + << "\n void LesCondLim::IntroductionDonnees(... "; + cout << " condition limite : "; tabInit_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + // on vérifie que c'est un élément sfe + if (!(ElementSfe(el.Id_interpolation()))) + {cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre " + << " de type SFE : et non l'element= "; el.Affiche(1); + cout << "\n void LesCondLim::IntroductionDonnees(... "; + cout << " condition limite : "; tabInit_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + }// fin boucle sur tabInit_i + }// fin boucle sur les éléments de la référence + } // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE + + else if (refinitial.Indic() != 1) + // cas d'element + { cout << "\n introduction autre que des noeuds, pas d\'action implentee a ce sujet !!"; + cout << "void LesCondLim::IntroductionDonnees(... " << endl; + tempsCL.Arret_du_comptage(); + Sortie(1); + } + else + // cas de noeuds + {// traitement proprement dit + const ReferenceNE & ref = ((ReferenceNE &) refinitial); + int refTaille = ref.Taille(); + for (int nn =1; nn<= refTaille;nn++) + {int tabInitiTaille = tabInit_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabInitiTaille;// début normale + if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // affectation de la valeur d'initialisation + { Ddl ddl = tabInit_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // ---modif 10 sep 2017 + // cas ou le ddl n'existe pas + // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre + // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose + // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas + // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour + // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être + // utilisé à t et tdt, donc il ne faut pas le mettre en HS + // par contre on le met en lisible c-a-d en donnée par défaut + + ddl.ChangeVariable_a_Donnee(); + if (!(noe.Existe_ici(ddl.Id_nom()))) + // cas ou le ddl n'existe pas + // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien + // { if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) + { if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) + { // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis + // initialisation a zero et on indique qu'il est hors service (non !! voir la modif 10 sept 2017) + noe.PlusDdl(ddl); + noe.Change_val_0(ddl.Id_nom(),0.); + noe.Change_val_t(ddl.Id_nom(),0.); +// ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service +// ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom()); + noe.Met_en_service(ddl.Id_nom()); + + noe.Change_fixe(ddl.Id_nom(),true); + } + } // fin du if (!(noe.Existe_ici(ddl.Id_nom()))) + } // fin de la boucle sur les ddl + } // fin de la boucle sur les noeuds de la référence + } // fin du traitement pour les noeuds + } // fin de la boucle sur le tableau générale d'initialisation + + // 2) cas des ddl imposes on verifie leurs existences et on crée si besoin + // on parcours le tableau de ddl bloques + // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt + int tabBloqTaille = tabBloq.Taille(); + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); + if ((refinitial.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) + {// cas des références d'arêtes, avec des conditions de tangente imposée + // on s'occupe de vérifier la cohérence de l'entrée des données, c'est tout + const ReferenceAF & ref = ((ReferenceAF &) refinitial); + // on renseigne les éléments ad hoc + int refTaille = ref.Taille(); + for (int ne =1; ne<= refTaille;ne++) + {int tabBloqiTaille = tabBloq_i.Taille(); + // dans le cas d'une référence de champ on vérifie le nombre de ddlLim + if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) + {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" + << " que le nombre d'element de la reference associee !! " + << "\n void LesCondLim::IntroductionDonnees(... "; + cout << " condition limite : "; tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + } + // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer + // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqiTaille;// début normale + if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;}; + for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 + // affectation de la valeur d'initialisation + { Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl + Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl + Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl + + // on vérifie qu'il s'agit bien de 3 coordonnées + if (ddl1.Id_nom()!=X1) + {cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 " + << "\n void LesCondLim::InitialDonnees(... "; + cout << " condition limite : "; tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + if (ddl2.Id_nom()!=X2) + {cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 " + << "\n void LesCondLim::InitialDonnees(... "; + cout << " condition limite : "; tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + if (ddl3.Id_nom()!=X3) + {cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 " + << "\n void LesCondLim::InitialDonnees(... "; + cout << " condition limite : "; tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + // on vérifie que le numéro de l'arête existe bien + int num_elem = ref.NumeroElem(ne); + int num_ar = ref.NumeroFA(ne); + // récup de l'élément + Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem); + if (!(el.AreteExiste(num_ar))) + {cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar + << " pour l'element " << num_elem << " n'existe pas !! " + << "\n void LesCondLim::InitialDonnees(... "; + cout << " condition limite : "; tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + // on vérifie que c'est un élément sfe + if (!(ElementSfe(el.Id_interpolation()))) + {cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre " + << " de type SFE : et non l'element= "; el.Affiche(1); + cout << "\n void LesCondLim::InitialDonnees(... "; + cout << " condition limite : "; tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + }// fin boucle sur tabBloq_i + }// fin boucle sur les noeuds de la référence + } // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE + + else if (refinitial.Indic() != 1) // cas d'une autre référence que des noeuds + // cas d'element + { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!"; + cout << "\n void LesCondLim::InitialDonnees(... " << endl; + tempsCL.Arret_du_comptage(); + Sortie (1); + } + else + // cas de noeuds + {const ReferenceNE & ref = ((ReferenceNE &) refinitial); + int refTaille = ref.Taille(); + for (int nn =1; nn<= refTaille;nn++) + {int tabBloqiTaille = tabBloq_i.Taille(); + // dans le cas d'une référence de champ on vérifie le nombre de ddlLim + if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) + {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" + << " que le nombre de noeud de la reference associee !! " + << "\n void LesCondLim::InitialDonnees(... "; + cout << " condition limite : "; tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + } + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqiTaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // affectation de la valeur d'initialisation + { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl + // récup du noeud + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // on regarde si les temps dépendent d'une fct nD + // si oui on modifie les bornes du ddl + if (tabBloq_i.Temps_depend_nD()) + LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); + + // on regarde si le temps est actif ou pas + if ((tabBloq_i.Temps_actif(0.))) {tabBloq_i.ElemLim(nd).Met_en_service();} + else { tabBloq_i.ElemLim(nd).Met_hors_service();}; + // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé + // on regarde du coté du noeuds + if (!noe.Existe_ici(ddl.Id_nom())) + // cas ou il faut creer un ddl sup + // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien + // {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) + { if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) + {// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis + // initialisation a zero et on indique qu'il est hors service + // ---modif 10 sep 2017 + // cas ou le ddl n'existe pas + // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre + // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose + // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas + // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour + // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être + // utilisé à t et tdt, donc il ne faut pas le mettre en HS + // par contre on le met en lisible c-a-d en donnée par défaut + + ddl.ChangeVariable_a_Donnee(); + noe.PlusDdl(ddl); + noe.Change_val_0(ddl.Id_nom(),0.); + noe.Change_val_t(ddl.Id_nom(),0.); +// ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service +// ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom()); + noe.Met_en_service(ddl.Id_nom()); + + noe.Change_fixe(ddl.Id_nom(),true); + }; + }; + // pour le reste on ne fait rien, se sera géré par les mises à jour + // en fonction de l'évolution du temps + } // fin boucle sur tabBloq_i + } // fin boucle sur les noeuds de la référence + } // fin du cas des noeuds + } // fin bouble sur tabBloq + // définition du nombre de maillage en cours dans le calcul + nb_maillage=lesMail->NbMaillage(); + tempsCL.Arret_du_comptage(); // temps cpu + }; + + +// initialisation des ddl avec le tableau de ddl d'init +// verif de l'existence de tous les ddl (initialisation et imposes) +// ajout si necessaire +// choix =false : indique qu'il faut initialiser que les ddl t +// choix = true : indique qu'il faut initialiser les ddl a t et t+dt +// vérification de l'existence des courbes de charge adoc si nécessaire +// idem pour les fonctions nD de charge adoc si nécessaire +// cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque +// le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont +// leur statut modifié de manière équivalente +// =0 pas d'association +// =1 association X V GAMMA +void LesCondLim::Initial(LesMaillages * lesMail,LesReferences* lesRef + ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD + ,bool choixtdt,int cas) + { + tempsCL.Mise_en_route_du_comptage(); // temps cpu + // 1) on parcours le tableau de ddl d'initialisation + int tabInitTaille = tabInit.Taille(); + for (int i=1;i<= tabInitTaille;i++) + { DdlLim& tabInit_i = tabInit(i); + // recup de la reference correspondant au mot cle + const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage()); + if ((refinitial.Indic() == 4) && + (tabInit_i.TypeDeCL()==TANGENTE_CL) ) + {// cas des références d'arêtes, avec des conditions de tangente imposée + const ReferenceAF & ref = ((ReferenceAF &) refinitial); + // on renseigne les éléments ad hoc + int refTaille = ref.Taille(); + for (int ne =1; ne<= refTaille;ne++) + {int tabInitiTaille = tabInit_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer + // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabInitiTaille;// début normale + if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;}; + for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 + // affectation de la valeur d'initialisation + { Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl + Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl + Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl + // récup de l'élément + Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); + SfeMembT & elsfe = (SfeMembT&) el; + // on renseigne l'élément + Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); + elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); + + }// fin boucle sur tabInit_i + }// fin boucle sur les éléments de la référence + } // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE + + else if (refinitial.Indic() != 1) + // cas d'element + { cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!"; + cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; + tempsCL.Arret_du_comptage(); + Sortie(1); + } + else + // cas de noeuds + {// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon + // la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout + // cas peut de fois, + const ReferenceNE & ref = ((ReferenceNE &) refinitial); + // traitement proprement dit + int refTaille = ref.Taille(); + for (int nn =1; nn<= refTaille;nn++) + {int tabInitiTaille = tabInit(i).Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabInitiTaille;// début normale + if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // affectation de la valeur d'initialisation + { Ddl ddl = tabInit_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // on vérifie que le ddl est compatible avec la dimension sinon message d'erreur + if (!CompatDim(ddl.Id_nom())) + {cout << "\n *** erreur, le ddl d'initialisation : " << ddl.Nom() + << " pour la reference " << ref.Nom() + << " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension() + << ") de l'espace de travail " ; + if (ParaGlob::NiveauImpression()>6) + cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ; + cout << endl; + tempsCL.Arret_du_comptage(); + Sortie (1); + }; + + if (noe.Existe_ici(ddl.Id_nom())) + // cas ou le ddl existe deja + { noe.Change_val_t(ddl.Id_nom(),ddl.Valeur()); + if (choixtdt) + noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur()); + // mise a jour des ddl aux temps 0 pour tous les ddl sauf ceux de position + // car ces derniers sont les seuls dont la position initiale est déterminées à la lecture + // du maillage + if (!(Meme_famille(ddl.Id_nom(),X1))) + noe.Change_val_0(ddl.Id_nom(),ddl.Valeur()); + // on regarde s'il fait partie de la combinaison + // si oui on met en place les ddl correspondant à HSLIBRE + Enum_ddl en = ddl.Id_nom(); + Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); + } + else + // cas ou le ddl n'existe pas + { // tout d'abord on regarde si c'est un déplacement + // if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + {if(!CompatDim(ddl.Nom())) // vérif de dimension + { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" + << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; + cout << " \n cas des ddl bloquees "; + cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; + tempsCL.Arret_du_comptage(); + Sortie (1); + }; + // cas ok on impose le déplacement sur le Xi correspondant + Enum_ddl en = ddl.Id_nom(); + //on cherche l'equivalent Ui en Xi + en = UxyzXi(en); + noe.Ajout_val_t(en,ddl.Valeur()); + // mise a jour des ddl aux autres temps + // noe.Ajout_val_0(en,ddl.Valeur()); + if (choixtdt) + noe.Ajout_val_tdt(en,ddl.Valeur()); + // puis on regarde si le ddl initial fait partie de la combinaison + // si oui on met en place les ddl correspondant à HSLIBRE + Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); + } + else + { // cas ou il faut creer un ddl sup + //noe.PlusDdl(ddl); + cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues" + << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; + cout << "\n cas des ddl d'initialisation "; + cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl; + tempsCL.Arret_du_comptage(); + Sortie (1); + }; + }; + }; + }; + }; + }; + // 2) cas des ddl imposes on verifie leurs existences + // on vérifie également l'existence des courbes de charge adoc si nécessaire + // idem pour les fonctions nD de charge adoc si nécessaire + // on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple + // vitesse et position ou accélération pour un même ddl + // on parcours le tableau de ddl bloques + // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt + int tabBloqTaille = tabBloq.Taille(); + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); + if ((refinitial.Indic() == 4) && + (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) + {// cas des références d'arêtes, avec des conditions de tangente imposée + // ici on s'occupe de renseigner les éléments + const ReferenceAF & ref = ((ReferenceAF &) refinitial); + // on renseigne les éléments ad hoc + int refTaille = ref.Taille(); + for (int ne =1; ne<= refTaille;ne++) + {int tabBloqiTaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer + // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqiTaille;// début normale + if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;}; + for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 + // affectation de la valeur d'initialisation + { Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl + Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl + Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl + // récup de l'élément + Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); + SfeMembT & elsfe = (SfeMembT&) el; + // on regarde si les temps dépendent d'une fct nD + // si oui on modifie les bornes du ddl + if (tabBloq_i.Temps_depend_nD()) + LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD); + // on continue que si le temps est actif ou pas + if ((tabBloq_i.Temps_actif(0.))) + { // on renseigne l'élément + Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); + elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); + }; + };// fin boucle sur tabBloq_i + };// fin boucle sur les noeuds de la référence + } // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE + + else if (refinitial.Indic() != 1) + // cas autre d'element par exemple + { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!"; + cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; + tempsCL.Arret_du_comptage(); + Sortie (1); + } + else + // cas de noeuds + {const ReferenceNE & ref = ((ReferenceNE &) refinitial); + int refTaille = ref.Taille(); + for (int nn =1; nn<= refTaille;nn++) + {int tabBloqiTaille = tabBloq_i.Taille(); + /* // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim + if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) + {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" + << " que le nombre de noeud de la reference associee !! "; + cout << " condition limite : "; tabBloq_i.Affiche(); + Sortie(1); + }*/ + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqiTaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // affectation de la valeur d'initialisation + { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl + // on vérifie que le ddl est compatible avec la dimension sinon message d'erreur + if (!CompatDim(ddl.Id_nom())) + {cout << "\n *** erreur, le ddl de blocage : " << ddl.Nom() + << " pour la reference " << ref.Nom() + << " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension() + << ") de l'espace de travail " ; + if (ParaGlob::NiveauImpression()>6) + cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ; + cout << endl; + tempsCL.Arret_du_comptage(); + Sortie (1); + }; + // récup du noeud + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // on regarde si les temps dépendent d'une fct nD + // si oui on modifie les bornes du ddl + if (tabBloq_i.Temps_depend_nD()) + LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); + + // on regarde si le temps est actif ou pas + if ((tabBloq_i.Temps_actif(0.))) + { // on n'intervient que si le temps initial est actif + tabBloq_i.ElemLim(nd).Met_en_service(); + // récup du noeud + string nom_courbe = tabBloq_i.Nom_courbe(nd); + Courbe1D * pt_courbe = NULL; + if (nom_courbe != "") + // cas de l'existence d'une courbe de charge + // appel pour récupérer la courbe (juste pour la vérif + // car on ne s'en sert pas aprés !) + { pt_courbe = lesCourbes1D->Trouve(nom_courbe); + }; + // idem pour les fonctions nD + string nom_fctnD = tabBloq_i.NomF_charge(nd); + Fonction_nD * pt_fctnD = NULL; + if (nom_fctnD != "") + // cas de l'existence d'une fonction de charge + // appel pour récupérer la fct (juste pour la vérif + // car on ne s'en sert pas aprés !) + { pt_fctnD = lesFonctionsnD->Trouve(nom_fctnD); + }; + // maintenant on regarde du coté des noeuds + if (!noe.Existe_ici(ddl.Id_nom())) + // cas ou il faut creer un ddl sup + // on regarde le cas eventuel des coordonnees entrainees + // si on est en entraine et que le ddl a imposer est un Ui + // alors on ne verifie que les dimensions et on indique le blocage + // {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) + {if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + { // cas d'un ddl de déplacement, et que le ddl X1 existe déjà + if(!CompatDim(ddl.Nom())) + { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" + << " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ; + cout << " \n cas des ddl bloquees "; + cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; + tempsCL.Arret_du_comptage(); + Sortie (1); + } + else // cas ou c'est Xi le ddl bloque, on indique le blocage + { Enum_ddl en = ddl.Id_nom(); + //on cherche l'equivalent Ui en Xi + en = UxyzXi(en); + noe.Change_fixe(en,true); + // on regarde s'il fait partie de la combinaison et on fixe les blocages + Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); + } + } + else + // cas d'un ddl inexistant diff de U, création puis initialisation a zero + { noe.PlusDdl(ddl); + noe.Change_val_0(ddl.Id_nom(),0.); + noe.Change_val_t(ddl.Id_nom(),0.); + if (choixtdt) + noe.Change_val_tdt(ddl.Id_nom(),0.); + // puis on indique que le ddl est bloque + noe.Change_fixe(ddl.Id_nom(),true); + // on regarde s'il fait partie de la combinaison et on fixe les blocages + Enum_ddl en = ddl.Id_nom(); + Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); + } + } + else // cas ou le ddl existe + // on indique que le ddl est bloque, mais on ne change pas sa valeur + // ce sera fait au moment de la mise à jour à tdt + { // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1) + // dans ce cas il est libre, on peut le bloquer sans pb, + // soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement + noe.Change_fixe(ddl.Id_nom(),true); + // on regarde s'il fait partie de la combinaison et on fixe les blocages + Enum_ddl en = ddl.Id_nom(); + Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); + }; + } + else + {// si le ddl bloqué n'est pas actif pour le temps 0. + tabBloq_i.ElemLim(nd).Met_hors_service(); + // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé + // récup du noeud + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // on regarde du coté du noeuds + if (!noe.Existe_ici(ddl.Id_nom())) + // cas ou il faut creer un ddl sup + // on regarde le cas eventuel des coordonnees entrainees + // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien + // {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) + {if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) + { // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis + // initialisation a zero et on indique qu'il est hors service (non cf modif qui suit) + // ---modif 10 sep 2017 + // cas ou le ddl n'existe pas + // on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre + // c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose + // on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas + // mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour + // or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être + // utilisé à t et tdt, donc il ne faut pas le mettre en HS + // par contre on le met en lisible c-a-d en donnée par défaut + Ddl ddl_inter(ddl); // pour pas que cela influe sur les autres noeuds + + ddl_inter.ChangeVariable_a_Donnee(); + noe.PlusDdl(ddl_inter); + noe.Change_val_0(ddl_inter.Id_nom(),0.); + noe.Change_val_t(ddl_inter.Id_nom(),0.); + if (choixtdt) noe.Change_val_tdt(ddl_inter.Id_nom(),0.); +// ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service +// ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom()); + noe.Met_en_service(ddl.Id_nom()); + + noe.Change_fixe(ddl.Id_nom(),true); + }; + }; + // pour le reste on ne fait rien, se sera géré par les mises à jour + // en fonction de l'évolution du temps + }; // fin du cas ddl bloqué et pas actif pour le temps 0. + }; + }; + }; + }; + // on initialise la situation de blocage et condition linéaires + Validation_blocage (lesRef,0.); + // vérif qu'il n'y a pas de surcharge de blocage + Verif_surcharge_blocage(lesMail,lesRef,0.,cas); + // pour le tps cpu, il y a une petite part de CLL, mais on la néglige + tempsCL.Arret_du_comptage(); // temps cpu + }; + + +//// mise à jour de l'initialisation, par exemple après un restart +//// même paramètres que Initial, par contre ici il n'y a aucune création +//void LesCondLim::Re_initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D +// ,bool choixtdt,int cas) +// { // 1) on parcours le tableau de ddl d'initialisation +// int tabInitTaille = tabInit.Taille(); +// for (int i=1;i<= tabInitTaille;i++) +// { DdlLim& tabInit_i = tabInit(i); +// // recup de la reference correspondant au mot cle +// const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage()); +// if ((refinitial.Indic() == 4) && +// (tabInit_i.TypeDeCL()==TANGENTE_CL) ) +// {// cas des références d'arêtes, avec des conditions de tangente imposée +// const ReferenceAF & ref = ((ReferenceAF &) refinitial); +// // on renseigne les éléments ad hoc +// int refTaille = ref.Taille(); +// for (int ne =1; ne<= refTaille;ne++) +// {int tabInitiTaille = tabInit_i.Taille(); +// // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer +// // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage +// int idebut=1; int ifinfin = tabInitiTaille;// début normale +// if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;}; +// for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 +// // affectation de la valeur d'initialisation +// { Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl +// Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl +// Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl +// // récup de l'élément +// Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); +// SfeMembT & elsfe = (SfeMembT&) el; +// // on renseigne l'élément +// Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); +// elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); +// +// }// fin boucle sur tabInit_i +// }// fin boucle sur les éléments de la référence +// } // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE +// +// else if (refinitial.Indic() != 1) +// // cas d'element +// { cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!"; +// cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; +// Sortie(1); +// } +// else +// // cas de noeuds +// {// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon +// // la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout +// // cas peut de fois, +// const ReferenceNE & ref = ((ReferenceNE &) refinitial); +// // traitement proprement dit +// int refTaille = ref.Taille(); +// for (int nn =1; nn<= refTaille;nn++) +// {int tabInitiTaille = tabInit(i).Taille(); +// // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer +// // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage +// int idebut=1; int ifinfin = tabInitiTaille;// début normale +// if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;}; +// for (int nd=idebut;nd<= ifinfin ;nd++) +// // affectation de la valeur d'initialisation +// { Ddl ddl = tabInit_i.ElemLim(nd); +// Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); +// if (noe.Existe_ici(ddl.Id_nom())) +// // cas ou le ddl existe deja +// { noe.Change_val_t(ddl.Id_nom(),ddl.Valeur()); +// if (choixtdt) +// noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur()); +// // mise a jour des ddl aux temps 0 pour tous les ddl sauf ceux de position +// // car ces derniers sont les seuls dont la position initiale est déterminées à la lecture +// // du maillage +// if (!(Meme_famille(ddl.Id_nom(),X1))) +// noe.Change_val_0(ddl.Id_nom(),ddl.Valeur()); +// // on regarde s'il fait partie de la combinaison +// // si oui on met en place les ddl correspondant à HSLIBRE +// Enum_ddl en = ddl.Id_nom(); +// Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); +// } +// else +// // cas ou le ddl n'existe pas +// { // tout d'abord on regarde si c'est un déplacement +// // if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) +// if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) +// { if(!CompatDim(ddl.Nom())) // vérif de dimension +// { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" +// << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; +// cout << " \n cas des ddl bloquees "; +// cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; +// Sortie (1); +// } +// // cas ok on impose le déplacement sur le Xi correspondant +// Enum_ddl en = ddl.Id_nom(); +// //on cherche l'equivalent Ui en Xi +// en = UxyzXi(en); +// noe.Ajout_val_t(en,ddl.Valeur()); +// // mise a jour des ddl aux autres temps +// // noe.Ajout_val_0(en,ddl.Valeur()); +// if (choixtdt) +// noe.Ajout_val_tdt(en,ddl.Valeur()); +// // puis on regarde si le ddl initial fait partie de la combinaison +// // si oui on met en place les ddl correspondant à HSLIBRE +// Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt); +// } +// else +// { // cas ou il faut creer un ddl sup +// //noe.PlusDdl(ddl); +// cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues" +// << " par les elements donc inutiles !! ddl = " << ddl.Nom() ; +// cout << "\n cas des ddl d'initialisation "; +// cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl; +// Sortie (1); +// } +// } +// } +// } +// } +// } +// // 2) cas des ddl imposes on verifie leurs existences +// // on vérifie également l'existence des courbes de charge adoc si nécessaire +// // on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple +// // vitesse et position ou accélération pour un même ddl +// // on parcours le tableau de ddl bloques +// // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt +// int tabBloqTaille = tabBloq.Taille(); +// for (int i=1;i<= tabBloqTaille;i++) +// { DdlLim& tabBloq_i = tabBloq(i); +// // recup de la reference correspondant au mot cle +// const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); +// if ((refinitial.Indic() == 4) && +// (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) +// {// cas des références d'arêtes, avec des conditions de tangente imposée +// // ici on s'occupe de renseigner les éléments +// const ReferenceAF & ref = ((ReferenceAF &) refinitial); +// // on renseigne les éléments ad hoc +// int refTaille = ref.Taille(); +// for (int ne =1; ne<= refTaille;ne++) +// {int tabBloqiTaille = tabBloq_i.Taille(); +// // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer +// // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage +// int idebut=1; int ifinfin = tabBloqiTaille;// début normale +// if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;}; +// for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3 +// // affectation de la valeur d'initialisation +// { Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl +// Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl +// Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl +// // récup de l'élément +// Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); +// SfeMembT & elsfe = (SfeMembT&) el; +// // on continue que si le temps est actif ou pas +// if ((tabBloq_i.Temps_actif(0.))) +// { // on renseigne l'élément +// Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur()); +// elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); +// }; +// }// fin boucle sur tabBloq_i +// }// fin boucle sur les noeuds de la référence +// } // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE +// +// else if (refinitial.Indic() != 1) +// // cas autre d'element par exemple +// { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!"; +// cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl; +// Sortie (1); +// } +// else +// // cas de noeuds +// {const ReferenceNE & ref = ((ReferenceNE &) refinitial); +// int refTaille = ref.Taille(); +// for (int nn =1; nn<= refTaille;nn++) +// {int tabBloqiTaille = tabBloq_i.Taille(); +// /* // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim +// if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille())) +// {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque" +// << " que le nombre de noeud de la reference associee !! "; +// cout << " condition limite : "; tabBloq_i.Affiche(); +// Sortie(1); +// }*/ +// // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer +// // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage +// int idebut=1; int ifinfin = tabBloqiTaille;// début normale +// if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; +// for (int nd=idebut;nd<= ifinfin ;nd++) +// // affectation de la valeur d'initialisation +// { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl +// // on regarde si le temps est actif ou pas +// if ((tabBloq_i.Temps_actif(0.))) +// { // on n'intervient que si le temps initial est actif +// tabBloq_i.ElemLim(nd).Met_en_service(); +// // récup du noeud +// Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); +// string nom_courbe = tabBloq_i.Nom_courbe(nd); +// Courbe1D * pt_courbe = NULL; +// if (nom_courbe != "") +// // cas de l'existence d'une courbe de charge +// // appel pour récupérer la courbe (juste pour la vérif +// // car on ne s'en sert pas aprés !) +// { pt_courbe = lesCourbes1D->Trouve(nom_courbe); +// } +// // maintenant on regarde du coté des noeuds +// if (!noe.Existe_ici(ddl.Id_nom())) +// // cas ou il faut creer un ddl sup +// // on regarde le cas eventuel des coordonnees entrainees +// // si on est en entraine et que le ddl a imposer est un Ui +// // alors on ne verifie que les dimensions et on indique le blocage +// // {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))) +// {if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) +// { // cas d'un ddl de déplacement, et que le ddl X1 existe déjà +// if(!CompatDim(ddl.Nom())) +// { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues" +// << " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ; +// cout << " \n cas des ddl bloquees "; +// cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; +// Sortie (1); +// } +// else // cas ou c'est Xi le ddl bloque, on indique le blocage +// { Enum_ddl en = ddl.Id_nom(); +// //on cherche l'equivalent Ui en Xi +// en = UxyzXi(en); +// noe.Change_fixe(en,true); +// // on regarde s'il fait partie de la combinaison et on fixe les blocages +// Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); +// } +// } +// else +// // cas d'un ddl inexistant diff de U, création puis initialisation a zero +// { noe.PlusDdl(ddl); +// noe.Change_val_0(ddl.Id_nom(),0.); +// noe.Change_val_t(ddl.Id_nom(),0.); +// if (choixtdt) +// noe.Change_val_tdt(ddl.Id_nom(),0.); +// // puis on indique que le ddl est bloque +// noe.Change_fixe(ddl.Id_nom(),true); +// // on regarde s'il fait partie de la combinaison et on fixe les blocages +// Enum_ddl en = ddl.Id_nom(); +// Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); +// } +// } +// else // cas ou le ddl existe +// // on indique que le ddl est bloque, mais on ne change pas sa valeur +// // ce sera fait au moment de la mise à jour à tdt +// { // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1) +// // dans ce cas il est libre, on peut le bloquer sans pb, +// // soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement +// noe.Change_fixe(ddl.Id_nom(),true); +// // on regarde s'il fait partie de la combinaison et on fixe les blocages +// Enum_ddl en = ddl.Id_nom(); +// Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt); +// } +// } +// else +// {// si le ddl bloqué n'est pas actif pour le temps 0. +// tabBloq_i.ElemLim(nd).Met_hors_service(); +// // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé +// // récup du noeud +// Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); +// // on regarde du coté du noeuds +// if (!noe.Existe_ici(ddl.Id_nom())) +// // cas ou il faut creer un ddl sup +// // on regarde le cas eventuel des coordonnees entrainees +// // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien +// // {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))) +// {if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)))) +// {// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis +// // initialisation a zero et on indique qu'il est hors service +// noe.PlusDdl(ddl); +// noe.Change_val_0(ddl.Id_nom(),0.); +// noe.Change_val_t(ddl.Id_nom(),0.); +// if (choixtdt) noe.Change_val_tdt(ddl.Id_nom(),0.); +// // puis on indique que le ddl est bloque et hors service +// noe.Met_hors_service(ddl.Id_nom()); +// noe.Change_fixe(ddl.Id_nom(),true); +// } +// } +// // pour le reste on ne fait rien, se sera géré par les mises à jour +// // en fonction de l'évolution du temps +// } // fin du cas ddl bloqué et pas actif pour le temps 0. +// } +// } +// } +// } +// // on initialise la situation de blocage et condition linéaires +// Validation_blocage (lesRef,0.); +// // vérif qu'il n'y a pas de surcharge de blocage +// Verif_surcharge_blocage(lesMail,lesRef,0.,cas); +// }; + + + // incrementation des coordonnees a t+dt et des ddl en fonctions des ddl imposes + // et du chargement + // coef: est un facteur multiplicatif des ddl sans courbes de charge, + // est supposé intégrer déjà le multiplicateur général + // en fait du chargement impose + // mult_gene : multiplicateur général de tous les chargements + // deltat : le pas de temps en cours + // temps : le temps courant où sont calculées les conditions + // ch_statut : indique s'il y a changement ou non de statut des conditions limites (pour les ddl aux noeuds) + // c-a-d un ddl qui passe de bloqué à non bloqué ou inversement: il s'agit uniquement des ddl aux noeuds + // c-a-d ceux qui ont une influence sur la mise en place des cl sur la raideur et le résidu + // cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque + // le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont + // leur statut modifié de manière équivalente + // =0 pas d'association + // =1 association X V GAMMA + // lorsque en_ddl est égal à NU_DDL, cela signifie que l'on met les conditions limites sur tous les + // ddl de noeud actifs + // lorsque en_ddl est différent de NU_DDL, il donne le type des seules ddl pour lesquels on met les + // conditions de blocage: par exemple X1 -> blocage sur X1,X2,X3 selon la dimension + + + void LesCondLim::MiseAJour_tdt + (const double& mult_gene,LesMaillages * lesMail,const double& deltat,const LesReferences* lesRef + ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD + ,const double& coef,bool& ch_statut + ,int cas,Enum_ddl en_ddl) +{ + tempsCL.Mise_en_route_du_comptage(); // temps cpu + // préparation + bool tous_les_blocages = true; + if (en_ddl != NU_DDL) tous_les_blocages = false; + // la mise en place des blocages s'effectue en deux temps, ceci pour préparer la vérification + // de la non sur imposition de ddl: ceci pour les ddl aux noeuds + // 1- au premier passage : on met en libre les ddl qui sont relachés, on met tous les ddl actifs + // en libre + // 2- au second passage : les ddl au temps actifs sont fixés (et éventuellement surfixé si pb) + // + // pour les ddl d'encastrement ou de symétrie pour les sfe, tout ce fait au premier passage uniquement + // ---- premier passage ---- + int tabBloqTaille =tabBloq.Taille(); + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // on regarde si les temps dépendent d'une fct nD + // si oui on modifie les bornes du ddl + if (tabBloq_i.Temps_depend_nD()) + LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD); + // pour le ddlLim, si le temps est inférieur au temps actif + // ou si d'une part le temps n'est pas actif et qu'au pas précédent + // il n'était pas également actif on ne fait rien + if (!(tabBloq_i.Pas_a_prendre_en_compte(temps))) + {bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier + // recup de la reference correspondant au mot cle + const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()); + if ((refinitial.Indic() == 4) && + (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) + {// cas des références d'arêtes, avec des conditions de tangente imposée + bool devient_actif = (actif_pour_le_temps && (!tabBloq_i.Etat_validation())); + bool devient_inactif = ((!actif_pour_le_temps) && (tabBloq_i.Etat_validation())); + // on n'intervient que s'il y a un changement d'état + if (devient_actif || devient_inactif) + {//int tabBloqitaille = tabBloq_i.Taille(); + const ReferenceAF & ref = ((ReferenceAF &) refinitial); + int reftaille = ref.Taille(); + // on boucle sur les numéros de la référence + for (int ne =1; ne<= reftaille;ne++) + {// on regarde si le temps est actif ou pas + if (devient_actif) + // cas ou on veut le blocage mais qu'au temps précédent ce n'était pas valide + { // récup de l'élément + SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); + // que ce soit dans le cas d'un champ ou normal, on n'a pas besoin d'itérer sur les ddl du ddlLim + // car d'un part pour le champ, on a autant de dim_espace ddl que d'élément dans la référence + // et d'autre part dans le cas normal on a uniquement un seul dim_espace ddl -> vecteur + // !!!!!! pour l'instant on considère que c'est en 3D + #ifdef MISE_AU_POINT + if ((ParaGlob::Dimension() < 3) || (tabBloq_i.Taille() != 3)) + { cout << "\n erreur, pour l'instant les conditions de type TANGENTE_CL ne sont operationnelles " + << " que pour la dimension 3 !! "; + cout << "\n reference concernee: "; ref.Affiche(); + cout << "\n condition limite concernee: ";tabBloq_i.Affiche(); + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + #endif + int tabBloqitaille = tabBloq_i.Taille(); // normalement = 3 ici + Tableau t_ddl(tabBloqitaille); // les valeurs du vecteur qui permet le calcul de la tangence + for (int nd=1;nd<=tabBloqitaille;nd++) + {Ddl ddl = tabBloq_i.ElemLim(nd); + // choix entre valeur simple et valeur qui varie + if(tabBloq_i.Nom_courbe(nd) != "") + { // cas d'une courbe de charge, récup de la courbe + Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd)); + // on change la valeur du ddl + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // pour l'instant ce n'est pas implanté + // en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la + // position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à + // l'élément qui updaterait sa position (qui peut être différente pour chaque élément) + // $$$ à faire s'il y a une demande, pour l'instant on attend $$$$ + cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant" + << " ce cas n'est pas implante, donc le demander !!! " + << "\n LesCondLim::MiseAJour_tdt(.... "; + tempsCL.Arret_du_comptage(); + Sortie(1); + } + else + { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 + ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd); + }; + t_ddl(nd) = ddl; + } + else if (tabBloq_i.NomF_charge(nd) != "") + { // cas d'une fonction nD de charge, récup + Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd)); + // on change la valeur du ddl + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // pour l'instant ce n'est pas implanté + // en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la + // position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à + // l'élément qui updaterait sa position (qui peut être différente pour chaque élément) + // $$$ à faire s'il y a une demande, pour l'instant on attend $$$$ + cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant" + << " ce cas n'est pas implante, donc le demander !!! " + << "\n LesCondLim::MiseAJour_tdt(.... "; + tempsCL.Arret_du_comptage(); + Sortie(1); + } + else + {// pour l'instant on limite l'utilisation des fonctions aux seules grandeurs globales + if (pt_fctnD->NbVariable_locale() != 0) + {cout << "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements, pour l'instant" + << " seule une dependance a des variables globales est possible !!! " + << "\n LesCondLim::MiseAJour_tdt(.... "; + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + Tableau & tab_ret = pt_fctnD->Valeur_pour_variables_globales(); + #ifdef MISE_AU_POINT + if (tab_ret.Taille() != 1) + {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " + << "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements" + << "\n LesCondLim::MiseAJour_tdt(.... "; + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + #endif + // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 + ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd); + }; + t_ddl(nd) = ddl; + } + else // cas d'un ddl à valeur fixe + { // cas d'un ddl à valeur fixe + t_ddl(nd) = ddl; + }; + }; + // on renseigne l'élément + Coordonnee3 vpla(t_ddl(1).Valeur(),t_ddl(2).Valeur(),t_ddl(3).Valeur()); + elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) ); + } + else if (devient_inactif) + // on relache le blocage si nécessaire, pour cela on regarde donc s'il y a changement de statut + { // récup de l'élément + SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne)); + // on renseigne l'élément + Coordonnee3 vpla; // initalisé à 0 par défaut, ne sert pas ici + elsfe.DefCondLim(RIEN_TYPE_CL,vpla, ref.NumeroFA(ne) ); + }; + // sinon on ne fait rien + }; //-- fin de la boucle sur ne + }//-- fin du test sur devient_actif ou devient_inactif + }//-- fin du cas ref d'encastrement ou de symétrie + else // cas d'une référence de noeud + {const ReferenceNE & ref = ((ReferenceNE &) refinitial); + int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // incrementation en fonction de la valeur de blocage et du coef + {Ddl ddl = tabBloq_i.ElemLim(nd); + // concernant le temps, soit le ddlLim est actif ou il change de statut: actif à non actif + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + // cas de deplacements imposes en entraine on change les Ui en Xi + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + bool a_considerer = tous_les_blocages; + if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux + {if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;} + Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier + if (a_considerer) + { if ( noe.En_service(ddlenu) ) + { // on regarde si le temps est actif ou pas + if (!actif_pour_le_temps) + // cas du temps non actif, on relache le blocage si nécessaire + // on regarde donc s'il y a changement de statut + {if (tabBloq_i.Etat_validation() && (noe.Ddl_fixe(ddlenu))) + {ch_statut = true; + Retire_cl(nd,tabBloq_i,ddlenu,noe,cas); + } + } //-- fin du test ou le temps n'est pas actif + else + // cas du temps actif + // on regarde s'il y a changement de statut + {if (!(tabBloq_i.Etat_validation())&& (!(noe.Ddl_fixe(ddlenu)))) + { // on change le statut que si c'est une variable, les données n'influencent pas les raideurs et seconds membres + if (noe.UneVariable(ddlenu)) + ch_statut = true; +// Mise_cl(nd,tabBloq_i,ddlenu,noe,cas); + }; + // gestion des surcharges de blocage + // au premier passage on met tous les ddl en libre s'ils sont actifs + if (noe.Ddl_fixe(ddlenu)) + Retire_cl(nd,tabBloq_i,ddlenu,noe,cas); + }//-- fin du test si le temps est actif + }//-- fin du test si le ddl du noeud est une variable et est en service + }//-- fin du test si le noeud est à considérer ou pas + }//-- fin de la boucle sur tabBloq_i: indice nd + }//-- fin de la boucle nn + }//-- fin du cas des noeuds + } // fin du if (!(tabBloq_i.Pas_a_prendre_en_compte(temps))) + }//-- fin de la boucle sur tabBloq + + // ---- second passage ---- + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + // on ne continue que si c'est une référence de noeud + if (ref.Indic() == 1) + { int reftaille = ref.Taille(); + // cas particulier des mouvements solides + if (tabBloq_i.Mouvement_Solide()) + {MiseAjour_tdt_second_passage_mvtSolide(mult_gene,lesMail,deltat,cas + ,lesCourbes1D,lesFonctionsnD,coef,tabBloq_i,ref,temps,en_ddl); + } + else + // cas différent des mouvements solides + {for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // incrementation en fonction de la valeur de blocage et du coef + {Ddl ddl = tabBloq_i.ElemLim(nd); + // pour le ddlLim, si le temps est inférieur au temps actif + // ou si d'une part le temps n'est pas actif et qu'au pas précédent + // il n'était pas également actif on ne fait rien + if (tabBloq_i.Pas_a_prendre_en_compte(temps)) break; + // maintenant soit le ddlLim est actif ou il change de statut: actif à non actif + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + +////--debug +//if (noe.Num_noeud()==197) +// {cout << "\n debug1: LesCondLim::MiseAJour_tdt(.."; +// noe.Affiche();cout << endl; +// }; +////--fin debug + + + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + // cas de deplacements imposes en entraine on change les Ui en Xi + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + bool a_considerer = tous_les_blocages; + if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux + {if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;} + Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier + if (a_considerer) + { // on regarde si les temps dépendent d'une fct nD + // si oui on modifie les bornes du ddl + if (tabBloq_i.Temps_depend_nD()) + LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); + bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier + bool une_variable = noe.UneVariable(ddlenu); // pour simplifier + // cas des variables: si le ddl du noeud est en service on continue sinon on ne fait rien + // ou cas d'une donnée et le temps actif + if ( ( une_variable && noe.En_service(ddlenu)) + ||(!une_variable && actif_pour_le_temps) ) + { // on regarde si le temps est actif ou pas, seul le cas actif est ici considérer + if (actif_pour_le_temps) + // gestion des surcharges de blocage + // au second passage on fixe les ddl actifs + {Mise_cl(nd,tabBloq_i,ddlenu,noe,cas); + // on choisit entre ddl à valeur fixe ou avec une courbe de charge + // coef intègre le multiplicateur global: mult_gene + if ((tabBloq_i.Nom_courbe(nd) != "")&&(tabBloq_i.NomF_charge(nd) == "")) + { // cas d'une courbe de charge, récup de la courbe + Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd)); + // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle + // car au paravant il pouvait être non nul + // ici changement et non ajout , prise en compte de la relativité du blocage + double val_final = 0.; + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat + ddl.Valeur() = ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) + * tabBloq_i.Echelle_courbe(nd); + val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu); + } + else + { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 + ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd); + val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu); + }; + noe.Change_val_tdt(ddlenu,val_final); // mise à jour + } + else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) == "")) + { // cas d'une fonction nD de charge, récup + Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd)); + // on commence par récupérer les conteneurs des grandeurs à fournir + List_io & li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire(); + List_io & li_quelc = pt_fctnD->Li_equi_Quel_evolue(); + // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire + Tableau val_ddl_enum(Valeur_multi_interpoler_ou_calculer + (noe, TEMPS_tdt,li_enu_scal)); + // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur + Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc); + // calcul de la valeur et retour dans tab_ret + Tableau & tab_ret = pt_fctnD->Valeur_FnD_Evoluee + (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL); + #ifdef MISE_AU_POINT + if (tab_ret.Taille() != 1) + {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " + << "\n *** blocage via une fonction nD pour l'evolution du ddl" + << Nom_ddl(ddlenu) + << "\n LesCondLim::MiseAJour_tdt(.... "; + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + #endif + // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle + // car au paravant il pouvait être non nul + // ici changement et non ajout , prise en compte de la relativité du blocage + double val_final = 0.; + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // pour l'instant a priori ce n'est pas possible car le temps + // est une variable globale que l'on ne peut pas modifier pour les fonctions nD + // il faut donc utiliser conjointement une courbe1D pour le temps et la fonction nD pour le reste + cout << "\n *** blocage relatif avec uniquement une fonction nD: ce n'est pas possible" + << " pour avoir un blocage relatif il faut utiliser conjointement une courbe de charge " + << " pour le temps et une fonction nD pour le reste !!!!" + << "\n LesCondLim::MiseAJour_tdt(.... "; + tempsCL.Arret_du_comptage(); + Sortie(1); + } + else + { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 + ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd); + val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu); + }; + noe.Change_val_tdt(ddlenu,val_final); // mise à jour + } + else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) != "")) + { // cas d'une fonction nD de charge, récup + Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd)); + // on commence par récupérer les conteneurs des grandeurs à fournir + List_io & li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire(); + List_io & li_quelc = pt_fctnD->Li_equi_Quel_evolue(); + // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire + Tableau val_ddl_enum(Valeur_multi_interpoler_ou_calculer + (noe, TEMPS_tdt,li_enu_scal)); + // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur + Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc); + // calcul de la valeur et retour dans tab_ret + Tableau & tab_ret = pt_fctnD->Valeur_FnD_Evoluee + (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL); + #ifdef MISE_AU_POINT + if (tab_ret.Taille() != 1) + {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " + << "\n *** blocage via une fonction nD pour l'evolution du ddl" + << Nom_ddl(ddlenu) + << "\n LesCondLim::MiseAJour_tdt(.... "; + tempsCL.Arret_du_comptage(); + Sortie(1); + }; + #endif + // idem pour la courbe 1D + Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd)); + // on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle + // car au paravant il pouvait être non nul + // ici changement et non ajout , prise en compte de la relativité du blocage + double val_final = 0.; + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat + ddl.Valeur() = tab_ret(1) * + (((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) + * tabBloq_i.Echelle_courbe(nd) + ); + + val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu); + } + else + { // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0 + ddl.Valeur() = tab_ret(1) * + (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd); + val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu); + }; + noe.Change_val_tdt(ddlenu,val_final); // mise à jour + } + else + { // cas d'un ddl à valeur fixe + // du au fait de l'initialisation d'un incrément à l'autre dans les algos globaux on change + double val_final=noe.Valeur_t(ddlenu); // récup de la valeur à t + val_final += coef * ddl.Valeur(); // mise en place du delta + noe.Change_val_tdt(ddlenu,val_final); + }; + + }; //-- fin du test si le temps est actif + }; //-- fin du test si le ddl du noeud est en service + }; //-- fin du test si le noeud est à considérer ou pas + }; //-- fin de la boucle sur tabBloq_i + }; //-- fin de la boucle sur nn + }; //-- fin du else du if (tabBloq_i.Mouvement_Solide()) + }; //-- fin du du test : if (ref.Indic() == 1) + };//-- fin de la boucle sur tabBloq + // vérif qu'il n'y a pas de surcharge de blocage + Verif_surcharge_blocage(lesMail,lesRef,temps,cas); + + tempsCL.Arret_du_comptage(); // temps cpu + +}; + +// validation des conditions de blocages, pour l'incrément. +// concernant l'activité des ddlLim, elle est enregistrée en fonction du temps +// idem pour les conditions linéaires +void LesCondLim::Validation_blocage (LesReferences* lesRef,const double& temps) + { + // tout d'abord les conditions de blocage + int tabBloqTaille =tabBloq.Taille(); + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + if (ref.Indic() == 1) // ok que si c'est une ref de noeud + { int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + for (int nd=1;nd<= tabBloqitaille;nd++) + // validation de l'activité du ddlLim + tabBloq_i.Validation(temps); + }; + }; + }; + // maintenant les conditions linéaires + int tabTaille = tab_iocondiline.Taille(); +////----- debug +//cout << "\n LesCondLim::Validation_blocage: avant validation \n temps = " << temps << "\n"; +//cout << tab_iocondiline; +////--- fin debug + for (int icondli=1;icondli<= tabTaille; icondli++) + tab_iocondiline(icondli).Validation(temps); +////----- debug +//cout << "\n LesCondLim::Validation_blocage: après validation \n"; +//cout << tab_iocondiline; +////--- fin debug + }; + + // test s'il y a changement de statut pour le temps indiqué par rapport à la situation actuelle ou pas + // n'effectue aucune autre opération + // si en_ddl est différent de NU_DDL on test le changement de statut uniquement pour le ddl en_ddl +bool LesCondLim::Changement_statut(const LesMaillages * lesMail,const LesReferences* lesRef + ,LesFonctions_nD* lesFonctionsnD + ,const double& temps,const Enum_ddl en_ddl) +// *************** a mettre en conformité avec miseà jour tdt ***************$ + + + + { cout << "\n methode pas operationnelle, a mettre a jour !!!!" + << "\n LesCondLim::Changement_statut(...."; + Sortie(1); + + // préparation + bool tous_les_blocages = true; + if (en_ddl != NU_DDL) tous_les_blocages = false; + bool ch_statut = false; // valeur de retour + + int tabBloqTaille =tabBloq.Taille(); + // on parcours le tableau de ddl bloques + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + for (int nd=1;nd<= tabBloqitaille;nd++) + // incrementation en fonction de la valeur de blocage et du coef + {Ddl ddl = tabBloq_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // on regarde si les temps dépendent d'une fct nD + // si oui on modifie les bornes du ddl + if (tabBloq_i.Temps_depend_nD()) + LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD); + Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + // cas de deplacements imposes en entraine on change les Ui en Xi + ddl.Change_nom(UxyzXi(ddlenu)); + bool a_bloquer = tous_les_blocages; + if (! a_bloquer) // cas ou on ne veut que certain blocage, a_bloque est faux + {if (Meme_famille(en_ddl,ddlenu)) a_bloquer = true;} + if (a_bloquer) + { if (!(tabBloq_i.Temps_actif(temps))) + // cas de la courbe non active pour le temps + { // si le ddl du noeud est en service on continue sinon on ne fait rien + if ( noe.En_service(ddlenu) ) + // on regarde s'il y a changement de statut et que c'est une variable + {if ((noe.Ddl_fixe(ddlenu)) && (noe.UneVariable(ddlenu))) + ch_statut = true; + } //-- fin du test si le ddl du noeud est en service + } //-- fin du test ou le temps n'est pas actif + else + // cas du temps actif + { if (ddl.Valeur() != 0) + {// si le ddl du noeud est en service on continue sinon on ne fait rien + if ( noe.En_service(ddlenu) ) + // on regarde s'il y a changement de statut et que c'est une variable + {if ( (!(noe.Ddl_fixe(ddlenu))) && (noe.UneVariable(ddlenu))) + ch_statut = true; + } //-- fin du test si le ddl du noeud est en service + } //-- fin du test si la valeur a bloquer est différente de 0 + } //-- fin du test si le temps est actif + } + } + } + } + return ch_statut; + }; + + +// récupération des tableaux d'indices généraux des variables ddl bloqués +// cas : donne le type d'association de ddl que l'on veut +// =0 -> pas d'association +// =1 -> association de Xi avec Vi avec Gammai +// t_assemb: donne pour chaque type d'association, le numéro d'assemblage correspondant au different ddl +// de l'association +// cas=1 -> numéro d'assemblage de X1 puis V1 puis GAMMA1 +// : en sortie une liste de Gene_asso, correspondant à tous les ddl bloqués et les +// les ddl associés +list LesCondLim::Tableau_indice + (const LesMaillages * lesMail,const Tableau & t_assemb + ,const LesReferences* lesRef,const double& temps,int cas) +{ // def de la liste de retour + list li_ret; + // préparation + int tabBloqTaille =tabBloq.Taille(); + // on parcours le tableau de ddl bloques + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + if (ref.Indic() == 1) // ok pour les noeuds uniquement + {int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // incrementation en fonction de la valeur de blocage + {Ddl ddl = tabBloq_i.ElemLim(nd); + const Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + // cas de deplacements imposes en entraine on change les Ui en Xi + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + // si le blocage est relatif à une donnée et non à une variable arrêt + if (!(noe.UneVariable(ddl.Id_nom()))) break; + // si le ddl concerne la direction 3 et que l'on est en axi, arrêt + // car le ddl 3 n'est pas utilisé en blocage en axi + Enum_ddl en_ddl = ddl.Id_nom(); // le type principal de l'élément Gene_asso + if (ParaGlob::AxiSymetrie() && FoncDim(en_ddl)) + {Enum_ddl prem_ddl = PremierDdlFamille(en_ddl); + // pour l'instant on ne traite que X, U, V et Gamma + bool fin_traitement = false; // init + switch (prem_ddl) + { case X1: if (en_ddl == X3)fin_traitement = true; + break; + case V1: if (en_ddl == V3)fin_traitement = true; + break; + case GAMMA1:if (en_ddl == GAMMA3)fin_traitement = true; + break; + default: + cout << "\n *** erreur pour l'instant en axi, seules les cas " + << " Xi, Vi, GAMMAi sont pris en compte pour les CL selon dir 3 " + << " \n LesCondLim::Tableau_indice(... "<< endl; + break; + }; + if (fin_traitement) break; + }; + + // on regarde si le ddl fait partie de la liste à scruter, si l'on est + // dans le cas d'une combinaison, sinon c'est ok + bool choix = true; // vrai a priori, c'est à dire le cas = 0 + // qui convient que dans le cas = 0, sinon: + if (cas!= 0) + { if (Dans_combinaison(cas,en_ddl)) + {choix = true;} + else + {choix = false;} // cas d'une combinaison , et d'un ddl qui ni appartiend pas + }; + if (choix) + { // on test que si le temps est actif + // ici les tmin et tmax du ddl ne sont pas modifiés, on considère que ce sont + // ceux qui ont été mise à jour à la précédente mise à jour + if ((tabBloq_i.Temps_actif(temps))) + { switch (cas) + { case 0 : // cas pas d'association + { // def du tableau de position pour l'élément Gene_asso + Tableau pointe(1); // dimension pour Xi,Vi,GAMMAi + // recup de la position du ddl + pointe(1) = noe.Pointeur_assemblage(en_ddl,t_assemb(1).n); + // ajout dans la liste + Gene_asso aa(en_ddl,pointe); + li_ret.push_back(aa); + break; + } + case 1 : // cas de l'association X V GAMMA + { // def du tableau de position pour l'élément Gene_asso + Tableau pointe(3); // dimension pour Xi,Vi,GAMMAi + // récup des ddl secondaire et du ddl principal bloqué + Tableau t_enu = MemeCombinaison(cas,en_ddl); + pointe(1) = noe.Pointeur_assemblage(t_enu(1),t_assemb(1).n); + pointe(2) = noe.Pointeur_assemblage(t_enu(2),t_assemb(2).n); + pointe(3) = noe.Pointeur_assemblage(t_enu(3),t_assemb(3).n); + // ajout dans la liste + Gene_asso aa(en_ddl,pointe); + li_ret.push_back(aa); +////// --debug +//cout << "\n debug LesCondlim::Tableau_indice(" +// << "\n li_ret.size= "<< li_ret.size() << endl; +////// -- fin debug + + break; + } + }; //-- fin du switch (cas) + }; //-- fin du if ((tabBloq_i.Temps_actif(temps))) + }; //-- fin du if (choix) + }; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++) + }; //-- fin du for (int nn =1; nn<= reftaille;nn++) + }; //-- fin du if (ref.Indic() == 1) + }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) +//// --debug +//cout << "\n debug LesCondlim::Tableau_indice(" +// << "\n li_ret.size= "<< li_ret.size() ; +//list ::iterator ie,iefin=li_ret.end();; // def d'un iterator adoc +//int ih=1; // indice +//for(ie=li_ret.begin(),ih=1;ie!=iefin;ie++,ih++) +// // comme les valeurs des X V Gamma vont être écrasé par le calcul global, on utilise +// // des conteneurs intermédiaires +// {//trois cas +// LesCondLim::Gene_asso & s = (*ie); // pour simplifier +// int ix=s.pointe(1); // début des Xi +// int iv=s.pointe(2); // début des Vi +// int ig=s.pointe(3); // début des gammai +// cout << "\n ix= " << ix << ", iv= "<< iv << ", ig= "<< ig; +// }; +//cout << endl; +//// -- fin debug + + // retour de la liste + return li_ret; + }; + + + +// mise en place des conditions limites sur les matrices et/ou second membres +// cas : indique un type d'association de ddl +// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré +// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès +// lors que l'un a été fixé par l'utilisateur +// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob +// mais sans sauvegarde (correspond par exemple à une partie de vecglob) +void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef, + Mat_abstraite & matglob,Vecteur& vecglob + ,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2) +{ + tempsCL.Mise_en_route_du_comptage(); // temps cpu + int tabBloqTaille =tabBloq.Taille(); + int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage + Tableau tmc; // tableau de travail + // on parcours le tableau de ddl bloques + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + if (ref.Indic() == 1) // ok pour les noeuds uniquement + {int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // mise en place de la condition limite + { Ddl ddl = tabBloq_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi +// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + // on continue uniquement si le ddl du tableau de blocage est en service + // et si pour le noeud c'est une variable + if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + { // récup des enu_ddl équivalent au groupe + tmc = MemeCombinaison(cas,ddl.Id_nom()); + int tailletmc = tmc.Taille(); + for (int itc=1;itc <= tailletmc;itc++) + {// on boucle sur tous les ddl a imposer + // calcul du pointeur correspondant au ddl cherche + int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); + // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif + if ((pt != -1) && (noe.En_service(tmc(itc)))) + {// ce que l'on veut c'est une variation nulle des ddl imposee + // -> valeur imposee = 0 + // cas de la matrice, et modif du second membre si la valeur imposee + // est differente de zero (ce qui n'est pas le cas ici !) + condlim(nb_casAss).Val_imposee_Mat(matglob,vecglob,pt,0.,vec2); + // cas du second membre et sauvegarde des reactions + condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2); + }; + }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) + }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) + }; //-- fin de for (int nn =1; nn<= reftaille;nn++) + }; //-- fin de if (ref.Indic() == 1) + }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) + // affichage éventuelle de la matrice de raideur et du second membre + if (ParaGlob::NiveauImpression() >= 10) + { string entete = " affichage de la matrice apres conditions limites des ddl initialement bloques "; + matglob.Affichage_ecran(entete); + entete = " affichage du second membre apres conditions limites des ddl initialement bloques "; + vecglob.Affichage_ecran(entete); + }; + tempsCL.Arret_du_comptage(); // temps cpu +}; + +// mise en place des conditions limites sur le second membres +// nb_casAssemb : le cas d'assemblage +// cas : indique un type d'association de ddl +// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré +// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un +// a été fixé par l'utilisateur +// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob +// mais sans sauvegarde (correspond par exemple à une partie de vecglob) +void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef, + Vecteur& vecglob,const Nb_assemb& nb_casAssemb + ,int cas,Vecteur* vec2) +{ + tempsCL.Mise_en_route_du_comptage(); // temps cpu + int tabBloqTaille =tabBloq.Taille(); + int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage + Tableau tmc; // tableau de travail + // on parcours le tableau de ddl bloques + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + if (ref.Indic() == 1) // ok pour les noeuds uniquement + {int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // mise en place de la condition limite + { Ddl ddl = tabBloq_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + // on continue uniquement si le ddl du tableau de blocage est en service + // et si pour le noeud c'est une variable + if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + { // récup des enu_ddl équivalent au groupe + tmc = MemeCombinaison(cas,ddl.Id_nom()); + int tailletmc = tmc.Taille(); + for (int itc=1;itc <= tailletmc;itc++) + {// on boucle sur tous les ddl a imposer + // calcul du pointeur correspondant au ddl cherche + int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); + // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif + if ((pt != -1) && (noe.En_service(tmc(itc)))) + {// ce que l'on veut c'est une variation nulle des ddl imposee + // -> valeur imposee = 0 + // cas du second membre et sauvegarde des reactions + condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2); + }; + }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) + }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) + }; //-- fin de for (int nn =1; nn<= reftaille;nn++) + }; //-- fin de if (ref.Indic() == 1) + }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) + // affichage éventuelle du second membre + if (ParaGlob::NiveauImpression() >= 10) + { string entete = " affichage du second membre apres conditions limites des ddl initialement bloques "; + vecglob.Affichage_ecran(entete); + }; + tempsCL.Arret_du_comptage(); // temps cpu + }; + +// mise en place des conditions limites sur deux matrices +// utilisé par exemple pour le flambement +// la première matrice est initialisée avec des 1 sur la diagonale +// la seconde avec des 0 sur la diagonale +// cas : indique un type d'association de ddl +// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré +// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un +// a été fixé par l'utilisateur +void LesCondLim::ImpConLimtdt2Mat(LesMaillages * lesMail,LesReferences* lesRef, + Mat_abstraite & matglob,Mat_abstraite & matgeom + ,const Nb_assemb& nb_casAssemb,int cas) +{ + tempsCL.Mise_en_route_du_comptage(); // temps cpu + int tabBloqTaille =tabBloq.Taille(); + int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage + Tableau tmc; // tableau de travail + // on parcours le tableau de ddl bloques + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + if (ref.Indic() == 1) // ok pour les noeuds uniquement + {int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // mise en place de la condition limite + { Ddl ddl = tabBloq_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + // on continue uniquement si le ddl du tableau de blocage est en service + // et si pour le noeud c'est une variable + if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + { // récup des enu_ddl équivalent au groupe + tmc = MemeCombinaison(cas,ddl.Id_nom()); + int tailletmc = tmc.Taille(); + for (int itc=1;itc <= tailletmc;itc++) + {// on boucle sur tous les ddl a imposer + // calcul du pointeur correspondant au ddl cherche + int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); + // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif + if ((pt != -1) && (noe.En_service(tmc(itc)))) + {// ici on ne fait que modifier les matrices -> un 1 sur la diagonale + // et 0 sur le reste de la ligne et colonne correspondantes + condlim(nb_casAss).Val_imposSimple_Mat(matglob,pt,1.); + condlim(nb_casAss).Val_imposSimple_Mat(matgeom,pt,0.); + }; + }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) + }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) + }; //-- fin de for (int nn =1; nn<= reftaille;nn++) + }; //-- fin de if (ref.Indic() == 1) + }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) + // affichage éventuelle des deux matrices de raideur + if (ParaGlob::NiveauImpression() >= 10) + { string entete = " affichage de la premiere matrice de raideur apres conditions limites (matglob) "; + entete += " des ddl initialement bloques"; + matglob.Affichage_ecran(entete); + entete = " affichage de la seconde matrice de raideur apres conditions limites (matgeom) "; + entete += " des ddl initialement bloques"; + matgeom.Affichage_ecran(entete); + }; + tempsCL.Arret_du_comptage(); // temps cpu +}; + +// récupération des reactions initiales, avant les rotations dues aux conditions linéaires +// il s'agit des réactions dues aux ddl bloqués et dues aux conditions linéaires +// et calcul des torseurs de réaction +void LesCondLim::ReacAvantCHrepere(Vecteur& residu,LesMaillages * lesMail, + LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas) +{ + int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage + Tableau tmc; // tableau de travail + // on cree une liste de stockage intermediaire + list lili; + list indice_tabBloq; // tableau de travail, qui sert pour le calcul des torseurs de réaction + ReactStoc elem; // element courant de stockage des réactions + + //----------- cas des ddl bloqués ----------------- + // on parcours le tableau de ddl bloques + int tabBloqTaille =tabBloq.Taille(); + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + if (!((ref.Indic() == 4) && // le cas des conditions de tangence sur + (tabBloq_i.TypeDeCL()==TANGENTE_CL )) // les arrêtes n'est pas à prendre en compte + && (ref.Indic() == 1)) // s'applique uniquement au cas des ref de noeuds + {int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // récupération de la condition limite + { Ddl ddl = tabBloq_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + // on continue uniquement si le ddl du tableau de blocage est en service + // et si pour le noeud c'est une variable + if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + { // récup des enu_ddl équivalent au groupe + tmc = MemeCombinaison(cas,ddl.Id_nom()); + int tailletmc = tmc.Taille(); + for (int itc=1;itc <= tailletmc;itc++) + {// on boucle sur tous les ddl a imposer + // calcul du pointeur correspondant au ddl cherche + int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); + // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif + if ((pt != -1) && (noe.En_service(tmc(itc)))) + { // maintenant on peut récupérer la réaction + elem.ddl = ddl; + elem.ddl.Valeur() = residu(pt); + elem.numMail = ref.Nbmaille(); + elem.numNoeud = ref.Numero(nn); + elem.casAss = nb_casAss; + lili.push_back(elem); // sauvegarde de la réaction + indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq + }; + }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) + }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) + }; //-- fin de for (int nn =1; nn<= reftaille;nn++) + }; //-- fin de if (!((ref.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) ) + }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) + + //----------- cas des conditions linéaires ----------------- + // on cree une liste de stockage intermediaire + list lili_CLin;List_io indice_dans_tab_iocondiline; + + // on a besoin d'enregistrer une seule fois chaque réaction, or le mode de fabrication des CLL + // fait que cela conduit à des redondances. Pour les repérer, on va utiliser un conteneur de drapeau + // de manière à limiter la taille de ce conteneur on utilise une map, c'est moins rapide en acces + // qu'un tableau, mais c'est mieux qu'une liste et c'est plus petit qu'un tableau, car a priori + // il y a moins beaucoup moins de ddl bloqué par les CLL que de ddl total du pb + map < int , bool, std::less > reac_deja_stocke; + + // on parcours le tableau des CLL + // on boucle sur le tableau de conditions limites linéaires enregistré + int tabTaille = tab_CLinApplique.Taille(); + for (int i=1;i<= tabTaille; i++) + {int sous_taille = tab_CLinApplique(i).Taille(); + for (int j=1; j<= sous_taille; j++) + { Condilineaire& condi = tab_CLinApplique(i)(j); + // on met à jour les pointeurs d'assemblage pour bien localiser les infos dans SM et K + // ce sera refait dans l'assemblage... + condi.ConditionPourPointeursAssemblage(nb_casAssemb); + // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 + if (condi.Iddl() > -1) + { // chaque ddl qui appartient à une CLL et qui est associé + // à un coefficient non nulle conduit à une condition limite + const Vecteur& Vectval = condi.Val(); + const Tableau& pt = condi.Pt_t(); + const Tableau& t_enu = condi.Tab_Enum(); + const Tableau < Noeud *>& t_noeud = condi.TabNoeud(); + + // on boucle sur les noeuds puis sur les ddl de la CLL + int taille = pt.Taille(); + int nb_noeud = t_noeud.Taille();int itab=1; + int nbddlfamille = taille / nb_noeud; + for (int i_noe=1;i_noe <= nb_noeud;i_noe++) + for (int i_fa =1; i_fa<= nbddlfamille; i_fa++,itab++) + { // on ne stocke que si la réaction n'a pas déjà été stockée + if ((reac_deja_stocke.find(pt(itab))==reac_deja_stocke.end()) + && (Vectval(itab) != 0.) ) // et que le coef est non nul + { // on définit la réaction + elem.ddl.Change_nom(t_enu(itab)); + elem.ddl.Valeur() = residu(pt(itab)); + elem.numMail = t_noeud(i_noe)->Num_Mail(); + elem.numNoeud = t_noeud(i_noe)->Num_noeud(); +// elem.casAss = condi.CasAssemb().n; + elem.casAss = nb_casAssemb.n; + lili_CLin.push_back(elem); // on sauvegarde la réaction + // sauvegarde de l'indice dans tab_iocondiline car le premier indice "i" + // de tab_CLinApplique est celui correspondant à la condition tab_iocondiline(i) + // le second indice permet de retrouver la ref + indice_dans_tab_iocondiline.push_back(DeuxEntiers(i,i_noe)); + // on renseigne la map + reac_deja_stocke[pt(itab)] = true; + }; + }; + }; + }; + }; + + //----------- fin du cas des conditions linéaires ----------------- +//--débug --- +//cout << "\n " << indice_dans_tab_iocondiline << endl; +//--débug--- + + + // ----- on initialise le tableau des torseurs de réaction + int tabtorsTaille = tab_torseurReac.Taille(); + for (int i=1;i<= tabtorsTaille;i++) + if (tab_torseurReac(i).existe_torseur_reac) + tab_torseurReac(i).Zero_init_torseur(); + int dima = ParaGlob::Dimension(); + if(ParaGlob::AxiSymetrie()) + // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les + // dimension-1 coordonnées donc on décrémente + dima--; + + // --- enregistrement des réactions pour ddl bloqué et calcul des torseurs + { // on encapsule + list ::iterator i; // def d'un iterator adoc + reaction.Change_taille((int)lili.size()); +// map_reaction.erase(map_reaction.begin(),map_reaction.end()); + int j; + list ::iterator i_taBloq=indice_tabBloq.begin(); + for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++,i_taBloq++) + { reaction(j) = *i; +// map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)] +// .push_back(&(reaction(j))); + // transfert des informations aux noeuds + ReactStoc& reac = reaction(j); // pour simplifier + // récup du noeud j du maillage i + Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud); + Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction + // dans le cas où la réaction n'existe pas on l'ajoute + // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas + // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité + { if (!noe.Existe_ici(enu_reac)) +// { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE); + { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE); + noe.PlusDdl(reac_ddl); + } + else + // sinon il faut le bloquer car la réaction est imposée + { noe.Change_fixe(enu_reac,true);}; + // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 + if (ttRG(*i_taBloq) != 0) // si = 0 c'est que le ddl n'est pas un déplacement classique + CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac); + }; + // mise à jour de la réaction + noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt + }; + // on va maintenant exporter les composantes du tenseur vers des grandeurs globales + int taille_tors_bloqu = ttRG_noms_ref.Taille(); + int taille_tors_bloquplus1 = taille_tors_bloqu +1; + // cas d'un blocage de ddl + {int il = 1; + for (int ia=1;iaGrandeurGlobal(nom_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'exportation de composantes de torseur !! " + << " la variable globale "<< (nom_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier + tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic); + }; + // 2) le moment + for (int ic= 1; ic < dimaPlus1; ic++) + {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); + // récup du pointeur de conteneur + const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'exportation de composantes de torseur !! " + << " la variable globale "<< (nom_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier + tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic); + }; + }; + }; + }; // fin encapsulation + + // --- enregistrement des réactions pour les CLL et calcul également des torseurs associés + // il s'agit des réactions définies précédemment (-- cas des conditions linéaires --) + { // on encapsule + list ::iterator i; // def d'un iterator adoc + List_io ::iterator iti = indice_dans_tab_iocondiline.begin(); + reaction_CLin.Change_taille((int)lili_CLin.size()); + int j; + for (i=lili_CLin.begin(),j=1 ; i != lili_CLin.end(); i++,j++,iti++) + { reaction_CLin(j) = *i; + // transfert des informations aux noeuds + ReactStoc& reac = reaction_CLin(j); // pour simplifier + // récup du noeud j du maillage i + Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud); + Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction + // dans le cas où la réaction n'existe pas on l'ajoute + // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas + // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité + { if (!noe.Existe_ici(enu_reac)) +// { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE); + { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE); + noe.PlusDdl(reac_ddl); + } + else + // sinon il faut le bloquer car la réaction est imposée + { noe.Change_fixe(enu_reac,true);}; + // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 + CalculTorseurReaction(tab_torseurReac(ttRGCLL((*iti).un)((*iti).deux)),noe,reac); + }; + // mise à jour de la réaction + noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt + }; + // exportation en grandeurs globales: cas d'un blocage venant d'une CLL + int taille_tors_bloqu = ttRG_noms_ref.Taille(); + int taille_tors_bloquplus1 = taille_tors_bloqu +1; + int taille_torsP1 = tab_torseurReac.Taille() + 1; + {int il = 1; //ttRGCLL_noms_ref.begin(); + for (int ia=taille_tors_bloquplus1;iaGrandeurGlobal(nom_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'exportation de composantes de torseur !! " + << " la variable globale "<< (nom_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier + tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic); + }; + // 2) le moment + for (int ic= 1; ic < dimaPlus1; ic++) + {string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); + // récup du pointeur de conteneur + const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'exportation de composantes de torseur !! " + << " la variable globale "<< (nom_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier + tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic); + }; + }; + }; + }; // fin encapsulation +}; + +// calcul des reactions et stockage des valeurs +// ceci dans le cas ou il n'y a pas de conditions lineaires appliquee +// on se sert des valeurs sauvegardees lors de la mise en place des CL bloquees +// cas : indique un type d'association de ddl +// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré +// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un +// a été fixé par l'utilisateur +void LesCondLim::CalculReaction(LesMaillages * lesMail,LesReferences* lesRef + ,const Nb_assemb& nb_casAssemb,int cas) +{ + int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage + Tableau tmc; // tableau de travail + // on cree une liste de stockage intermediaire + list lili; + list indice_tabBloq; // tableau de travail + ReactStoc elem; // l'element courant + // on parcours le tableau de ddl bloques + int tabBloqTaille =tabBloq.Taille(); + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + if (ref.Indic() == 1) // ok pour les noeuds uniquement + {int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + // calcul de la reaction + { Ddl ddl = tabBloq_i.ElemLim(nd); + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + // on continue uniquement si le ddl du tableau de blocage est en service + // et si pour le noeud c'est une variable + if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + { // récup des enu_ddl équivalent au groupe + tmc = MemeCombinaison(cas,ddl.Id_nom()); + int tailletmc = tmc.Taille(); + for (int itc=1;itc <= tailletmc;itc++) + {// on boucle sur tous les ddl a imposer + // calcul du pointeur correspondant au ddl cherche + int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss); + // cas ou le ddl fait partie du cas d'assemblage et qu'il est actif + if ((pt != -1) && (noe.En_service(tmc(itc)))) + { elem.ddl = ddl; + elem.ddl.Valeur() = condlim(nb_casAss).ValReact(pt); + elem.numMail = ref.Nbmaille(); + elem.numNoeud = ref.Numero(nn); + elem.casAss = nb_casAss; + lili.push_back(elem); + indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq + }; + }; //-- fin de for (int itc=1;itc <= tailletmc;itc++) + }; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom()))) + }; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++) + }; //-- fin de for (int nn =1; nn<= reftaille;nn++) + }; //-- fin de if (ref.Indic() == 1) + }; //-- fin de for (int i=1;i<= tabBloqTaille;i++) + // on initialise le tableau des torseurs de réaction + int tabtorsTaille = tab_torseurReac.Taille(); + for (int i=1;i<= tabtorsTaille;i++) + if (tab_torseurReac(i).existe_torseur_reac) + tab_torseurReac(i).Zero_init_torseur(); + + // enregistrement + list ::iterator i,ilfin = lili.end(); // def d'un iterator adoc + reaction.Change_taille((int)lili.size()); +// map_reaction.erase(map_reaction.begin(),map_reaction.end()); + int j; + list ::iterator i_taBloq=indice_tabBloq.begin(); + for (i=lili.begin(),j=1 ; i != ilfin; i++,j++,i_taBloq++) + {reaction(j) = *i; +// map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)] +// .push_back(&(reaction(j))); + // transfert des informations aux noeuds + ReactStoc& reac = reaction(j); // pour simplifier + // récup du noeud j du maillage i + Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud); + Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction + // dans le cas où la réaction n'existe pas on l'ajoute + // a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas + // ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité + { if (!noe.Existe_ici(enu_reac)) +// { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE); + { Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE); + noe.PlusDdl(reac_ddl); + } + else + // sinon il faut le bloquer car la réaction est imposée + { noe.Change_fixe(enu_reac,true);}; + // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 + CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac); + }; + // mise à jour de la réaction + noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt + }; + // on va maintenant exporter les composantes du tenseur vers des grandeurs globales + int taille_tors_bloqu = ttRG_noms_ref.Taille(); + int taille_tors_bloquplus1 = taille_tors_bloqu +1; + int dima = ParaGlob::Dimension(); + if(ParaGlob::AxiSymetrie()) + // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les + // dimension-1 coordonnées donc on décrémente + dima--; + // cas d'un blocage de ddl + {int il = 1; + for (int ia=1;iaGrandeurGlobal(nom_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'exportation de composantes de torseur !! " + << " la variable globale "<< (nom_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier + tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic); + }; + // 2) le moment + for (int ic= 1; ic < dimaPlus1; ic++) + {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); + // récup du pointeur de conteneur + const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'exportation de composantes de torseur !! " + << " la variable globale "<< (nom_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesCondLim::ReacAvantCHrepere(..."<Grandeur_pointee())); // pour simplifier + tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic); + }; + }; + }; +}; + +// récupération des reactions= residu et stockage des valeurs +// NB: après changement de repère, il n'y a plus que des ddl bloqués +// cas : indique un type d'association de ddl +// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré +// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un +// a été fixé par l'utilisateur +void LesCondLim::ReacApresCHrepere(Vecteur& residu,LesMaillages * lesMail, + LesReferences* ,const Nb_assemb& nb_casAssemb,int ) +{ + int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage + Tableau tmc; // tableau de travail + // on cree une liste de stockage intermediaire + list lili; + list indice_tabBloq; // tableau de travail + ReactStoc elem; // l'element courant + + //----------- cas des ddl bloqués ----------------- + // l'indice des ddl bloqués reste inchangé après chgt de repère on utilise donc les + // réactions avant rotation par simplicité + // a priori ce sont exactement les mêmes conditions qui existent avant et après chgt de repère + // sauf la valeur de la réaction + int nb_reac = reaction.Taille(); + for (int i=1; i<= nb_reac; i++) + if (reaction(i).casAss == nb_casAss) // si ce n'est pas le bon cas d'assemblage on ne fait rien + { elem = reaction(i); + Noeud & noe=lesMail->Noeud_LesMaille(elem.numMail,elem.numNoeud); + elem.ddl.Valeur() = residu(noe.Position_ddl(elem.ddl.Id_nom(),nb_casAss) ); + lili.push_back(elem); + }; + + // ------- cas des CLL -------------- + // contrairement aux cas des ddl boqués ici on ne peut pas utiliser reaction_CLin + // car il y a une seule réaction dans le nouveau repère alors qu'il y en avait autant que de ddl + // dans la CLL, dans le repère initial, donc on reparcours le tableau des CLL + // on parcours le tableau des CLL + // on boucle sur le tableau de conditions limites linéaires enregistré + // et pour chaque element on impose une condition lineaire + int tabTaille = tab_CLinApplique.Taille(); + for (int i=1;i<= tabTaille; i++) + {int sous_taille = tab_CLinApplique(i).Taille(); + for (int j=1; j<= sous_taille; j++) + { Condilineaire& condi = tab_CLinApplique(i)(j); + // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 + if (condi.Iddl() > -1) + { if (condi.CasAssemb() == nb_casAssemb) + { // la condition limite concerne uniquement un ddl pour chaque CLL + // il s'agit du premier ddl, pour le premier noeud + // on définit la réaction + elem.ddl.Change_nom(condi.Tab_Enum()(1)); + elem.ddl.Valeur() = residu(condi.Pt_t()(1)); + elem.numMail = condi.TabNoeud()(1)->Num_Mail(); + elem.numNoeud = condi.TabNoeud()(1)->Num_noeud(); + elem.casAss = condi.CasAssemb().n; + lili.push_back(elem); // on sauvegarde la réaction + }; + }; + }; + }; + + // enregistrement + list ::iterator i; // def d'un iterator adoc + reactionApresCHrepere.Change_taille((int)lili.size()); + int j; + for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++) + {reactionApresCHrepere(j) = *i;}; + + }; + + +// affichage sur la sortie sort des reactions +void LesCondLim::Affiche_reaction(ofstream& sort,const LesMaillages * lesMail) const + { // l'entete + sort << "\n=========================================================================="; + sort << "\n sortie des efforts generes par l\'exterieur sur les noeuds "; + sort << "\n==========================================================================\n"; + sort << "\n\n 1) les reactions individuelles \n "; + + // on balaie le tableau de reaction et on constitue une liste intermédiaire, pour éviter + // de sortir des doublons + int reactionTaille = reaction.Taille(); + List_io li_inter; + +// Tableau reaction; // les reactions pour les ddl bloqués + for (int i= 1; i<= reactionTaille;i++) + li_inter.push_back(reaction(i)); + li_inter.sort(); // on organise la liste + li_inter.unique(); // on supprime les doublons + + // *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non + // le contraire + List_io ::iterator il,ilfin=li_inter.end(); + for (il= li_inter.begin(); il != ilfin;il++) + { sort << "\ncas assemb " << (*il).casAss + << " maillage " << (*il).numMail <<", noeud " <<(*il).numNoeud + << ", ddl = " << (*il).ddl.Nom() << ", valeur = " << (-(*il).ddl.Valeur()) ; + }; + // on s'occupe maintenant des torseurs de réactions globales si éventuellement il en existe + sort << "\n\n\n=========================================================================="; + sort << "\n 2) les torseurs globaux "; + sort << "\n==========================================================================\n"; + // au niveau des références, il est possible d'avoir une référence qui sert pour plusieurs conditions limites + // aussi on va globaliser les torseurs de réaction en sortie + + int dima = ParaGlob::Dimension(); + if(ParaGlob::AxiSymetrie()) + // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les + // dimension-1 coordonnées donc on décrémente + dima--; + int ttail = tab_torseurReac.Taille(); + for (int i=1;i<= ttail;i++) + { TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier + if (torseurReac.existe_torseur_reac) + {// tout d'abord l'affichage de l'entête + if (torseurReac.bloque_ou_CLL) + // cas où le torseur provient d'une condition ddl bloquée + {DdlLim& tabBloq_i = tabBloq(*(ttorBloq(i).begin())); // pour simplifier (on ne prend que le + // premier des bloqués), tous les autres ont le même nom de maillage et de ref + sort << "\n"; + if (tabBloq_i.NomMaillage() != NULL) + sort << " nom_maillage " << *(tabBloq_i.NomMaillage()); + sort << " nom_ref " << tabBloq_i.NomRef() + << "\n F= "; + } + else + // cas où le torseur provient d'une condition CLL + {I_O_Condilineaire& iocondiline_i = tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier + sort << "\n"; + if (iocondiline_i.NomMaillage() != NULL) + // cas où on considère les noms de maillage + { int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier + if (num_ref == 1) + {// cas d'une référence principale de CLL + const string& nom_maillage = *(iocondiline_i.NomMaillage()); + sort << " nom_maillage " << nom_maillage + << " nom_ref " << iocondiline_i.NomRef() << "_CLL "; + } + else + {// cas d'une référence associé + // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris + // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1 + // qui correspond à la référence principale +//debug +//cout << "\n (*(ttorCLL(i).begin())).deux= " << (*(ttorCLL(i).begin())).deux << endl ; +//fin debug + const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux - 1); + sort << " nom_maillage " << nom_maillage + << " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1) + << "_CLL "; + } + } + else + {// cas où on ne considère pas les noms de maillage + int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier + if (num_ref == 1) + // cas d'une référence principale de CLL + { sort << " nom_ref " << iocondiline_i.NomRef() << "_CLL "; } + else + // cas d'une référence associé + // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris + // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1 + // qui correspond à la référence principale + { sort << " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1) + << "_CLL "; + }; + }; + sort << "\n F= "; + }; + // et maintenant l'affichage des infos + torseurReac.resultante.Affiche(sort,ParaGlob::NbdigdoCA()); + switch (dima) + {case 1: break; // pas de moment en dimension 1 + case 2: sort << "\n M=" << setprecision(ParaGlob::NbdigdoCA()) + << torseurReac.moment(1); // la première composante est le moment + break; + case 3: sort << "\n M="; + torseurReac.moment.Affiche(sort,ParaGlob::NbdigdoCA()); + break; + }; + }; + }; + // sortie des réactions dues aux conditions linéaires + sort << "\n\n\n=========================================================================="; + sort << "\n 3) les reactions dues aux conditions lineaires "; + sort << "\n==========================================================================\n"; + + // on balaie le tableau de reaction_CLin + // *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non le contraire +// non, j'ai l'impression qu'il ne faut pas ici changer de signe ??? à voir par la suite en fonction des résultats +// si finalement ?? + int reaction_CLinTaille = reaction_CLin.Taille(); + for (int i= 1; i<= reaction_CLinTaille;i++) + { sort << "\ncas assemb " << reaction_CLin(i).casAss + << " maillage " << reaction_CLin(i).numMail <<", noeud " < > tab_indi(nb_maillage); // un tableau de travail + for (int i= 1; i<= reactionTaille;i++) // on remplit le tableau d'adressage indirecte + tab_indi(reaction(i).numMail).push_back(DeuxEntiers(i,reaction(i).numNoeud)); + // on trie et on ordonne + for (int i=1;i<=nb_maillage;i++) + { list & indica = (tab_indi(i)); // pour simplifier + indica.sort(); // ordonne en fonction du numéro de noeud + list ::iterator ili,ilifin=indica.end(); + // --- tout d'abord on sort une ref sur la liste des noeuds en réaction au cas ou + sort << "\n # pour information la ref des noeuds concernes\n "; + sort << "\n # nom_mail= "<NomMaillage(i) + <<"\n# N_list_noe_en_react "; + int compteur=0; int total_force=0; + for (ili=indica.begin();ili != ilifin;ili++) + // là on suit la progression des numéros de noeuds + { ReactStoc& rea = reaction((*ili).un); + int num_noeud = (*ili).deux; // le noeud considéré + bool sortie_valide=false; // la sortie est validée ou non + while (num_noeud == (*ili).deux) + {switch (rea.ddl.Id_nom()) // on regarde les ddl + { case X1 : sortie_valide=true;break; + case X2 : sortie_valide=true;break; + case X3 : sortie_valide=true;break; + default: break; + }; + ili++; + }; + // arrivée ici il y a une incrémentation de trop, on revient en arrière + ili--; + if (sortie_valide) + { total_force++; + sort << num_noeud << " ";compteur++; + if (compteur > 20) {sort << "\n"; compteur=0;}; + }; + }; + + // --- maintenant on sort les forces + sort << "\n\n # --- les (" <& tab,const Nb_assemb& nb_casAssemb,Vecteur* vec2) + { + tempsCLL.Mise_en_route_du_comptage(); // temps cpu + + // on boucle sur le tableau et pour chaque element on impose une condition lineaire + int tabTaille = tab.Taille(); + bool modification = false; // init du retour + for (int i=1;i<= tabTaille; i++) + {Condilineaire& condi = tab(i); + // calcul des pointeurs d'assemblage + condi.ConditionPourPointeursAssemblage(nb_casAssemb); + // application de la condition + condlim(nb_casAssemb.n).CondlineaireCHRepere + ( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2); + modification=true; + }; + // affichage éventuelle de la matrice de raideur et du second membre + if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0)) + { string entete = " affichage de la matrice apres changement de repere du aux conditions limites externes (ex contact)"; + matglob.Affichage_ecran(entete); + entete = " affichage du second membre apres changement de repere du aux conditions limites externes (ex contact) "; + vecglob.Affichage_ecran(entete); + }; + tempsCLL.Arret_du_comptage(); // temps cpu + // retour du fait qu'il y a eu ou non une modification faite + return modification; + }; + +// mise en place de condition externe lineaires en une opération +// retour de la raideur et du second membre sans changement de repere +// ramène si oui ou non, il y a eu un changement effectué +// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob +// mais sans sauvegarde (correspond par exemple à une partie de vecglob) +bool LesCondLim::CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob + ,const Tableau & tab + ,const Nb_assemb& nb_casAssemb,Vecteur* vec2) + { + tempsCLL.Mise_en_route_du_comptage(); // temps cpu + + // on boucle sur le tableau et pour chaque element on impose une condition lineaire + int tabTaille = tab.Taille(); + bool modification = false; // init du retour + for (int i=1;i<= tabTaille; i++) + {Condilineaire& condi = tab(i); + // calcul des pointeurs d'assemblage + condi.ConditionPourPointeursAssemblage(nb_casAssemb); + // application d'une condition linéaire seule, avec en retour, la situation de la condition linéaire + // imposée, ramené dans le repère initial + condlim(nb_casAssemb.n).CondiLineaireImposeComplet + ( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2); + modification=true; + }; + // affichage éventuelle de la matrice de raideur et du second membre + if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0)) + { string entete = " affichage de la matrice apres application CLL externes (ex contact) "; + matglob.Affichage_ecran(entete); + entete = " affichage du second membre apres apres application CLL externes (ex contact) "; + vecglob.Affichage_ecran(entete); + }; + tempsCLL.Arret_du_comptage(); // temps cpu + // retour du fait qu'il y a eu ou non une modification faite + return modification; + }; + + +//initialisation, mise a zero des sauvegarde + void LesCondLim::InitSauve(const Nb_assemb& nb_casAssemb) + { condlim(nb_casAssemb.n).EffaceSauvegarde(); // blocages : second membre et matrice, + condlim(nb_casAssemb.n).EffaceCoLin(); // conditions lineaires + // puis les torseurs de réactions + int taille = tab_torseurReac.Taille(); + for (int i=1; i<= taille; i++) + if (tab_torseurReac(i).existe_torseur_reac) + tab_torseurReac(i).Zero_init_torseur(); + }; + +//----- lecture écriture dans base info ----- + // le cas d'assemblage n'est pas sauvegardé, car ce n'est pas une variable + // qui appartient réellement à la classe + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) +void LesCondLim::Lecture_base_info(ifstream& ent,const int cas,LesReferences& ,LesCourbes1D& + ,LesFonctions_nD& lesFonctionsnD) + { // les conditions linéaires qui varies par exemples dues au contact sont stockées + // autre part, dans LesContacts par exemple + string toto; + switch (cas) + { case 1: + { cout << "== lecture des conditions limites \n"; + // lecture du type et vérification + string nomtype; + ent >> nomtype; + if (nomtype != "****LesCondLim") + Sortie(1); + // lecture des différents tableaux + ent >> toto >> tabBloq >> toto >> tabInit + >> toto >> tab_iocondiline >> toto >> reaction >> toto >> reaction_CLin; + // dimensionnement du tableau des torseurs résultants + LesCondLim::DimensionneTorseurs(); + break; + } + case 2: + {// on lit les grandeurs relatives aux réactions + ent >> toto; + reaction.Entree(ent); + ent >> toto; + reaction_CLin.Entree(ent); + // lectue des temps cpu de l'algo: + ent >> toto >> tempsCL; + ent >> toto >> tempsCLL; + break; + } + default: + { cout << "\n **** erreur !! cas non prevu: cas = " << cas + << "\n LesCondLim::Lecture_base_info(..."; + Sortie(1); + } + }; + // on met à jour le tableau map_reaction +// map_reaction.erase(map_reaction.begin(),map_reaction.end()); +// int tail_reaction=reaction.Taille(); +// for (int j=1; j<=tail_reaction; j++) +// { map_reaction["mail"+ChangeEntierSTring(reaction(j).numMail) +// +"noeud"+ChangeEntierSTring(reaction(j).numNoeud)].push_back(&(reaction(j))); +// }; + }; + // cas donne le niveau de sauvegarde + // = 1 : on sauvegarde tout + // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) +void LesCondLim::Ecriture_base_info(ofstream& sort,const int cas) + { // les conditions linéaires qui varies par exemples dues au contact sont stockées + // autre part, dans LesContacts par exemple + switch (cas) + { case 1: + {// écriture du type + sort << "\n ****LesCondLim \n"; + // écriture des différents tableaux + sort << " blocage " << tabBloq; + sort << " initialisation " << tabInit; + sort << " CLL_en_entree " << tab_iocondiline; + sort << " reactions " << reaction; + sort << " reac_CLineaire " << reaction_CLin << " "; + break; + } + case 2: + {// on sort les grandeurs relatives aux réactions + // en fait les réactions sont également sauvé aux noeuds mais peut-être que ce sera utile + // d'avoir ici le type réaction stocké ?? donc on laisse + sort << " reac_ddl_bloque "; + reaction.Sortir(sort); + sort << " reac_CLineaire "; + reaction_CLin.Sortir(sort); sort << " "; + // écriture des temps cpu de l'algo: + sort << "\n tps_cpu_CL " << tempsCL; + sort << "\n tps_cpu_CLL " << tempsCLL; + break; + } + default: + { cout << "\n **** erreur !! cas non prevu: cas = " << cas + << "\n LesCondLim::Ecriture_base_info(..."; + Sortie(1); + } + }; + }; + + + + diff --git a/Maillage/LesCondLim.h b/Maillage/LesCondLim.h new file mode 100644 index 0000000..c02b480 --- /dev/null +++ b/Maillage/LesCondLim.h @@ -0,0 +1,581 @@ + +// 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: . + +/************************************************************************ + * DATE: 23/01/97 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: Gestion des differentes conditions limites * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ +#ifndef LESCONDLIM_H +#define LESCONDLIM_H + +#include "LectBloc_T.h" +#include "Tableau_T.h" +#include "DdlLim.h" +#include "UtilLecture.h" +#include "LesReferences.h" +#include "MotCle.h" +#include "LesMaillages.h" +#include "CondLim.h" +#include "Condilineaire.h" +#include "Nb_assemb.h" +#include "LesCourbes1D.h" +#include "LesFonctions_nD.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" +#include "Basiques.h" +#include "I_O_Condilineaire.h" +#include "Temps_CPU_HZpp.h" + +/** @defgroup Les_classes_relatives_aux_conditions_limites +* +* BUT:Gestion des differentes conditions limites +* +* \author Gérard Rio +* \version 1.0 +* \date 23/01/97 +* \brief Gestion des differentes conditions limites +* +*/ + +/// @addtogroup Les_classes_relatives_aux_conditions_limites +/// @{ +/// +class LesCondLim +{ + public : + // CONSTRUCTEURS : + LesCondLim (); // par defaut + // DESTRUCTEUR : + ~LesCondLim (); + + // METHODES PUBLIQUES : + + // lecture des conditions limites : ddl bloque + void Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef); + + // lecture des conditions limites linéaires + void Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef); + + // lecture des conditions limites : initialisation + void Lecture3(UtilLecture & entreePrinc,LesReferences& lesRef); + + // affichage des informations concernant les conditions limites + void Affiche() const ; // affichage de tous les infos + void Affiche1() const ; // affichage des ddl bloques + void Affiche2() const ; // affichage des conditions limites linéaires + void Affiche3() const ; // affichage des ddl d'initialisation + + // introduction des données et variables pour leurs emplois futures, avec init par défaut + void IntroductionDonnees (LesMaillages * lesMail,LesReferences* lesRef + ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD); + + // initialisation des ddl avec le tableau de ddl d'init + // verif de l'existence de tous les ddl (initialisation et imposes) + // ajout si necessaire, dans ce dernier cas l'initialisation est a zero + // choix = false : indique qu'il faut initialiser que les ddl a t + // choix = true : indique qu'il faut initialiser les ddl a t et t+dt + // vérification de l'existence des courbes de charge adoc si nécessaire + // cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque + // le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont + // leur statut modifié de manière équivalente + // =0 pas d'association + // =1 association X V GAMMA + void Initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D + ,LesFonctions_nD* lesFonctionsnD,bool choix,int cas); + +// // mise à jour de l'initialisation, par exemple après un restart +// // même paramètres que Initial, par contre ici il n'y a aucune création +// void Re_initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,bool choix,int cas); + + // initialisation du nombre de cas d'assemblage + // si inf au nombre actuel, aucune action + void InitNombreCasAssemblage(int nb_cas) + { if (nb_cas > condlim.Taille()) + condlim.Change_taille(nb_cas); + }; + + // incrementation des coordonnees a t+dt et des ddl en fonctions des ddl imposes + // et du chargement + // coef: est un facteur multiplicatif des ddl sans courbes de charge, + // est suposé intégrer déjà le multiplicateur général + // en fait du chargement impose + // mult_gene : multiplicateur général de tous les chargements + // deltat : incrément de temps actuel + // temps : le temps courant où sont calculées les conditions + // ch_statut : indique s'il y a changement ou non de statut des conditions limites (pour les ddl aux noeuds) + // c-a-d un ddl qui passe de bloqué à non bloqué ou inversement: il s'agit uniquement des ddl aux noeuds + // c-a-d ceux qui ont une influence sur la mise en place des cl sur la raideur et le résidu + // cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque + // le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont + // leur statut modifié de manière équivalente + // =0 pas d'association + // =1 association X V GAMMA + // lorsque en_ddl est égal à NU_DDL, cela signifie que l'on met les conditions limites sur tous les + // ddl de noeud actifs + // lorsque en_ddl est différent de NU_DDL, il donne le type des seules ddl pour lesquels on met les + // conditions de blocage: par exemple X1 -> blocage sur X1,X2,X3 selon la dimension + void MiseAJour_tdt + (const double& mult_gene,LesMaillages * lesMail,const double& deltat,const LesReferences* lesRef + ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD + ,const double& coef,bool& ch_statut + ,int cas , Enum_ddl en_ddl = NU_DDL); + + // mise en place de la répercussion sur les noeuds des conditions linéaires imposées externes (par les données d'entrées), + // ne prend pas en charge par exemple les CL dues aux contacts(gérés par CL) + // pour les paramètres: voir MiseAJour_tdt + void MiseAJour_condilineaire_tdt + (const double& mult_gene,LesMaillages * lesMail,const double& deltat,LesReferences* lesRef + ,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD + ,const double& coef,bool& ch_statut + ,int cas ,Enum_ddl en_ddl = NU_DDL); + + // validation des conditions de blocages et des conditions linéaire, pour l'incrément. + // concernant l'activité des ddlLim, elle est enregistrée en fonction du temps + // idem pour les conditions linéaires + void Validation_blocage (LesReferences* lesRef,const double& temps); + + // test s'il y a changement de statut pour le temps indiqué par rapport à la situation actuelle ou pas + // n'effectue aucune autre opération + // si en_ddl est différent de NU_DDL on test le changement de statut uniquement pour le ddl en_ddl + bool Changement_statut(const LesMaillages * lesMail,const LesReferences* lesRef + ,LesFonctions_nD* lesFonctionsnD + ,const double& temps,const Enum_ddl en_ddl = NU_DDL) ; + // récupération des tableaux d'indices généraux des ddl bloqués + // cas : donne le type d'association de ddl que l'on veut + // =0 -> pas d'association + // =1 -> association de Xi avec Vi avec Gammai + // t_assemb: donne pour chaque type d'association, le numéro d'assemblage correspondant au different ddl + // de l'association + // cas=1 -> numéro d'assemblage de X1 puis V1 puis GAMMA1 + // : en sortie une liste de Gene_asso, correspondant à tous les ddl bloqués et les + // les ddl associés + + // définition d'un conteneur pour la routine Tableau_indice + class Gene_asso + { public : + Gene_asso () : ty_prin(NU_DDL),pointe() {}; + Gene_asso (Enum_ddl ty_prin,const Tableau & pointes) : + ty_prin(ty_prin),pointe(pointes) {}; + Gene_asso (const Gene_asso& a) : ty_prin(a.ty_prin),pointe(a.pointe) {}; + Gene_asso& operator= (const Gene_asso& a) + {ty_prin=a.ty_prin;pointe=a.pointe;return (*this);}; + bool operator== (const Gene_asso& a) const + {if((ty_prin==a.ty_prin)&&(pointe==a.pointe)) return true;else return false;}; + bool operator!= (const Gene_asso& a) const + {if ( (*this)==a ) return true; else return false;}; + Enum_ddl ty_prin; // le ddl principal bloqué + Tableau pointe; // la position générale des ddl, principal et secondaire + // pour le cas 1 : pointe(k) -> la position du ddl Xi , puis Vi puis Gammai + }; + + list Tableau_indice(const LesMaillages * lesMail,const Tableau & t_assemb + ,const LesReferences* lesRef,const double& temps,int cas ); + + // mise en place des conditions limites sur les matrices et second membres + // (autres que les conditions linéaires) + // nb_casAssemb : le cas d'assemblage + // cas : indique un type d'association de ddl + // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré + // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un + // a été fixé par l'utilisateur + // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob + // mais sans sauvegarde (correspond par exemple à une partie de vecglob) + void ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef, + Mat_abstraite & matglob,Vecteur& vecglob + ,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2); + + // mise en place des conditions limites sur le second membres + // nb_casAssemb : le cas d'assemblage + // cas : indique un type d'association de ddl + // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré + // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un + // a été fixé par l'utilisateur + // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob + // mais sans sauvegarde (correspond par exemple à une partie de vecglob) + void ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef, + Vecteur& vecglob,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2); + + // mise en place des conditions limites sur deux matrices + // utilisé par exemple pour le flambement + // la première matrice est initialisée avec des 1 sur la diagonale + // la seconde avec des 0 sur la diagonale + // nb_casAssemb : le cas d'assemblage + // cas : indique un type d'association de ddl + // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré + // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un + // a été fixé par l'utilisateur + void ImpConLimtdt2Mat(LesMaillages * lesMail,LesReferences* lesRef, + Mat_abstraite & matglob,Mat_abstraite & matgeom + ,const Nb_assemb& nb_casAssemb,int cas); + + // retourne la valeur absolu du maxi des efforts exterieurs + // et le numero ili du ddl correspondant dans l'assemblage global + double MaxEffort(int & ili,const Nb_assemb& nb_casAssemb) + { return condlim(nb_casAssemb.n).MaxEffort(ili);}; + + // calcul des reactions et stockage des valeurs + // ceci dans le cas ou il n'y a pas de conditions lineaires appliquee + // on se sert des valeurs sauvegardees lors de la mise en place des CL bloquees + // nb_casAssemb : le cas d'assemblage + // cas : indique un type d'association de ddl + // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré + // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un + // a été fixé par l'utilisateur + void CalculReaction(LesMaillages * lesMail,LesReferences* lesRef + ,const Nb_assemb& nb_casAssemb,int cas); + + // récupération des reactions initiales, avant les rotations dues aux conditions linéaires + // il s'agit des réactions dues aux ddl bloqués et dues aux conditions linéaires + // et calcul des torseurs de réaction + void ReacAvantCHrepere(Vecteur& residu,LesMaillages * lesMail, + LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas); + + // récupération des reactions= residu et stockage des valeurs + // NB: après changement de repère, il n'y a plus que des ddl bloqués + // cas : indique un type d'association de ddl + // = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré + // = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un + // a été fixé par l'utilisateur + void ReacApresCHrepere(Vecteur& residu,LesMaillages * lesMail, + LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas); + + // affichage sur la sortie sort des reactions + void Affiche_reaction(ofstream& sort,const LesMaillages * lesMail) const ; + + // ------------------ conditions linéaires externes ---------------------------------------------- + + // mise en place de condition externe lineaires + // expression de la raideur et du second membre dans un nouveau repere + // ramène si oui ou non, il y a eu un changement effectué + // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob + // mais sans sauvegarde (correspond par exemple à une partie de vecglob) + bool CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob + ,const Tableau & tabCondLine + ,const Nb_assemb& nb_casAssemb,Vecteur* vec2); + + // blocage des seconds membres pour les conditions lineaires + // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob + // mais sans sauvegarde (correspond par exemple à une partie de vecglob) + inline void CoLinBlocage(Mat_abstraite & matglob,Vecteur& vecglob + ,const Nb_assemb& nb_casAssemb,Vecteur* vec2) + { condlim(nb_casAssemb.n).CondlineaireImpose ( matglob, vecglob,vec2);}; + + // retour des ddl dans le repere general, ceci dans le cas d'utilisation + // de conditions lineaires + inline void RepInitiaux( Vecteur& sol,const Nb_assemb& nb_casAssemb) + { condlim(nb_casAssemb.n).RepInitiaux(sol); }; + + // mise en place de condition externe lineaires en une opération + // retour de la raideur et du second membre sans changement de repere + // ramène si oui ou non, il y a eu un changement effectué + // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob + // mais sans sauvegarde (correspond par exemple à une partie de vecglob) + bool CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob + ,const Tableau & tabCondLine + ,const Nb_assemb& nb_casAssemb,Vecteur* vec2); + + + // -------- conditions linéaires internes: imposées par les conditions limites en entrée ----------- + + // mise en place des conditions linéaires imposées par les données d'entrée + // expression de la raideur et du second membre dans un nouveau repere + // ramène si oui ou non, il y a eu un changement effectué + // vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob + // mais sans sauvegarde (correspond par exemple à une partie de vecglob) + bool CoLinCHrepere_int(Mat_abstraite & matglob,Vecteur& vecglob,const Nb_assemb& nb_casAssemb,Vecteur* vec2); + // effacement du marquage de ddl bloque du au conditions lineaire imposées par les conditions d'entrée + void EffMarque(); + + // def de la largeur de bande en fonction des conditions linéaire limite en entrée + // casAssemb : donne le cas d'assemblage en cours + // les condi linéaires ne donnent pas des largeurs de bande sup et inf égales !!! + // demi = la demi largeur de bande , + // total = le maxi = la largeur sup + la largeur inf +1 + // cumule = la somme des maxis, ce qui donnera la largeur finale, due à des multiples multiplications: une par conditions linéaires + // dans le cas où on tiens compte des conditions linéaires par rotation (c-a-d sans multiplicateur ou pénalisation) + // en retour, ramène un booleen qui : + // = true : si la largeur de bande en noeud est supérieure à 1 + // = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur + // en noeud + bool Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb,LesMaillages * lesMail,LesReferences* lesRef + ,int& cumule); + + // création d'un tableau de condition linéaire, correspondant à toutes les conditions linéaires d'entrées + // qu'elles soient actives ou pas (a prior cette méthode est conçu pour donner des infos relativement à la largeur + // de bandes en noeuds due aux CLL) + // chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, + Tableau > ConnectionCLL(const LesMaillages * lesMail,const LesReferences* lesRef) const; + + // idem ConnectionCLL avec une liste, mais spécifiquement les conditions de type "stricte_egalite" entre ddl de noeud + // correspondant à toutes les conditions linéaires d'entrées actives uniquement + // (a priori cette méthode est conçu pour donner des infos pour condenser les pointeurs d'assemblages: + // LesMaillages::MiseAJourPointeurAssemblage() ) + // chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, et le type enumere de ddl + list ConnectionCLL_stricte_egalite + (const LesMaillages * lesMail,const LesReferences* lesRef) const; + + // récupération du tableau de conditions linéaires en cours + //résultant de l'application des conditions lues (indépendamment du contact par exemple) + // mis à jour après la méthode: MiseAJour_condilineaire_tdt + const Tableau < Tableau >& Tab_CLinApplique() const {return tab_CLinApplique;}; + + // indique si oui ou non il y a des conditions limites linéaires en entrée + bool ExisteCondiLimite() const {return tab_iocondiline.Taille();}; + + // ----------------------- fin conditions linéaires ------------------------------------------- + + //initialisation, mise a zero des sauvegarde + void InitSauve(const Nb_assemb& nb_casAssemb); + + // lecture de donnée en fonction d'un indicateur : int type + // pour l'instant ne fait rien + void LectureDonneesExternes(UtilLecture& ,LesReferences& ,const int ,const string&) {}; + + // affichage et definition interactive des commandes pour les conditions limites CL + void Info_commande_LesCondLim1(UtilLecture & entreePrinc); + + // affichage et definition interactive des commandes pour les conditions limites CLL + void Info_commande_LesCondLim2(UtilLecture & entreePrinc); + + // affichage et definition interactive des commandes pour les initialisations + void Info_commande_LesCondLim3(UtilLecture & entreePrinc); + + //----- lecture écriture de restart ----- + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) + void Lecture_base_info(ifstream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D + ,LesFonctions_nD& lesFonctionsnD); + // cas donne le niveau de sauvegarde + // = 1 : on sauvegarde tout + // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) + void Ecriture_base_info(ofstream& sort,const int cas); + + //------- temps cpu ----- + // retourne temps cumulé pour imposer les CL imposées + const Temps_CPU_HZpp& Temps_cpu_CL() const {return tempsCL;}; + // retourne le temps cumulé pour imposer les CLL + const Temps_CPU_HZpp& Temps_cpu_CLL() const {return tempsCLL;}; + +// --- conteneur pour les réactions ----- + class ReactStoc + { public : + // surcharge de l'operator de lecture typée + friend istream & operator >> (istream &, ReactStoc &); + // surcharge de l'operator d'ecriture typée + friend ostream & operator << (ostream &, const ReactStoc &); + + //Surcharge d'operateur logique + bool operator == ( const ReactStoc& a) const + { return ((numMail==a.numMail)&&(numNoeud==a.numNoeud) + &&(ddl==a.ddl)&&(casAss==a.casAss)); + }; + bool operator != ( const ReactStoc& a) const { return !(*this == a);}; + // !*!*!*! classement uniquement sur le numéro de noeud !*!*!*! + // --->> non: changement 3/1/2018 + bool operator < ( const ReactStoc& a) const + {if (numMail < a.numMail) return true; + else if (numMail == a.numMail) return (numNoeud < a.numNoeud); + else // cas où numMail > a.numMail + return false; + //return (numNoeud < a.numNoeud); + }; + bool operator > ( const ReactStoc& a) const { return !(*this < a);};; + + public : int numMail; // numero de maillage + int numNoeud ; // numero de noeud + Ddl ddl; // le ddl bloque + int casAss; // cas d'assemblage + }; + + class TorseurReac + {// surcharge de l'operator de lecture typée + friend istream & operator >> (istream &, TorseurReac &); + // surcharge de l'operator d'ecriture typée + friend ostream & operator << (ostream &, const TorseurReac &); + + public : + // constructeurs + TorseurReac():existe_torseur_reac(false),resultante(),moment(),bloque_ou_CLL(true) {}; + TorseurReac(const TorseurReac& a): + existe_torseur_reac(a.existe_torseur_reac),resultante(a.resultante) + ,moment(a.moment),bloque_ou_CLL(a.bloque_ou_CLL) {}; + // méthodes + void Activation(int dima) {existe_torseur_reac=true;resultante.Change_dim(dima); + moment.Change_dim(dima);}; + void Zero_init_torseur() {resultante.Zero();moment.Zero();}; + + // données + bool existe_torseur_reac; // indique si le Torseur doit-être calculé ou non + Coordonnee resultante; // la résultante du torseur + Coordonnee moment; // le moment du torseur par rapport à l'origine + bool bloque_ou_CLL; // true provient d'un ddl bloqué, false provient d'une CLL + }; + + + // retourne les réactions aux conditions limites à un noeud noe d'un maillage mail + // s'il n'y a pas de conditions limites : retour d'une liste vide +// const list& Reaction_noeud_mail(int mail,int noeud) const ; + + // retourne la liste des types de ddl actuellement imposés + // aux noeuds pour chaque maillage, la liste est exhaustive + // elle contiend tous les types au moins une fois utilisée + // cela ne signifie pas que le ddl en question soit présent + // pour tous les noeud du maillage considéré + // - le tableau de retour est indicé par le numéro de maillage correspondant + // - il y a une liste par maillage + Tableau > Les_type_de_ddl_en_reaction() const; + + // retourne la liste des torseurs de réaction actuellement actif pour les maillages + // appelons tab_lili la liste: + // - tab_lili(i) concerne le maillage nb i + // - les éléments de tab_lili(i) sont les noms des références qui conduisent à un torseur de réaction + // actif, et un indice de gestion utilisé par LesCondLim pour retrouver + // rapidemment les informations + Tableau < List_io > TabListTorseurReaction(const LesMaillages & lesmail) const; + // retourne le torseur de réaction correspondant à l'indice i + const TorseurReac & Torseur_de_reaction(int i) const {return tab_torseurReac(i);}; + + private : + // VARIABLES PROTEGEES : + Tableau tabBloq; // tableau des ddl bloques + Tableau tab_torseurReac; // tableau des torseurs de réaction + // relatif aux ddl bloqués et aux conditions linéaires + // de 1 à ttRG.Taille() on a les torseurs relatifs à tabBloq + // puis de ttRG.Taille() à la fin c-a-d ttRG.Taille()+ttRGCLL.Taille(), + // on a les torseurs relatifs à tab_iocondiline + + // un tableau, qui permet de passer de tabBloq à tab_torseurReac + Tableau ttRG; // tabBloq(i) contribue au torseur tab_torseurReac(ttRG(i)) + // ttorBloq(i) contient tous les numéros de tabBloq qui contribue au torseur i + Tableau < List_io > ttorBloq; + Tableau tabInit; // tableau des ddl d'initialisation + Tableau reaction; // les reactions pour les ddl bloqués + Tableau reaction_CLin; // les reactions pour les conditions linéaires + Tableau reactionApresCHrepere; // les reactions après CHrepere + + // tableau des conditions linéaires a imposer par les données d'entrée + Tableau tab_iocondiline; + Tableau < Tableau > tab_CLinApplique; // tableau des conditions linéaires + //résultant de l'application de tab_iocondiline + // un tableau à deux dim, qui permet de passer de tab_CLinApplique à tab_torseurReac + Tableau < Tableau > ttRGCLL; // tab_CLinApplique(i)(j) contribue au torseur tab_torseurReac(ttRGCLL(i)(j)) + // ttorCLL(i) contient tous les numéros de tab_iocondiline qui contribue au torseur i, avec + // le premier élément de l'instantce DeuxEntiers = le numéros dans tab_iocondiline, le second élement = le rang de + // la référence dans la condition linéaire + Tableau < List_io > ttorCLL; + + //deux liste de noms de ref qui servent pour accèder aux grandeurs globales correspondantes + // aux composantes des torseurs de réaction + // voir: DimensionneTorseurs() : + // ttRG_noms_ref + _Re_ + i -> ième composante de Re a tdt + // et à la place de Re -> Mo pour le moment + Tableau ttRG_noms_ref; // nom générique associé aux torseurs de ddl bloqué + Tableau ttRGCLL_noms_ref; // idem pour les CLL + + // une map pour faire l'association entre numéro de maillage et numéro de noeud d'une part + // et le tableau de réaction pour un accès quasi-directe +// map < string, list , std::less > map_reaction; + int nb_maillage; // sauvegarde du nombre de maillage + + Tableau < CondLim > condlim; // les fonctions et données qui permettent d'imposer les cl + // aux matrices, aux second membres, de remonter aux efforts apres + // resolution etc ..., le tableau est indicé par le numéro de cas d'assemblage + + //------- temps cpu ----- + Temps_CPU_HZpp tempsCL; // temps cumulé pour imposer les CL imposées + Temps_CPU_HZpp tempsCLL; // temps cumulé pour imposer les CLL + + // ----fonctions internes pour simplifier + + // cas de l'initialisation: prise en compte de l'appartenance à un groupe + // fixe : donne le type d'initialisation que l'on veut + // une_variable: indique si le ddl est une variable (=true) ou une donnée (=false) + void Init_appart_groupe(bool une_variable,Enum_ddl a,bool fixe,Noeud& noe, int cas,bool choix); + //cas courant: mise en place du blocage sur un ddl ou un groupe si besoin est + void Mise_cl(int nd,DdlLim& ddl,Enum_ddl a,Noeud& noe, int cas); + // cas courant : on retire le blocage sur un ddl ou un groupe si besoin est + void Retire_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas); + // vérification qu'il n'y a pas de surcharge de blocage + // choix indique si l'on vérifie à t ou à tdt + void Verif_surcharge_blocage(const LesMaillages * lesMail,const LesReferences* lesRef,const double& temps,int cas) ; + // fourni la liste des ddl associé de même dim, pour un du groupe et en fonction du cas d'association + // ramène une référence sur tab_travail qui est mis à jour + Tableau & Ddl_associe( Ddl& ddl,Noeud& noe,Tableau & tab_travail,int cas); + // cas particulier des mouvements solides, dans le second passage pour la méthode MiseAJour_tdt + void MiseAjour_tdt_second_passage_mvtSolide(const double& mult_gene,LesMaillages * lesMail + ,const double& deltat,int cas + ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD,const double& coef + ,DdlLim& tabBloq_i,const ReferenceNE & ref,const double& temps,Enum_ddl en_ddl); + // mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 + // --> pour au final obtenir le torseur des efforts globaux résultant de l'application d'un DdlLim + void CalculTorseurReaction(TorseurReac& tr, const Noeud& noe, ReactStoc& reac); + + // récupération de valeurs à un noeud pour les grandeur enu + // ici il s'agit de grandeur scalaires + Tableau Valeur_multi_interpoler_ou_calculer + (const Noeud& noe, Enum_dure temps,const List_io& enu); + // récupération de valeurs à un noeud pour les grandeur enu + // ici il s'agit de grandeurs tensorielles + void Valeurs_Tensorielles_interpoler_ou_calculer + (const Noeud& noe, Enum_dure temps,List_io& enu); + // dimensionnement du tableau des torseurs ainsi que des tableaux ttRG et ttorBloq + // en fonction de tabBloq (utilisé plusieurs fois), puis de ttRGCLL en fonction de tab_iocondiline + void DimensionneTorseurs(); + + // DdlLim à un noeud: mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD + void Mise_a_jour_t_minmax_ddlLim(Noeud& noe,DdlLim& ddlLim,LesFonctions_nD* lesFonctionsnD); + // DdlLim général: mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD + // ici les fct nD doivent dépendre uniquement de grandeur générale + void Mise_a_jour_t_minmax_ddlLim(DdlLim& ddlLim,LesFonctions_nD* lesFonctionsnD); + + }; + /// @} // end of group + + +#endif diff --git a/Maillage/LesCondLim2.cc b/Maillage/LesCondLim2.cc new file mode 100644 index 0000000..b32132b --- /dev/null +++ b/Maillage/LesCondLim2.cc @@ -0,0 +1,1965 @@ + + +// 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 "LesCondLim.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" +#include "CharUtil.h" +#include "TypeQuelconqueParticulier.h" + + + + // retourne la liste des types de ddl actuellement imposés + // aux noeuds pour chaque maillage, la liste est exhaustive + // elle contiend tous les types au moins une fois utilisée + // cela ne signifie pas que le ddl en question soit présent + // pour tous les noeud du maillage considéré + // - le tableau de retour est indicé par le numéro de maillage correspondant + // - il y a une liste par maillage +Tableau > LesCondLim::Les_type_de_ddl_en_reaction() const + { // définition du tableau de retour + Tableau > tab_li(nb_maillage); + // on boucle sur les réactions en cours pour remplir le tableau + int nb_reac=reaction.Taille(); + for (int i=1;i<=nb_reac;i++) + { List_io & li=tab_li(reaction(i).numMail); + Ddl_enum_etendu ddl_enu = (reaction(i).ddl.Id_nom()); + if (find(li.begin(),li.end(),ddl_enu) == li.end()) + li.push_back(ddl_enu); + }; + // retour du tableau de listes + return tab_li; + }; + +/* // retourne les réactions aux conditions limites à un noeud noe d'un maillage mail + // en paramètre il y a un pointeur sur la liste de retour, pour éviter la création + // d'une liste intermédiaire + // s'il n'y a pas de conditions limites : retour d'une liste vide +const list& LesCondLim::Reaction_noeud_mail(int numNoeud,int numMail) const + { string cle("mail"+ChangeEntierSTring(numMail)+"noeud"+ChangeEntierSTring(numNoeud)); + map < string, list , std::less >::const_iterator it = map_reaction.find(cle); + if (it != map_reaction.end()) + { return (*it).second;}; + // sinon pas d'existence donc retour d'une liste vide + const list li; // construction d'une liste vide + return li; + }; */ + +// retourne la liste des torseurs de réaction actuellement actif pour les maillages +// appelons tab_lili la liste: +// - tab_lili(i) concerne le maillage nb i +// - les éléments de tab_lili(i) sont les noms des références qui conduisent à un torseur de réaction +// actif, et un indice de gestion utilisé par LesCondLim pour retrouver +// rapidemment les informations +Tableau < List_io > LesCondLim::TabListTorseurReaction(const LesMaillages & lesmail) const + { // def de la grandeur de retour + Tableau < List_io > tab_lili(nb_maillage); + string nom; // une variable de travail + // on balaie le tableau des torseur + int ttail = tab_torseurReac.Taille(); // tabBloq, tab_iocondiline et tab_torseurReac n'ont pas la même dimension + for (int i=1;i<= ttail;i++) + { TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier + if (torseurReac.existe_torseur_reac) + {if (torseurReac.bloque_ou_CLL) + // cas où le torseur provient d'une condition ddl bloquée + {DdlLim& tabBloq_i = tabBloq(*(ttorBloq(i).begin())); // pour simplifier + if (tabBloq_i.NomMaillage() != NULL) + { const string& nom_maillage = *(tabBloq_i.NomMaillage()); // nom de maillage lue + tab_lili(lesmail.NumMaillage(nom_maillage)).push_back(String_et_entier(tabBloq_i.NomRef(),i)); + } + else + {tab_lili(1).push_back(String_et_entier(tabBloq_i.NomRef(),i)); + }; + } + else + // cas où le torseur provient d'une condition CLL + {I_O_Condilineaire& iocondiline_i = tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier + if (iocondiline_i.NomMaillage() != NULL) + // cas où on considère les noms de maillage + { int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier + if (num_ref == 1) + { // cas d'une référence principale de CLL + const string& nom_maillage = *(iocondiline_i.NomMaillage()); + tab_lili(lesmail.NumMaillage(nom_maillage)).push_back + (String_et_entier(iocondiline_i.NomRef()+"_CLL",i)); + } + else + {// cas d'une référence associé + // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris + // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1 + // qui correspond à la référence principale + const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux-1); + tab_lili(lesmail.NumMaillage(nom_maillage)).push_back + (String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i)); + }; + } + else + {// cas où on ne considère pas les noms de maillage + int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier + if (num_ref == 1) + {// cas d'une référence principale de CLL + tab_lili(1).push_back(String_et_entier(iocondiline_i.NomRef()+"_CLL",i)); + } + else + {// cas d'une référence associé + // on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris + // la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1 + // qui correspond à la référence principale + tab_lili(1).push_back + (String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i)); + }; + }; + }; + }; + }; + // retour des infos + return tab_lili; + }; + +// affichage et definition interactive des commandes pour les conditions limites CL +void LesCondLim::Info_commande_LesCondLim1(UtilLecture & entreePrinc) +{ + cout << "\n# ----- definition des conditions limites cinematiques ----- "; + bool plusieurs_maillages = false; + string rep="_"; + + ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier + // écriture de l'entête + sort << "\n blocages #------------# " + << "\n#-----------------------------------------------------------" + << "\n# nom du maillage | Ref noeud | Blocages" + << "\n#-----------------------------------------------------------"; + // def des conditions + try + {cout << "\n cas d'un seul maillage (par defaut) : rep o " + << "\n cas de plusieurs maillages : rep n "; + rep = lect_return_defaut(true,"o"); + if (rep == "n") + { plusieurs_maillages = true; cout << "\n --> les prochaines CL seront associees a un nom de maillage ";}; + rep="_"; // init + // boucle globale + while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) + { cout << "\n (0 ou f) (fin) " + << "\n (1) def d'une nouvelle condition " + << "\n "; + rep = lect_return_defaut(false,"f"); + + if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe + break; + int num = ChangeEntier(rep); + bool choix_valide=false; + if ((num >= 0)&&(num<=1)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + }; + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: // def d'une liste d'elements associe a un nom de loi + { DdlLim unddl; // init + unddl.Info_commande_DdlLim(sort,plusieurs_maillages); + break; + } + default: + cout << "\n le cas "< les prochaines CLL seront associees a un nom de maillage ";}; + rep="_"; // init + // boucle globale + while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) + { cout << "\n (0 ou f) (fin) " + << "\n (1) def d'une nouvelle condition " + << "\n "; + rep = lect_return_defaut(false,"f"); + + if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe + break; + int num = ChangeEntier(rep); + bool choix_valide=false; + if ((num >= 0)&&(num<=1)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + }; + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: // def d'une liste d'elements associe a un nom de loi + { I_O_Condilineaire uneCLL; // init + uneCLL.Info_commande_conditionLineaire(sort,plusieurs_maillages); + break; + } + default: + cout << "\n le cas "< les prochaines CL seront associees a un nom de maillage ";}; + rep="_"; // init + // boucle globale + while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) + { cout << "\n (0 ou f) (fin) " + << "\n (1) def d'une nouvelle condition " + << "\n "; + rep = lect_return_defaut(false,"f"); + + if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe + break; + int num = ChangeEntier(rep); + bool choix_valide=false; + if ((num >= 0)&&(num<=1)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + }; + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: // def d'une liste d'elements associe a un nom de loi + { DdlLim unddl; // init + unddl.Info_commande_DdlLim(sort,plusieurs_maillages); + break; + } + default: + cout << "\n le cas "< tmc = MemeCombinaison(cas,enu); + int taille = tmc.Taille(); + for (int i=1;i<=taille;i++) + {if(tmc(i) != enu) // on ne traite que les cas différents du ddl principal + { if (noe.Existe_ici(tmc(i))) + { // le ddl existe déjà, on le met à fixe + // mais on ne change pas sa valeur + if (fixe) + { noe.Change_fixe(tmc(i),true);} + // en fait on ne met pas à libre si fixe en false, on ne vérifie pas qu'il y a superposition + // de plusieurs initialisations en libre, celle-ci pouvant venir de plusieurs raisons que l'on ne peut + // pas gérer ici : par exemple au moment de la création des éléments il y a mise en place des ddl à libre + // avant l'initialisation donc si l'on impose par exemple la vitesse, X sera en souslibre !! + // else + // { noe.Change_fixe(tmc(i),false);} + } + else + // sinon on le cré, et on met à zéro + { if (fixe) + { if (une_variable) { Ddl inter(tmc(i),0.0,HSFIXE); noe.PlusDdl(inter);} + else { Ddl inter(tmc(i),0.0,HS_LISIBLE_FIXE); noe.PlusDdl(inter);}; + } + else + { if (une_variable) { Ddl inter(tmc(i),0.0,HSLIBRE); noe.PlusDdl(inter);} + else { Ddl inter(tmc(i),0.0,HS_LISIBLE_LIBRE); noe.PlusDdl(inter);}; + }; + noe.Change_val_0(tmc(i),0.); + noe.Change_val_t(tmc(i),0.); + if (choix) + noe.Change_val_tdt(tmc(i),0.); + }; + }; + }; + }; //-- fin du cas ou le ddl fait partie d'une combinaison +}; + +// mise en place du blocage sur un ddl ou un groupe si besoin est +void LesCondLim::Mise_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas) + { + // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl + // on vérifie que le ddl appartient au groupe sinon traitement simple + if (Dans_combinaison(cas,enu)) + { // le ddl appartient au groupe, on modifie globalement + // récup des enu_ddl équivalent au groupe + Tableau tmc = MemeCombinaison(cas,enu); + int taille = tmc.Taille(); + for (int i=1;i<=taille;i++) + noe.Change_fixe(tmc(i),true); + // le ddl du tableau des ddl bloqués est mis en service + (ddlbloqu.ElemLim(nd)).Met_en_service(); + } + else // le ddl fixé n'appartient pas au groupe on le traite isolément + { noe.Change_fixe(enu,true); // le noeud est fixé + // le ddl du tableau est mis en service + (ddlbloqu.ElemLim(nd)).Met_en_service(); + }; + }; + + +// on retire le blocage sur un ddl ou un groupe si besoin est +void LesCondLim::Retire_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas) + { // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl + // on vérifie que le ddl appartient au groupe sinon traitement simple + if (Dans_combinaison(cas,enu)) + { // le ddl appartient au groupe, on modifie globalement + // récup des enu_ddl équivalent au groupe + Tableau tmc = MemeCombinaison(cas,enu); + int taille = tmc.Taille(); + for (int i=1;i<=taille;i++) + noe.Change_fixe(tmc(i),false); + // le ddl du tableau des ddl bloqués est mis hors service + (ddlbloqu.ElemLim(nd)).Met_hors_service(); + } + else // le ddl fixé n'appartient pas au groupe on le traite isolément + { noe.Change_fixe(enu,false); // le noeud est libéré + // le ddl du tableau est mis hors service + (ddlbloqu.ElemLim(nd)).Met_hors_service(); + }; + }; + +// vérification qu'il n'y a pas de surcharge de blocage +// choix indique si l'on vérifie à t ou à tdt +void LesCondLim::Verif_surcharge_blocage + (const LesMaillages * lesMail,const LesReferences* lesRef,const double& temps,int cas) +{ // prépa retour + bool erreur_blocage = false; + Tableau tmc; // tableau de travail + + int tabBloqTaille =tabBloq.Taille(); + // on parcours le tableau de ddl bloques + for (int i=1;i<= tabBloqTaille;i++) + { DdlLim& tabBloq_i = tabBloq(i); + // recup de la reference correspondant au mot cle + const ReferenceNE & ref = + ((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage())); + + if (!((ref.Indic() == 4) && // dans le cas des conditions de tangence sur + (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) // les arrêtes on n'applique pas ces vérifs + ) + {int reftaille = ref.Taille(); + for (int nn =1; nn<= reftaille;nn++) + {int tabBloqitaille = tabBloq_i.Taille(); + // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer + // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage + int idebut=1; int ifinfin = tabBloqitaille;// début normale + if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;}; + for (int nd=idebut;nd<= ifinfin ;nd++) + {Ddl ddl = tabBloq_i.ElemLim(nd); + // pour le ddlLim, si le temps est inférieur au temps actif + // ou si d'une part le temps n'est pas actif et qu'au pas précédent + // il n'était pas également actif on ne fait rien + if (tabBloq_i.Pas_a_prendre_en_compte(temps)) break; + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + // on regarde si l'on a fixé plusieurs fois ou libéré plusieurs foix + // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi + // if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + // récup des enu_ddl équivalent au groupe, pour l'instant on n'a que la combinaison 1 qui comporte plus d'un élément + if (Dans_combinaison(cas,ddl.Id_nom())) + {tmc = MemeCombinaison(cas,ddl.Id_nom());} + else + // sinon pour l'instant on fait comme si cas == 0 c'est à dire pas de combinaison + {tmc = MemeCombinaison(0,ddl.Id_nom());}; + int tailletmc = tmc.Taille(); + for (int itc=1;itc <= tailletmc;itc++) + {if (noe.Ddl_sous_ou_sur_fixe(tmc(itc))) + // cas d'un problème éventuel + { // message d'avertissement + if (ParaGlob::NiveauImpression() >= 6) + cout << "\n ***** ATTENTION *****, le ddl " << ddl.Nom() << " du noeud " << noe.Num_noeud() + << " du maillage " << lesMail->NomMaillage(noe.Num_Mail()) << " est bloque plusieurs fois"; + if (ParaGlob::NiveauImpression() >= 7) + cout << ", cela indique que plusieurs conditions limites sont supperposees"; + if (ParaGlob::NiveauImpression() >= 8) + { cout << " \n temps = " << temps << ", reference de blocage, et ddl limite correspondant"; + ref.Affiche(); tabBloq_i.Affiche(); + cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl; + } + // remise à normal du ddl pour que le calcul puisse continuer + noe.Retour_a_la_normal_sur_ou_sous_fixe(tmc(itc)); + erreur_blocage = true; // pour un traitement global d'erreur éventuel + }; + }; //-- fin du for (int itc=1;itc <= tailletmc;itc++) + }; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++) + }; //-- fin du for (int nn =1; nn<= reftaille;nn++) + }; //-- fin du if (!((ref.Indic() == 4) &&(tabBloq_i.TypeDeCL()==TANGENTE_CL) ) + }; //-- fin du for (int i=1;i<= tabBloqTaille;i++) +}; + +// fourni la liste des ddl associé de même dim, pour un du groupe et en fonction du cas d'association +// ramène une référence sur tab_travail qui est mis à jour +Tableau & LesCondLim::Ddl_associe (Ddl& ddl,Noeud& noe,Tableau & tab_travail,int cas) + { // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi +// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); + if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom())); + Enum_ddl enu = ddl.Id_nom(); // pour simplifier + // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl + // on vérifie que le ddl appartient au groupe sinon traitement simple + if (Dans_combinaison(cas,enu)) + { // le ddl appartient au groupe, on modifie globalement + // récup des enu_ddl équivalent au groupe + Tableau tmc = MemeCombinaison(cas,enu); + int taille = tmc.Taille(); + for (int i=1;i<=taille;i++) + { ddl.Change_nom(tmc(i)); + tab_travail(i) = ddl; + } + } + else // le ddl fixé n'appartient pas au groupe on le traite isolément + { tab_travail.Change_taille(1); + tab_travail(1) = ddl; + }; + return tab_travail; + }; + +// cas particulier des mouvements solides, dans le second passage pour la méthode MiseAJour_tdt +void LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(const double& mult_gene,LesMaillages * lesMail + ,const double& deltat,int cas + ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD,const double& coef + ,DdlLim& tabBloq_i,const ReferenceNE & ref,const double& temps,Enum_ddl en_ddl) + { bool tous_les_blocages = true; + if (en_ddl != NU_DDL) tous_les_blocages = false; + int reftaille = ref.Taille(); + int dima = ParaGlob::Dimension(); + if(ParaGlob::AxiSymetrie()) + // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les + // dimension-1 coordonnées donc on décrémente + dima--; + // on regarde si les temps dépendent d'une fct nD + // si oui on modifie les bornes du ddl + if (tabBloq_i.Temps_depend_nD()) + LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD); + // pour le ddlLim, si le temps est inférieur au temps actif + // ou si d'une part le temps n'est pas actif et qu'au pas précédent + // il n'était pas également actif on ne fait rien + if (tabBloq_i.Pas_a_prendre_en_compte(temps)) + return; + bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier + if (!actif_pour_le_temps) + return; // je ne vois pas trop pourquoi, mais semble cohérent avec le prog général (à voir) + // petite vérif + int tabBloqitaille = tabBloq_i.Taille(); // normalement il y a uniquement les déplacements + #ifdef MISE_AU_POINT + if (tabBloqitaille != dima) + { cout << "\nErreur : le nombre de ddl bloque pour un mouvement solide doit etre egale a la dimension du pb " + << " ici ParaGlob::Dimension() = " << dima << " et le nombre de ddl bloque = " << tabBloqitaille ; + cout << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... "; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + Sortie(1); + }; + #endif + + // --- dans le cas où il y a des centres de rotation qui sont des positions de noeud, on renseigne + // a) récupération des centres de rotation noeud, éventuellement + const list & lis_centre_noeud = (tabBloq_i.MouvementSolide())->Liste_ident_centreNoeud(); + if (lis_centre_noeud.size() != 0) + { list ::const_iterator ict,ictfin=lis_centre_noeud.end(); + list list_coor; // liste des coordonnées des noeuds centre de rotation + for (ict = lis_centre_noeud.begin();ict!=ictfin;ict++) + {if ((*ict).nom == "") + // cas où on n'a pas de nom de maillage + { list_coor.push_back(lesMail->Noeud_LesMaille(1, (*ict).n).Coord2()); } + else // cas où on a plusieurs maillages + { int num_maill= lesMail->NumMaillage((*ict).nom); + list_coor.push_back(lesMail->Noeud_LesMaille(num_maill, (*ict).n).Coord2()); + }; + }; + // b) maintenant on passe l'info au mouvement solide + (tabBloq_i.MouvementSolide())->RenseigneCentreNoeud(list_coor); + }; + + // maintenant soit le ddlLim est actif ou il change de statut: actif à non actif + // on boucle sur les noeuds de la référence + for (int nn =1; nn<= reftaille;nn++) + {// ici on travaille sur les dima ddl de déplacements en même temps: + // mais on se sert du premier comme indicateur + Ddl ddl = tabBloq_i.ElemLim(1); // le premier ddl normalement est UX + // on fait une manip sur les UX <-> Xi pour distinguer les cas méca du solide et les autres + Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn)); + if (noe.Existe_ici(X1)) + // cas de deplacements imposes en entraine on change donc les Ui en Xi + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + bool a_considerer = tous_les_blocages; + if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux + {if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;}; + if (a_considerer) + { // def du point qui contiendra les coordonnées finales après rotation + Coordonnee M(dima); + // traitement en fonction du cas où il y courbe de charge ou pas + if ((tabBloq_i.Nom_courbe(1) != "")&&(tabBloq_i.NomF_charge(1) == "")) + { // cas d'une courbe de charge, récup de la courbe + // pour les mouvements solides la courbe de charge et l'échelle sont stockées dans le premier ddl + Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1)); + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat + M = noe.Coord1(); // on travaille donc à partir des coordonnées à t + double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1) + * ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ; + (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); + } + else + { // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent + // et ici on considère la totalité du chargement de 0 au temps actuel + M = noe.Coord0(); // on travaille donc avec les coordonnées initiales + double amplitude = mult_gene * (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(1); + (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); + }; + } + else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) == "")) + { // cas d'une fonction nD de charge, récup + Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1)); + // on commence par récupérer les conteneurs des grandeurs à fournir + List_io & li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire(); + List_io & li_quelc = pt_fctnD->Li_equi_Quel_evolue(); + // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire + Tableau val_ddl_enum(Valeur_multi_interpoler_ou_calculer + (noe, TEMPS_tdt,li_enu_scal)); + // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur + Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc); + // calcul de la valeur et retour dans tab_ret + Tableau & tab_ret = pt_fctnD->Valeur_FnD_Evoluee + (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL); + #ifdef MISE_AU_POINT + if (tab_ret.Taille() != 1) + {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " + << "\n *** blocage via une fonction nD pour l'evolution d'un mouvement solide " + << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... "; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + Sortie(1); + }; + #endif + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // pour l'instant a priori ce n'est pas possible car le temps + // est une variable globale que l'on ne peut pas modifier pour les fonctions nD + // il faut donc utiliser conjointement une courbe1D pour le temps et la fonction nD pour le reste + cout << "\n *** blocage relatif d'un mouvement solide avec uniquement une fonction nD: ce n'est pas possible" + << " pour avoir un blocage relatif il faut utiliser conjointement une courbe de charge " + << " pour le temps et une fonction nD pour le reste !!!!" + << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... "; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + Sortie(1); + } + else + { // la fonction donne la valeur de l'amplitude de 0 au temps présent + // et ici on considère la totalité du chargement de 0 au temps actuel + M = noe.Coord0(); // on travaille donc avec les coordonnées initiales + double amplitude = mult_gene * (tab_ret(1)) * tabBloq_i.Echelle_courbe(1); + (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); + }; + } + else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) != "")) + { // cas d'une fonction nD de charge, récup + Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1)); + // on commence par récupérer les conteneurs des grandeurs à fournir + List_io & li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire(); + List_io & li_quelc = pt_fctnD->Li_equi_Quel_evolue(); + // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire + Tableau val_ddl_enum(Valeur_multi_interpoler_ou_calculer + (noe, TEMPS_tdt,li_enu_scal)); + // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur + Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc); + // calcul de la valeur et retour dans tab_ret + Tableau & tab_ret = pt_fctnD->Valeur_FnD_Evoluee + (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL); + #ifdef MISE_AU_POINT + if (tab_ret.Taille() != 1) + {cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte " + << "\n *** blocage via une fonction nD pour l'evolution d'un mouvement solide " + << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... "; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + Sortie(1); + }; + #endif + // idem pour la courbe 1D + Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1)); + if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent + { // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat + M = noe.Coord1(); // on travaille donc à partir des coordonnées à t + double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1) * tab_ret(1) + * ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ; + (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); + } + else + { // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent + // et ici on considère la totalité du chargement de 0 au temps actuel + M = noe.Coord0(); // on travaille donc avec les coordonnées initiales + double amplitude = mult_gene * (pt_courbe->Valeur(temps)) + * tab_ret(1) * tabBloq_i.Echelle_courbe(1); + (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude); + }; + } + else + // cas d'un mouvement à valeur fixe, on calcul l'accroissement par rapport au pas précédent + // coef intègre le multiplicateur global: mult_gene, et intègre l'acroissement par rapport au pas précédent + { M = noe.Coord1(); + (tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,coef); + }; + + // maintenant on s'occupe de la mise à jour ou non des positions du noeud + for (int nd=1;nd<= tabBloqitaille ;nd++) // en fait ici nd =1 pour UX, =2 pour UY et =3 pour UZ + {Ddl ddl = tabBloq_i.ElemLim(nd); + if (noe.Existe_ici(X1)) + // cas de deplacements imposes en entraine on change donc les Ui en Xi + ddl.Change_nom(UxyzXi(ddl.Id_nom())); + Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier + bool une_variable = noe.UneVariable(ddlenu); // pour simplifier + // cas des variables: si le ddl du noeud est en service on continue sinon on ne fait rien + // ou cas d'une donnée et le temps actif, mais si on arrive ici le temps est forcément actif + if ( ( une_variable && noe.En_service(ddlenu)) ||(!une_variable) ) + { // gestion des surcharges de blocage + // au second passage on fixe les ddl actifs + Mise_cl(nd,tabBloq_i,ddlenu,noe,cas); + // on met à jour les coordonnées finales + noe.Change_val_tdt(ddlenu,M(nd)); // car nd =1 pour UX, =2 pour UY, =3 pour UZ + };//-- fin du test si le ddl du noeud est en service + }; //-- fin de la boucle sur tabBloq_i + };//-- fin du test si le noeud est à considérer ou pas + }; //-- fin de la boucle sur nn + }; + +// mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3 +// --> pour au final obtenir le torseur des efforts globaux résultant de l'application d'un DdlLim +void LesCondLim::CalculTorseurReaction(TorseurReac& tr, const Noeud& noe, ReactStoc& reac) + { int dimension = ParaGlob::Dimension(); + if(ParaGlob::AxiSymetrie()) + // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les + // dimension-1 coordonnées donc on décrémente + dimension--; + switch (dimension) + { case 1: // pas de moment, et uniquement une résultante suivant x + if (reac.ddl.Id_nom() == X1) tr.resultante(1) += reac.ddl.Valeur(); + break; + case 2 : // un moment autour de z, et deux composantes de résultante + // le moment est en dim 2, on stocke le moment dans la première composante !!! + switch (reac.ddl.Id_nom()) + { case X1: + { tr.resultante(1) += reac.ddl.Valeur(); + tr.moment(1) -= noe.Valeur_tdt(X2) * reac.ddl.Valeur(); // correspond à z + break; + }; + case X2: + { tr.resultante(2) += reac.ddl.Valeur(); + tr.moment(1) += noe.Valeur_tdt(X1) * reac.ddl.Valeur(); // correspond à z + break; + }; + default: break; + } + break; + case 3 : // 3 composante de moment et de résultante + switch (reac.ddl.Id_nom()) + { case X1: + { tr.resultante(1) += reac.ddl.Valeur(); + tr.moment(2) += noe.Valeur_tdt(X3) * reac.ddl.Valeur(); + tr.moment(3) -= noe.Valeur_tdt(X2) * reac.ddl.Valeur(); + break; + }; + case X2: + { tr.resultante(2) += reac.ddl.Valeur(); + tr.moment(1) -= noe.Valeur_tdt(X3) * reac.ddl.Valeur(); + tr.moment(3) += noe.Valeur_tdt(X1) * reac.ddl.Valeur(); + break; + }; + case X3: + { tr.resultante(3) += reac.ddl.Valeur(); + tr.moment(1) += noe.Valeur_tdt(X2) * reac.ddl.Valeur(); + tr.moment(2) -= noe.Valeur_tdt(X1) * reac.ddl.Valeur(); + break; + }; + default: break; + } + break; + // les autres cas ne sont pas pris en compte + }; + }; + + +// mise en place des conditions linéaires imposées par les données d'entrée +// expression de la raideur et du second membre dans un nouveau repere +// ramène si oui ou non, il y a eu un changement effectué +// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob +// mais sans sauvegarde (correspond par exemple à une partie de vecglob) +bool LesCondLim::CoLinCHrepere_int(Mat_abstraite & matglob,Vecteur& vecglob + ,const Nb_assemb& nb_casAssemb,Vecteur* vec2) + { // on boucle sur le tableau de conditions limites linéaires enregistré + // et pour chaque element on impose une condition lineaire + bool modification = false; // init du retour + int tabTaille = tab_CLinApplique.Taille(); + for (int i=1;i<= tabTaille; i++) + {int sous_taille = tab_CLinApplique(i).Taille(); + for (int j=1; j<= sous_taille; j++) + { Condilineaire& condi = tab_CLinApplique(i)(j); +//debug +//cout << "\n LesCondLim::CoLinCHrepere_int " << condi; +//fin debug + // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 + if (condi.Iddl() > -1) + { // calcul des pointeurs d'assemblage + condi.ConditionPourPointeursAssemblage(nb_casAssemb); + // application de la condition + condlim(nb_casAssemb.n).CondlineaireCHRepere + ( matglob,vecglob,condi.Pt_t(),condi.Val(),0.,vec2); // ancienne version +// la valeur imposée est systématiquement 0 comme pour le cas des autres conditions bloquée +// car la résolution donnera delta_ddl' qui doit être null pour les ddl imposés + modification=true; + }; + }; + }; + + // affichage éventuelle de la matrice de raideur et du second membre + if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0)) + { string entete = " affichage de la matrice apres changements de reperes dus aux conditions lineaires "; + matglob.Affichage_ecran(entete); + entete = " affichage du second membre apres changements de reperes dus aux conditions lineaires "; + vecglob.Affichage_ecran(entete); + }; + // retour du fait qu'il y a eu ou non une modification faite + return modification; + }; + +// effacement du marquage de ddl bloque du au conditions lineaire extérieures (hors du contact par exemple) +void LesCondLim::EffMarque() + { // préparation + // on boucle sur le tableau des conditions limites linéaires imposées réellement + int tabTaille = tab_CLinApplique.Taille(); + for (int icondli=1;icondli<= tabTaille; icondli++) + { Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli); + int nbcondi = t_condiAppli.Taille(); + // on boucle sur les conditions + for (int ico=1;ico<=nbcondi;ico++) + { Condilineaire & condi = t_condiAppli(ico); // pour simplifier + // on n'intervient que si la condition est exploitable c-a-d Iddl() > -1 + if (condi.Iddl() > -1) + { // récup du noeud principal + Noeud * noe=condi.Noe(); + noe->Change_fixe(condi.Tab_Enum()(1),false); + }; + }; + }; + }; + +// def de la largeur de bande en fonction des conditions linéaire limite en entrée +// casAssemb : donne le cas d'assemblage en cours +// les condi linéaires ne donnent pas des largeurs de bande sup et inf égales !!! +// demi = la demi largeur de bande , +// total = le maxi = la largeur sup + la largeur inf +1 +// cumule = la somme des maxis, ce qui donnera la largeur finale, due à des multiples multiplications: une par conditions linéaires +// dans le cas où on tiens compte des conditions linéaires par rotation (c-a-d sans multiplicateur ou pénalisation) +// en retour, ramène un booleen qui : +// = true : si la largeur de bande en noeud est supérieure à 1 +// = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur +// en noeud +bool LesCondLim::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb + ,LesMaillages * lesMail,LesReferences* lesRef,int& cumule) + { demi = total = cumule = 0; // initialisation + bool retour = false; // par défaut + int nb_ass = casAssemb.n; + // on boucle sur le tableau et pour chaque condition + int tabTaille = tab_iocondiline.Taille(); // le nombre de condition + for (int icondli=1;icondli<= tabTaille; icondli++) + {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier + // recup de la reference principal correspondant au mot cle + const ReferenceNE & refp = + ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); + int nb_n_princ = refp.Taille(); + // recup du tableau des références secondaires associées si elles existent + const Tableau & nomRefassocie = iocondiline_i.ReferenceAssociees(); + const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); + + int tailrefasso = nomRefassocie.Taille(); + Tableau * > tab_numNoeud_associe(tailrefasso); + Tableau tab_numMail_associe(tailrefasso); + if (tailrefasso != 0) + {retour = true; // comme il y a des ref associés, la largeur en noeud sera > à 1 + for (int k=1;k<=tailrefasso;k++) + {const string * nom_maillage=NULL; + if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); + const ReferenceNE & refasso = + ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); + tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés + tab_numMail_associe(k)= refasso.Nbmaille(); + }; + }; + // on boucles sur les noeuds de la ref principale + int tail_t_noe = tailrefasso+1; + Tableau t_noe(tail_t_noe); // tableau de travail + // dans la boucle qui suit on définit t_noe, c'est à dire l'ensemble des noeuds + // concernés par la condition linéaire. + // puis avec ce tableau, on en déduit la largeur de bande associée + for (int in=1;in<=nb_n_princ;in++) + { // récup du noeud principal + Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); + t_noe(1)= &noe; + // on ne continue que si le type de ddl de la condition limite est actif pour le noeud + // et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte + // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) + Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier + if (enu_condline==UX) enu_condline = X1; // les ui sont géré avec les xi + if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline)) + {// récupération des noeuds associés, on utilise le même indice dans les ref associées que + // dans la ref principale + for (int ia = 1;ia<=tailrefasso;ia++) + t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); + // maintenant on va effectivement pouvoir calculer la largeur de bande correspondant + // aux noeuds du tableau t_noe + + // 1) on a par défaut au moins une relation entre les ddl du noeud principal + int diprinc = noe.NB_ddl_actif_casAssemb(nb_ass); + if ( diprinc-1 > demi) demi = diprinc-1; + if ( (2*diprinc-1) > total) total = 2*diprinc-1; + cumule += 2*diprinc-1; + + // 2) maintenant on s'occupe de la relation entre les différents noeuds de numéros différencts + int maxiPourLaCondition=0; // stocke le maxi pour chaque condition linéaire + for (int inoe=1; inoe<= tail_t_noe;inoe++) + for ( int jnoe=inoe+1; jnoe<=tail_t_noe;jnoe++) + { Noeud & nne = *(t_noe(inoe)); + Noeud & nno = *(t_noe(jnoe)); + int di=0; + if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass)) + { di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass) + + nne.NB_ddl_actif_casAssemb(nb_ass); + } + else + { di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass) + + nno.NB_ddl_actif_casAssemb(nb_ass); + }; + if ( di > demi) demi = di; + if ( di > maxiPourLaCondition) maxiPourLaCondition = di; + if ( di > total) total = di; + // cumule += di; + }; + cumule += maxiPourLaCondition; + }; + }; // -- fin de la boucle sur les noeuds de la liste principale + }; // -- fin de la boucle sur le tableau des conditions linéaire + // prise en compte de la diagonale + demi += 1; total += 1; + // retour + return retour; + }; + + +// dimensionnement du tableau des torseurs ainsi que des tableaux ttRG et ttorBloq +// en fonction de tabBloq (utilisé plusieurs fois), puis de ttRGCLL en fonction de tab_iocondiline +void LesCondLim::DimensionneTorseurs() + { // dimensionnement du tableau des torseurs résultants + // 1) on s'occupe tout d'abord des ddl bloqués + + int taille = tabBloq.Taille(); + ttRG.Change_taille(taille); + int dima = ParaGlob::Dimension(); + if(ParaGlob::AxiSymetrie()) + // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les + // dimension-1 coordonnées donc on décrémente + dima--; + // on remplit le tableau ttRG + list li_nomRef; // liste de travail: + list li_nomRef_CL; // idem, mais spécifique aux CL + // sert ensuite pour définir ttRG_noms_ref + + int taille_tors=0; + // on en profite pour définir un tableau de nom de ref qui contiendra les infos + // en string nécessaires pour cibler les composantes du torseur, externalisées comme + // grandeurs globales + for (int i=1;i<=taille;i++) + if (tabBloq(i).Existe_ici_un_deplacement()) + {// on a un candidat possible, on regarde si la référence n'existe pas + Deux_String candid(tabBloq(i).NomRef(),tabBloq(i).NomRef()); // le premier string ici est pour remplir + string nom_Ref_CL(tabBloq(i).NomRef()); + bool avec_nom_maillage=false; + if (tabBloq(i).NomMaillage() != NULL) + {candid.nom1 = *(tabBloq(i).NomMaillage());avec_nom_maillage=true; + nom_Ref_CL = *(tabBloq(i).NomMaillage()) +"_"+ nom_Ref_CL; + }; + list ::iterator ili,ilifin=li_nomRef.end(); + int it=1; // future position dans le tableau tab_torseurReac + for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++) + if (*ili == candid) break; + if (ili == li_nomRef.end()) + {// aucun élément trouvé, on ajoute un nouveau + li_nomRef.push_back(candid); + li_nomRef_CL.push_back(nom_Ref_CL); + taille_tors++; ttRG(i)=taille_tors; + } + else // on a trouvé un élément identique déjà existant de numéro it + {ttRG(i)=it;}; + }; + + // 2) puis on s'occupe des CLL + + int taille_tors_CLL=0; + list li_nomRef_CLL; // liste de travail, mais spécifique aux CLL + // sert ensuite pour définir ttRGCLL_noms_ref + + // on boucle sur le tableau initiale des conditions lineaires en entrée + int tabCLLTaille = tab_iocondiline.Taille(); + ttRGCLL.Change_taille(tabCLLTaille); // premier dimensionnement + // on en profite pour définir un tableau de nom de ref qui contiendra les infos + // en string nécessaires pour cibler les composantes du torseur, externalisées comme + // grandeurs globales + for (int icondli=1;icondli<= tabCLLTaille; icondli++) + {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier + // on regarde s'il faut considérer la condition linéaire, en fonction de en_ddl + Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier + if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1))) + {// récup des références secondaires éventuelles + const Tableau & tabnomRef = iocondiline_i.ReferenceAssociees(); + int tabnomRefTaille = tabnomRef.Taille(); + const Tableau & nom_mail_associe = iocondiline_i.NomMaillageAssociees(); + // second dimensionnement + ttRGCLL(icondli).Change_taille(tabnomRefTaille+1); + // maintenant on rempli le tableau + // a) tout d'abord la ref principal (on encapsule) + {Deux_String candid(iocondiline_i.NomRef()+"CLL",iocondiline_i.NomRef()+"CLL"); + string nom_Ref_CLL(iocondiline_i.NomRef()+"CLL"); + bool avec_nom_maillage=false; + if (iocondiline_i.NomMaillage() != NULL) + {candid.nom1 = *(iocondiline_i.NomMaillage());avec_nom_maillage=true; + nom_Ref_CLL = *(iocondiline_i.NomMaillage()) +"_"+ nom_Ref_CLL; + }; + // on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un + list ::iterator ili,ilifin=li_nomRef.end(); + int it=1; // future position dans le tableau tab_torseurReac + for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++) + if (*ili == candid) break; + if (ili == li_nomRef.end()) + {// aucun élément trouvé, on ajoute un nouveau + li_nomRef.push_back(candid); + li_nomRef_CLL.push_back(nom_Ref_CLL); + taille_tors++; taille_tors_CLL++; ttRGCLL(icondli)(1)=taille_tors; + } + else // on a trouvé un élément identique déjà existant de numéro it + {ttRGCLL(icondli)(1)=it; + }; + }; // fin encapsulage + // b) maintenant on regarde les références secondaires + for (int ir=1;ir<=tabnomRefTaille;ir++) + { Deux_String candid(tabnomRef(ir)+"CLL",tabnomRef(ir)+"CLL"); + string nom_Ref_CLL(tabnomRef(ir)+"CLL"); + if (iocondiline_i.NomMaillage() != NULL) + {candid.nom1 = nom_mail_associe(ir); + nom_Ref_CLL = nom_mail_associe(ir) +"_"+ nom_Ref_CLL; + }; + // on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un + list ::iterator ili,ilifin=li_nomRef.end(); + int it=1; // future position dans le tableau tab_torseurReac + for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++) + if (*ili == candid) break; + if (ili == li_nomRef.end()) + {// aucun élément trouvé, on ajoute un nouveau + li_nomRef.push_back(candid); + li_nomRef_CLL.push_back(nom_Ref_CLL); + taille_tors++;taille_tors_CLL++; ttRGCLL(icondli)(ir+1)=taille_tors; + } + else // on a trouvé un élément identique déjà existant de numéro it + {ttRGCLL(icondli)(ir+1)=it;}; + }; // fin boucle sur les références secondaires + }; //-- fin du test if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1))) + }; //-- fin de la boucle sur les conditions linéaires + + // maintenant on dimensionne le tableau de torseurs + int taille_tors_bloqu = taille_tors - taille_tors_CLL; + tab_torseurReac.Change_taille(taille_tors); + for (int ia=1;ia<=taille_tors;ia++) + {tab_torseurReac(ia).Activation(dima); + // on définit si le torseur correspond à un ddl bloqué ou une CLL + if (ia > taille_tors_bloqu) + {tab_torseurReac(ia).bloque_ou_CLL = false;} + else + {tab_torseurReac(ia).bloque_ou_CLL = true;} + }; + // maintenant on dimensionne et rempli ttorBloq + ttorBloq.Change_taille(taille_tors_bloqu); + for (int ib=1;ib<=taille;ib++) + if (ttRG(ib) != 0 ) + ttorBloq(ttRG(ib)).push_back(ib); // cas d'une ref qui contient un déplacement + // et ensuite on dimensionne et rempli ttorCLL + ttorCLL.Change_taille(taille_tors); + for (int ib=1;ib<=tabCLLTaille;ib++) + { int tai = ttRGCLL(ib).Taille(); + for (int j=1;j<=tai;j++) + if (ttRGCLL(ib)(j) != 0 ) + ttorCLL(ttRGCLL(ib)(j)).push_back(DeuxEntiers(ib,j)); // cas d'une ref qui contient un déplacement + }; + + // on définit les tableaux ttRG_noms_ref et ttRGCLL_noms_ref + int nb_RG_noms_ref = li_nomRef_CL.size(); + ttRG_noms_ref.Change_taille(nb_RG_noms_ref); + {list ::iterator ili,ilifin=li_nomRef_CL.end(); + int i=1; + for (ili = li_nomRef_CL.begin();ili != ilifin; ili++,i++) + ttRG_noms_ref(i)=(*ili); + }; + ttRGCLL_noms_ref.Change_taille(li_nomRef_CLL.size()); + {list ::iterator ili,ilifin=li_nomRef_CLL.end(); + int i=1; + for (ili = li_nomRef_CLL.begin();ili != ilifin; ili++,i++) + ttRGCLL_noms_ref(i)=(*ili); + }; + + // on va maintenant définir des grandeurs globales qui permettront de récupérer les réactions par + // exemple via des fonctions nD + Ddl_enum_etendu ddl("comp_tors_reaction"); + Ddl_etendu v(ddl); + int taille_tors_bloquplus1 = taille_tors_bloqu +1; + {int il = 1; + for (int ia=1;iaGrandeurGlobal(nom_ref) == NULL) + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + + } + // 2) le moment + for (int ic= 1; ic < dimaPlus1; ic++) + {string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); + Grandeur_Ddl_etendu grand_courant(v,nom_ref); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE); + // on définit le type quelconque associé + TypeQuelconque typQ(enuType,X1,grand_courant); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + // si celle-ci n'existe pas déjà + if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL) + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + } + }; + }; + // maintenant on s'occupe des conditions concernant les CLL + {int taille_torsPlusUn = taille_tors+1; + int il = 1; + for (int ia=taille_tors_bloquplus1;iaGrandeurGlobal(nom_ref) == NULL) + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + } + // 2) le moment + for (int ic= 1; ic < dimaPlus1; ic++) + {string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic); + Grandeur_Ddl_etendu grand_courant(v,nom_ref); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE); + // on définit le type quelconque associé + TypeQuelconque typQ(enuType,X1,grand_courant); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + // si celle-ci n'existe pas déjà + if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL) + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + } + }; + }; + + +//--- débug --- +//cout << "\n " << ttorCLL << endl; +//--- fin débug --- + + }; + + +// DdlLim : mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD +void LesCondLim::Mise_a_jour_t_minmax_ddlLim(Noeud& noe,DdlLim& ddlLim,LesFonctions_nD* lesFonctionsnD) + {// on regarde le temps min + string nom_t_min = ddlLim.Nom_fctnD_tmin(); + if (nom_t_min != "") + { Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_min); // récup de la fonction + // récup des valeurs au noeud, pour alimenter la fonction + Tableau tab(noe.Valeur_multi_et_Tensorielle + (fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue()) + ); + // appel fonction + Tableau & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL); + ddlLim.Mise_a_jour_tmin(tab_ret(1)); + #ifdef MISE_AU_POINT + // on vérifie que la fonction est scalaire + if (tab_ret.Taille() != 1) + { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min + << " qui gere le temps mini " + << " elle retourne une grandeur vectorielle " + << " ce n'est pas normal !! , on arrete le calcul " + << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(nom_t_max); // récup de la fonction + // récup des valeurs au noeud, pour alimenter la fonction + Tableau tab(noe.Valeur_multi_et_Tensorielle + (fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue()) + ); + // appel fonction + Tableau & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL); + ddlLim.Mise_a_jour_tmax(tab_ret(1)); + #ifdef MISE_AU_POINT + // on vérifie que la fonction est scalaire + if (tab_ret.Taille() != 1) + { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max + << " qui gere le temps maxi " + << " elle retourne une grandeur vectorielle " + << " ce n'est pas normal !! , on arrete le calcul " + << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(nom_t_min); // récup de la fonction + // appel fonction + Tableau & tab_ret = fct->Valeur_pour_variables_globales(); + ddlLim.Mise_a_jour_tmin(tab_ret(1)); + #ifdef MISE_AU_POINT + // on vérifie que la fonction est scalaire + if (tab_ret.Taille() != 1) + { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min + << " qui gere le temps mini " + << " elle retourne une grandeur vectorielle " + << " ce n'est pas normal !! , on arrete le calcul " + << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(nom_t_max); // récup de la fonction + // appel fonction + Tableau & tab_ret = fct->Valeur_pour_variables_globales(); + ddlLim.Mise_a_jour_tmax(tab_ret(1)); + #ifdef MISE_AU_POINT + // on vérifie que la fonction est scalaire + if (tab_ret.Taille() != 1) + { cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max + << " qui gere le temps maxi " + << " elle retourne une grandeur vectorielle " + << " ce n'est pas normal !! , on arrete le calcul " + << "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); + int nb_n_princ = refp.Taille(); + Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli); + t_condiAppli.Change_taille(0); // a priori 0 c'est-à-dire qu'il n'y en a pas + + // on boucle sur les noeuds de la référence principale + for (int in=1;in<=nb_n_princ;in++) + { // récup du noeud principal + Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); + if (a_considerer) + { bool actif_pour_le_temps = iocondiline_i.Temps_actif(temps); // pour simplifier +//debug +//cout << "\n LesCondLim::MiseAJour_condilineaire_tdt " +// << " actif_pour_le_temps= "<< actif_pour_le_temps << endl; +//fin debug + if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline)) + { if ((!actif_pour_le_temps) && (iocondiline_i.Etat_validation())) + // cas du temps non actif, mais qui était actif au pas précédent + { ch_statut = true; } + else if ((actif_pour_le_temps) && (!iocondiline_i.Etat_validation())) + { ch_statut = true; }; + }; //-- fin du test si le noeud est à considérer ou pas + }; + }; // fin de la boucle sur les noeuds de la ref principale + + // II) ---- un deuxième passage pour le traitement des conditions limites de projection --- + // sur un plan ou une droite +// ** je ne comprends pas pourquoi il faut l'usine à gaz Pas_a_prendre_en_compte( qui fait que si au +// temps précédent c'était actif, alors au temps actuel, même en dehors de l'intervalle c'est également à considérer +// cela conduit à des erreurs donc je supprime et met un cas plus restrictif : Pas_a_prendre_en_compte_dans_intervalle( +// mais il faudrait également changer dans tous les chargement les fct du même type : Pas_a_prendre_en_compte( +// if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte(temps)) + if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte_dans_intervalle(temps)) + && (iocondiline_i.PlanDroite())) + {// construction des données nécessaires + // on regarde si l'on utilise un noeud rotation + const String_et_entier* mailEtNumCentreNoeud = iocondiline_i.RefNoeudRotation(); + if ( mailEtNumCentreNoeud != NULL) // utilisation d'un noeud rotation, on renseigne + { if (mailEtNumCentreNoeud->nom == "") + // cas par défaut de noeud du premier maillage + {iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(1,mailEtNumCentreNoeud->n)));} + else + // sinon il y a un nom de maillage + {int imail = lesMail->NumMaillage(mailEtNumCentreNoeud->nom); + iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(imail,mailEtNumCentreNoeud->n)));}; + }; + + // on regarde s'il y a des fonctions de charge si oui on renseigne + int nbfct = iocondiline_i.ExisteFonctionChargeCoef(); + if (nbfct) + {Vecteur valfct(nbfct),deltatvalfct(nbfct); + for (int ifct = 1; ifct <= nbfct; ifct++) + {Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct)); + valfct(ifct)=pt_courbe->Valeur(temps); + deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))); + }; + // on renseigne la condition limite + iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct); + // on actualise la direction actuelle ou normale pour plan droite + iocondiline_i.ActualiseDirectionPlanDroite(); + }; + + int dima = ParaGlob::Dimension(); + if(ParaGlob::AxiSymetrie()) + // cas d'élément axisymétrique, dans ce cas on ne prend en compte que les + // dimension-1 coordonnées donc on décrémente + dima--; + int posi = Id_nom_ddl("X1") -1; // position du ddl X1 + // on boucle sur les noeuds de la référence principale pour appliquer la condition + for (int in=1;in<=nb_n_princ;in++) + { // récup du noeud principal + Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); + //si le noeud est par ailleurs bloqué, ce n'est pas possible (sauf cas particulier + // non pris en compte car c'est trop spécifique, il faut utiliser une CL classique à la place + // d'utiliser ce type de condition linéaire, on test donc pour éviter des déconvenues + + int indi = 0; + switch (dima) + { case 3: if (noe.Ddl_fixe(Enum_ddl(posi+3))) + { indi=3; + if (!iocondiline_i.Coherence_condi_PlanDroite(indi)) + {break;} + else {indi = 0;}; // on remet à 0 si c'est cohérent + } + case 2: if (noe.Ddl_fixe(Enum_ddl(posi+2))) + { indi=2; + if (!iocondiline_i.Coherence_condi_PlanDroite(indi)) + {break;} + else {indi = 0;}; // on remet à 0 si c'est cohérent + } + case 1: if (noe.Ddl_fixe(Enum_ddl(posi+1))) + { indi=1; + if (!iocondiline_i.Coherence_condi_PlanDroite(indi)) + {break;} + else {indi = 0;}; // on remet à 0 si c'est cohérent + } + default: break; + }; + + if (indi) + { // cas où il existe un blocage sur le noeud, la condition linéaire n'est pas licite + cout << "\n erreur concernant une condition lineaire par projection " + << ", le noeud : "<& nomRefassocie = iocondiline_i.ReferenceAssociees(); + const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); + int tailrefasso = nomRefassocie.Taille(); + Tableau * > tab_numNoeud_associe(tailrefasso); + Tableau tab_numMail_associe(tailrefasso); + if (tailrefasso != 0) + {for (int k=1;k<=tailrefasso;k++) + {const string * nom_maillage=NULL; + if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); + const ReferenceNE & refasso = + ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); + tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés + tab_numMail_associe(k)= refasso.Nbmaille(); + }; + }; + // -- maintenant que l'est là, il y a de bonnes raisons de penser que les conditions sont effectives + // on dimensionne correctement le tableau finale + t_condiAppli.Change_taille(nb_n_princ); // mise à jour de la taille au cas où + // éventuellement, due à la non activité des ddl, la condition peut néanmoins ne pas être construite + // par défaut on met le Iddl() en négatif, histoire de rendre par défaut la condition non exploitable + // ceci sera changé durant la construction effective, si elle a lieu. D'autre part au moment de l'utilisation de la condition + // le test sur le Iddl() permettra de savoir si la condition est exploitable ou non + for (int ijk=1;ijk<=nb_n_princ;ijk++) + t_condiAppli(ijk).ChangeIddl()=-1; + + // on boucles sur les noeuds de la ref principale + Tableau t_noe(tailrefasso+1); // tableau de travail + // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds + // concernés par la condition linéaire. + for (int in=1;in<=nb_n_princ;in++) + { // récup du noeud principal + Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); + t_noe(1)= &noe; + // on ne continue que si le type de ddl de la condition limite est actif pour le noeud + // et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte + // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) + if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline)) + {// récupération des noeuds associés, on utilise le même indice dans les ref associées que + // dans la ref principale + for (int ia = 1;ia<=tailrefasso;ia++) + t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); + + // on commence par voir s'il y a des fonctions de charge si oui on renseigne + int nbfct = iocondiline_i.ExisteFonctionChargeCoef(); + if (nbfct) + {Vecteur valfct(nbfct),deltatvalfct(nbfct); + for (int ifct = 1; ifct <= nbfct; ifct++) + {Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct)); + valfct(ifct)=pt_courbe->Valeur(temps); + deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))); + }; + // on renseigne la condition limite + iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct); + }; + // on calcul les coefs effectifs de condition limite + Condilineaire & condi = t_condiAppli(in); // pour simplifier + // on constuit la condition et on impose la valeur c-a-d: + // on met en place la condition limite sur le ddl ddl_i du noeud principal + // qui correspond au ddl_i' dans le nouveau repèrere qui recevra la condition bloqué + // en fait ddl_i sera la seul modification de ddl due à la mise en place de la CLL + iocondiline_i.ConstructionCondition(t_noe,condi); + + construction_effectuee = true; // on enregistre + }; // -- fin du cas ou c'est une variable et qu'elle est active + + }; // -- fin de la boucle sur les noeuds de la ref principal + + }; // -- fin du test pour savoir s'il faut considérer la condition linéaire ou pas + + }; //-- fin de la boucle sur l'ensemble des conditions linéaire + + // 2--- on boucle sur toutes les conditions linéaires effectives, pour imposer les blocages + for (int icondli=1;icondli<= tabTaille; icondli++) + {Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli); + int taille = t_condiAppli.Taille(); + for (int i=1;i<=taille;i++) + { double Uk_impose = t_condiAppli(i).Val_Uk_impose(); // récup de la valeur a imposer + // dans le cas où c'est une condition de projection, la condition a déjà été effectuée + // donc il ne faut pas la faire ici: le test de Uk_impose, permet de le savoir + if (Uk_impose != ConstMath::tresgrand) + { Noeud* noe = t_condiAppli(i).Noe(); // pour simplifier + Enum_ddl leEnuAChanger = t_condiAppli(i).Tab_Enum()(1); // le enu a changer + noe->Change_val_tdt(leEnuAChanger,Uk_impose); + }; + }; + }; + tempsCLL.Arret_du_comptage(); // temps cpu + + }; + +// création d'un tableau de condition linéaire, correspondant à toutes les conditions linéaires d'entrées +// qu'elles soient actives ou pas (a priori cette méthode est conçu pour donner des infos relativement à la largeur +// de bandes en noeuds due aux CLL) +// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, +Tableau > LesCondLim::ConnectionCLL + (const LesMaillages * lesMail,const LesReferences* lesRef) const + { + // on boucle sur le tableau et pour chaque element on impose une condition lineaire + int tabTaille = tab_iocondiline.Taille(); + Tableau > t_connectionCLL(tabTaille); + for (int icondli=1;icondli<= tabTaille; icondli++) + {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier + Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier + // recup de la reference principal correspondant au mot cle + const ReferenceNE & refp = + ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); + int nb_n_princ = refp.Taille(); + Tableau & connectionCLL = t_connectionCLL(icondli); // pour simplifier + connectionCLL.Change_taille(nb_n_princ); // mise à jour de la taille + + // ---- traitement des conditions limites de projection --- + // sur un plan ou une droite + if (iocondiline_i.PlanDroite()) + {Tableau t_noe(1); // tableau de travail + for (int in=1;in<=nb_n_princ;in++) + { // récup du noeud principal + t_noe(1)= &lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); + // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi + Enum_ddl enu = enu_condline; // init + if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX)) + enu = UxyzXi(enu_condline); + // on ne continue que si le type de ddl de la condition limite est une variable + // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) + if (t_noe(1)->UneVariable(enu)) + // on renseigne la condition uniquement sur le tableau de noeud + { connectionCLL(in).ChangeTabNoeud(t_noe); }; + }; // -- fin de la boucle sur les noeuds de la ref principal + }// -- fin du test pour savoir si c'est une condition de projection ou non + + // --- cas des conditions linéaires générales --------- + else + {// recup du tableau des références secondaires associées si elles existent + const Tableau & nomRefassocie = iocondiline_i.ReferenceAssociees(); + const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); + int tailrefasso = nomRefassocie.Taille(); + Tableau * > tab_numNoeud_associe(tailrefasso); + Tableau tab_numMail_associe(tailrefasso); + if (tailrefasso != 0) + {for (int k=1;k<=tailrefasso;k++) + {const string * nom_maillage=NULL; + if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); + const ReferenceNE & refasso = + ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); + tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés + tab_numMail_associe(k)= refasso.Nbmaille(); + }; + }; + // on boucles sur les noeuds de la ref principale + Tableau t_noe(tailrefasso+1); // tableau de travail + // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds + // concernés par la condition linéaire. + for (int in=1;in<=nb_n_princ;in++) + { // récup du noeud principal + Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); + t_noe(1)= &noe; + Condilineaire& condCLL = connectionCLL(in); // pour simplifier + // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi + Enum_ddl enu = enu_condline; // init + if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX)) + enu = UxyzXi(enu_condline); + // on ne continue que si le type de ddl de la condition limite est une variable, + // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) + if (noe.UneVariable(enu) ) + {// récupération des noeuds associés, on utilise le même indice dans les ref associées que + // dans la ref principale + for (int ia = 1;ia<=tailrefasso;ia++) + t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); + }; + // on renseigne la condition uniquement sur le tableau de noeud + condCLL.ChangeTabNoeud(t_noe); + }; // -- fin du cas ou c'est une variable + + }; // -- fin de la boucle sur les noeuds de la ref principal + }; //-- fin de la boucle sur l'ensemble des conditions linéaire + + // retour + return t_connectionCLL; + }; + + +// idem ConnectionCLL avec une liste, mais spécifiquement les conditions de type "stricte_egalite" entre ddl de noeud +// correspondant à toutes les conditions linéaires d'entrées actives uniquement +// (a priori cette méthode est conçu pour donner des infos pour condenser les pointeurs d'assemblages: +// LesMaillages::MiseAJourPointeurAssemblage() ) +// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, et le type enumere de ddl +list LesCondLim::ConnectionCLL_stricte_egalite + (const LesMaillages * lesMail,const LesReferences* lesRef) const + { + // def de la liste de retour + list list_condi; + // on boucle sur le tableau et pour chaque element on analyse la condition lineaire + int tabTaille = tab_iocondiline.Taille(); + for (int icondli=1;icondli<= tabTaille; icondli++) + {I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier + Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier + Tableau tab_enu(1); tab_enu(1) = enu_condline; // servira pour construire les Condilineaires + // recup de la reference principal correspondant au mot cle + const ReferenceNE & refp = + ((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage())); + int nb_n_princ = refp.Taille(); + + // --- on ne continue que s'il s'agit d'une condition stricte_egalite et que la condition + // est active pour le temps actuel + if ((iocondiline_i.StricteEgalite()) + && (iocondiline_i.Temps_actif(ParaGlob::Variables_de_temps().TempsCourant()))) + {// recup du tableau des références secondaires associées si elles existent + const Tableau & nomRefassocie = iocondiline_i.ReferenceAssociees(); + const Tableau & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees(); + int tailrefasso = nomRefassocie.Taille(); + Tableau * > tab_numNoeud_associe(tailrefasso); + Tableau tab_numMail_associe(tailrefasso); + if (tailrefasso != 0) + {for (int k=1;k<=tailrefasso;k++) + {const string * nom_maillage=NULL; + if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k); + const ReferenceNE & refasso = + ((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage)); + tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés + tab_numMail_associe(k)= refasso.Nbmaille(); + }; + }; + // on boucles sur les noeuds de la ref principale + Tableau t_noe(tailrefasso+1); // tableau de travail + // l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds + // concernés par la condition linéaire. + for (int in=1;in<=nb_n_princ;in++) + { // récup du noeud principal + Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in)); + t_noe(1)= &noe; + // s'il s'agit d'un ddl de déplacement, il faut le changer en Xi + Enum_ddl enu = enu_condline; // init + if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX)) + enu = UxyzXi(enu_condline); + // on ne continue que si le type de ddl de la condition limite est une variable, + // on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps) + if (noe.UneVariable(enu) ) + {// récupération des noeuds associés, on utilise le même indice dans les ref associées que + // dans la ref principale + for (int ia = 1;ia<=tailrefasso;ia++) + t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in))); + }; + // on renseigne une condition uniquement sur le tableau de noeud + Condilineaire condi_stric_egal(tab_enu,t_noe); + list_condi.push_back(condi_stric_egal); + }; // -- fin du cas ou c'est une variable + + }; // -- fin de la boucle sur les noeuds de la ref principal + + }; //-- fin de la boucle sur l'ensemble des conditions linéaire + + // retour + return list_condi; + }; + + +// récupération de valeurs à un noeud pour les grandeur enu +// ici il s'agit de grandeur scalaires +Tableau LesCondLim::Valeur_multi_interpoler_ou_calculer + (const Noeud& noe, Enum_dure temps,const List_io& enu) + { + // recup de l'incrément de temps + double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant(); + double unSurDeltat=0; + if (Abs(deltat) >= ConstMath::trespetit) + {unSurDeltat = 1./deltat;} + else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand + { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb + if (unSurDeltat < 0) + { cout << "\n le pas de temps est négatif !! "; }; + unSurDeltat = ConstMath::tresgrand; + }; + // le tableau de retour + Tableau tab_ret (enu.size()); + + // on balaie la liste des grandeurs à sortir + List_io::const_iterator ie,iefin=enu.end(); + int it; // it est l'indice dans le tableau de retour + for (it=1,ie=enu.begin(); ie!=iefin;ie++,it++) + { if ((Meme_famille((*ie).Enum(),X1)) && ((*ie).Nom_vide())) + {switch (temps) + {case TEMPS_0 : tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1);break; + case TEMPS_t : tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1);break; + case TEMPS_tdt : tab_ret(it)= noe.Coord2()((*ie).Enum() - X1 +1);break; + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n"; + Sortie(1); + }; + } + else if ((Meme_famille((*ie).Enum(),UX)) && ((*ie).Nom_vide())) + {int i_cor = (*ie).Enum() - UX +1; // l'indice de coordonnée + switch (temps) + {case TEMPS_0 : tab_ret(it)= 0.;break; + case TEMPS_t : tab_ret(it)= noe.Coord1()(i_cor)-noe.Coord0()(i_cor);break; + case TEMPS_tdt : tab_ret(it)= noe.Coord2()(i_cor)-noe.Coord0()(i_cor);break; + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n"; + Sortie(1); + }; + } + // cas particulier de la position à t, indépendamment du temps + else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 123) + {tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1); + } + // cas particulier de la position à t0, indépendamment du temps + else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 126) + {tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1); + } + else if ((*ie).Nom_vide()) + {// il s'agit d'un ddl pur on le récupère directement + switch (temps) + {case TEMPS_0 : tab_ret(it)= noe.Valeur_0((*ie).Enum());break; + case TEMPS_t : tab_ret(it)= noe.Valeur_t((*ie).Enum());break; + case TEMPS_tdt : tab_ret(it)= noe.Valeur_tdt((*ie).Enum());break; + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "LesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n"; + Sortie(1); + }; + } + // --- a complèter ---- + else + { tab_ret(it) = 0.; + cout << "\n cas de ddl actuellement non traite " + << "\n pas de ddl " << (*ie).Nom() << " au noeud " + << noe.Num_noeud() <<" du maillage "<< noe.Num_Mail() + << "\n ou cas non implante pour l'instant, on retourne 0" + << "\n LesCondLim::Valeur_multi_interpoler_ou_calculer(.. "; + }; + };// -- fin de la boucle sur la liste de Ddl_enum_etendu + // liberation des tenseurs intermediaires + LibereTenseur(); + return tab_ret; + }; + +// récupération de valeurs à un noeud pour les grandeur enu +// ici il s'agit de grandeurs tensorielles +void LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer + (const Noeud& noe, Enum_dure temps,List_io& enu) + +{ // ----- def de grandeurs de travail + int dim_espace = ParaGlob::Dimension(); + + // on initialise ces variables booléennes et les conteneurs + List_io::iterator ipq,ipqfin=enu.end(); + for (ipq=enu.begin();ipq!=ipqfin;ipq++) + {TypeQuelconque_enum_etendu enuq = (*ipq).EnuTypeQuelconque().EnumTQ(); + switch (enuq.Position()) + { case POSITION_GEOMETRIQUE : + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); + Coordonnee* M = gr.ConteneurCoordonnee(); + switch (temps) + {case TEMPS_0 : (*M)= noe.Coord0();break; + case TEMPS_t : (*M)= noe.Coord1();break; + case TEMPS_tdt : (*M)= noe.Coord2();break; + default : + cout << "\nErreur : valeur incorrecte du temps !\n"; + cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); + Sortie(1); + }; + break; + } + case POSITION_GEOMETRIQUE_t : + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); + Coordonnee* M = gr.ConteneurCoordonnee(); + (*M)= noe.Coord1(); + break; + } + case POSITION_GEOMETRIQUE_t0 : + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); + Coordonnee* M = gr.ConteneurCoordonnee(); + (*M)= noe.Coord0(); + break; + } + case DEPLACEMENT : + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); + Coordonnee* M = gr.ConteneurCoordonnee(); + switch (temps) + {case TEMPS_0 : M->Zero();break; + case TEMPS_t : (*M)= noe.Coord1()-noe.Coord0();break; + case TEMPS_tdt : (*M)= noe.Coord2()-noe.Coord0();break; + default : + cout << "\nErreur : valeur incorrecte du temps !\n"; + cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); + Sortie(1); + }; + break; + } + case FORCE_GENE_EXT : case FORCE_GENE_INT : case VECT_PRESSION : case VECT_FORCE_VOLUM : + case VECT_DIR_FIXE : case VECT_SURF_SUIV : case VECT_HYDRODYNA_Fn : case VECT_HYDRODYNA_Ft : + case VECT_HYDRODYNA_T : case VECT_LINE : case VECT_LINE_SUIV : case VECT_REAC : case VECT_REAC_N : + case FORCE_CONTACT : case FORCE_GENE_TOT: case RESIDU_GLOBAL: + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); + Coordonnee* F = gr.ConteneurCoordonnee(); + // on vérifie l'existante + #ifdef MISE_AU_POINT + if (!(noe.Existe_ici(enuq))) + {cout << "\nErreur : " << enuq.Nom() << " n'existe pas au noeud " + << noe.Num_noeud() << " du maillage "<< noe.Num_Mail() + << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); + Sortie(1); + }; + #endif + // récupération de la grandeur quelconque + const TypeQuelconque& toto = noe.Grandeur_quelconque(enuq); + const Grandeur_coordonnee& titi = *((const Grandeur_coordonnee* ) toto.Const_Grandeur_pointee()); + (*F) = titi.ConteneurCoordonnee_const(); // ouf + break; + } + case VITESSE : + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee())); + Coordonnee* V = gr.ConteneurCoordonnee(); + // on vérifie l'existante + #ifdef MISE_AU_POINT + if (!(noe.Existe_ici(V1))) + {cout << "\nErreur : la vitesse n'existe pas au noeud " + << noe.Num_noeud() << " du maillage "<< noe.Num_Mail() + << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n"; + if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage(); + if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage(); + Sortie(1); + }; + #endif + // récupération de la vitesse + switch (temps) + { case TEMPS_0 : + {switch (dim_espace) + {case 3: (*V)(3) = noe.Valeur_0(V3); + case 2: (*V)(2) = noe.Valeur_0(V2); + case 1: (*V)(1) = noe.Valeur_0(V1); + break; + default: break; + }; + break; + } + case TEMPS_t : + {switch (dim_espace) + {case 3: (*V)(3) = noe.Valeur_t(V3); + case 2: (*V)(2) = noe.Valeur_t(V2); + case 1: (*V)(1) = noe.Valeur_t(V1); + break; + default: break; + }; + break; + } + case TEMPS_tdt : + {switch (dim_espace) + {case 3: (*V)(3) = noe.Valeur_tdt(V3); + case 2: (*V)(2) = noe.Valeur_tdt(V2); + case 1: (*V)(1) = noe.Valeur_tdt(V1); + break; + default: break; + }; + break; + } + default: break; + }; + break; + } + default : + {// on initialise la grandeur pour éviter d'avoir des valeurs aléatoires + ((*ipq).Grandeur_pointee())->InitParDefaut(); + if (ParaGlob::NiveauImpression() > 0) + {cout << "\nWarning : attention cas non traite: " + << (*ipq).EnuTypeQuelconque().NomPlein() << "!\n"; + // on initialise la grandeur pour éviter d'avoir des valeurs aléatoires + if (ParaGlob::NiveauImpression() > 5) + cout << "\n LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(...."; + }; + } + }; + }; + + + // liberation des tenseurs intermediaires + LibereTenseur(); +}; + + diff --git a/Maillage/LesMaillages.cc b/Maillage/LesMaillages.cc new file mode 100644 index 0000000..672f152 --- /dev/null +++ b/Maillage/LesMaillages.cc @@ -0,0 +1,3872 @@ + +// 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 "LesMaillages.h" +#include "ElemMeca.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" +#include "MathUtil.h" +#include "ConstMath.h" +#include "LaList.h" +#include "CharUtil.h" +#include "TypeQuelconqueParticulier.h" + +#ifndef SYSTEM_MAC_OS_X_unix + #include "Frontier.h" +#endif + + +// Constructeur + // constructeur par défaut +LesMaillages::LesMaillages(): + tabMaillage(0),listFrontiere(),t_i_n(0) + ,tab_nb_assemb(0),tt_noeud_front(),tous_indices() + ,nbEnreg(0),nbMaillageTotal(0),nbPortion(0),entreePrinc(NULL),paraGlob(NULL) + ,lesRef(NULL),domEsclave(0),mapNomMail() + ,ddl_representatifs_des_physiques(),types_de_problemes() + ,integ_vol_typeQuel(),integ_vol_typeQuel_t(),ref_integ_vol() + ,integ_vol_t_typeQuel(),integ_vol_t_typeQuel_t(),ref_integ_vol_t() + ,statistique_typeQuel(),statistique_typeQuel_t(),ref_statistique() + ,pour_statistique_de_ddl() + ,statistique_t_typeQuel(),statistique_t_typeQuel_t(),ref_statistique_t() + ,pour_statistique_t_de_ddl() + + { cout << "\n erreur: ce constructeur ne doit pas etre utilise !!" + << "\n LesMaillages::LesMaillages()"; + Sortie(1); + }; + +LesMaillages::LesMaillages(UtilLecture * ent,ParaGlob * para,LesReferences* Ref) : +/* nbEnreg(para->NombreMaillage()), // Nombre initial de maillage est determine + // dans les parametres globaux + tabMaillage(nbEnreg) // def du tableau de maillage */ + tabMaillage(5),listFrontiere(),t_i_n() + ,tab_nb_assemb(0),tt_noeud_front(),tous_indices() + ,mapNomMail() + ,ddl_representatifs_des_physiques(),types_de_problemes() + ,integ_vol_typeQuel(),integ_vol_typeQuel_t(),ref_integ_vol() + ,integ_vol_t_typeQuel(),integ_vol_t_typeQuel_t(),ref_integ_vol_t() + ,statistique_typeQuel(),statistique_typeQuel_t(),ref_statistique() + ,pour_statistique_de_ddl() + ,statistique_t_typeQuel(),statistique_t_typeQuel_t(),ref_statistique_t() + ,pour_statistique_t_de_ddl() + { lesRef = Ref; + // mise à jour de la map qui fait la liaison nom de maillage <=> numéro de maillage + lesRef->MiseAJourMap(mapNomMail); + entreePrinc = ent; + nbEnreg = 5; + nbMaillageTotal = 0 ; // pour l'instant pas de maillage + nbPortion = nbEnreg ; + paraGlob = para; + domEsclave = 0; // a priori pas de maillage esclave + }; + +//constructeur de copie +LesMaillages::LesMaillages(const LesMaillages& a) + { cout << "\n erreur: pour l'instant ce constructeur ne doit pas etre utilise !!" + << "\n LesMaillages::LesMaillages(const LesMaillages& a)"; + Sortie(1); + }; + + +// Destructeur +LesMaillages::~LesMaillages() + { int tabMaillage_Taille=tabMaillage.Taille(); + if (tabMaillage_Taille>=1) + for (int i=1;i<= tabMaillage_Taille;i++) + if (tabMaillage(i)!=NULL) + {delete tabMaillage(i);tabMaillage(i)=NULL;} + }; + +// METHODES PUBLIQUES : +// lecture des maillages et des references s'y rapportant +void LesMaillages::LectureLesMaillages() + { if (ParaGlob::NiveauImpression() >= 4) + cout << " debut de la lecture des maillages " << endl; + // --- rechercher d'un premier maillage maillage + int lectureEnCour = 0; + // lecture du premier maillage obligatoire + if ((strstr(entreePrinc->tablcar,"noeuds")!=NULL) || + (strstr(entreePrinc->tablcar,"nom_maillage")!=NULL)) + { if (ParaGlob::NiveauImpression() >= 5) + cout << " lecture du premier maillage " << endl; + tabMaillage(1) = new Maillage (mapNomMail,1,paraGlob->Dimension()); + // indique que les prochaines references seront pour le maillage 1 + lesRef->NbMaille(1); + tabMaillage(1)->LectureMaillage(entreePrinc,*lesRef); + // opération d'affinage + tabMaillage(1)->LectureEtApplicationAffinage(entreePrinc,*lesRef); + // init du nombre de maillage + nbMaillageTotal = 1 ; +/*////------- debug +//cout << "\n debug1 LesMaillages::LectureLesMaillages "; +//{ +// map < string, int , std::less >::iterator id1, idfin=mapNomMail.end(); +// for (id1=mapNomMail.begin();id1!=idfin;id1++) +// cout << "\n "<<(*id1).first << " , " << (*id1).second ; +// cout << endl; +//// mapNomMail; +// +//};*/ + } + else + { cout << " *** erreur dans la lecture du premier maillage " << '\n'; + cout << " un premier maillage est obligatoire !!! " << '\n'; + Sortie(1); + }; + // --- recherche s'il y a d'autres maillages + // tout d'abord on passe le numéro de version si besoin est: + if (strstr(entreePrinc->tablcar,"version:")!=NULL) + entreePrinc->NouvelleDonnee(); + if ((strstr(entreePrinc->tablcar,"noeuds")!=NULL) || + (strstr(entreePrinc->tablcar,"nom_maillage")!=NULL)) + do { nbMaillageTotal++; + #ifdef ETUDIANT_LIMITATION + if (nbMaillageTotal > nb_maxi_maillage) + { cout << "\n nombre maxi de maillage autorisé atteind " << nb_maxi_maillage; + Sortie(1); + } + #endif + if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + tabMaillage(nbMaillageTotal) = new Maillage (mapNomMail,nbMaillageTotal,paraGlob->Dimension()); + // indique le nb de maillage pour l'enregistrement des prochaines references + lesRef->NbMaille(nbMaillageTotal); + //lect des autres MAILlages + if (ParaGlob::NiveauImpression() >= 5) + cout << " lecture du maillage nb: " << nbMaillageTotal << endl; + tabMaillage(nbMaillageTotal)->LectureMaillage(entreePrinc,*lesRef); +/*////------- debug +//cout << "\n debug2 LesMaillages::LectureLesMaillages "; +//{ +// map < string, int , std::less >::iterator id1, idfin=mapNomMail.end(); +// for (id1=mapNomMail.begin();id1!=idfin;id1++) +// cout << "\n "<<(*id1).first << " , " << (*id1).second ; +// cout << endl; +//// mapNomMail; +// +//};*/ + // on demande au maillage de lire éventuellement des rotation, collapse etc. + // --> opération d'affinage, juste pour ce maillage + tabMaillage(nbMaillageTotal)->LectureEtApplicationAffinage(entreePrinc,*lesRef); + // maintenant on regarde si l'on veut une fusion avec le maillage précédent + if (strstr(entreePrinc->tablcar,"fusion_avec_le_maillage_precedent_")!=NULL) + {// si oui on appel la méthode de fusion pour le maillage précédent + List_io < string > nom_mails_a_fusionner; // on crée une liste qui sert pour l'appel général + nom_mails_a_fusionner.push_back(tabMaillage(nbMaillageTotal)->NomDuMaillage()); + int nbMaillageTotal_save = nbMaillageTotal; + Fusion_maillages(nom_mails_a_fusionner,tabMaillage(nbMaillageTotal-1)->NomDuMaillage(),lesRef); + // on vérifie qu'il n'y a pas eu de nouveau maillage créé durant la fusion + if (nbMaillageTotal != nbMaillageTotal_save) + { cout << "\n erreur, il y a eu un nouveau maillage cree, ce n'est pas normal, la suite est impossible " + << "\n LesMaillages::LectureLesMaillages() " << endl ; + Sortie(1); + }; +////------- debug +//cout << "\n debug LesMaillages::LectureLesMaillages : avant le delete"; +//lesRef->Affiche(2,0); +////----- fin debug +//{ +// map < string, int , std::less >::iterator id1, idfin=mapNomMail.end(); +// for (id1=mapNomMail.begin();id1!=idfin;id1++) +// cout << "\n "<<(*id1).first << " , " << (*id1).second ; +// cout << endl; +//// mapNomMail; +// +//}; + // maintenant on va supprimer le maillage que l'on vient de lire + Suppression_maillage(tabMaillage(nbMaillageTotal)->NomDuMaillage()); +////------- debug +//cout << "\n debug LesMaillages::LectureLesMaillages : après le delete "; +//lesRef->Affiche(2,0); +//{ +// map < string, int , std::less >::iterator id1, idfin=mapNomMail.end(); +// for (id1=mapNomMail.begin();id1!=idfin;id1++) +// cout << "\n "<<(*id1).first << " , " << (*id1).second ; +// cout << endl; +//// mapNomMail; +// +//}; + entreePrinc->NouvelleDonnee(); // on prépare la nouvelle lecture + // après la fusion, on peut encore avoir de l'affinage + // on demande au maillage de lire éventuellement des rotation, collapse etc. + // --> opération d'affinage + tabMaillage(nbMaillageTotal)->LectureEtApplicationAffinage(entreePrinc,*lesRef); + }; +/*////------- debug +//cout << "\n debug LesMaillages::LectureLesMaillages après LectureEtApplicationAffinage "; +//{ +// map < string, int , std::less >::iterator id1, idfin=mapNomMail.end(); +// for (id1=mapNomMail.begin();id1!=idfin;id1++) +// cout << "\n "<<(*id1).first << " , " << (*id1).second ; +// cout << endl; +//// mapNomMail; +// +//};*/ + + if ((strstr(entreePrinc->tablcar,"noeuds")!=NULL) || + (strstr(entreePrinc->tablcar,"nom_maillage")!=NULL)) {lectureEnCour = 1;} + else {lectureEnCour = 0;}; + } while (lectureEnCour == 1); + // fin de la lecture des maillages les uns après les autres +//---- essai d'une renumérotation globale + //--- on regarde si l'on demande une renumérotation globale de tous les maillages + // n'est actif que s'il y a plusieurs maillages, + if (strstr(entreePrinc->tablcar,"renumerotation_tous_maillages_")!=NULL) +// if (nbMaillageTotal != 1) + { if (ParaGlob::NiveauImpression() >= 5) + cout << " renumerotation globale de tous les noeuds de tous les maillages " << endl; + // on définit un tableau vide de conditions linéaires (ne sert pas ici) + Tableau > condCLL; + // appel de l'utilitaire dans lesMaillages avec les conditions linéaire éventuelles + TroisEntiers nouvelles_largeur_en_ddl; + this->Renumerotation(*lesRef,condCLL,nouvelles_largeur_en_ddl); + entreePrinc->NouvelleDonnee(); // positionnement sur une nouvelle info + }; +// else +// { if (ParaGlob::NiveauImpression() >= 5) +// cout << " il n'y a qu'un seul maillage, doncrenumerotation globale de tous les noeuds de tous les maillages " << endl; +// + + + + // --- on examine le cas où il y a une distinction domaine esclave/ou non +// if ((strstr(entreePrinc->tablcar,"domaine_esclave")!=NULL) && (nbMaillageTotal != 1)) + if (strstr(entreePrinc->tablcar,"domaine_esclave")!=NULL) + // cas ou l'on a des domaines esclaves, lecture du nombre + { entreePrinc->NouvelleDonnee(); + if (ParaGlob::NiveauImpression() >= 5) + cout << " lecture du nombre de domaines esclaves " << endl; + *(entreePrinc->entree) >> domEsclave; // lecture du nombre + if (ParaGlob::NiveauImpression() >= 5) cout << domEsclave << endl; + if ((domEsclave <1) || (domEsclave > nbMaillageTotal)) + // domEsclave doit etre > 0 et < nbMaillageTotal, s'il = nbMaillageTotal + // on n'a aucun maillage maitre -> pb, sauf s'il y a de l'auto contact, c'est géré par le contact + { cout << "\n le nombre de maillage esclave lu : " << domEsclave + << ", n\'est pas acceptable, (nbMaillageTotal = " << nbMaillageTotal << " )" + << endl; + entreePrinc->MessageBuffer("** lecture des domaines esclaves **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + entreePrinc->NouvelleDonnee(); // positionnement sur une nouvelle info + }; +// // --- vérification obsolète mais que l'on conserve pour l'instant +// if ((paraGlob->TypeCalcul() == NON_DYNA_CONT) && (domEsclave < 1)) +// { cout << "\n erreur, le type de calcul : NON_DYNA_CONT necessite d\'avoir plusieurs" +// << " maillages et de savoir le nombre de domaine esclave !! " +// << "\n LesMaillages::LectureLesMaillages() " << endl; +// entreePrinc->MessageBuffer("** lecture des domaines esclaves **"); +// throw (UtilLecture::ErrNouvelleDonnee(-1)); +// Sortie(1); +// }; + // --- on vérifie que les références sont correctes + const Reference* refG = lesRef->Init_et_Premiere(); + while (refG != NULL) + { // on définit la référence réelle + // et on voit s'il n'y a pas d'erreur lorsque l'on essaie d'utiliser la référence + // 1- cas des noeuds + if ( refG->Indic() == 1) + { const ReferenceNE & ref = (ReferenceNE &) (*refG); + int ref_Taille=ref.Taille(); + for (int j= 1; j<= ref_Taille; j++) + {int nb = ref.Numero(j) ; // le numero du dans le maillage + int nn = ref.Nbmaille(); // le numero du maillage + // on tente de récupérer le noeud, ce qui permet de vérifier son existence + try {Noeud& toto = Noeud_LesMaille(nn,nb);} + // si le noeud n'existe pas il y a une erreur qui est récupérer + catch (ErrSortie erreur) + { // cas d'un noeud n'existant pas + cout << "\n erreur dans la verification de la liste : " ; + ref.Affiche(); + cout << "\n peut-etre que le noeud nb : " << nb << " du maillage : " << nn + << " n'existe pas ? " << endl; + Sortie(-1); // on force la sortie + }; + }; + }; + // 2- cas des éléments + if ( refG->Indic() == 2) + { const ReferenceNE & ref = (ReferenceNE &) (*refG); + int ref_Taille=ref.Taille(); + for (int j= 1; j<= ref_Taille; j++) + {int nb = ref.Numero(j) ; // le numero de l'element dans le maillage + int nn = ref.Nbmaille(); // le numero du maillage + // on tente de récupérer l'élément, ce qui permet de vérifier son existence + try {Element& toto = Element_LesMaille(nn,nb);} + // si l'élément n'existe pas il y a une erreur qui est récupérer + catch (ErrSortie erreur) + { // cas d'un élément n'existant pas + cout << "\n erreur dans la verification de la liste : " ; + ref.Affiche(); + cout << "\n peut-etre que l'element nb : " << nb << " du maillage : " << nn + << " n'existe pas ? " << endl; + Sortie(-1); // on force la sortie + }; + }; + }; + // 3- cas des faces ou des arrêtes + if (( refG->Indic() == 3) || ( refG->Indic() == 4)) + { const ReferenceAF & ref = (ReferenceAF &) (*refG); + int ref_Taille=ref.Taille(); + for (int j= 1; j<= ref_Taille; j++) + {int nb = ref.NumeroElem(j) ; // le numero de l'element dans le maillage + int nn = ref.Nbmaille(); // le numero du maillage + // on tente de récupérer l'élément, ce qui permet de vérifier son existence + try {Element& toto = Element_LesMaille(nn,nb);} + // si l'élément n'existe pas il y a une erreur qui est récupérer + catch (ErrSortie erreur) + { // cas d'un élément n'existant pas + cout << "\n erreur dans la verification de la liste : " ; + ref.Affiche(); + cout << "\n peut-etre que l'element nb : " << nb << " du maillage : " << nn + << " n'existe pas ? " << endl; + Sortie(-1); // on force la sortie + }; + }; + }; + + refG = lesRef->Reference_suivante(); + }; + // on s'occupe de mettre à jour les types de pb et les ddl types associés + Mise_a_jour_type_pb_type_associe_ddl(); + + if (ParaGlob::NiveauImpression() >= 4) + cout << " fin de la lecture des maillages " << endl; + }; + +// affichage et definition interactive des commandes +void LesMaillages::Info_commande_lesMaillages() + { // def des maillages +// int lectureEnCour = 0; + // def d'un premier maillage + tabMaillage(1) = new Maillage (mapNomMail,1,paraGlob->Dimension()); + cout << "\n# ----- definition des maillages ----- "; + cout << "\n# def des fichiers de maillage "; + string rep="_"; + + if (rep != "f") + {ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier + sort << "\n#--------------------------------------" + << "\n#| definition du (ou des) maillage(s) |" + << "\n#--------------------------------------"; + cout << "\n dans le fichier de commande final, on utilisera de preference une inclusion " + << "\n d'un fichier qui contiendra le maillage (ou plusieurs fichiers pour plusieurs maillages\n"; + + while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) + { + try + { cout + << "\n (0 ou f) (fin) " + << "\n (1) (defaut) inclusion de fichier et affinage " + << "\n (2) fusion des deux precedents maillages " +// << "\n (3) renumerotation de tous les maillages " +// << "\n (4 ou ? ) exemple - informations sur fichier ! " + << "\n (3 ou ? ) exemple - informations sur fichier ! " + << "\n "; + if (rep != "f") + rep = lect_return_defaut(false,"1"); + + if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe + break; + int num = ChangeEntier(rep); + if (Minuscules(rep) == "?") + num = 3; //4; + bool choix_valide=false; + if ((num >= 0)&&(num<=3)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 3 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + } + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: // inclusion de fichier et affinage + { string repi; + while (Minuscules(repi) != "f") + {// indique que les prochaines references seront pour le maillage 1, systématiquement + lesRef->NbMaille(1); int cas = 1; + tabMaillage(1)->Info_commande_Maillages(entreePrinc,*lesRef, cas); + nbMaillageTotal = 1 ; + cout << "\n autre fichier ou fin (rep o ou f) "; + repi = lect_return_defaut(false,"f"); + }; + sort << "\n \n "; + break; + } + case 2: // fusion des deux precedents maillages + { sort << "\n fusion_avec_le_maillage_precedent_ "; + int cas = 3; // on rappelle l'affinage en fin de maillage + tabMaillage(1)->Info_commande_Maillages(entreePrinc,*lesRef, cas); + break;} +// case 3: // renumerotation de tous les maillages +// { sort << "\n renumerotation_tous_maillages_ "; +// break;} + case 3: // exemple - informations sur fichier + { cout << "\n on se reportera a la documentation pour une information precise " + << " ici il y a sortie sur le fichier .info d'exemple et d'infos succintes "; + sort << "\n# exemples: tout d'abord l'inclusion, " + << "\n# 2 solutions equivalentes : soit deux fichiers par maillage -> exemple" + << "\n# < nom_de_maillage.her # fichier qui contiend le maillage" + << "\n# < nom_de_maillage.lis # fichier qui contiend les references " + << "\n# soit un seul fichier par maillage -> exemple" + << "\n# < nom_de_maillage.her # fichier qui contiend le maillage" + << "\n \n# maintenant on presente un exemple de contenu de mailage correspondant aux choix propose" + << "\n#------------------------------ exemple de contenu maillage -----------------"; + // indique que les prochaines references seront pour le maillage 1 + lesRef->NbMaille(1);int cas = 2; + tabMaillage(1)->Info_commande_Maillages(entreePrinc,*lesRef, cas); + nbMaillageTotal = 1 ; + + sort << "\n#-------------------------- fin exemple de contenu maillage -----------------\n \n "; + break; + }; + default: + cout << "\n le cas "< complet +// = false -> incomplet +bool LesMaillages::Complet() + { bool res = true; + for ( int i=1; i<= nbMaillageTotal;i++) + res = res && tabMaillage(i)->Complet(); + return res; + }; + +// introduction des lois de comportement dans les elements qui le necessite +// des sections pour les poutres etc c-a-d , completer les elements +// avec les donnees qui ont ete acquises apres la lecture du maillage +// def des tableaux de ddl dans les noeuds +// def des pointeurs d'assemblage dans les noeuds +void LesMaillages::Completer(DiversStockage* divers,LesLoisDeComp* lesLois + ,LesFonctions_nD* lesFonctionsnD ) + { + // cas des dilatations thermiques + int divers_TabDila_Taille=divers->TabCoefDila().Taille(); + for (int ii=1;ii<= divers_TabDila_Taille;ii++) + { string nomDila = (divers->TabCoefDila())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_Dila = (divers->TabCoefDila())(ii); + // soit c'est une valeur fixe soit une fonction nD + double val = 0; // init par défaut + string nom_fct_nD("_"); // "" + if (div_Dila.Val() != NULL) // cas d'une valeur fixe + { val = *(div_Dila.Val());} // recup de la valeur + else if (div_Dila.Fct_nD() != NULL) // cas d'une fonction nD + { nom_fct_nD = *(div_Dila.Fct_nD());} + else // sinon il y a un pb + { cout << "\n *** erreur de definition de la dilatation les infos lues ne sont pas correctes: "; + div_Dila.Affiche(); + Sortie(1); + }; + const Reference & refG = lesRef->Trouve(nomDila,div_Dila.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la reference " << refG.Nom() << " ne concerne pas des elements "; + cout << " \n cas des donnees relatives aux masses volumiques "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // creation d'un bloc general contenant des informations + BlocGen bloc(2,1); + bloc.Change_nom(1,"dilatation_thermique"); + bloc.Change_nom(2,nom_fct_nD); // s'il contient "_" cela veut dire : pas de fctnD + bloc.Change_val(1, val); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur la dilatation thermique n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + }; + } + }; + + // cas des lois de comportement + int lesLois_TabRefLoi_Taille = lesLois->TabRefLoi().Taille(); + for (int i=1;i<= lesLois_TabRefLoi_Taille;i++) + { string nomLoi = (lesLois->TabRefLoi())(i).st2; + // recup de la reference + const LesLoisDeComp::RefLoi & refloi = (lesLois->TabRefLoi())(i); // ref de loi + const Reference& refG = lesRef->Trouve(refloi.st1,(refloi.nom_maillage)); + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la reference " << refG.Nom() << " ne concerne pas des elements "; + cout << " \n cas des donnees relatives aux lois de comportement "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int j= 1; j<= ref_Taille; j++) + {int nb = ref.Numero(j) ; // le numero de l'element dans le maillage + int nn = ref.Nbmaille(); // le numero du maillage + // le pointeur le loi + LoiAbstraiteGeneral * pt = lesLois->PtLoi_abstraite(nomLoi); + if (pt == NULL) + { // cas d'un pointeur en retour null, la loi n'existe pas + cout << "\n *** erreur en lecture: la loi de nom : " << nomLoi + << " n'existe pas !! revoyez vos donnees "; + if (ParaGlob::NiveauImpression() > 5) + cout << "\n LesMaillages::Completer( ... "; + Sortie(1); + } + // attribution du pointeur + Element_LesMaille(nn,nb).DefLoi(pt); + } + } + // cas des sections d' elements + int divers_TabSect_Taille=divers->TabSect().Taille(); + for (int ii=1;ii<= divers_TabSect_Taille;ii++) + { //string nomSect = (divers->TabSect())(ii).nomref; // recup du nom de la ref + string nomSect = (divers->TabSect())(ii).NomRef(); // recup du nom de la ref + //double val = (divers->TabSect())(ii).val; // recup de la valeur + const BlocDdlLim& div_sect = (divers->TabSect())(ii); + // soit c'est une valeur fixe soit une fonction nD + double val = 0; // init par défaut + string nom_fct_nD("_"); // "" + if (div_sect.Val() != NULL) // cas d'une valeur fixe + { val = *(div_sect.Val());} // recup de la valeur + else if (div_sect.Fct_nD() != NULL) // cas d'une fonction nD + { nom_fct_nD = *(div_sect.Fct_nD());} + else // sinon il y a un pb + { cout << "\n *** erreur de definition de la section les infos lues ne sont pas correctes: "; + div_sect.Affiche(); + Sortie(1); + }; + const Reference & refG = lesRef->Trouve(nomSect,div_sect.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la reference " << refG.Nom() << " ne concerne pas des elements "; + cout << " \n cas des donnees relatives aux sections "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // creation d'un bloc general contenant des informations + BlocGen bloc(2,1); + bloc.Change_nom(1,"sections"); + bloc.Change_nom(2,nom_fct_nD); // s'il contient "_" cela veut dire : pas de fctnD + bloc.Change_val(1, val); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur la section n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + }; + } + } + + // cas des variation de section d' elements + int divers_TabVarSect_Taille=divers->TabVarSect().Taille(); + for (int ii=1;ii<= divers_TabVarSect_Taille;ii++) + { string nomVarSect = (divers->TabVarSect())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_varsect = (divers->TabVarSect())(ii); + double val = div_varsect.Val(); // recup de la valeur + const Reference & refG = lesRef->Trouve(nomVarSect,div_varsect.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la reference " << refG.Nom() << " ne concerne pas des elements "; + cout << " \n cas des donnees relatives aux variations de sections "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // creation d'un bloc general contenant des informations + BlocGen bloc(1,1); + bloc.Change_nom(1,"variation_section"); + bloc.Change_val(1, val); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur la variation de section n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() <<" "<< poi->Interpolation()<<" "<TypeProblem(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + } + } + }; + + // cas des epaisseurs d' elements + int divers_TabEpaiss_Taille=divers->TabEpaiss().Taille(); + for (int ii=1;ii<= divers_TabEpaiss_Taille;ii++) + { string nomSect = (divers->TabEpaiss())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_epai = (divers->TabEpaiss())(ii); + // soit c'est une valeur fixe soit une fonction nD + double val = 0; // init par défaut + string nom_fct_nD("_"); // "" + if (div_epai.Val() != NULL) // cas d'une valeur fixe + { val = *(div_epai.Val());} // recup de la valeur + else if (div_epai.Fct_nD() != NULL) // cas d'une fonction nD + { nom_fct_nD = *(div_epai.Fct_nD());} + else // sinon il y a un pb + { cout << "\n *** erreur de definition de l'epaisseur les infos lues ne sont pas correctes: "; + div_epai.Affiche(); + Sortie(1); + }; + + const Reference& refG = lesRef->Trouve(nomSect,div_epai.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la référence " << refG.Nom() << " ne concerne pas des éléments "; + cout << " \n cas des données relatives aux épaisseurs d'éléments "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // creation d'un bloc general contenant des informations + BlocGen bloc(2,1); + bloc.Change_nom(1,"epaisseurs"); + bloc.Change_nom(2,nom_fct_nD); // s'il contient "_" cela veut dire : pas de fctnD + bloc.Change_val(1, val); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur l\'epaisseur n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + }; + } + } + // cas des largeurs d' elements + int divers_TabLargeurs_Taille=divers->TabLargeurs().Taille(); + for (int ii=1;ii<= divers_TabLargeurs_Taille;ii++) + { string nomSect = (divers->TabLargeurs())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_larg = (divers->TabLargeurs())(ii); + // soit c'est une valeur fixe soit une fonction nD + double val = 0; // init par défaut + string nom_fct_nD("_"); // "" + if (div_larg.Val() != NULL) // cas d'une valeur fixe + { val = *(div_larg.Val());} // recup de la valeur + else if (div_larg.Fct_nD() != NULL) // cas d'une fonction nD + { nom_fct_nD = *(div_larg.Fct_nD());} + else // sinon il y a un pb + { cout << "\n *** erreur de definition de la largeur les infos lues ne sont pas correctes: "; + div_larg.Affiche(); + Sortie(1); + }; + const Reference& refG = lesRef->Trouve(nomSect,div_larg.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la référence " << refG.Nom() << " ne concerne pas des éléments "; + cout << " \n cas des données relatives aux largeurs d'éléments "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // creation d'un bloc general contenant des informations + BlocGen bloc(2,1); + bloc.Change_nom(2,nom_fct_nD); // s'il contient "_" cela veut dire : pas de fctnD + bloc.Change_nom(1,"largeurs"); + bloc.Change_val(1, val); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur la largeur n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + }; + } + } + // cas des masses volumique d' elements + int divers_TabMasseVolu_Taille=divers->TabMasseVolu().Taille(); + for (int ii=1;ii<= divers_TabMasseVolu_Taille;ii++) + { string nomMasseVol = (divers->TabMasseVolu())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_massevolu = (divers->TabMasseVolu())(ii); + // soit c'est une valeur fixe soit une fonction nD + double val = 0; // init par défaut + string nom_fct_nD("_"); // "" + if (div_massevolu.Val() != NULL) // cas d'une valeur fixe + { val = *(div_massevolu.Val());} // recup de la valeur + else if (div_massevolu.Fct_nD() != NULL) // cas d'une fonction nD + { nom_fct_nD = *(div_massevolu.Fct_nD());} + else // sinon il y a un pb + { cout << "\n *** erreur de definition de la masse volumique les infos lues ne sont pas correctes: "; + div_massevolu.Affiche(); + Sortie(1); + }; + const Reference & refG = lesRef->Trouve(nomMasseVol,div_massevolu.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la référence " << refG.Nom() << " ne concerne pas des éléments "; + cout << " \n cas des données relatives aux masses volumiques "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // creation d'un bloc general contenant des informations + BlocGen bloc(2,1); + bloc.Change_nom(1,"masse_volumique"); + bloc.Change_nom(2,nom_fct_nD); // s'il contient "_" cela veut dire : pas de fctnD + bloc.Change_val(1, val); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur la masse volumique n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + }; + } + } + + // cas des gestions d'hourglass d'elements + int divers_TabGesHourglass_Taille=divers->TabGesHourglass().Taille(); + for (int ii=1;ii<= divers_TabGesHourglass_Taille;ii++) + { string nomGesHourglass = (divers->TabGesHourglass())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_GesHourglass = (divers->TabGesHourglass())(ii); + // double val = div_GesHourglass.Val(); // recup de la valeur + const Reference & refG = lesRef->Trouve(nomGesHourglass,div_GesHourglass.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la référence " << refG.Nom() << " ne concerne pas des éléments "; + cout << " \n cas des données relatives aux gestions des modes d'hourglass "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // creation d'un bloc general contenant des informations + BlocGen bloc(1,2); + bloc.Change_nom(1,div_GesHourglass.Nom(2)); + bloc.Change_val(1, div_GesHourglass.Val(1)); + // récupération éventuelle de la loi si besoin + LoiAbstraiteGeneral * loiHourglass = NULL; + + if ( (Id_Nom_StabHourglass(div_GesHourglass.Nom(2).c_str()) == STABHOURGLASS_PAR_COMPORTEMENT) + || (Id_Nom_StabHourglass(div_GesHourglass.Nom(2).c_str()) == STABHOURGLASS_PAR_COMPORTEMENT_REDUIT)) + // le pointeur le loi + { loiHourglass = lesLois->PtLoi_abstraite(div_GesHourglass.Nom(3));}; + // demande a l'element de se completer + poi = poi->Complet_Hourglass(loiHourglass,bloc); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur la gestion d'hourglass: " << div_GesHourglass << " n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + } + }; + }; + + // cas des intégrales sur le volume + int divers_TabIntegVol_Taille=divers->TabIntegVol().Taille(); + // on redimentionne les tableaux de sauvegardes + integ_vol_typeQuel.Change_taille(divers_TabIntegVol_Taille); + integ_vol_typeQuel_t.Change_taille(divers_TabIntegVol_Taille); + ref_integ_vol.Change_taille(divers_TabIntegVol_Taille); + for (int ii=1;ii<= divers_TabIntegVol_Taille;ii++) + { string nomIntegVol = (divers->TabIntegVol())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_IntegVol = (divers->TabIntegVol())(ii); + const Reference & refG = lesRef->Trouve(nomIntegVol,div_IntegVol.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la référence " << refG.Nom() << " ne concerne pas des éléments "; + cout << " \n cas des données relatives aux integrations sur le volume "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + // creation d'un bloc general contenant des informations + // n= nombre de string, m nombre de double + BlocGen bloc(4,1) ; // par defaut +////--- debug +//cout << "\n -- debug LesMaillages::Completer( "; +//div_IntegVol.Affiche(); cout << endl; +////--- fin debug + string nom_inter("integrale_sur_volume_"); + bloc.Change_nom(1,nom_inter); // le type d'intégrale: de volume ici + bloc.Change_nom(2,div_IntegVol.Nom(2)); // mot clé : ex: un_ddl_etendu_ + bloc.Change_nom(3,div_IntegVol.Nom(3)); // ex: le nom du ddl : ex UX + // construction d'un nom qui servira à discriminer les différents conteneurs + string nom_ref("int_vol_");// init + if ((div_IntegVol.NomMaillage() == NULL) // cas d'un seule maillage + && (nbMaillageTotal==1)) // enregistré + {nom_ref +=(refG.Nom());} + else if (div_IntegVol.NomMaillage() != NULL) // cas de plusieurs maillages + {nom_ref += (*div_IntegVol.NomMaillage())+"_"+(refG.Nom());} + else // sinon pb + { cout << "\n erreur il manque le nom de maillage alors qu'il y a plusieurs maillages en cours "; + cout << " \n cas des données relatives aux integrations sur le volume "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + + bloc.Change_val(1,ii); // on indique le numéro du stockage global + // on commence par définir le conteneur global qui sera stocké dans LesMaillages + ref_integ_vol(ii) = &refG; + if (bloc.Nom(2) == "un_ddl_etendu_") + { // il s'agit d'une intégrale d'un ddl étendu de nom: bloc.Nom(3) + nom_ref += "_ddl_etendu_"+bloc.Nom(3); + Ddl_etendu ddl(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc + Grandeur_Ddl_etendu grand_courant(ddl,nom_ref);// le conteneur ad hoc + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME,nom_ref,SCALAIRE_DOUBLE); +// TypeQuelconque typQ(INTEG_SUR_VOLUME,EPS11,grand_courant); + TypeQuelconque typQ(enuType,EPS11,grand_courant); + integ_vol_typeQuel(ii) = (typQ); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "_t_"; + Ddl_etendu ddl_t(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc + Grandeur_Ddl_etendu grand_courant_t(ddl_t,nom_ref_t);// le conteneur ad hoc + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME,nom_ref_t,SCALAIRE_DOUBLE); +// TypeQuelconque typQ_t(INTEG_SUR_VOLUME,EPS11,grand_courant_t); + TypeQuelconque typQ_t(enuType_t,EPS11,grand_courant_t); + integ_vol_typeQuel_t(ii) = (typQ_t); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); + } + else if (bloc.Nom(2) == "une_fonction_nD_") + { // il s'agit d'une intégrale d'une fonction nD de nom: bloc.Nom(3) + nom_ref += "_fct_nD_"+bloc.Nom(3); + // on récupère le pointeur de fonction correspondant: + Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3)); + int nb_composante = fct->NbComposante(); + Grandeur_Vecteur_Nommer grand_courant(nom_ref,nb_composante,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME,nom_ref,VECTEUR); +// TypeQuelconque typQ(INTEG_SUR_VOLUME,EPS11,grand_courant); + TypeQuelconque typQ(enuType,EPS11,grand_courant); + integ_vol_typeQuel(ii) = (typQ); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "_t_"; + Grandeur_Vecteur_Nommer grand_courant_t(nom_ref_t,nb_composante,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME,nom_ref_t,VECTEUR); +// TypeQuelconque typQ_t(INTEG_SUR_VOLUME,EPS11,grand_courant_t); + TypeQuelconque typQ_t(enuType_t,EPS11,grand_courant_t); + integ_vol_typeQuel_t(ii) = (typQ_t); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); +////--- debug +//cout << "\n -- debug LesMaillages::Completer( "; +//if (nom_ref_t == "int_vol_E_tout_fct_nD_fct1_t_") +// { const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref_t)); +// TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); +// cout << "\n gr_quelc= "<< (*gr_quelc) << endl; +// Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier +// cout << "\n gr.NbMaxiNumeroOrdre()= "<Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur l'integration de ";bloc.Affiche(); + cout << " n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + }; + }; + ref_integ_vol(ii)= &refG; // sauvegarde + }; + + // cas des intégrales sur le volume et le temps + int divers_TtabIntegVol_et_temps_Taille=divers->TtabIntegVol_et_temps().Taille(); + // on redimentionne les tableaux de sauvegardes + integ_vol_t_typeQuel.Change_taille(divers_TtabIntegVol_et_temps_Taille); + integ_vol_t_typeQuel_t.Change_taille(divers_TtabIntegVol_et_temps_Taille); + ref_integ_vol_t.Change_taille(divers_TtabIntegVol_et_temps_Taille); + for (int ii=1;ii<= divers_TtabIntegVol_et_temps_Taille;ii++) + { string nomIntegVol = (divers->TtabIntegVol_et_temps())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_IntegVol = (divers->TtabIntegVol_et_temps())(ii); + const Reference & refG = lesRef->Trouve(nomIntegVol,div_IntegVol.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la référence " << refG.Nom() << " ne concerne pas des éléments "; + cout << " \n cas des données relatives aux integrations sur le volume et le temps "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + // creation d'un bloc general contenant des informations + // n= nombre de string, m nombre de double + BlocGen bloc(4,1) ; // par defaut + string nom_inter("integrale_sur_vol_et_temps_"); + bloc.Change_nom(1,nom_inter); // le type d'intégrale: de volume ici + bloc.Change_nom(2,div_IntegVol.Nom(2)); + bloc.Change_nom(3,div_IntegVol.Nom(3)); + // construction d'un nom qui servira à discriminer les différents conteneurs + string nom_ref("int_vol_temps_");// init + if ((div_IntegVol.NomMaillage() == NULL) // cas d'un seule maillage + && (nbMaillageTotal==1)) // enregistré + {nom_ref +=(refG.Nom());} + else if (div_IntegVol.NomMaillage() != NULL) // cas de plusieurs maillages + {nom_ref += (*div_IntegVol.NomMaillage())+"_"+(refG.Nom());} + else // sinon pb + { cout << "\n erreur il manque le nom de maillage alors qu'il y a plusieurs maillages en cours "; + cout << " \n cas des données relatives aux integrations sur le volume et le temps "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + bloc.Change_val(1,ii); // on indique le numéro du stockage global + // on commence par définir le conteneur global qui sera stocké dans LesMaillages + ref_integ_vol_t(ii) = &refG; + if (bloc.Nom(2) == "un_ddl_etendu_") + { // il s'agit d'une intégrale d'un ddl étendu de nom: bloc.Nom(3) + nom_ref += "_ddl_etendu_"+bloc.Nom(3); + Ddl_etendu ddl(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc + Grandeur_Ddl_etendu grand_courant(ddl,nom_ref);// le conteneur ad hoc + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME_ET_TEMPS,nom_ref,SCALAIRE_DOUBLE); +// TypeQuelconque typQ(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant); + TypeQuelconque typQ(enuType,EPS11,grand_courant); + integ_vol_t_typeQuel(ii) = (typQ); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "_t_"; + Ddl_etendu ddl_t(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc + Grandeur_Ddl_etendu grand_courant_t(ddl,nom_ref_t);// le conteneur ad hoc + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME_ET_TEMPS,nom_ref_t,SCALAIRE_DOUBLE); +// TypeQuelconque typQ_t(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant_t); + TypeQuelconque typQ_t(enuType_t,EPS11,grand_courant_t); + integ_vol_t_typeQuel_t(ii) = (typQ_t); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); + } + else if (bloc.Nom(2) == "une_fonction_nD_") + { // il s'agit d'une intégrale d'une fonction nD de nom: bloc.Nom(3) + nom_ref += "_fct_nD_"+bloc.Nom(3); + // on récupère le pointeur de fonction correspondant: + Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3)); + int nb_composante = fct->NbComposante(); + Grandeur_Vecteur_Nommer grand_courant(nom_ref,nb_composante,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME_ET_TEMPS,nom_ref,VECTEUR); +// TypeQuelconque typQ(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant); + TypeQuelconque typQ(enuType,EPS11,grand_courant); + integ_vol_t_typeQuel(ii) = (typQ); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "_t_"; + Grandeur_Vecteur_Nommer grand_courant_t(nom_ref_t,nb_composante,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (INTEG_SUR_VOLUME_ET_TEMPS,nom_ref_t,VECTEUR); +// TypeQuelconque typQ_t(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant_t); + TypeQuelconque typQ_t(enuType_t,EPS11,grand_courant_t); + integ_vol_t_typeQuel_t(ii) = (typQ_t); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); + }; + bloc.Change_nom(4,nom_ref); // on indique le nom de référencement global + // puis on alimente les éléments concernés par ces calculs +////--- debug +//cout << "\n -- debug LesMaillages::Completer( "; +//bloc.Affiche(); cout << endl; +////--- fin debug + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + if (poi == NULL) + { // cas d'un probleme + cout << "\n erreur l'integration de ";bloc.Affiche(); + cout << " n'est pas adapte a l\'element "; + poi = & Element_LesMaille(nnn,nbb); + cout << "\n element " << poi->Geometrie() << poi->Interpolation(); + cout << "\n LesMaillages::Completer( etc ... " << endl; + Sortie(1); + }; + }; + }; + + // cas de la stabilisation transversale de membrane et ou de biel + int divers_TabStabMembBiel_Taille=divers->TabStabMembBiel().Taille(); + // on redimentionne les tableaux de sauvegardes + for (int ii=1;ii<= divers_TabStabMembBiel_Taille;ii++) + { string nomStabMembBiel = (divers->TabStabMembBiel())(ii).NomRef(); // recup du nom de la ref + // on récupère la taille réel du conteneur + int nb_info = (divers->TabStabMembBiel())(ii).DimNom(); + // creation d'un bloc general contenant des informations + // n= nombre de string, m nombre de double + BlocGen bloc(nb_info,0) ; // par defaut + // on récupère le bloc gen qui est par défaut de type 4,0 mais en fait est peut-être différent + // via la lecture. Comme on ramène un pointeur, on récupère le vrai bloc lu, modifié éventuellement en taille + const BlocDdlLim& div_TabStabMembBiel = (divers->TabStabMembBiel())(ii); + const Reference & refG = lesRef->Trouve(nomStabMembBiel,div_TabStabMembBiel.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la référence " << refG.Nom() << " ne concerne pas des éléments "; + cout << " \n cas des données relatives a la stabilisation transversale de membrane ou de biel "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + string nom_inter("stabilisation_transvers_membrane_biel_"); + bloc.Change_nom(1,nom_inter); // le mot clé + // ensuite le type de stabilisation + bloc.Change_nom(2,div_TabStabMembBiel.Nom(2)); + // puis un des deux mots clés : "une_valeur_numerique_" ou "une_fonction_nD_" + bloc.Change_nom(3,div_TabStabMembBiel.Nom(3)); + // un string qui contient: soit la valeur numérique, soit le nom de la fonction nD + bloc.Change_nom(4,div_TabStabMembBiel.Nom(4)); + // s'il y a des infos supplémentaires, on les recopie + if (nb_info > 4) + for (int i=4;i<=nb_info;i++) + bloc.Change_nom(i,div_TabStabMembBiel.Nom(i)); + + // puis on alimente les éléments concernés par ces calculs +////--- debug +//cout << "\n -- debug LesMaillages::Completer( "; +//bloc.Affiche(); cout << endl; +////--- fin debug + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + }; + }; + + +// // retourne le tableau sur la définition d'un repère d'anisotropie aux éléments +// const Tableau < BlocDdlLim >& TabRepAnisotrope() const {return tabRepAnisotrope;}; + // cas de la définition de repère d'anisotropie + int divers_TabRepAnisotrope_Taille=divers->TabRepAnisotrope().Taille(); + // on redimentionne les tableaux de sauvegardes + for (int ii=1;ii<= divers_TabRepAnisotrope_Taille;ii++) + { string nomRepAnisotrope = (divers->TabRepAnisotrope())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_TabRepAnisotrope = (divers->TabRepAnisotrope())(ii); + const Reference & refG = lesRef->Trouve(nomRepAnisotrope,div_TabRepAnisotrope.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des éléments + if ( refG.Indic() != 2) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la reference " << refG.Nom() << " ne concerne pas des elements "; + cout << " \n cas des donnees relatives a la definition de repere d'anisotropie "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + // creation d'un bloc general contenant des informations + // n= nombre de string, m nombre de double + BlocGen bloc(5,0) ; // par defaut + string nom_inter("repere_anisotropie_"); + bloc.Change_nom(1,nom_inter); // le mot clé + // ensuite le type l'identificateur de repere + bloc.Change_nom(2,div_TabRepAnisotrope.Nom(2)); + // ensuite le type de repere + bloc.Change_nom(3,div_TabRepAnisotrope.Nom(3)); + // puis la méthode de définition du repère + bloc.Change_nom(4,div_TabRepAnisotrope.Nom(4)); + // un string qui contient le nom de la fonction nD + bloc.Change_nom(5,div_TabRepAnisotrope.Nom(6)); + // puis on alimente les éléments concernés par ces calculs +////--- debug +//cout << "\n -- debug LesMaillages::Completer( "; +//bloc.Affiche(); cout << endl; +////--- fin debug + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // demande a l'element de se completer + poi = poi->Complete(bloc,lesFonctionsnD); + }; + }; + + + // cas de statistique d'une ref de noeuds pour une grandeur quelconque + int divers_TabStatistique_Taille=divers->TabStatistique().Taille(); + // on redimentionne les tableaux de sauvegardes + statistique_typeQuel.Change_taille(divers_TabStatistique_Taille); + statistique_typeQuel_t.Change_taille(divers_TabStatistique_Taille); + ref_statistique.Change_taille(divers_TabStatistique_Taille); + pour_statistique_de_ddl.Change_taille(divers_TabStatistique_Taille); + for (int ii=1;ii<= divers_TabStatistique_Taille;ii++) + { string nomStatistique = (divers->TabStatistique())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_Statistique = (divers->TabStatistique())(ii); + const Reference & refG = lesRef->Trouve(nomStatistique,div_Statistique.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des noeuds + if ( refG.Indic() != 1) + { // erreur la référence ne concerne pas des éléments + cout << "\n erreur la reference " << refG.Nom() << " ne concerne pas des Noeuds "; + cout << " \n cas des donnees relatives aux statistiques "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + // creation d'un bloc general contenant des informations + // n= nombre de string, m nombre de double + BlocGen bloc(4,1) ; // par defaut + ////--- debug + //cout << "\n -- debug LesMaillages::Completer( "; + //div_Statistique.Affiche(); cout << endl; + ////--- fin debug + string nom_inter("statistique_"); + bloc.Change_nom(1,nom_inter); // le type de statistique + bloc.Change_nom(2,div_Statistique.Nom(2)); // mot clé : ex: un_ddl_etendu_ + bloc.Change_nom(3,div_Statistique.Nom(3)); // ex: le nom du ddl : ex UX + // construction d'un nom qui servira à discriminer les différents conteneurs + string nom_ref("statistique_");// init + if ((div_Statistique.NomMaillage() == NULL) // cas d'un seule maillage + && (nbMaillageTotal==1)) // enregistré + {nom_ref +=(refG.Nom());} + else if (div_Statistique.NomMaillage() != NULL) // cas de plusieurs maillages + {nom_ref += (*div_Statistique.NomMaillage())+"_"+(refG.Nom());} + else // sinon pb + { cout << "\n erreur il manque le nom de maillage alors qu'il y a plusieurs maillages en cours "; + cout << " \n cas des donnees relatives aux statistiques sur ref de noeuds "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + + bloc.Change_val(1,ii); // on indique le numéro du stockage global + // on commence par définir le conteneur global qui sera stocké dans LesMaillages + ref_statistique(ii) = &refG; + if (bloc.Nom(2) == "un_ddl_etendu_") + { // il s'agit d'une statistique d'un ddl étendu de nom: bloc.Nom(3) + nom_ref += "_ddl_etendu_"+bloc.Nom(3); + // on sauvegarde le Ddl_enum_etendu associé + pour_statistique_de_ddl(ii) = Ddl_enum_etendu(bloc.Nom(3)); + // on définit le conteneur résultat: on stocke un vecteur, car pour un ddl -> 10 valeurs + Grandeur_Vecteur_Nommer gvec_courant(nom_ref,10); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE,nom_ref,VECTEUR); + TypeQuelconque typQ(enuType,X1,gvec_courant); + statistique_typeQuel(ii) = (typQ); // stockage interne à LesMaillages + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "__t_"; + // on définit le conteneur résultat: on stocke un vecteur, car pour un ddl -> 10 valeurs + Grandeur_Vecteur_Nommer gvec_courant_t(nom_ref_t,10); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE,nom_ref_t,VECTEUR); + TypeQuelconque typQ_t(enuType_t,X1,gvec_courant_t); + statistique_typeQuel_t(ii) = (typQ_t); // stockage interne à LesMaillages + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); + } + else if (bloc.Nom(2) == "une_fonction_nD_") + { // il s'agit d'une statistique d'une fonction nD de nom: bloc.Nom(3) + nom_ref += "_fct_nD_"+bloc.Nom(3); + // on récupère le pointeur de fonction correspondant: + Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3)); + int nb_composante = fct->NbComposante(); + int dim_necessaire = (6*nb_composante + 4); // cf. la méthode CalStatistique() + Grandeur_Vecteur_Nommer grand_courant(nom_ref,dim_necessaire,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE,nom_ref,VECTEUR); + TypeQuelconque typQ(enuType,X1,grand_courant); + statistique_typeQuel(ii) = (typQ); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "__t_"; + Grandeur_Vecteur_Nommer grand_courant_t(nom_ref_t,dim_necessaire,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE,nom_ref_t,VECTEUR); + TypeQuelconque typQ_t(enuType_t,X1,grand_courant_t); + statistique_typeQuel_t(ii) = (typQ_t); // stockage interne à LesMaillages + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); + ////--- debug + //cout << "\n -- debug LesMaillages::Completer( "; + //if (nom_ref_t == "int_vol_E_tout_fct_nD_fct1_t_") + // { const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref_t)); + // TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + // cout << "\n gr_quelc= "<< (*gr_quelc) << endl; + // Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) gr_quelc->Grandeur_pointee()); // pour simplifier + // cout << "\n gr.NbMaxiNumeroOrdre()= "<Complete(bloc,lesFonctionsnD); +// if (poi == NULL) +// { // cas d'un probleme +// cout << "\n erreur l'integration de ";bloc.Affiche(); +// cout << " n'est pas adapte a l\'element "; +// poi = & Element_LesMaille(nnn,nbb); +// cout << "\n element " << poi->Geometrie() << poi->Interpolation(); +// cout << "\n LesMaillages::Completer( etc ... " << endl; +// Sortie(1); +// }; +// }; + }; + + // cas des statistiques sur des ref de noeuds avec cumul en temps + int divers_TabStatistique_et_temps_Taille=divers->TabStatistique_et_temps().Taille(); + // on redimentionne les tableaux de sauvegardes + statistique_t_typeQuel.Change_taille(divers_TabStatistique_et_temps_Taille); + statistique_t_typeQuel_t.Change_taille(divers_TabStatistique_et_temps_Taille); + ref_statistique_t.Change_taille(divers_TabStatistique_et_temps_Taille); + pour_statistique_t_de_ddl.Change_taille(divers_TabStatistique_et_temps_Taille,NU_DDL); + for (int ii=1;ii<= divers_TabStatistique_et_temps_Taille;ii++) + { string nomStatistique = (divers->TabStatistique_et_temps())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_Statistique = (divers->TabStatistique_et_temps())(ii); + const Reference & refG = lesRef->Trouve(nomStatistique,div_Statistique.NomMaillage()); // recup de la reference + // vérif que la référence s'adresse à des noeuds + if ( refG.Indic() != 1) + { // erreur la référence ne concerne pas des noeuds + cout << "\n erreur la reference " << refG.Nom() << " ne concerne pas des noeuds "; + cout << " \n cas des donnees relatives aux statistiques de ref de noeuds avec cumul en temps "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + // creation d'un bloc general contenant des informations + // n= nombre de string, m nombre de double + BlocGen bloc(4,1) ; // par defaut + string nom_inter("statistique_et_temps_"); + bloc.Change_nom(1,nom_inter); // le type de statistique + bloc.Change_nom(2,div_Statistique.Nom(2)); + bloc.Change_nom(3,div_Statistique.Nom(3)); + // construction d'un nom qui servira à discriminer les différents conteneurs + string nom_ref("statistique_temps_");// init + if ((div_Statistique.NomMaillage() == NULL) // cas d'un seule maillage + && (nbMaillageTotal==1)) // enregistré + {nom_ref +=(refG.Nom());} + else if (div_Statistique.NomMaillage() != NULL) // cas de plusieurs maillages + {nom_ref += (*div_Statistique.NomMaillage())+"_"+(refG.Nom());} + else // sinon pb + { cout << "\n erreur il manque le nom de maillage alors qu'il y a plusieurs maillages en cours "; + cout << " \n cas des données relatives aux statistiques sur des ref de noeuds avec cumul en temps "; + cout << "\n LesMaillages::Completer( .... "; + Sortie(1); + }; + bloc.Change_val(1,ii); // on indique le numéro du stockage global + // on commence par définir le conteneur global qui sera stocké dans LesMaillages + ref_statistique_t(ii) = &refG; + if (bloc.Nom(2) == "un_ddl_etendu_") + { // il s'agit d'une statistique d'un ddl étendu de nom: bloc.Nom(3) + nom_ref += "_ddl_etendu_"+bloc.Nom(3); + // on sauvegarde le Ddl_enum_etendu associé + pour_statistique_t_de_ddl(ii) = Ddl_enum_etendu(bloc.Nom(3)); + // on définit le conteneur résultat: on stocke un vecteur, car pour un ddl -> 10 valeurs + Grandeur_Vecteur_Nommer gvec_courant(nom_ref,10); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE_ET_TEMPS,nom_ref,VECTEUR); + TypeQuelconque typQ(enuType,X1,gvec_courant); + statistique_t_typeQuel(ii) = (typQ); // stockage interne à LesMaillages + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "__t_"; + // on définit le conteneur résultat: on stocke un vecteur, car pour un ddl -> 10 valeurs + Grandeur_Vecteur_Nommer gvec_courant_t(nom_ref_t,10); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE_ET_TEMPS,nom_ref_t,VECTEUR); + TypeQuelconque typQ_t(enuType_t,X1,gvec_courant_t); + statistique_t_typeQuel_t(ii) = (typQ_t); // stockage interne à LesMaillages + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); + } + else if (bloc.Nom(2) == "une_fonction_nD_") + { // il s'agit d'une statistique d'une fonction nD de nom: bloc.Nom(3) + nom_ref += "_fct_nD_"+bloc.Nom(3); + // on récupère le pointeur de fonction correspondant: + Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3)); + int nb_composante = fct->NbComposante(); + int dim_necessaire = (6*nb_composante + 4); // cf. la méthode CalStatistique() + Grandeur_Vecteur_Nommer grand_courant(nom_ref,dim_necessaire,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE_ET_TEMPS,nom_ref,VECTEUR); + TypeQuelconque typQ(enuType,X1,grand_courant); + statistique_t_typeQuel(ii) = (typQ); + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref); + // idem pour la grandeur à t + string nom_ref_t = nom_ref + "__t_"; + Grandeur_Vecteur_Nommer grand_courant_t(nom_ref_t,dim_necessaire,fct); + // on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas + // et on récupère un exemplaire + TypeQuelconque_enum_etendu enuType_t = + TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu + (STATISTIQUE_ET_TEMPS,nom_ref_t,VECTEUR); + TypeQuelconque typQ_t(enuType_t,X1,grand_courant_t); + statistique_t_typeQuel_t(ii) = (typQ_t); // stockage interne à LesMaillages + // et on ajoute une grandeur globale qui sera indexée par le nom de référence + ParaGlob::param->Ajout_grandeur_consultable(&typQ_t,nom_ref_t); + }; + bloc.Change_nom(4,nom_ref); // on indique le nom de référencement global +// // puis on alimente les éléments concernés par ces calculs +// ////--- debug +// //cout << "\n -- debug LesMaillages::Completer( "; +// //bloc.Affiche(); cout << endl; +// ////--- fin debug +// for (int jj= 1; jj<= ref_Taille; jj++) +// {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage +// int nnn = ref.Nbmaille(); // le numero du maillage +// // recup de l'element +// Element * poi = & Element_LesMaille(nnn,nbb); +// // demande a l'element de se completer +// poi = poi->Complete(bloc,lesFonctionsnD); +// if (poi == NULL) +// { // cas d'un probleme +// cout << "\n erreur l'integration de ";bloc.Affiche(); +// cout << " n'est pas adapte a l\'element "; +// poi = & Element_LesMaille(nnn,nbb); +// cout << "\n element " << poi->Geometrie() << poi->Interpolation(); +// cout << "\n LesMaillages::Completer( etc ... " << endl; +// Sortie(1); +// }; +// }; + }; + + + + // cas des tableaux de ddl pour les noeuds +// InitPositionAssemblage(nb_assemb); + }; + +// ramene le nombre total de ddl du pb +int LesMaillages::NbTotalDdlActifs() const + { // init du nombre de ddl actifs du pb + int nb = 0; + // puis boucle sur les maillages et les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + nb += Noeud_LesMaille(i1,i2).Nombre_var_ddl_actives(); + } + return nb; + }; + +// ramene le nombre total de ddl actifs du pb +// pour un type de ddl donné, dans le cas de type +// vectoriel on cumule les ddl de l'ensemble de la dimension +int LesMaillages::NbTotalDdlActifs(Enum_ddl enum_ddl) const + { // init du nombre de ddl actifs du pb + int nb = 0; + // puis boucle sur les maillages et les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + nb += Noeud_LesMaille(i1,i2).Nombre_var_ddl_actives(enum_ddl); + } + return nb; + }; + +// ramene le nombre total de points d'intégration correspondant à un ddl donné +int LesMaillages::NbTotalPtInteg(Enum_ddl enum_ddl) const + { // init du nombre de points d'intégration + int nb = 0; + // puis boucle sur les maillages et les éléments + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelmax; i2++) + nb += Element_LesMaille_const(i1,i2).NbPtInteg(enum_ddl); + } + return nb; + }; + +// ramene le nombre total de grandeurs génératrices, calculées aux points d'intégrations, +// correspondant à un ddl donné. +int LesMaillages::NbTotalGrandeursGeneratrices(Enum_ddl enum_ddl) const + { // init du nombre de grandeurs génératrices + int nb = 0; + // puis boucle sur les maillages et les éléments + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelmax; i2++) + { // on récupère le nombre de points d'intégrations + int nbptinteg = Element_LesMaille_const(i1,i2).NbPtInteg(enum_ddl); + // on récupère le nombre de grandeurs génératrices pour le ddl + int nbGG = Element_LesMaille_const(i1,i2).NbGrandeurGene(enum_ddl); + // calcul + nb += nbptinteg * nbGG; + } + } + return nb; + }; + +//récupération d'une grandeur vectoriel de dimension, la dimension +// de l'espace, défini au noeud et transféré dans un vecteur global +// qui cumule de manière séquentielle toutes les grandeurs +// en entrée : enum_ddl donne le type de la grandeur à récupérer +// en fait de la première composante +// duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt +// enum_actif : le transfert s'effectue que si le ddl enum_actif est actif +// ce qui permet la différentiation entre les différents ddl +// vect : est le vecteur global de stockage qui normalement a été +// au préalable dimensionné avec NbTotalDdlActifs(Enum_ddl enum_ddl) +// Important: pour chaque famille de ddl, les ddl sont classés de manière croissante, ce qui signifie +// que c'est l'ordre des pointeurs d'assemblage si et seulement si, ces ddl ont été rangés dans les noeuds +// au préalable +// en retour : une référence sur vect +Vecteur & LesMaillages::Vect_loc_vers_glob(Enum_dure duree,Enum_ddl enum_actif + ,Vecteur& vect,Enum_ddl enum_ddl) +{ // recup de la dimension + int dimen = ParaGlob::Dimension(); + // dans le cas axisymétrique il n'y a pas de variation suivant le dernier axe + if (ParaGlob::AxiSymetrie()) + dimen--; + int ivect = 1; // position global + // maintenant on passe en revue les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le ddl existe et que le ddl actif est actif + if ((noo->Existe_ici(enum_ddl)) && (noo->En_service(enum_actif)) + && (noo->UneVariable(enum_actif))) + // dans le cas où enum_ddl == X1, on regarde s'il ne faut pas associer l'épaisseur + // l'épaisseur n'est associée que si elle est une variable + switch (duree) + { case TEMPS_0 : + { for (int ii=1; ii<= dimen; ii++,ivect++) + vect(ivect) = noo->Valeur_0(Enum_ddl(ii-1 + enum_ddl) ); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {vect(ivect) = noo->Valeur_0(EPAIS);ivect++;}; + break; + } + case TEMPS_t : + { for (int ii=1; ii<= dimen; ii++,ivect++) + vect(ivect) = noo->Valeur_t(Enum_ddl(enum_ddl + ii-1)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {vect(ivect) = noo->Valeur_t(EPAIS);ivect++;}; + break; + } + case TEMPS_tdt : + { for (int ii=1; ii<= dimen; ii++,ivect++) + vect(ivect) = noo->Valeur_tdt(Enum_ddl(enum_ddl + ii-1)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {vect(ivect) = noo->Valeur_tdt(EPAIS);ivect++;}; + break; + } + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "LesMaillages::Vect_loc_vers_glob(Enum_dure... \n"; + Sortie(1); + } + } + } + return vect; + }; + +// fonction inverse de Vect_loc_vers_glob, il s'agit ici de passer +// de la grandeur globale aux grandeurs locale +void LesMaillages::Vect_glob_vers_local(Enum_dure duree,Enum_ddl enum_actif + ,const Vecteur& vect,Enum_ddl enum_ddl) +{ // recup de la dimension + int dimen = ParaGlob::Dimension(); + // dans le cas axisymétrique il n'y a pas de variation suivant le dernier axe + if (ParaGlob::AxiSymetrie()) + dimen--; + int ivect = 1; // position global + // maintenant on passe en revu les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le ddl existe et que le ddl actif est actif + if ((noo->Existe_ici(enum_ddl)) && (noo->En_service(enum_actif)) + && (noo->UneVariable(enum_actif))) + // dans le cas où enum_ddl == X1, on regarde s'il ne faut pas associer l'épaisseur + // l'épaisseur n'est associée que si elle est une variable + switch (duree) + { case TEMPS_0 : + { for (int ii=1; ii<= dimen; ii++,ivect++) + noo->Change_val_0(Enum_ddl(ii-1 + enum_ddl),vect(ivect)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {noo->Change_val_0(EPAIS,vect(ivect));ivect++;}; + break; + } + case TEMPS_t : + { for (int ii=1; ii<= dimen; ii++,ivect++) + noo->Change_val_t(Enum_ddl(ii-1 + enum_ddl),vect(ivect)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {noo->Change_val_t(EPAIS,vect(ivect));ivect++;}; + break; + } + case TEMPS_tdt : + { for (int ii=1; ii<= dimen; ii++,ivect++) + noo->Change_val_tdt(Enum_ddl(ii-1 + enum_ddl),vect(ivect)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {noo->Change_val_tdt(EPAIS,vect(ivect));ivect++;}; + break; + } + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "LesMaillages::Vect_glob_vers_local(Enum_dure... \n"; + Sortie(1); + } + } + } + }; + + +//récupération d'une grandeur vectoriel de dimension, la dimension +// de l'espace, défini au noeud et transféré dans un vecteur global +// qui cumule de manière séquentielle toutes les grandeurs +// en entrée : tab_enum_ddl donne le tableau des type de la grandeur à récupérer +// en fait de la première composante +// duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt +// tab_enum_actif : pour chaque élément tab_enum_ddl(i), le transfert s'effectue que si +// le ddl tab_enum_actif(i) est actif +// ce qui permet la différentiation entre les différents ddl +// vect : est le vecteur global de stockage qui normalement a été +// au préalable dimensionné avec somme des NbTotalDdlActifs(Enum_ddl enum_ddl), avec enum_ddl +// qui balaie l'ensemble des éléments de tab_enum_ddl +// Important: pour chaque famille de ddl, les ddl sont classés de manière croissante, ce qui signifie +// que c'est l'ordre des pointeurs d'assemblage si et seulement si, ces ddl ont été rangés dans les noeuds +// au préalable +// en retour : une référence sur vect +Vecteur & LesMaillages::Vect_loc_vers_glob(Enum_dure duree,const Tableau & tab_enum_actif + ,Vecteur& vect,const Tableau & tab_enum_ddl) +{ // recup de la dimension + int dimen = ParaGlob::Dimension(); + // dans le cas axisymétrique il n'y a pas de variation suivant le dernier axe + if (ParaGlob::AxiSymetrie()) + dimen--; + int ivect = 1; // position global + + int taill_tab = tab_enum_ddl.Taille(); + #ifdef MISE_AU_POINT + if (taill_tab != tab_enum_actif.Taille()) + {cout << "\n *** erreur , la dimension: "< tab_enum_actif est differente " + << " de la taille: "< tab_enum_ddl " + << "\n LesMaillages::Vect_loc_vers_glob( ..."<Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on boucle sur les ddl + for (int i=1;i<= taill_tab;i++) + {Enum_ddl enum_actif=tab_enum_actif(i); + Enum_ddl enum_ddl = tab_enum_ddl(i); + // on regarde si le ddl existe et que le ddl actif est actif + if ((noo->Existe_ici(enum_ddl)) && (noo->En_service(enum_actif)) + && (noo->UneVariable(enum_actif))) + // dans le cas où enum_ddl == X1, on regarde s'il ne faut pas associer l'épaisseur + // l'épaisseur n'est associée que si elle est une variable + switch (duree) + { case TEMPS_0 : + { for (int ii=1; ii<= dimen; ii++,ivect++) + vect(ivect) = noo->Valeur_0(Enum_ddl(ii-1 + enum_ddl) ); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {vect(ivect) = noo->Valeur_0(EPAIS);ivect++;}; + break; + } + case TEMPS_t : + { for (int ii=1; ii<= dimen; ii++,ivect++) + vect(ivect) = noo->Valeur_t(Enum_ddl(enum_ddl + ii-1)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {vect(ivect) = noo->Valeur_t(EPAIS);ivect++;}; + break; + } + case TEMPS_tdt : + { for (int ii=1; ii<= dimen; ii++,ivect++) + vect(ivect) = noo->Valeur_tdt(Enum_ddl(enum_ddl + ii-1)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {vect(ivect) = noo->Valeur_tdt(EPAIS);ivect++;}; + break; + } + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "LesMaillages::Vect_loc_vers_glob(Enum_dure... \n"; + Sortie(1); + }; + }; + }; + } + return vect; +}; + +// fonction inverse de Vect_loc_vers_glob, il s'agit ici de passer +// de la grandeur globale aux grandeurs locale +void LesMaillages::Vect_glob_vers_local(Enum_dure duree,const Tableau & tab_enum_actif + ,const Vecteur& vect,const Tableau & tab_enum_ddl) +{ // recup de la dimension + int dimen = ParaGlob::Dimension(); + // dans le cas axisymétrique il n'y a pas de variation suivant le dernier axe + if (ParaGlob::AxiSymetrie()) + dimen--; + int ivect = 1; // position global + + int taill_tab = tab_enum_ddl.Taille(); + #ifdef MISE_AU_POINT + if (taill_tab != tab_enum_actif.Taille()) + {cout << "\n *** erreur , la dimension: "< tab_enum_actif est differente " + << " de la taille: "< tab_enum_ddl " + << "\n LesMaillages::Vect_glob_vers_local( ..."<Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on boucle sur les ddl + for (int i=1;i<= taill_tab;i++) + {Enum_ddl enum_actif=tab_enum_actif(i); + Enum_ddl enum_ddl = tab_enum_ddl(i); + // on regarde si le ddl existe et que le ddl actif est actif + if ((noo->Existe_ici(enum_ddl)) && (noo->En_service(enum_actif)) + && (noo->UneVariable(enum_actif))) + // dans le cas où enum_ddl == X1, on regarde s'il ne faut pas associer l'épaisseur + // l'épaisseur n'est associée que si elle est une variable + switch (duree) + { case TEMPS_0 : + { for (int ii=1; ii<= dimen; ii++,ivect++) + noo->Change_val_0(Enum_ddl(ii-1 + enum_ddl),vect(ivect)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {noo->Change_val_0(EPAIS,vect(ivect));ivect++;}; + break; + } + case TEMPS_t : + { for (int ii=1; ii<= dimen; ii++,ivect++) + noo->Change_val_t(Enum_ddl(ii-1 + enum_ddl),vect(ivect)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {noo->Change_val_t(EPAIS,vect(ivect));ivect++;}; + break; + } + case TEMPS_tdt : + { for (int ii=1; ii<= dimen; ii++,ivect++) + noo->Change_val_tdt(Enum_ddl(ii-1 + enum_ddl),vect(ivect)); + if ((enum_ddl == X1) && noo->Existe_ici(EPAIS) && (noo->UneVariable(EPAIS))) + {noo->Change_val_tdt(EPAIS,vect(ivect));ivect++;}; + break; + } + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "LesMaillages::Vect_glob_vers_local(Enum_dure... \n"; + Sortie(1); + }; + }; + }; + }; +}; + + + +//récupération d'une grandeur scalaire +// défini au noeud et transféré dans un vecteur global +// qui cumule de manière séquentielle toutes les grandeurs +// en entrée : enum_ddl donne le type de la grandeur à récupérer +// duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt +// enum_actif : le transfert s'effectue que si le ddl enum_actif est actif +// ce qui permet la différentiation entre les différents ddl +// vect : est le vecteur global de stockage qui normalement a été +// au préalable dimensionné avec NbTotalDdlActifs(Enum_ddl enum_ddl) +// en retour : une référence sur vect +Vecteur & LesMaillages::Scalaire_loc_vers_glob(Enum_dure duree,Enum_ddl enum_actif + ,Vecteur& vect,Enum_ddl enum_ddl) +{ int ivect = 1; // position global + // maintenant on passe en revu les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++,ivect++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + if (noo->Existe_ici(enum_actif)) // ellimine les noeuds non concernés + {// on regarde si le ddl existe et que le ddl actif est actif + if ((noo->Existe_ici(enum_ddl)) && (noo->En_service(enum_actif)) + && (noo->UneVariable(enum_actif))) + switch (duree) + { case TEMPS_0 : {vect(ivect) = noo->Valeur_0(enum_ddl); break;} + case TEMPS_t : {vect(ivect) = noo->Valeur_t(enum_ddl); break;} + case TEMPS_tdt : {vect(ivect) = noo->Valeur_tdt(enum_ddl); break;} + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "LesMaillages::Scalaire_loc_vers_glob(Enum_dure... \n"; + Sortie(1); + } + } + } + } + return vect; + }; + +// fonction inverse de Scalaire_loc_vers_glob, il s'agit ici de passer +// de la grandeur globale à la grandeur locale +void LesMaillages::Scalaire_glob_vers_local(Enum_dure duree,Enum_ddl enum_actif + ,Vecteur& vect,Enum_ddl enum_ddl) +{ int ivect = 1; // position global + // maintenant on passe en revu les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++,ivect++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + if (noo->Existe_ici(enum_actif)) // élimine les noeuds non concernés + {// on regarde si le ddl existe et que le ddl actif est actif + if ((noo->Existe_ici(enum_ddl)) && (noo->En_service(enum_actif)) + && (noo->UneVariable(enum_actif))) + switch (duree) + { case TEMPS_0 : {noo->Change_val_0(enum_ddl,vect(ivect)); break;} + case TEMPS_t : {noo->Change_val_t(enum_ddl,vect(ivect)); break;} + case TEMPS_tdt : {noo->Change_val_tdt(enum_ddl,vect(ivect)); break;} + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "LesMaillages::Scalaire_glob_vers_local(Enum_dure... \n"; + Sortie(1); + }; + } + } + } + }; + +// fonctions idem que pour les ddl : mais pour un Ddl_etendu +Vecteur & LesMaillages::Scalaire_loc_vers_glob(Enum_ddl enum_actif + ,Vecteur& vect,const Ddl_enum_etendu& enum_ddl_etend) +{ int ivect = 1; // position global + // maintenant on passe en revu les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++,ivect++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + if (noo->Existe_ici(enum_actif)) // ellimine les noeuds non concernés + // on regarde si le ddl existe et que le ddl actif est actif + {if ((noo->Existe_ici_ddlEtendu(enum_ddl_etend)) && (noo->En_service(enum_actif))) + vect(ivect) = (noo->DdlEtendue(enum_ddl_etend)).ConstValeur(); + } + } + } + return vect; + }; + +// fonctions idem que pour les ddl : mais pour un Ddl_etendu +void LesMaillages::Scalaire_glob_vers_local(Enum_ddl enum_actif + ,Vecteur& vect,const Ddl_enum_etendu& enum_ddl_etend) +{ int ivect = 1; // position global + #ifdef MISE_AU_POINT + // on vérifie qu'il y a le bon nombre d'informations + int nb_info = 0; + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + nb_info += tabMaillage(i1)->Nombre_noeud(); + if (vect.Taille() != nb_info) + {cout << "\nerreur en affectation de grandeurs vers les maillages: vecteur globale "; + cout << " dim vecteur = " << vect.Taille() << " alorq qu'il faut " << nb_info <<'\n'; + cout << "\n LesMaillages::Scalaire_glob_vers_local(Enum_ddl enum_actif" << endl; + Sortie(1); + }; + #endif + // maintenant on passe en revu les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++,ivect++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + if ((noo->Existe_ici_ddlEtendu(enum_ddl_etend)) && (noo->En_service(enum_actif))) + // on récupère le ddl étendu pour le modifier + (noo->ModifDdl_etendu(enum_ddl_etend)).Valeur() = vect(ivect); + } + } + }; + +// fonctions idem que pour les ddl_etendu : mais pour une grandeur quelconque +Vecteur & LesMaillages::Quelconque_loc_vers_glob(Enum_ddl enum_actif,Vecteur& vect,const TypeQuelconque& type_generique) +//Vecteur & LesMaillages::Scalaire_loc_vers_glob(Enum_ddl enum_actif +// ,Vecteur& vect,const Ddl_enum_etendu& enum_ddl_etend) +{ int ivect = 1; // position global + int dim = ParaGlob::Dimension(); // dimension du pb + // maintenant on passe en revue les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++,ivect++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le conteneur existe, si oui on transfert, si non, on passe les valeurs + TypeQuelconque_enum_etendu enuq = type_generique.EnuTypeQuelconque(); + if (noo->Existe_ici(enum_actif)) // ellimine les noeuds non concernés + {if ((noo->Existe_ici(enuq)) && (noo->En_service(enum_actif))) + {// dépend du type de grandeur + EnumTypeGrandeur enuGrandeur = type_generique.EnuTypeGrandeur(); + switch (enuGrandeur) + {case COORDONNEE: + {TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(enuq); // récup du conteneur du noeud + // récup de la grandeur + Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); + Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées + switch (dim) // on rempli le vecteur + { case 3: vect(ivect)=conoe(3);ivect++; + case 2: vect(ivect)=conoe(2);ivect++; + case 1: vect(ivect)=conoe(1);ivect++; + }; + } + default: + cout << "\n ** erreur, pour l'instant le transfert depuis les noeuds de " + << (enuq.NomPlein()) << " n'est pas implante ... le demander !! " + << "\n LesMaillages::Quelconque_loc_vers_glob(..."<Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le conteneur existe, si oui on transfert, si non, on passe les valeurs + TypeQuelconque_enum_etendu enuq = type_generique.EnuTypeQuelconque(); + if (noo->Existe_ici(enum_actif)) // ellimine les noeuds non concernés + { +////-------- debug +//if (!((noo->Existe_ici(enuq)) && (noo->En_service(enum_actif)))) +// {cout << "\n debug LesMaillages::Quelconque_glob_vers_local( "; +// cout << "\n enuq: " << enuq.NomPlein()<< " noo->Existe_ici(enuq) "<< (noo->Existe_ici(enuq)) +// << "\n enum_actif: " << Nom_ddl(enum_actif) << " noo->En_service(enum_actif) " << noo->En_service(enum_actif) +// << flush; +// }; +////-------- fin debug + + if ((noo->Existe_ici(enuq)) && (noo->En_service(enum_actif))) + {// dépend du type de grandeur + EnumTypeGrandeur enuGrandeur = type_generique.EnuTypeGrandeur(); + switch (enuGrandeur) + {case COORDONNEE: + {TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(enuq); // récup du conteneur du noeud + // récup de la grandeur + Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); + Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées + switch (dim) // on rempli les coordonnées + { case 3: conoe(3)=vect(ivect+2); + case 2: conoe(2)=vect(ivect+1); + case 1: conoe(1)=vect(ivect); + }; + ivect +=dim; + break; + } + default: + cout << "\n ** erreur, pour l'instant le transfert vers les noeuds de " + << (enuq.NomPlein()) << " n'est pas implante ... le demander !! " + << "\n LesMaillages::Quelconque_glob_vers_local(..."< > LesMaillages::Les_type_de_ddl_par_noeud(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // vecteur intermédiaire dont la taille peut augmenter + List_io tab_enu_final; + // on boucle sur les noeuds + int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // recup du tableau de type de ddl associé + List_io tab_enum_ddl(noo->Les_type_de_ddl(absolue)); + tab_enum_ddl.sort(); // ordonne la liste + tab_enu_final.merge(tab_enum_ddl); // ajout de la liste + tab_enu_final.unique(); // supprime les doublons + }; + // mise à jour du tableau global + List_io tab_enu_etendu_final; + List_io tab_inter = Ddl_enum_etendu::TransfoList_io(tab_enu_final); + tab_inter.sort(); + tab_enu_etendu_final.merge(tab_inter);tab_enu_etendu_final.unique(); + tab_ret_enum(i1) = tab_enu_etendu_final; + } + return tab_ret_enum; // retour du tableau + }; + +// retourne la liste des types de ddl étendu actuellement utilisé +// aux noeuds pour chaque maillage, la liste est exhaustive +// elle contiend tous les types au moins une fois utilisée +// cela ne signifie pas que le ddl en question soit présent +// pour tous les noeud du maillage considéré +// - le tableau de retour est indicé par le numéro de maillage correspondant +// - il y a une liste par maillage +Tableau > LesMaillages::Les_type_de_ddl_etendu_par_noeud(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // vecteur intermédiaire dont la taille peut augmenter pour les ddl étendus + List_io tab_enu_etendu_final; + // on boucle sur les noeuds + int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // recup du tableau de type de ddl étendues + List_io tab_enum_etendu_ddl(noo->Les_type_de_ddl_etendu( absolue)); + tab_enum_etendu_ddl.sort(); // ordonne la liste + tab_enu_etendu_final.merge(tab_enum_etendu_ddl); // ajout de la liste + tab_enu_etendu_final.unique(); // supprime les doublons + }; + // mise à jour du tableau global + tab_ret_enum(i1) = tab_enu_etendu_final; + } + return tab_ret_enum; // retour du tableau + }; + + +// retourne la liste des types quelconque actuellement utilisé +// aux noeuds pour chaque maillage, la liste est exhaustive +// elle contiend tous les types au moins une fois utilisée +// cela ne signifie pas que le ddl en question soit présent +// pour tous les noeud du maillage considéré +// - le tableau de retour est indicé par le numéro de maillage correspondant +// - il y a une liste par maillage +Tableau > LesMaillages::Les_type_de_TypeQuelconque_par_noeud(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // grandeurs de travail + int dim = ParaGlob::Dimension(); + Coordonnee coor(dim); // un type coordonnee typique + // maintenant on définit une grandeur typique de type Grandeur_coordonnee + Grandeur_coordonnee gt(coor); + TypeQuelconque typQ(VECT_REAC_N,X1,gt); +// // idem pour la variation de position entre t et t+dt +// TypeQuelconque typQ2(DELTA_XI,X1,gt); + + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // vecteur intermédiaire dont la taille peut augmenter pour les ddl étendus + List_io tab_enu_etendu_final; + // on boucle sur les noeuds + int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // recup du tableau de tous les TypeQuelconque disponibles au noeud + List_io tab_enum_etendu_ddl(noo->Les_TypeQuelconque(absolue)); + + // --- on rajoute les réactions par défaut + // sous forme d'un vecteur + tab_enum_etendu_ddl.push_back(typQ); +// Pour l'instant ce n'est pas fini donc on met en commentaire, sinon c'est pas clair +// pour l'utilisateur !! +// // --- on ajoute le delta des positions +// tab_enum_etendu_ddl.push_back(typQ2); + // -- on traite + tab_enum_etendu_ddl.sort(); // ordonne la liste + tab_enu_etendu_final.merge(tab_enum_etendu_ddl); // ajout de la liste + tab_enu_etendu_final.unique(); // supprime les doublons + }; + // mise à jour du tableau global + tab_ret_enum(i1) = tab_enu_etendu_final; + } + return tab_ret_enum; // retour du tableau + }; + + // intro de certains conteneurs internes en relation par exemple avec les demandes de visualisation + // ou autre + // exemple: si VECT_REAC_N qui est un type quelconque, a été choisit + // il faut qu'il soit présent aux noeuds, alors qu'il est alimenter par les ddl pur ... + // on introduit donc le type quelconque associé + // NB: le conteneur passé en paramètre ne sert que pour localiser les grandeurs +void LesMaillages::Intro_Conteneurs_internes_noeud_relier_auto_autres_grandeur + ( const List_io < TypeQuelconque > & glob_noeud_evol_retenu) +{ + + // grandeurs de travail + int dim = ParaGlob::Dimension(); + Coordonnee coor(dim); // un type coordonnee typique + // maintenant on définit une grandeur typique de type Grandeur_coordonnee + Grandeur_coordonnee gt(coor); + TypeQuelconque typQ2(VECT_REAC_N,X1,gt); + List_io ::const_iterator il,ilfin=glob_noeud_evol_retenu.end(); + + + for (int i= 1;i<= nbMaillageTotal; i++) + {for (il=glob_noeud_evol_retenu.begin();il != ilfin; il++) + { TypeQuelconque_enum_etendu enuQ = (*il).EnuTypeQuelconque(); + + // on passe en revue les types concernés + if (enuQ == VECT_REAC_N) + // il faut alors vérifier que le conteneur existe aux noeuds + {// on boucle sur les noeuds + int nbnoeudmax = tabMaillage(i)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i,i2); + if (!(noo->Existe_ici(enuQ))) + // cas où on n'a pas le type présent, on l'introduit + {noo->AjoutUnTypeQuelconque(typQ2);}; + }; + }; + }; + }; + +}; + + // idem que Intro_Conteneurs_internes_noeud_relier_auto_autres_grandeur + // mais ciblé en fonction d'un tableau indicé sur les maillages +void LesMaillages::Intro_Conteneurs_internes_noeud_relier_auto_autres_grandeur + ( const Tableau < List_io < TypeQuelconque > > & tab_noeud_evol_retenu) +{ + + // grandeurs de travail + int dim = ParaGlob::Dimension(); + Coordonnee coor(dim); // un type coordonnee typique + // maintenant on définit une grandeur typique de type Grandeur_coordonnee + Grandeur_coordonnee gt(coor); + TypeQuelconque typQ2(VECT_REAC_N,X1,gt); + + for (int i= 1;i<= nbMaillageTotal; i++) + {List_io ::const_iterator il,ilfin=tab_noeud_evol_retenu(i).end(); + for (il=tab_noeud_evol_retenu(i).begin();il != ilfin; il++) + {TypeQuelconque_enum_etendu enuQ = (*il).EnuTypeQuelconque(); + + // on passe en revue les types concernés + if (enuQ == VECT_REAC_N) + // il faut alors vérifier que le conteneur existe aux noeuds + {// on boucle sur les noeuds + int nbnoeudmax = tabMaillage(i)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i,i2); + if (!(noo->Existe_ici(enuQ))) + // cas où on n'a pas le type présent, on l'introduit + {noo->AjoutUnTypeQuelconque(typQ2);}; + }; + }; + }; + }; + +}; + +// retourne la liste des types de ddl actuellement utilisé +// aux éléments pour chaque maillage, la liste est exhaustive +// elle contiend tous les types au moins une fois utilisée +// cela ne signifie pas que le ddl en question soit présent +// pour tous les éléments du maillage considéré +// - le tableau de retour est indicé par le numéro de maillage correspondant +// - il y a une liste par maillage +// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière +Tableau > LesMaillages::Les_type_de_ddl_par_element(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // vecteur intermédiaire dont la taille peut augmenter + List_io tab_enu_final; + // on définit une liste de signature d'élément, ce qui permet de tester que les types d'éléments différents + list list_signature_elem; + // on boucle sur les elements + int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { // recup du element + Element * nee = & Element_LesMaille(i1,i2); + // recup du tableau de type de ddl associé + // on regarde si un élément de même type n'a pas déjà été considéré + if (find(list_signature_elem.begin(),list_signature_elem.end(),nee->Signature_element())==list_signature_elem.end()) + { // nouveau type d'élément , on récupère les données particulières + List_io tab_enum_ddl(nee->Les_type_de_ddl_internes(absolue)); + tab_enu_final.sort(); // ordonne la liste + tab_enu_final.merge(tab_enum_ddl); // ajout de la liste + tab_enu_final.unique(); // supprime les doublons + // on ajoute la signature + list_signature_elem.push_back(nee->Signature_element()); + }; + } + // mise à jour du tableau global + tab_ret_enum(i1) = tab_enu_final; + } + return tab_ret_enum; // retour du tableau + }; + +// retourne la liste des grandeurs évoluées interne actuellement utilisés +// par les éléments, c'est-à-dire comme les ddl mais directement sous forme de vecteur, tenseurs ..., +// la liste est exhaustive, elle contiend tous les types au moins une fois utilisée +// cela ne signifie pas que la donnée particulière en question soit présent +// pour tous les éléments du maillage considéré +// - le tableau de retour est indicé par le numéro de maillage correspondant +// - il y a une liste par maillage +// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière +Tableau > LesMaillages::Les_type_de_donnees_evolues_internes_par_element(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // on définit une liste de signature d'élément, ce qui permet de tester que les types d'éléments différents + list list_signature_elem; + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // liste intermédiaire dont la taille peut augmenter + List_io tab_enu_final; + list_signature_elem.clear(); + // on boucle sur les elements + int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { // recup de l'element + Element * nee = & Element_LesMaille(i1,i2); + // on regarde si un élément de même type n'a pas déjà été considéré + if (find(list_signature_elem.begin(),list_signature_elem.end(),nee->Signature_element())==list_signature_elem.end()) + { // nouveau type d'élément , on récupère les données particulières + // les opérations qui suivent sont assez longues mais normalement n'arrives pas souvent + // recup du tableau de type de données particulières associées + List_io tab_enum_parti(nee->Les_type_evolues_internes(absolue)); + tab_enu_final.sort(); // ordonne la liste + tab_enum_parti.sort(); // idem la nouvelle + tab_enu_final.merge(tab_enum_parti); // ajout de la liste + tab_enu_final.unique(); // supprime les doublons + // on ajoute la signature + list_signature_elem.push_back(nee->Signature_element()); + }; + }; + // mise à jour du tableau global + tab_ret_enum(i1) = tab_enu_final; + }; + return tab_ret_enum; // retour du tableau + }; + +// retourne la liste des types de données particulières actuellement utilisés +// aux éléments pour chaque maillage, la liste est exhaustive +// elle contiend tous les types au moins une fois utilisée +// cela ne signifie pas que la donnée particulière en question soit présent +// pour tous les éléments du maillage considéré +// - le tableau de retour est indicé par le numéro de maillage correspondant +// - il y a une liste par maillage +Tableau > LesMaillages::Les_type_de_donnees_particulieres_par_element(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // vecteur intermédiaire dont la taille peut augmenter + List_io tab_enu_final; + // on définit une liste de signature d'élément, ce qui permet de tester que les types d'éléments différents + list list_signature_elem; + // on boucle sur les elements + int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { // recup du element + Element * nee = & Element_LesMaille(i1,i2); + // on regarde si un élément de même type n'a pas déjà été considéré + if (find(list_signature_elem.begin(),list_signature_elem.end(),nee->Signature_element())==list_signature_elem.end()) + { // nouveau type d'élément , on récupère les données particulières + // les opérations qui suivent sont assez longues mais normalement n'arrives pas souvent + // recup du tableau de type de données particulières associées + List_io tab_enum_parti(nee->Les_types_particuliers_internes(absolue)); + tab_enu_final.sort(); // ordonne la liste + tab_enu_final.merge(tab_enum_parti); // ajout de la liste + tab_enu_final.unique(); // supprime les doublons + // on ajoute la signature + list_signature_elem.push_back(nee->Signature_element()); + }; + }; + // mise à jour du tableau global + tab_ret_enum(i1) = tab_enu_final; + }; +//----- debug +// cout << "\n debug LesMaillages::Les_type_de_donnees_particulieres_par_element " +// << tab_ret_enum << endl; +// ------ fin debug + + + return tab_ret_enum; // retour du tableau + }; + +// Au niveau des noeuds: transfert des coordonnées de grandeurs vectorielles à des grandeurs évoluées +// stockée sous forme de grandeurs TypeQuelconque +// exemple: les réactions qui sont naturellement stockée en composantes +// le principe est que ce passage s'effectue si les conteneurs existent au niveau des noeuds +void LesMaillages::PassageInterneDansNoeud_composantes_vers_vectorielles() +{ + int dim = ParaGlob::Dimension(); // dimension du pb + if(ParaGlob::AxiSymetrie()) + dim--; // en axisymétrie on récupère uniquement les forces en x et y + // on boucle sur les maillages puis sur les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // --- cas des réactions: + {// on regarde si le conteneur existe, si oui on transfert, si non, on passe les valeurs + EnumTypeQuelconque enuq = VECT_REAC_N; + if ((noo->Existe_ici(enuq)) && (noo->Existe_ici(R_X1))) + {TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(enuq); // récup du conteneur du noeud + // récup de la grandeur + Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); + Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées + switch (dim) // on rempli les coordonnées + { case 3: conoe(3)=noo->Valeur_tdt(R_X3); + case 2: conoe(2)=noo->Valeur_tdt(R_X2); + case 1: conoe(1)=noo->Valeur_tdt(R_X1); + }; + }; + }; + }; + }; +}; + +// retourne la liste des types de grandeur quelconque actuellement utilisé +// aux faces élément pour chaque maillage, la liste est exhaustive +// elle contiend tous les types au moins une fois utilisée +// cela ne signifie pas que la grandeur en question soit présent +// pour tous les éléments du maillage considéré +// - le tableau de retour est indicé par le numéro de maillage correspondant +// - il y a une liste par maillage +Tableau > LesMaillages::Les_type_de_donnees_evolues_internes_par_face_element(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // vecteur intermédiaire dont la taille peut augmenter + List_io tab_enu_final; + // on définit une liste de signature d'élément, ce qui permet de tester que les types d'éléments différents + list list_signature_elem; + // on boucle sur les elements + int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { // recup du element + Element * nee = & Element_LesMaille(i1,i2); + // on regarde si un élément de même type n'a pas déjà été considéré + if (find(list_signature_elem.begin(),list_signature_elem.end(),nee->Signature_element())==list_signature_elem.end()) + { // nouveau type d'élément , on récupère les données particulières + // les opérations qui suivent sont assez longues mais normalement n'arrives pas souvent + // recup du tableau de type de données particulières associées + List_io tab_enum_parti(nee->Les_type_quelconque_de_face(absolue)); + tab_enu_final.sort(); // ordonne la liste + tab_enu_final.merge(tab_enum_parti); // ajout de la liste + tab_enu_final.unique(); // supprime les doublons + // on ajoute la signature + list_signature_elem.push_back(nee->Signature_element()); + }; + }; + // mise à jour du tableau global + tab_ret_enum(i1) = tab_enu_final; + }; +//----- debug +// cout << "\n debug LesMaillages::Les_type_de_donnees_evolues_internes_par_face_element " +// << tab_ret_enum << endl; +// ------ fin debug + + + return tab_ret_enum; // retour du tableau + }; + +// retourne la liste des types de grandeur quelconque actuellement utilisé +// aux arêtes élément pour chaque maillage, la liste est exhaustive +// elle contiend tous les types au moins une fois utilisée +// cela ne signifie pas que la grandeur en question soit présent +// pour tous les éléments du maillage considéré +// - le tableau de retour est indicé par le numéro de maillage correspondant +Tableau > LesMaillages::Les_type_de_donnees_evolues_internes_par_arete_element(bool absolue) + { // def de la liste de retour + Tableau > tab_ret_enum(nbMaillageTotal); + // on boucle sur les maillages + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // vecteur intermédiaire dont la taille peut augmenter + List_io tab_enu_final; + // on définit une liste de signature d'élément, ce qui permet de tester que les types d'éléments différents + list list_signature_elem; + // on boucle sur les elements + int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { // recup du element + Element * nee = & Element_LesMaille(i1,i2); + // on regarde si un élément de même type n'a pas déjà été considéré + if (find(list_signature_elem.begin(),list_signature_elem.end(),nee->Signature_element())==list_signature_elem.end()) + { // nouveau type d'élément , on récupère les données particulières + // les opérations qui suivent sont assez longues mais normalement n'arrives pas souvent + // recup du tableau de type de données particulières associées + List_io tab_enum_parti(nee->Les_type_quelconque_de_arete(absolue)); + tab_enu_final.sort(); // ordonne la liste + tab_enu_final.merge(tab_enum_parti); // ajout de la liste + tab_enu_final.unique(); // supprime les doublons + // on ajoute la signature + list_signature_elem.push_back(nee->Signature_element()); + }; + }; + // mise à jour du tableau global + tab_ret_enum(i1) = tab_enu_final; + }; +//----- debug +// cout << "\n debug LesMaillages::Les_type_de_donnees_evolues_internes_par_arete_element " +// << tab_ret_enum << endl; +// ------ fin debug + + + return tab_ret_enum; // retour du tableau + }; + + +// initialisation d'un ou ne plusieurs nouveaux cas d'assemblage +// ramène le numéro du premier nouveau cas d'assemblage +Nb_assemb LesMaillages::InitNouveauCasAssemblage(int nb_cas) + { // on récupère le nombre actuel de cas d'assemblage + int nb_actuel = tab_nb_assemb; + // on parcours le noeud pour les dimensionner aux nouveaux cas d'assemblage + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // initialisation + noo->InitNouveauCasAssemb(nb_cas); + } + } + // dans le cas ou nb_cas est null pb + #ifdef MISE_AU_POINT + if (nb_cas == 0) + { cout << "\n erreur, le nombre de nouveau cas d'assemblage demandé est nul !!" + << " \n LesMaillages::InitNouveauCasAssemblage(int nb_cas) " ; + Sortie(1); + } + #endif + // mise à jour du nombre de cas d'assemblage + tab_nb_assemb += nb_cas; + // mise à jour du tableau t_i_n + t_i_n.Change_taille(tab_nb_assemb); + // retour du premier nouveau cas d'assemblage + nb_actuel++; + return Nb_assemb(nb_actuel); + }; + +// met a jour les pointeurs d'assemblage dans les noeuds +// et enregistre les ddl_actifs et leurs ordres au niveau des noeuds +// a effectuer si l'on a changer de nb de noeuds, de nb de ddl, de nb de maillage +// casAssemb : donne le cas d'assemblage qui est a considérer +void LesMaillages::MiseAJourPointeurAssemblage(const Nb_assemb& casAssemb) + { // pour la construction du tableau t_i_n pour le cas d'assemblage + // on utilise une liste intermédiaire car on ne connait pas le nombre d'élément final + list list_in ; + // definition de la position globale d'assemblage + int pointeur=0 ; // position d'assemblage + int nb_assemb = casAssemb.n; + bool absolue = true; // par défaut on travaille en absolu, mais en fait + // cela n'a pas d'importance ici, car on n'utilise que le type + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // enregistrement des variables ddl actives + noo->Enreg_ordre_variable_ddl_actives(nb_assemb); + // on change le pointeur + noo->ChangePosiAssemb(pointeur,nb_assemb); + // récup de tous les ddl du noeud + List_io list_ddl = noo->Les_type_de_ddl(absolue); + // on définit le tableau d'indexage t_in + List_io ::iterator ie,iefin=list_ddl.end(); + for(ie=list_ddl.begin();ie!=iefin;ie++) + { if (noo->En_service(*ie) && noo->UneVariable(*ie)) + // si le ddl est en service on l'enregistre + {Posi_ddl_noeud posi(i1,*ie,noo->Num_noeud()); + list_in.push_back(posi); + pointeur++; + } + } + } + } + // construction du tableau t_i_n pour le cas d'assemblage + Tableau & t_in = t_i_n(nb_assemb); // pour simplifier + int taille_tab = (int) list_in.size(); // la taille finale + t_in.Change_taille(taille_tab); int i; + list::iterator ile; + for (i=1,ile=list_in.begin();i<=taille_tab;i++,ile++) + t_in(i) = (*ile); + }; + +// met a jour les pointeurs d'assemblage dans les noeuds pour un cas d'assemblage +// a effectuer si l'on a changer de nb de noeuds, de nb de ddl, de nb de maillage +// casAssemb : donne le cas d'assemblage qui est a considérer +// ici, l'assemblage suit l'ordre du tableau de noeud passé en paramètre +// le tableau de noeuds rassemble tous les noeuds des maillages mais avec une numérotation propre +void LesMaillages::MiseAJourPointeurAssemblage_interne + (const Nb_assemb& casAssemb,Tableau & tab_N_final) + { // pour la construction du tableau t_i_n pour le cas d'assemblage + // on utilise une liste intermédiaire car on ne connait pas le nombre d'élément final + list list_in ; + // definition de la position globale d'assemblage + int pointeur=0 ; // position d'assemblage + int nb_assemb = casAssemb.n; + bool absolue = true; // par défaut on travaille en absolu, mais en fait + // cela n'a pas d'importance ici, car on n'utilise que le type + int nb_noeud = tab_N_final.Taille(); + for (int i = 1; i<= nb_noeud; i++) + { // recup du noeud + Noeud * noo = tab_N_final(i); +//if (noo->Num_noeud() != i) +// cout << "\n debug LesMaillages::MiseAJourPointeurAssemblage_interne " +// << " noo->Num_noeud()= "<< noo->Num_noeud() << " i= " << i << endl; + + // enregistrement des variables ddl actives + noo->Enreg_ordre_variable_ddl_actives(nb_assemb); + // on change le pointeur + noo->ChangePosiAssemb(pointeur,nb_assemb); + // récup de tous les ddl du noeud + List_io list_ddl = noo->Les_type_de_ddl(absolue); + // on définit le tableau d'indexage t_in + List_io ::iterator ie,iefin=list_ddl.end(); + for(ie=list_ddl.begin();ie!=iefin;ie++) + { if (noo->En_service(*ie) && noo->UneVariable(*ie)) + // si le ddl est en service on l'enregistre + {Posi_ddl_noeud posi(noo->Num_Mail(),*ie,noo->Num_noeud()); + list_in.push_back(posi); + pointeur++; + } + }; + }; + // construction du tableau t_i_n pour le cas d'assemblage + Tableau & t_in = t_i_n(nb_assemb); // pour simplifier + int taille_tab = (int) list_in.size(); // la taille finale + t_in.Change_taille(taille_tab); int i; + list::iterator ile; + for (i=1,ile=list_in.begin();i<=taille_tab;i++,ile++) + t_in(i) = (*ile); + }; + +// remise à jour des tableaux de pointeurs t_i_n uniquement, due à un changement de numéro de noeud +// en fonction d'un changement de num de noeud (mais pas de changement de pointeur d'assemblage +// pour chaque noeud, tab_N_final(i) correspond au noeud qui avait le numéro i ancien +// et qui a maintenant le numéro tab_N_final(i)->Num_noeud() +void LesMaillages::MiseAJourTableau_t_i_n(const Nb_assemb& nb_casAssemb,Tableau & tab_N_final) + { int nb_assemb = nb_casAssemb.n; + // le tableau t_i_n pour le cas d'assemblage + Tableau & t_in = t_i_n(nb_assemb); // pour simplifier +// pour mémoire un élément Posi_ddl_noeud // données +// int nb_maillage; // le numéro du maillage +// int nb_noeud; // le numéro du noeud +// Enum_ddl enu; // l'identifieur du ddl + + int taille_tab = t_in.Taille(); + for (int i=1;i<= taille_tab;i++) + { int ancien_num_noeud = t_in(i).Nb_noeud(); + int nouveau_num_noeud = tab_N_final(ancien_num_noeud)->Num_noeud(); + t_in(i).Nb_noeud() = nouveau_num_noeud; +////--- vérif debug +//Coordonnee co = Noeud_LesMaille(t_in(i).Nb_maillage(),t_in(i).Nb_noeud()).Coord0(); +//if (i==taille_tab) +// cout << "\n debug LesMaillages::MiseAJourTableau_t_i_n "<< co << endl; +////-- fin debug + }; + }; + + +// mise a zero de tous les ddl actifs autres que les deplacements +// si indic = false; pas de creation des tableaux a t+dt +// si indic = true; creation des tableaux a t+dt +// cas = true; les coordonnées à t et éventuellement à t+dt sont initialisées +// aux valeurs de t=0, sinon on ne les modifies pas +void LesMaillages::ZeroDdl(bool indic,bool cas) + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); +// if (i2 >= 583) +// { +// //debug +// cout << "\n debug LesMaillages::ZeroDdl "; +// cout << "\n pb coordonnee 2 noeud 583 "; +// // fin debug +// } + if (indic) // construit les tableaux de ddl a t+dt selon indic + noo->Travail_tdt(); + +// if ((i2 >= 583)&&(!(tabMaillage(1)->Noeud_mail(583).ExisteCoord2()))) +// { +// //debug +// cout << "\n debug LesMaillages::ZeroDdl "; +// cout << "\n pb coordonnee 2 noeud 583 "; +// // fin debug +// } + + + noo->ZeroVariablesDdl(cas); + } + } +////debug +//cout << "\n debug LesMaillages::ZeroDdl "; +//cout << "\n coordonnees0 du noeud 583 "; +//tabMaillage(1)->Noeud_mail(583).Coord0().Affiche(); +// +//tabMaillage(1)->Noeud_mail(583).Coord2().Affiche(); +//// fin debug + }; + +// ramene la demi largeur de bande en ddl et la largeur de bande +// casAssemb : donne le cas d'assemblage qui est a considérer +void LesMaillages::Largeur_Bande(int& demi, int& total,const Nb_assemb& casAssemb) + { int demib =0; + int totalb = 0; + demi = 0; total = 0; + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { demib =0; + totalb = 0; + tabMaillage(i1)->Largeur_Bande(demib,totalb,casAssemb); + if (demib > demi) demi = demib; + if (totalb > total ) total = totalb; + } + }; + +// méthode permettant le calcul des matrices de connexion pour chaque +// élément ceci par rapport à la numérotation absolu des ddl +// casAssemb : donne le cas d'assemblage qui est a considérer + // les petites matrices sont carrées, ils sont définit par un tableau ligne qui contiend + // la position d'un terme de la petite matrice dans la grande matrice + // exemple : pet_mat(k)(i), pet_mat(k)(j) : indique le numéro de ligne et le numéro de colonne + // d'un élément non nul dans la grande matrice + +void LesMaillages::Table_connexion + (Tableau < Tableau >& pet_mat_mat,const Nb_assemb& casAssemb) const + { // calcul du nombre d'élément totaux + int nbelem=0; + for (int i = 1; i<= nbMaillageTotal; i++) + nbelem += Nombre_element(i); + // on dimensionne le tableau en conséquence + pet_mat_mat.Change_taille(nbelem); + // récup du numéro d'assemblage + int nb_casAssemb = casAssemb.n; + // on passe en revue tous les éléments et on rempli de tableau + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelmax = Nombre_element(i1); + for (int jel = 1; jel <= nbelmax; jel++) + { // récup de l'élément + Element& elem = tabMaillage(i1)->Element_mail(jel); + Tableau & tabb = (pet_mat_mat(jel)); // simplification + const Tableau& tab_noeud = elem.Tab_noeud (); // recup tab_noeud + const DdlElement & tab_ddl = elem.TableauDdl(); // tableau des ddl + // dimensionnement du tableau de connexion + tabb.Change_taille(tab_ddl.NbDdl()); + + // differents indices de lignes + int iloc, inoeud ; + // boucle sur les noeuds de l'element + int inoeud_max = tab_noeud.Taille(); + for ( inoeud=1,iloc=1; inoeud<= inoeud_max; inoeud++) + {Noeud& noei = *(tab_noeud(inoeud)); // simplification + // boucle sur les ddl du noeudElement + int ni_nbddl = tab_ddl.NbDdl(inoeud); + for (int i = 1;i<= ni_nbddl ;i++,iloc++) + // enregistrement de la position si le pointeur d'assemblage est valide + { int pt = noei.Pointeur_assemblage(tab_ddl(inoeud,i),nb_casAssemb); + if (pt != -1) + tabb(iloc) = pt; + } + } // fin de la boucle sur les noeuds de l'élément + + } // fin de la boucle sur les éléments d'un maillage + } // fin de la boucle sur les maillages + }; + +// actualisation des ddl et des grandeurs actives de t+dt vers t +void LesMaillages::TdtversT() + {// tout d'abord on s'occupe des ddl + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + Noeud_LesMaille(i1,i2).TdtversT(); + }; + // puis on s'occupe des éléments + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + elem.TdtversT(); + } + } + + // cas des intégrales et on alimente les grandeurs globales + {int taille = integ_vol_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_integ_vol(il) != NULL) // si NULL => la grandeur reste fixe et n'est pas intégrée + {TypeQuelconque& TQ_t = integ_vol_typeQuel_t(il); // pour simplifier + TypeQuelconque& TQ = integ_vol_typeQuel(il); // pour simplifier + // transfert des intégrales finalisées + (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); +// !! non ce sera fait dans l'intégration, et il vaut mieux garder une valeur correcte +// TQ.Grandeur_pointee()->InitParDefaut(); // on initialise pour le prochain calcul + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + // --> au début les grandeurs auront les mêmes valeurs à t et tdt + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'integration !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + + // on réinitialise également les grandeurs à 0, car le calcul est fait dans les éléments + // et le stockage à t est sauvegardé dans les éléments, du coup si on n'initialise pas ici + // au final on aura 2 fois l'intégrale à chaque pas de temps !! + {int taille = integ_vol_t_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_integ_vol_t(il) != NULL) // si ==NULL => la grandeur reste fixe et n'est pas intégrée + {TypeQuelconque& TQ_t = integ_vol_t_typeQuel_t(il); // pour simplifier + TypeQuelconque& TQ = integ_vol_t_typeQuel(il); // pour simplifier + // transfert des intégrales finalisées + (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); +// !! non ce sera fait dans l'intégration, et il vaut mieux garder une valeur correcte +// TQ.Grandeur_pointee()->InitParDefaut(); // on initialise pour le prochain calcul + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + // --> au début les grandeurs auront les mêmes valeurs à t et tdt + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'integration !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + + // cas des statistiques et on alimente les grandeurs globales + {int taille = statistique_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_statistique(il) != NULL) // si NULL => la grandeur reste fixe et n'est pas calculée + {TypeQuelconque& TQ_t = statistique_typeQuel_t(il); // pour simplifier + TypeQuelconque& TQ = statistique_typeQuel(il); // pour simplifier + // transfert des statistiques finalisées + (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + // --> au début les grandeurs auront les mêmes valeurs à t et tdt + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans statistique !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans statistique !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + + // on réinitialise également les grandeurs à 0, car le calcul est fait dans les éléments + // et le stockage à t est sauvegardé dans les éléments, du coup si on n'initialise pas ici + // au final on aura 2 fois l'intégrale à chaque pas de temps !! + {int taille = statistique_t_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_statistique_t(il) != NULL) // si ==NULL => la grandeur reste fixe et n'est pas intégrée + {TypeQuelconque& TQ_t = statistique_t_typeQuel_t(il); // pour simplifier + TypeQuelconque& TQ = statistique_t_typeQuel(il); // pour simplifier + // transfert des statistiques finalisées + (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); +// !! non ce sera fait dans l'intégration, et il vaut mieux garder une valeur correcte +// TQ.Grandeur_pointee()->InitParDefaut(); // on initialise pour le prochain calcul + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + // --> au début les grandeurs auront les mêmes valeurs à t et tdt + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans statistique avec cumul en temps !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans statistique avec cumul en temps !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + + + }; + +// actualisation des ddl et des grandeurs actives de t vers tdt +void LesMaillages::TversTdt() + {// tout d'abord on s'occupe des ddl + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + Noeud_LesMaille(i1,i2).TversTdt(); + }; + // puis on s'occupe des éléments + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + elem.TversTdt(); + } + }; + + // -- cas des intégrales de volumes + // on réinitialise les grandeurs qui vont être calculée + // ceux à t ne changent pas + {int taille = integ_vol_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_integ_vol(il) != NULL) // si == NULL => la grandeur reste fixe et n'est pas intégrée + {TypeQuelconque& TQ = integ_vol_typeQuel(il); // pour simplifier + TypeQuelconque& TQ_t = integ_vol_typeQuel_t(il); // pour simplifier + // transfert des intégrales finalisées + (TQ.Grandeur_pointee())->Affectation_numerique(*(TQ_t.Grandeur_pointee())); +// !! non ce sera fait dans l'intégration, et il vaut mieux garder une valeur correcte +// TQ.Grandeur_pointee()->InitParDefaut(); + // cas des grandeurs à tdt: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + // donc on le remet à du pas précédent à t + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TversTdt()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'integration !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TversTdT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + + // -- cas des intégrales de volumes et en temps + // on réinitialise également les grandeurs à 0, car le calcul est fait dans les éléments + // et le stockage à t est sauvegardé dans les éléments, du coup si on n'initialise pas ici + // au final on aura 2 fois l'intégrale à la fin du pas de temps !! + // par contre avant l'initialisation, on met à jour la variable globale + {int taille = integ_vol_t_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_integ_vol_t(il) != NULL) // si NULL => la grandeur reste fixe et n'est pas intégrée + {TypeQuelconque& TQ_t = integ_vol_t_typeQuel_t(il); // pour simplifier + TypeQuelconque& TQ = integ_vol_t_typeQuel(il); // pour simplifier + // on remet à t les grandeurs globales + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'integration !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TversTdT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); +// !! non ce sera fait dans l'intégration, et il vaut mieux garder une valeur correcte +// // maintenant on initialise le conteneur local +// TQ.Grandeur_pointee()->InitParDefaut(); // on initialise pour le prochain calcul + }; + }; + + + // -- cas des statistiques sur des ref de noeuds + // on réinitialise les grandeurs qui vont être calculée + // ceux à t ne changent pas + {int taille = statistique_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_statistique(il) != NULL) // si == NULL => la grandeur reste fixe et n'est pas intégrée + {TypeQuelconque& TQ = statistique_typeQuel(il); // pour simplifier + TypeQuelconque& TQ_t = statistique_typeQuel_t(il); // pour simplifier + // transfert des intégrales finalisées + (TQ.Grandeur_pointee())->Affectation_numerique(*(TQ_t.Grandeur_pointee())); +// !! non ce sera fait dans l'intégration, et il vaut mieux garder une valeur correcte +// TQ.Grandeur_pointee()->InitParDefaut(); + // cas des grandeurs à tdt: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + // donc on le remet à du pas précédent à t + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TversTdt()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'integration !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TversTdT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + + // -- cas des statistiques sur des refs de noeuds avec cumul en temps + +//**** à voir si c'est vrai pour les statistiques + + // on réinitialise également les grandeurs à 0, car le calcul est fait dans les éléments + // et le stockage à t est sauvegardé dans les éléments, du coup si on n'initialise pas ici + // au final on aura 2 fois l'intégrale à la fin du pas de temps !! + // par contre avant l'initialisation, on met à jour la variable globale + + {int taille = statistique_t_typeQuel.Taille(); + for (int il =1;il <= taille ;il++) + if (ref_statistique_t(il) != NULL) // si NULL => la grandeur reste fixe + {TypeQuelconque& TQ_t = statistique_t_typeQuel_t(il); // pour simplifier + TypeQuelconque& TQ = statistique_t_typeQuel(il); // pour simplifier + // on remet à t les grandeurs globales + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans statistique avec cumul en temps !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::TdtversT()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans statistique avec cumul en temps !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::TversTdT()"<Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); +// !! non ce sera fait dans l'intégration, et il vaut mieux garder une valeur correcte +// // maintenant on initialise le conteneur local +// TQ.Grandeur_pointee()->InitParDefaut(); // on initialise pour le prochain calcul + }; + }; + }; + +// actualisation des ddl actifs a t+dt, a partir du resultat de la resolution +// casAssemb : donne le cas d'assemblage qui est a considérer +void LesMaillages::PlusDelta_tdt(Vecteur& sol,const Nb_assemb& casAssemb) + { // on balaie le tableau d'indexage + Tableau & ti_n = t_i_n(casAssemb.n); // pour simplifier + int ti_nTaille = ti_n.Taille(); + for (int i=1;i<=ti_nTaille;i++) + { Posi_ddl_noeud& a = ti_n(i); + Noeud_LesMaille(a.Const_Nb_maillage(),a.Const_Nb_noeud()).Ajout_val_tdt(a.Const_Enu(),sol(i)); + }; + }; + +// actualisation des ddl actifs a t, a partir du resultat de la resolution +// casAssemb : donne le cas d'assemblage qui est a considérer +void LesMaillages::PlusDelta_t(Vecteur& sol,const Nb_assemb& casAssemb) + { // on balaie le tableau d'indexage + Tableau & ti_n = t_i_n(casAssemb.n); // pour simplifier + int ti_nTaille = ti_n.Taille(); + for (int i=1;i<=ti_nTaille;i++) + { Posi_ddl_noeud& a = ti_n(i); + Noeud_LesMaille(a.Const_Nb_maillage(),a.Const_Nb_noeud()).Ajout_val_t(a.Const_Enu(),sol(i)); + }; + }; + +// récupération du vecteur correspondant à l'incrément de déplacement entre t et tdt +// en paramètre le vecteur vide et en sortie le vecteur rempli +// casAssemb : donne le cas d'assemblage qui est a considérer +Vecteur& LesMaillages::RecupDepde_tatdt(Vecteur& sol,const Nb_assemb& casAssemb) + { // on balaie le tableau d'indexage + Tableau & ti_n = t_i_n(casAssemb.n); // pour simplifier + int ti_nTaille = ti_n.Taille(); + for (int i=1;i<=ti_nTaille;i++) + { Posi_ddl_noeud& a = ti_n(i); + Noeud & noe = Noeud_LesMaille(a.Const_Nb_maillage(),a.Const_Nb_noeud()); + sol(i) = noe.Valeur_tdt(a.Const_Enu()) - noe.Valeur_t(a.Const_Enu()); + }; + return sol; + }; + +// changement des ddl à tdt par ceux correspondant au vecteur passé en paramètre +// casAssemb : donne le cas d'assemblage qui est a considérer +void LesMaillages::ChangeDdla_tdt(Vecteur& sol,const Nb_assemb& casAssemb) + { // on balaie le tableau d'indexage + Tableau & ti_n = t_i_n(casAssemb.n); // pour simplifier + int ti_nTaille = ti_n.Taille(); + for (int i=1;i<=ti_nTaille;i++) + { Posi_ddl_noeud& a = ti_n(i); + Noeud_LesMaille(a.Const_Nb_maillage(),a.Const_Nb_noeud()).Change_val_tdt(a.Const_Enu(),sol(i)); + }; + }; + +// retrouver le ddl correspondant a un pointeur de position +// d'assemblage, le nb du noeud et du maillage +// insol = le pointeur d'assemblage; +// ddl = le ddl en sortie; a t+dt si elle il existe +// sinon la valeur a t +// casAssemb : donne le cas d'assemblage qui est a considérer +Ddl LesMaillages::NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage,const Nb_assemb& casAssemb) + { // on utilise le tableau d'indexage + Posi_ddl_noeud& a = t_i_n(casAssemb.n)(inSol); + nbNoeud = a.Const_Nb_noeud(); nbMaillage = a.Const_Nb_maillage(); + Noeud & noe = Noeud_LesMaille(a.Const_Nb_maillage(),a.Const_Nb_noeud()); + if (noe.Tdt()) + return noe.Ddl_noeud_tdt(a.Const_Enu()); + else + return noe.Ddl_noeud_t(a.Const_Enu()); + }; +// idem en ramenant en plus la valeur du ddl a 0 +Ddl LesMaillages::NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage, double& val0 + ,const Nb_assemb& casAssemb) + { // on utilise le tableau d'indexage + Posi_ddl_noeud& a = t_i_n(casAssemb.n)(inSol); + nbNoeud = a.Const_Nb_noeud(); nbMaillage = a.Const_Nb_maillage(); + Noeud & noe = Noeud_LesMaille(a.Const_Nb_maillage(),a.Const_Nb_noeud()); + val0=noe.Valeur_0(a.Const_Enu()); + if (noe.Tdt()) + return noe.Ddl_noeud_tdt(a.Const_Enu()); + else + return noe.Ddl_noeud_t(a.Const_Enu()); + }; + +// creation des elements frontiere +// creation des elements frontiere: cela n'a lieu qu'une seule fois +// si les frontières existent déjà, --> aucune action, --> ramène 0 +// sinon il y a réellement création, et --> ramène 1 +int LesMaillages::CreeElemFront() + { int retour = 0; + + if ((listFrontiere.Taille() == 0) || (tt_noeud_front.Taille() == 0)) + { for (int nbmail=1;nbmail<=nbMaillageTotal;nbmail++) + tabMaillage(nbmail)->CreeElemFront(); + listFrontiere.Change_taille(nbMaillageTotal); + tt_noeud_front.Change_taille(nbMaillageTotal); + for (int nbmail=1;nbmail<=nbMaillageTotal;nbmail++) + {listFrontiere(nbmail) = tabMaillage(nbmail)->ListFront(); + tt_noeud_front(nbmail) = &(tabMaillage(nbmail)->Tab_noeud_front()); + }; + retour = 1; + } + else + {retour = 0;}; +//// pour le débug +//for (int nbmail=1;nbmail<=nbMaillageTotal;nbmail++) +// {int nbfront = listFrontiere(nbmail)->size(); +// cout << "\n maillage " << nbmail << " -------- "; +// LaLIST ::iterator iff,iffin = listFrontiere(nbmail)->end(); +// iff=listFrontiere(nbmail)->begin(); +//// for (iff=listFrontiere(nbmail)->begin();iff !=iffin;iff++) +// Front& titi = (*iff); +// titi.Affiche(); cout << "\n"; +// +// }; +// +// Sortie(1); +//// fin débug + +//// pour le débug +//for (int nbmail=1;nbmail<=nbMaillageTotal;nbmail++) +// {int nbfront = listFrontiere(nbmail)->size(); +// cout << "\n maillage " << nbmail << " -------- "; +// LaLIST ::iterator iff,iffin = listFrontiere(nbmail)->end(); +// for (iff=listFrontiere(nbmail)->begin();iff !=iffin;iff++) +// {(*iff).Affiche(); cout << "\n";}; +// }; +// Sortie(1); +//// fin débug + + // retour + return retour; + }; + +// ramene le tableau des noeuds des frontières des maillages esclaves +Tableau < Tableau *> LesMaillages::Tab_noeud_frontiere_esclave() + { Tableau < Tableau *> ret(domEsclave); + if ((domEsclave)&&(ParaGlob::NiveauImpression()>2)) + cout << "\n >>>> Information maillages : "; + for (int i=1;i<=domEsclave;i++) + {ret(i) = tt_noeud_front(i); + if (ParaGlob::NiveauImpression()>2) + cout << "\n il y a "<Taille() + << " noeuds esclaves possible sur front. du maillage " << i ; + + }; + return ret; + }; + +// calcul et ramene le tableau de tous les noeuds des maillages esclaves +// noeuds de la frontière et noeuds internes +// s'ils existent, sinon le tableau est vide +// le tableau n'est pas sauvegarde +const Tableau LesMaillages::Esclave() + { // tout d'abord on cherche la taille du tableau + int tail = 0; + for (int i=1;i<= domEsclave;i++) + tail += tabMaillage(i)->Nombre_noeud(); +// tail += tabMaillage(i)->Nombre_noeud(); + // dimensionnement du tableau + Tableau tab(tail); + // remplissage du tableau + int indice =1; + for (int i=1;i<= domEsclave;i++) + {int nbnimax = tabMaillage(i)->Nombre_noeud(); + for (int j=1; j<= nbnimax;j++,indice++) + tab(indice) = &(tabMaillage(i)->Noeud_mail(j)); + }; + // retour + return tab; + }; + +// inactive tous les ddl et les données +void LesMaillages::Inactive_ddl_et_donnees() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + Noeud_LesMaille(i1,i2).Met_hors_service(); + } + }; +// inactive tous les ddl mais pas les données +void LesMaillages::Inactive_ddl() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + Noeud_LesMaille(i1,i2).Met_hors_service_ddl(); + } + }; +// inactive les ddl primaires +void LesMaillages::Inactive_ddl_primaire() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + Element_LesMaille(i1,i2).Inactive_ddl_primaire(); + } + }; +// active les ddl primaires +void LesMaillages::Active_ddl_primaire() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + Element_LesMaille(i1,i2).Active_ddl_primaire(); + } + }; +// introduction des ddl de contraintes si cela veut dire quelques chose +// pour l'élément +void LesMaillages::Plus_ddl_Sigma() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).Plus_ddl_Sigma(); + } + } + }; +// inactivation des ddls de contraintes si cela veut dire quelques chose +// pour l'élément +void LesMaillages::Inactive_ddl_Sigma() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).Inactive_ddl_Sigma(); + } + } + }; +// activation des ddls de contraintes si cela veut dire quelques chose +// pour l'élément +void LesMaillages::Active_ddl_Sigma() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).Active_ddl_Sigma(); + } + } + }; +// activation du premier ddl de contraintes si cela veut dire quelques chose +// pour l'élément +void LesMaillages::Active_premier_ddl_Sigma() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).Active_premier_ddl_Sigma(); + } + } + }; + +// introduction des ddl d'erreur si cela veut dire quelques chose +// pour l'élément +void LesMaillages::Plus_ddl_Erreur() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).Plus_ddl_Erreur(); + } + } + }; +// inactivation des ddls d'erreur si cela veut dire quelques chose +// pour l'élément +void LesMaillages::Inactive_ddl_Erreur() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).Inactive_ddl_Erreur(); + } + } + }; +// activation des ddls d'erreur si cela veut dire quelques chose +// pour l'élément +void LesMaillages::Active_ddl_Erreur() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).Active_ddl_Erreur(); + } + } + }; + +// d'une manière plus générique une fonction pour activer une série de ddl +// donnée par un identificateur, si c'est une grandeur vectoriel c'est l'ensemble +// des ddl du vecteur qui sont inactivé. +void LesMaillages::Active_un_type_ddl_particulier(Enum_ddl eni) + { // on retient le premier ddl de la famille + Enum_ddl en = PremierDdlFamille(eni); + // il y a deux versions suivant que le ddl est une grandeur vectorielle ou pas + if (FoncDim(en)) + // oui c'est une fonction vectorielle + { // recup de la dimension + int dimen = ParaGlob::Dimension(); + // dans le cas où le calcul est axisymétrique on décrémente de 1 + if (ParaGlob::AxiSymetrie()) + dimen--; + // création du tableau de ddl de travail + Tableau taben(dimen); + for (int ii=1; ii<= dimen; ii++) + taben(ii) = Enum_ddl(en + ii-1); + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le ddl existe + if (noo->Existe_ici(en)) + // si oui on l'active + noo->Met_en_service(taben); + // dans le cas où en = X1, on regarde le cas des épaisseurs + // celles-ci sont par exemple utilisées pour les coques et plaques et correspondent + // à une dimension du même ordre que Xi + if (en == X1) + if ( noo->Existe_ici(EPAIS) && noo->UneVariable(EPAIS)) + noo->Met_en_service(EPAIS); + } + } + } + else // cas où il s'agit d'une grandeur scalaire + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le ddl existe + if (noo->Existe_ici(en)) + // si oui on l'active + noo->Met_en_service(en); + } + } + }; +//idem pour un tableau +void LesMaillages::Active_un_type_ddl_particulier(Tableau & tab_en) + { int tab_enTaille = tab_en.Taille(); + for (int it=1;it<=tab_enTaille;it++) Active_un_type_ddl_particulier(tab_en(it)); + }; +//idem pour une liste +void LesMaillages::Active_un_type_ddl_particulier(const list & list_en) + { list ::const_iterator il,ilfin=list_en.end(); + for (il = list_en.begin();il != ilfin;il++) Active_un_type_ddl_particulier((*il)); + }; + +// idem la fonction Active_ddl_noeud mais ici pour l'inactivation +void LesMaillages::Inactive_un_type_ddl_particulier(Enum_ddl eni) + { // on retient le premier ddl de la famille + Enum_ddl en = PremierDdlFamille(eni); + // il y a deux versions suivant que le ddl est une grandeur vectorielle ou pas + if (FoncDim(en)) + // oui c'est une fonction vectorielle + { // recup de la dimension + int dimen = ParaGlob::Dimension(); + // dans le cas où le calcul est axisymétrique on décrémente de 1 + if (ParaGlob::AxiSymetrie()) + dimen--; + // création du tableau de ddl de travail + Tableau taben(dimen); + for (int ii=1; ii<= dimen; ii++) + taben(ii) = Enum_ddl(en + ii-1); + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le ddl existe + if (noo->Existe_ici(en)) + // si oui on l'inactive + noo->Met_hors_service(taben); + // dans le cas où en = X1, on regarde le cas des épaisseurs + // celles-ci sont par exemple utilisées pour les coques et plaques et correspondent + // à une dimension du même ordre que Xi + if (PremierDdlFamille(en) == X1) + if ( noo->Existe_ici(EPAIS) && noo->UneVariable(EPAIS)) + noo->Met_hors_service(EPAIS); + } + } + } + else // cas où il s'agit d'une grandeur scalaire + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le ddl existe + if (noo->Existe_ici(en)) + // si oui on l'inactive + noo->Met_hors_service(en); + } + } + }; +//idem pour un tableau +void LesMaillages::Inactive_un_type_ddl_particulier(Tableau & tab_en) + { int tab_enTaille = tab_en.Taille(); + for (int it=1;it<=tab_enTaille;it++) Inactive_un_type_ddl_particulier(tab_en(it)); + }; +//idem pour une liste +void LesMaillages::Inactive_un_type_ddl_particulier(const list & list_en) + { list ::const_iterator il,ilfin=list_en.end(); + for (il = list_en.begin();il != ilfin;il++) Inactive_un_type_ddl_particulier((*il)); + }; + +// Calcul de l'erreur sur l'ensemble des éléments +// type indique le type d'erreur retenue +// type = 1 : cas d'un calcul aux moindres carrés +// et retour un tableau de tableau de grandeurs sur les maillages en cours +// ret(i) : concerne le maillage i +// ret(i)(1) : somme des erreurs sur l'ensemble des éléments: est homogêne à +// un |delta contrainte| * domaine +// ret(i)(2) : somme de la grandeur de ref du calcul d'erreur sur l'ensemble des +// éléments: est homogêne à une |contrainte| * domaine +// ret(i)(3) : le maxi pour les tous les éléments de |delta contrainte| * domaine +// ret(i)(4) : le maxi pour les tous les éléments de |contrainte| * domaine +// ret(i)(5) : le maxi pour les tous les éléments de l'erreur relative +Tableau > LesMaillages::ErreurSurChaqueElement(int type) + { double errElemRelative; // variable de travail + Tableau > ret(nbMaillageTotal); // init du tableau de retour + + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + double ErreurTot = 0.; // erreur totale + ret(i1).Change_taille(5); + double numerateur,denominateur; + double numtot = 0.; double denotot = 0.; + double maxi_numerateur = 0.; double maxi_denominateur = 0.; + double maxi_relatif = 0.; + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + { // calcul des elements d'erreur + ((ElemMeca&) elem).ErreurElement(type,errElemRelative + ,numerateur,denominateur); + numtot += numerateur; denotot += denominateur; + maxi_numerateur = DabsMaX(maxi_numerateur,numerateur); + maxi_denominateur = DabsMaX(maxi_denominateur, denominateur); + double relatif = 0.; + if (Dabs(denominateur) > ConstMath::petit) + { relatif = numerateur/denominateur;} + else + { relatif = numerateur; }; // on prend les valeurs non relatives si + maxi_relatif = DabsMaX(maxi_relatif, relatif); + }; + }; + ret(i1)(1)=numtot; + ret(i1)(2)=denotot; + ret(i1)(3)=maxi_numerateur; + ret(i1)(4)=maxi_denominateur; +// ret(i1)(5)=maxi_relatif; + } + + // maintenant on va calculer la vraie erreur relative et on l'attribue aux éléments + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + double maxi_relatif = 0.; + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + { double erreur_absolue = ((ElemMeca&) elem).Erreur_sigma(); + double erreur_relative = erreur_absolue/ret(i1)(4); + ((ElemMeca&) elem).Change_erreur_relative(erreur_relative); + maxi_relatif = DabsMaX(maxi_relatif, erreur_relative); + }; + }; + ret(i1)(5)=maxi_relatif; + }; + +////--- debug +//cout << "\n debug LesMaillages::ErreurSurChaqueElement " +// << "\n Int_(delta sig)^2= " << numtot << ", int_sig^2= "< indicTravail_t(nbMaillageTotal,false); + + // cas des contraintes + if (type == 1) + { // on parcours les éléments pour trouver le bon fichier + int i1; + for (i1 = 1; i1<= nbMaillageTotal; i1++) + // on regarde si le nom de maillage correspond + if ( tabMaillage(i1)->NomDuMaillage() == nomMaillage) + break; + if (i1 == nbMaillageTotal+1) + { cout << "\n erreur, on n'a pas trouve un nom de maillage utilisable pour la lecture de " + << "\n de donnees externes sur fichier !"; + entreePrinc->MessageBuffer(" LesMaillages::LectureDonneesExternes(..."); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + // on initialise le travail à t, nécessaire pour le calcul des métriques avec + // les coordonnées à t + if (!indicTravail_t(i1)) + { Travail_t(i1); + ZeroDdl(false); // mise à zéro des ddl sauf les déplacements qui sont = coord0 + // et mémorisation + indicTravail_t(i1) = true; + } + // maintenant passage de l'entête + entreePrinc->NouvelleDonnee(); + int toto,nbe; + *(entreePrinc->entree) >> toto >> nbe; + // passage des identificateurs des contraintes + entreePrinc->NouvelleDonnee(); + // lecture des données pour chaque élément + int nbelementmax = tabMaillage(i1)->Nombre_element(); + // vérif du nombre d'élément + if (nbe != nbelementmax) + { // cas d'une différence + cout << "\n erreur (1) dans la lecture externe des contraintes, le nombre d'element interne" + << "\n au calcul, et le nombre externe sur fichier est different!"; + entreePrinc->MessageBuffer(" LesMaillages::LectureDonneesExternes(..."); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + for (int i2 = 1; i2 <= nbelementmax; i2++) + { // lecture d'un premier enregistrement + entreePrinc->NouvelleDonnee(); + Element & elem = Element_LesMaille(i1,i2); + // lecture du type d'élément (ne sert à rien ici) + int typelem; + *(entreePrinc->entree) >> typelem; + // lecture des contraintes + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + ((ElemMeca&) elem).LectureContraintes(entreePrinc); + } + } + // cas des déplacements + if (type == 2) + { // on parcours les éléments pour trouver le bon fichier + int i1; + for (i1 = 1; i1<= nbMaillageTotal; i1++) + // on regarde si le nom de maillage correspond + if ( tabMaillage(i1)->NomDuMaillage() == nomMaillage) + break; + // on initialise le travail à t, nécessaire pour le calcul des métriques avec + // les coordonnées à t + if (!indicTravail_t(i1)) + { Travail_t(i1); + ZeroDdl(false); // mise à zéro des ddl sauf les déplacements qui sont = coord0 + // et mémorisation + indicTravail_t(i1) = true; + } + // maintenant on lit le nombre de déplacements enregistrés dans le fichier + entreePrinc->NouvelleDonnee(); + int nbenreg; + *(entreePrinc->entree) >> nbenreg; + // récup du nombre de noeud du maillage + int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + if (nbnoeudmax != nbenreg) + { // cas d'une différence + cout << "\n erreur (2) dans la lecture externe des contraintes, le nombre de noeuds interne" + << "\n au calcul, et le nombre externe sur fichier est different!"; + cout << "\n LesMaillages::LectureDonneesExternes( etc ... " << endl; + entreePrinc->MessageBuffer(" LesMaillages::LectureDonneesExternes(..."); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + } + // lecture des données pour chaque noeud + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // lecture d'un premier enregistrement + entreePrinc->NouvelleDonnee(); + Noeud_LesMaille(i1,i2).LectureDeplacements(entreePrinc); + } + } + }; + + +// mise en place du travail à t sur les maillages +// indique que l'on va utiliser les ddl en 0, t +// si les grandeurs en tdt existaient, elles sont supprimées +void LesMaillages::Travail_t() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // construit les tableaux de ddl a t + noo->Travail_t(); + } + } + }; + +// mise en place du travail à t tdt sur les maillages +// indique que l'on va utiliser les ddl en 0, t, tdt +void LesMaillages::Travail_tdt() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // construit les tableaux de ddl a t + noo->Travail_tdt(); + } + } + }; + + +// idem pour un maillage donné de numéro num +void LesMaillages::Travail_t(int num) + { int nbnoeudmax = tabMaillage(num)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(num,i2); + // construit les tableaux de ddl a t + noo->Travail_t(); + } + }; + +// définition des coordonnées à t identiques à ceux à t=0, +void LesMaillages::Insert_coord1() + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // construit les coordonnées de ddl a t + noo->Insert_coord1(); + } + } + }; + +// ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage +double LesMaillages::Max_var_dep_t_a_tdt() const + { double ret=0.; + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + ret=MaX(tabMaillage(i1)->Max_var_dep_t_a_tdt(),ret); + return ret; + }; + +// ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments pour tous les maillages +double LesMaillages::Min_dist2Noeud_des_elements(Enum_dure temps) const + { double ret=ConstMath::tresgrand; + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + ret=MiN(tabMaillage(i1)->Min_dist2Noeud_des_elements(temps),ret); + return ret; + }; + + diff --git a/Maillage/LesMaillages.h b/Maillage/LesMaillages.h new file mode 100644 index 0000000..4b7c9fd --- /dev/null +++ b/Maillage/LesMaillages.h @@ -0,0 +1,957 @@ + +// 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: . + +/************************************************************************ + * DATE: 23/01/97 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: definir le groupe de maillage * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ +#ifndef LESMAILLAGES_H +#define LESMAILLAGES_H + +#include "Maillage.h" +#include "Tableau_T.h" +#include "UtilLecture.h" +#include "ParaGlob.h" +#include "LesReferences.h" +// #include "bool.h" +#include "DiversStockage.h" +#include "LesLoisDeComp.h" +#include "Front.h" +#include "Enum_dure.h" +#include "Nb_assemb.h" +#include "Basiques.h" +#include "Enum_dure.h" +#include "TypeQuelconque.h" +#include "Enum_IO_XML.h" + +/** @defgroup Les_Maillages Les_Maillages +* +* BUT: definir le groupe de maillage * +* +* \author Gérard Rio +* \version 1.0 +* \date 23/01/97 +* \brief Définition du groupe de maillage +* +*/ + +/// @addtogroup Les_Maillages +/// @{ +/// + +//------------------------------------------------------------------ +//! LesMaillages: l'ensemble des maillages +//------------------------------------------------------------------ +/// \author Gérard Rio +/// \version 1.0 +/// \date 23/01/97 + +class LesMaillages +{ + public : + // VARIABLES PUBLIQUES : + + // CONSTRUCTEURS : le pointeur sur UtilLecture permet d'avoir acces a la lecture + // le second pointe sur les variables globales + // le troisieme pointe sur l' instance des references + LesMaillages (UtilLecture * , ParaGlob *,LesReferences* lesRef); + // constructeur par défaut + LesMaillages(); + // Constructeur de copie, + LesMaillages(const LesMaillages& lesmail); + // DESTRUCTEUR : + ~LesMaillages(); + // METHODES PUBLIQUES : + // lecture des maillages et des references s'y rapportant + void LectureLesMaillages(); + // création et ajout d'un nouveau maillage en fonction d'un nom et d'une liste + // d'éléments + // *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments, + // ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé + // >> ramène le numéro du nouveau maillage + int Creation_nouveau_maillage + (list & li_noeud,list & list_elem,const string& nom_maillage); + // suppression d'un maillage existant + // par défaut, tous les noeuds et éléments du maillage sont supprimés + // si sans_conservation_noeuds_elements est false: les noeuds et les éléments ne sont pas supprimés + // mais ils ne sont plus référencés dans ce maillage ! + void Suppression_maillage( const string& nom_maillage,const bool sans_conservation_noeuds_elements = true); + // ajout d'un tableau de noeud à un maillage + void Ajout_de_Noeuds(const list & taN, int numMail) + {tabMaillage(numMail)->Ajout_de_Noeuds(taN);}; + // -- ajout de noeuds, éléments et éventuellement de ref à un maillage + // ajout d'une liste d'éléments et de noeud à un maillage + // si le numéro de maillage associé à l'élément ou noeud est nul, il est remplacé par celui du maillage + // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a + // création d'un nouvel item identique, avec le numéro this + // ajout éventuel d'une liste de références associées , si celle-ci est non-nulle + // il y a création de nouvelles ref correspondantes au numéro de maillage de this + // et ces références sont rajoutées à lesRef + // les noeuds qui sont associés aux éléments de taE, doivent faire partie : soit de taN, soit du maillage this + void Ajout_elements_et_noeuds(const list & taN, const list & taE,list * lref,LesReferences* lesRef, int numMail ) + {tabMaillage(numMail)->Ajout_elements_et_noeuds(taN,taE,lref,lesRef);}; + + // affichage et definition interactive des commandes + void Info_commande_lesMaillages(); + + // Affiche les donnees du maillage + void Affiche () const ; + // Affiche les donnees du maillage dans le fichier de nom nom_fichier + // au format du fichier ".her" + void Affiche (char* nom_fichier) const ; + + // test si toutes les informations des maillages sont completes + // = true -> complet + // = false -> incomplet + bool Complet(); + + // introduction des lois de comportement dans les elements qui le necessite + // des sections pour les biellettes etc c-a-d , completer les elements + // avec les donnees qui ont ete acquises apres la lecture du maillage + // def des tableaux de ddl dans les noeuds + // def des pointeurs d'assemblage dans les noeuds + void Completer(DiversStockage* divers,LesLoisDeComp* lesLois + ,LesFonctions_nD* lesFonctionsnD); + + // mise à jour des repères d'anisotropie + void Mise_a_jour_repere_anisotropie(DiversStockage* divers,LesFonctions_nD* lesFonctionsnD); + + // ramene le nombre de maillage + inline int NbMaillage() const + { return nbMaillageTotal;}; + + // ramene le nombre d'element du maillage i + inline int Nombre_element(int i) const + { return tabMaillage(i)->Nombre_element();}; + + // ramene le nombre de noeud du maillage i + inline int Nombre_noeud(int i) const + { return tabMaillage(i)->Nombre_noeud();}; + + // ramene l'element j du maillage i + inline Element& Element_LesMaille(int i, int j) const + {return tabMaillage(i)->Element_mail(j);}; + // idem mais en version constant + inline const Element& Element_LesMaille_const(int i, int j) const + {return tabMaillage(i)->Element_mail_const(j);}; + + // ramene le noeud j du maillage i + inline Noeud& Noeud_LesMaille(int i, int j) const + {return tabMaillage(i)->Noeud_mail(j);}; + + // Retourne le tableau des noeuds du maillage i + inline Tableau& Tab_noeud (int i) + { return tabMaillage(i)->Tab_noeud(); }; + + // Retourne le nom du maillage i + string NomMaillage(int i) const {return tabMaillage(i)->NomDuMaillage();}; + // retourne le numéro du maillage de nom donné + // ou 0 si le nom ne correspond pas à un maillage + int NumMaillage(const string& nom) const + {map < string, int , std::less >::const_iterator itmap = mapNomMail.find(nom); + if (itmap!=mapNomMail.end()) {return (*itmap).second;} + else {return 0;}; + }; + + // suppression éventuelle des noeuds, non référencés par les éléments et les références + // dans tous les maillages + void SuppressionNoeudNonReferencer(LesReferences& lesRef) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->SuppressionNoeudNonReferencer(lesRef);}; + // Affichage des noeuds, non référencés par les éléments + void AffichageNoeudNonReferencer() + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->AffichageNoeudNonReferencer();}; + + // renumérotation des noeuds de tous les maillagesen même temps, + prise en compte + // des conditions linéaires qui existent entre les noeuds + // ramène false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure), vrai sinon + // si le pointeur d'assemblage est non nulle, cela veut dire que l'on veut également une mise à jour + // globale des pointeurs d'assemblages (ce qui est différent de la méthode : MiseAJourPointeurAssemblage( + // qui agit maillage après maillage) + // si le pointeur d'assemblage est non nulle et le drapeau: sans_changement_num_noeud = true + // cela signifie que l'on désire uniquement une renumérotation de pointeur sans les noeuds + // ramène dans tous les cas les nouvelles largeurs en ddl + // nouvelles_largeur_en_ddl.un = la largeur totale résultante + // nouvelles_largeur_en_ddl.deux = la demie largeur totale résultante + // nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis + // uniquement (sans les CLL) + // + bool Renumerotation(LesReferences& lesRef,const Tableau >& condCLL + ,TroisEntiers& nouvelles_largeur_en_ddl,const Nb_assemb* nb_casAssemb = NULL + ,bool sans_changement_num_noeud = false); + + // renumérotation des noeuds maillages par maillage, + // === sans prise en compte de conditions linéaires === + // en sortie les maillages sont mis à jour si la nouvelle numérotation conduit à une largeur de bande + // plus faible que la largeur initiale: en noeuds + // ramène: false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure) + // vrai sinon + bool Renumerotation(LesReferences& lesRef); + + // création éventuelle d'une référence sur les noeuds, non référencés par les éléments + // dans tous les maillages + void CreationRefNoeudNonReferencer(LesReferences& lesRef) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->CreationRefNoeudNonReferencer(lesRef);}; + + // ramène le numéro du noeud le plus proche du point donné pour t=0, + // ceci pour le maillage i, par défaut i vaut 1 + inline int Noeud_le_plus_proche_0(const Coordonnee& M,int i = 1) + { return tabMaillage(i)->Noeud_le_plus_proche_0(M); }; + // idem à t + inline int Noeud_le_plus_proche_t(const Coordonnee& M,int i = 1) + { return tabMaillage(i)->Noeud_le_plus_proche_t(M); }; + // idem à tdt + inline int Noeud_le_plus_proche_tdt(const Coordonnee& M,int i = 1) + { return tabMaillage(i)->Noeud_le_plus_proche_tdt(M); }; + + // ramène le numéro de l'élément qui contiend un point donné et le numéro du point + // d'intégration le plus proche pour les ddl de la liste (ddl spécifique à l'élément c'est-a-dire + // hors des ddl des noeuds de l'éléments) + // ceci pour le maillage i, (par défaut i vaut 1) + // si pas de numéro d'élément ramène un numéro d'élément nulle + // si les numéros de point d'intégration ne sont pas identique pour l'ensemble + // des ddl, pb !!, le numéro du pt integ de retour est alors négatif + // si pb ramène un numéro d'élément nulle + // enu_temps: dit si les coordonnées du point M sont à 0 ou t ou tdt + inline Maillage::NBelemEtptInteg Element_le_plus_proche + (Enum_dure enu_temps,const List_io & list_enu,const Coordonnee& M,int i = 1) + { return tabMaillage(i)->Element_le_plus_proche(enu_temps,list_enu,M); }; + + // ramène la liste des problèmes physiques gérés par les éléments de tous les maillages + inline const list & Ddl_representatifs_des_physiques()const + {return ddl_representatifs_des_physiques;}; + + // ramene la liste des degrés de liberté inconnus, associés aux pb + // physiques gérés par les éléments qui existent dans tous les maillages + // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i + // Si éléments thermiques -> ddl de température + // Si éléments méca + éléments thermiques -> ddl Xi et température + // etc. en fonction des éléments qui existent dans les maillages + inline const list & Types_de_problemes() const + {return types_de_problemes;}; + + + // ramene le nombre total de ddl actifs du pb + int NbTotalDdlActifs() const ; + // idem mais pour un type de ddl donné, dans le cas de type + // vectoriel on cumule les ddl de l'ensemble de la dimension + int NbTotalDdlActifs(Enum_ddl enum_ddl) const; + + // ramene le nombre total de points d'intégration correspondant à un ddl donné + int NbTotalPtInteg(Enum_ddl enum_ddl) const ; + + // ramene le nombre total de grandeurs génératrices, calculées aux points d'intégrations, + // correspondant à un ddl donné. + int NbTotalGrandeursGeneratrices(Enum_ddl enu) const ; + + //récupération d'une grandeur vectoriel de dimension, la dimension + // de l'espace, défini au noeud et transféré dans un vecteur global + // qui cumule de manière séquentielle toutes les grandeurs + // en entrée : enum_ddl donne le type de la grandeur à récupérer + // en fait de la première composante + // duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt + // enum_actif : le transfert s'effectue que si le ddl enum_actif est actif + // ce qui permet la différentiation entre les différents ddl + // vect : est le vecteur global de stockage qui normalement a été + // au préalable dimensionné avec NbTotalDdlActifs(Enum_ddl enum_ddl) + // en retour : une référence sur vect + Vecteur & Vect_loc_vers_glob(Enum_dure duree,Enum_ddl enum_actif + ,Vecteur& vect,Enum_ddl enum_ddl); + + // fonction inverse de Vect_loc_vers_glob, il s'agit ici de passer + // de la grandeur globale aux grandeurs locale + void Vect_glob_vers_local(Enum_dure duree,Enum_ddl enum_actif + ,const Vecteur& vect,Enum_ddl enum_ddl) ; + + + //récupération d'une grandeur vectoriel de dimension, la dimension + // de l'espace, défini au noeud et transféré dans un vecteur global + // qui cumule de manière séquentielle toutes les grandeurs + // en entrée : tab_enum_ddl donne le tableau des type de la grandeur à récupérer + // en fait de la première composante + // duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt + // tab_enum_actif : pour chaque élément tab_enum_ddl(i), le transfert s'effectue que si + // le ddl tab_enum_actif(i) est actif + // ce qui permet la différentiation entre les différents ddl + // vect : est le vecteur global de stockage qui normalement a été + // au préalable dimensionné avec somme des NbTotalDdlActifs(Enum_ddl enum_ddl), avec enum_ddl + // qui balaie l'ensemble des éléments de tab_enum_ddl + // Important: pour chaque famille de ddl, les ddl sont classés de manière croissante, ce qui signifie + // que c'est l'ordre des pointeurs d'assemblage si et seulement si, ces ddl ont été rangés dans les noeuds + // au préalable + // en retour : une référence sur vect + Vecteur & Vect_loc_vers_glob(Enum_dure duree,const Tableau & tab_enum_actif + ,Vecteur& vect,const Tableau & tab_enum_ddl); + + // fonction inverse de Vect_loc_vers_glob, il s'agit ici de passer + // de la grandeur globale aux grandeurs locale + void Vect_glob_vers_local(Enum_dure duree,const Tableau & tab_enum_actif + ,const Vecteur& vect,const Tableau & tab_enum_ddl) ; + + //récupération d'une grandeur scalaire + // défini au noeud et transféré dans un vecteur global + // qui cumule de manière séquentielle toutes les grandeurs + // en entrée : enum_ddl donne le type de la grandeur à récupérer + // duree : indique à quel temps doit s'effectuer le transfert, t=0 ou t ou tdt + // enum_actif : le transfert s'effectue que si le ddl enum_actif est actif + // ce qui permet la différentiation entre les différents ddl + // vect : est le vecteur global de stockage qui normalement a été + // au préalable dimensionné avec NbTotalDdlActifs(Enum_ddl enum_ddl) + // en retour : une référence sur vect + Vecteur & Scalaire_loc_vers_glob(Enum_dure duree,Enum_ddl enum_actif + ,Vecteur& vect,Enum_ddl enum_ddl); + + // fonction inverse de Scalaire_loc_vers_glob, il s'agit ici de passer + // de la grandeur globale à la grandeur locale + void Scalaire_glob_vers_local(Enum_dure duree,Enum_ddl enum_actif + ,Vecteur& vect,Enum_ddl enum_ddl); + + // deux fonctions idem que pour les ddl : mais pour un Ddl_etendu + Vecteur & Scalaire_loc_vers_glob(Enum_ddl enum_actif,Vecteur& vect,const Ddl_enum_etendu& enum_ddl_etend); + void Scalaire_glob_vers_local(Enum_ddl enum_actif,Vecteur& vect,const Ddl_enum_etendu& enum_ddl_etend); + + // deux fonctions idem que pour les ddl_etendu : mais pour une grandeur quelconque + Vecteur & Quelconque_loc_vers_glob(Enum_ddl enum_actif,Vecteur& vect,const TypeQuelconque& type_generique); + void Quelconque_glob_vers_local(Enum_ddl enum_actif,Vecteur& vect,const TypeQuelconque& type_generique); + + // retourne la liste des types de ddl principaux actuellement utilisé + // aux noeuds pour chaque maillage, la liste est exhaustive + // elle contiend tous les types au moins une fois utilisée + // cela ne signifie pas que le ddl en question soit présent + // pour tous les noeud du maillage considéré + // - le tableau de retour est indicé par le numéro de maillage correspondant + // - il y a une liste par maillage + Tableau > Les_type_de_ddl_par_noeud(bool absolue); + + // retourne la liste des types de ddl étendu actuellement utilisé + // aux noeuds pour chaque maillage, la liste est exhaustive + // elle contiend tous les types au moins une fois utilisée + // cela ne signifie pas que le ddl en question soit présent + // pour tous les noeud du maillage considéré + // - le tableau de retour est indicé par le numéro de maillage correspondant + // - il y a une liste par maillage + Tableau > Les_type_de_ddl_etendu_par_noeud(bool absolue); + + // retourne la liste des types quelconque actuellement utilisé + // aux noeuds pour chaque maillage, la liste est exhaustive + // elle contiend tous les types au moins une fois utilisée + // cela ne signifie pas que le ddl en question soit présent + // pour tous les noeud du maillage considéré + // - le tableau de retour est indicé par le numéro de maillage correspondant + // - il y a une liste par maillage + // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière + Tableau > Les_type_de_TypeQuelconque_par_noeud(bool absolue); + + // initialisation par défaut de tous les conteneurs aux noeuds + // de tous les maillages + // contenant li_restreinte_TQ + // ces conteneurs sont supposés déjà existés + // typiquement si le conteneurs est un scalaire, on met 0 + void Init_par_defaut_conteneurs(List_io < TypeQuelconque >& li_restreinte_TQ); + // idem pour une seule grandeur + void Init_par_defaut_conteneurs(TypeQuelconque_enum_etendu enuTypeQuelconque); + + // intro de certains conteneurs internes en relation par exemple avec les demandes de visualisation + // ou autre + // exemple: si VECT_REAC_N qui est un type quelconque, a été choisit + // il faut qu'il soit présent aux noeuds, alors qu'il est alimenter par les ddl pur ... + // on introduit donc le type quelconque associé + // NB: le conteneur passé en paramètre ne sert que pour localiser les grandeurs + void Intro_Conteneurs_internes_noeud_relier_auto_autres_grandeur + ( const List_io < TypeQuelconque > & glob_noeud_evol_retenu); + + // idem mais ciblé en fonction d'un tableau indicé sur les maillages + void Intro_Conteneurs_internes_noeud_relier_auto_autres_grandeur + ( const Tableau < List_io < TypeQuelconque > > & tab_noeud_evol_retenu); + + // retourne la liste des types de ddl actuellement utilisé + // aux éléments pour chaque maillage, la liste est exhaustive + // elle contiend tous les types au moins une fois utilisée + // cela ne signifie pas que le ddl en question soit présent + // pour tous les éléments du maillage considéré + // - le tableau de retour est indicé par le numéro de maillage correspondant + // - il y a une liste par maillage + Tableau > Les_type_de_ddl_par_element(bool absolue); + // idem pour les grandeurs évoluées interne actuellement utilisés + // par les éléments, c'est-à-dire comme les ddl mais directement sous forme de vecteur, tenseurs ... + Tableau > Les_type_de_donnees_evolues_internes_par_element(bool absolue); + // idem pour les grandeurs particulières + Tableau > Les_type_de_donnees_particulieres_par_element(bool absolue); + + // retourne la liste des types de grandeur quelconque actuellement utilisé + // aux faces élément pour chaque maillage, la liste est exhaustive + // elle contiend tous les types au moins une fois utilisée + // cela ne signifie pas que la grandeur en question soit présent + // pour tous les éléments du maillage considéré + // - le tableau de retour est indicé par le numéro de maillage correspondant + // - il y a une liste par maillage + Tableau > Les_type_de_donnees_evolues_internes_par_face_element(bool absolue); + // idem pour les arêtes d'élément + Tableau > Les_type_de_donnees_evolues_internes_par_arete_element(bool absolue); + + // Au niveau des noeuds: transfert des coordonnées de grandeurs vectorielles à des grandeurs évoluées + // stockée sous forme de grandeurs TypeQuelconque + // exemple: les réactions qui sont naturellement stockée en composantes + // le principe est que ce passage s'effectue si les conteneurs existent au niveau des noeuds + void PassageInterneDansNoeud_composantes_vers_vectorielles(); + + // ..... transfert de grandeurs des points d'intégration aux noeuds ..... + // 1- en entrée les type évoluées et les types particuliers que l'on veut transférer + // 2- en entrée: cas qui indique la méthode de transfert à utiliser + // =1 : les valeurs aux noeuds sont obtenue par moyennage des valeurs des pts d'integ les plus près + // des éléments qui entourent le noeud + // on décompose le processus en 4 étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois + // le même transfert + // les méthodes: AjoutConteneurAuNoeud, InitUpdateAuNoeud, sont générales, peuvent être utilisés pour autres choses + + + // A) première étape def des conteneurs et c'est tout, la méthode peut donc être utilisée + // pour autre chose. tabQ: permet d'avoir plusieurs listes de TypeQuelconque + // en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur + // est nulle on n'en tient pas compte + void AjoutConteneurAuNoeud(int num_maillage,const List_io < Ddl_enum_etendu >& lienu + ,const Tableau * >& tabQ) + { tabMaillage(num_maillage)->AjoutConteneurAuNoeud(lienu,tabQ);}; + // fonctions utilitaires du même genre pour tous les maillages + // ajout sur tous les maillages d'un ou plusieur ddl_enum_etendu comme conteneur + // en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur + // est nulle on n'en tient pas compte + void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu + ,const Tableau * >& tabQ) + { for (int imail=1;imail<=nbMaillageTotal;imail++) + tabMaillage(imail)->AjoutConteneurAuNoeud(lienu,tabQ);}; + + // B) initialisation des updates sur les noeuds + // lorsque l'on a des listes différentes pour chaque maillage on peut directement utiliser la routine de Maillage + void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu + , const Tableau * >& tabQ,int cas) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->InitUpdateAuNoeud(lienu,tabQ,cas);}; + void InitUpdateAuNoeud(int numMail,const List_io < Ddl_enum_etendu >& lienu + , const Tableau * >& tabQ,int cas) + { tabMaillage(numMail)->InitUpdateAuNoeud(lienu,tabQ,cas);}; + // C) exécution du transfert + // transfert de ddl des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds, on ne remplace pas) + // les ddl doivent déjà exister aux noeuds sinon erreur + // il doit s'agir du même type de répartition de pt d'integ pour toutes les grandeurs + void TransfertPtIntegAuNoeud(int numMail,Element& ele,const List_io < Ddl_enum_etendu >& lietendu + ,const Tableau > & tab_val,int cas) + { tabMaillage(numMail)->TransfertPtIntegAuNoeud(ele,lietendu,tab_val,cas);}; + // idem pour des grandeurs quelconques + // les informations sont ici contenues dans les types quelconques + // liQ_travail: est une liste de travail qui sera utilisée dans le transfert + void TransfertPtIntegAuNoeud(int numMail,Element& ele,const Tableau >& tab_liQ + ,List_io < TypeQuelconque > & liQ_travail,int cas) + { tabMaillage(numMail)->TransfertPtIntegAuNoeud(ele,tab_liQ,liQ_travail,cas);}; + // D) dernière étape: (par exemple calcul des moyennes en chaque noeuds) + void FinTransfertPtIntegAuNoeud(const List_io < Ddl_enum_etendu >& lienu + , const Tableau * >& tabQ,int cas) + { for (int i=1;i<=nbMaillageTotal;i++) tabMaillage(i)->FinTransfertPtIntegAuNoeud(lienu,tabQ,cas);}; + void FinTransfertPtIntegAuNoeud(int numMail,const List_io < Ddl_enum_etendu >& lienu + , const Tableau * >& tabQ,int cas) + { tabMaillage(numMail)->FinTransfertPtIntegAuNoeud(lienu,tabQ,cas);}; + + // ..... cumul et moyenne de grandeurs venant des éléments vers les noeuds (exemple la pression appliquée) ..... + // on décompose le processus en 4 étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois + // la même opération (typiquement à chaque incrément) + // on peut utiliser: + // A) AjoutConteneurAuNoeud : pour ajouter des conteneurs ad hoc aux noeuds + // B) InitUpdateElementAuNoeud: avant le cumul, initialise les conteneurs + // initialise uniquement les grandeurs qui sont gérées par l'élément + // C) Accumul_aux_noeuds : balaie les éléments avec cumul aux noeuds, uniquement des grandeurs gérées par l'élement + // D) MoyenneCompteurAuNoeud : effectue les moyennes aux noeuds + + // accumulation aux noeuds de grandeurs venant de tous les éléments vers ses noeuds (exemple la pression appliquée) + // autres que celles aux pti classiques, mais directements disponibles + // le contenu du conteneur stockées dans liQ est utilisé en variable intermédiaire + void Accumul_aux_noeuds(int numMail,const List_io < Ddl_enum_etendu >& lietendu + ,List_io < TypeQuelconque > & liQ,int cas) + { tabMaillage(numMail)->Accumul_aux_noeuds(lietendu,liQ,cas);}; + + // fonctions utilitaires du même genre pour tous les maillages + + // ajout sur tous les maillages d'un conteneur particulier quelconque + void AjoutConteneurAuNoeud(TypeQuelconque& tQ) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->AjoutConteneurAuNoeud(tQ);}; + + // ajout sur tous les maillages d'un ou plusieur ddl_enum_etendu comme conteneur + void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->AjoutConteneurAuNoeud(lienu);}; + // initialisation des updates de ddl_étendu uniquement sur les noeuds: on met à 0 les ddl_etendu correspondant, + // les compteurs, comptant le nombre de fois où les noeuds sont modifiés, sont mis à 0 + void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->InitUpdateAuNoeud(lienu);}; + // idem pour un seul ddl_etendu + void InitUpdateAuNoeud(const Ddl_enum_etendu & enu) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->InitUpdateAuNoeud(enu);}; + // moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié) + void MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu) + { for (int imail=1;imail<=nbMaillageTotal;imail++) tabMaillage(imail)->MoyenneCompteurAuNoeud(enu);}; + + // initialisation d'un ou de plusieurs nouveau cas d'assemblage + // ramène le numéro du premier nouveau cas d'assemblage + Nb_assemb InitNouveauCasAssemblage(int nb_cas); + + // ramène le nombre total de cas d'assemblage actuellement pris en compte dans les + // maillages + int Nb_total_en_cours_de_cas_Assemblage() const {return tab_nb_assemb;}; + + + // met a jour les pointeurs d'assemblage dans les noeuds pour un cas d'assemblage + // a effectuer si l'on a changer de nb de noeuds, de nb de ddl, de nb de maillage + // casAssemb : donne le cas d'assemblage qui est a considérer + void MiseAJourPointeurAssemblage(const Nb_assemb& nb_casAssemb); + + // mise a zero de tous les ddl actifs autres que les deplacements + // si indic = false; pas de creation des tableaux a t+dt + // si indic = true; creation des tableaux a t+dt + // cas = true; les coordonnées à t et éventuellement à t+dt sont initialisées + // aux valeurs de t=0 (cas par défaut), + // sinon on ne les modifies pas. + void ZeroDdl(bool indic,bool cas = true); + + // force la mise à une valeur d'un ddl (ou de la liste de ddl fonction de la dimention) particulier, quelques soit son activité + // si fonction_de_la_dimension = true : c'est toute les ddl fct de la dimension qui sont mis à la valeur + void Force_Ddl_aux_noeuds_a_une_valeur(Enum_ddl enu, const double& val,Enum_dure temps, bool fonction_de_la_dimension) + { for (int imail=1;imail<=nbMaillageTotal;imail++) + tabMaillage(imail)->Force_Ddl_aux_noeuds_a_une_valeur(enu,val,temps,fonction_de_la_dimension);}; + // mise à zéro de dd_enum_etendu aux noeuds : force la mise à une valeur à 0 + void Force_Ddl_etendu_aux_noeuds_a_zero(const Tableau& tab_enu) + { for (int imail=1;imail<=nbMaillageTotal;imail++) + tabMaillage(imail)->Force_Ddl_etendu_aux_noeuds_a_zero(tab_enu);}; + + // ramene la demi largeur de bande en ddl et la largeur de bande + // casAssemb : donne le cas d'assemblage qui est a considérer + void Largeur_Bande(int& demi, int& total,const Nb_assemb& nb_casAssemb); + + // méthode permettant le calcul des matrices de connexion pour chaque + // élément ceci par rapport à la numérotation absolu des ddl + // casAssemb : donne le cas d'assemblage qui est a considérer + void Table_connexion + (Tableau < Tableau >& petites_matricespetites_matrices + ,const Nb_assemb& nb_casAssemb) const; + + // actualisation des ddl et des grandeurs actives de t+dt vers t + void TdtversT(); + // actualisation des ddl et des grandeurs actives de t vers tdt + void TversTdt(); + + // actualisation des ddl a t+dt, a partir du resultat de la resolution + // casAssemb : donne le cas d'assemblage qui est a considérer + void PlusDelta_tdt(Vecteur& sol,const Nb_assemb& nb_casAssemb); + // actualisation des ddl actifs a t, a partir du resultat de la resolution + // casAssemb : donne le cas d'assemblage qui est a considérer + void PlusDelta_t(Vecteur& sol,const Nb_assemb& nb_casAssemb); + // récupération du vecteur correspondant à l'incrément de ddl entre t et tdt + // en paramètre le vecteur vide et en sortie le vecteur rempli + // casAssemb : donne le cas d'assemblage qui est a considérer + Vecteur& RecupDepde_tatdt(Vecteur& sol,const Nb_assemb& nb_casAssemb); + // changement des ddl à tdt par ceux correspondant au vecteur passé en paramètre + // casAssemb : donne le cas d'assemblage qui est a considérer + void ChangeDdla_tdt(Vecteur& sol,const Nb_assemb& nb_casAssemb); + + // retrouver le ddl correspondant a un pointeur de position + // d'assemblage, le nb du noeud et du maillage + // insol = le pointeur d'assemblage; + // ddl = le ddl en sortie; a t+dt si elle il existe + // sinon la valeur a t + // casAssemb : donne le cas d'assemblage qui est a considérer + Ddl NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage + ,const Nb_assemb& nb_casAssemb); + // idem en ramenant en plus la valeur du ddl a 0 + // casAssemb : donne le cas d'assemblage qui est a considérer + Ddl NoeudIndice(int inSol,int& nbNoeud, int& nbMaillage, double& val0 + ,const Nb_assemb& nb_casAssemb); + + // calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement + // a priori le calcul s'effectue par une moyenne des normales des éléments qui + // entourent le noeud. + // init -> calcul des normales à t=0 + // et ajout conteneur aux noeuds des normales à t = 0 et t + void InitNormaleAuxNoeuds() + { for (int imail=1;imail<=nbMaillageTotal;imail++) + tabMaillage(imail)->InitNormaleAuxNoeuds();}; + // mise à jour -> mise à jour des normales à t + void MiseAjourNormaleAuxNoeuds() + { for (int imail=1;imail<=nbMaillageTotal;imail++) + tabMaillage(imail)->MiseAjourNormaleAuxNoeuds();}; + // mise à jour -> mise à jour des normales à t + // mais ici, on calcule les normales à tdt, et on transfert à t + // cette méthode est utile si on veut utiliser des normales à t pour une valeur + // particulière (transitoire) de la géométrie à tdt + // cf: l'algo non dyna par exempel + void MiseAjourNormaleAuxNoeuds_de_tdt_vers_T() + { for (int imail=1;imail<=nbMaillageTotal;imail++) + tabMaillage(imail)->MiseAjourNormaleAuxNoeuds_de_tdt_vers_T();}; + + // ---------- particularité aux contacts ---------- + // creation des elements frontiere: cela n'a lieu qu'une seule fois + // si les frontières existent déjà, --> aucune action, --> ramène 0 + // sinon il y a réellement création, et --> ramène 1 + int CreeElemFront(); + // ramene le nombre de maillage esclave + inline int NbEsclave() { return domEsclave;}; + // ramene le tableau des list des elements frontiere + inline Tableau *>& ListFrontiere() { return listFrontiere;}; + // ramene un tableau des noeuds des frontières des maillages esclaves + Tableau < Tableau *> Tab_noeud_frontiere_esclave(); + // ramene le tableau des noeuds des frontières des maillages + const Tableau *>& Tab_noeud_frontiere() {return tt_noeud_front;}; + // calcul et ramene le tableau de tous les noeuds des maillages esclaves + // noeuds de la frontière et noeuds internes + // s'ils existent, sinon le tableau est vide + // le tableau n'est pas sauvegarde + const Tableau Esclave(); + // mise à jour des boites d'encombrements des éléments, qui contiennent des éléments frontières + // et des éléments frontières eux-même + void Mise_a_jour_boite_encombrement_elem_front(Enum_dure temps); + // crée et ramene pour tous les maillages, la liste des éléments qui contiennent chaque noeud + // mis à jour lorsque lors de la création des frontières + const Tableau < const Tableau > *>& Indice() ; + + // inactive tous les ddl et les données + void Inactive_ddl_et_donnees(); + // inactive les ddl mais pas les données + void Inactive_ddl(); + + // inactive les ddl primaires + void Inactive_ddl_primaire(); + // active les ddl primaires + void Active_ddl_primaire(); + // introduction des ddl de contraintes si cela veut dire quelques chose + // pour l'élément + void Plus_ddl_Sigma(); + // inactivation des ddls de contraintes si cela veut dire quelques chose + // pour l'élément + void Inactive_ddl_Sigma(); + // activation des ddls de contraintes si cela veut dire quelques chose + // pour l'élément + void Active_ddl_Sigma(); + // activation du premier ddl de contraintes si cela veut dire quelques chose + // pour l'élément + void Active_premier_ddl_Sigma(); + // introduction des ddl d'erreur si cela veut dire quelques chose + // pour l'élément + void Plus_ddl_Erreur(); + // inactivation des ddls d'erreur si cela veut dire quelques chose + // pour l'élément + void Inactive_ddl_Erreur(); + // activation des ddls d'erreur si cela veut dire quelques chose + // pour l'élément + void Active_ddl_Erreur(); + + // d'une manière plus générique une fonction pour activer une série de ddl + // donnée par un identificateur, si c'est une grandeur vectoriel c'est l'ensemble + // des ddl du vecteur qui sont inactivé. + void Active_un_type_ddl_particulier(Enum_ddl en); + void Active_un_type_ddl_particulier(Tableau& tab_en); // idem mais pour un tableau + void Active_un_type_ddl_particulier(const list& list_en); // idem pour une liste + // idem la fonction Active_ddl_noeud mais ici pour l'inactivation + void Inactive_un_type_ddl_particulier(Enum_ddl en); + void Inactive_un_type_ddl_particulier(Tableau& tab_en); // idem mais pour un tableau + void Inactive_un_type_ddl_particulier(const list & list_en); // idem pour une liste + // -- encore plus générique + // changement de toutes les conditions données (service, variable, fixage ..) + // selon le tableau de ddl passé en paramètre + // par contre les valeurs de ta ne sont pas utilisé donc les valeurs actuelles restent inchangé + void ChangeToutesLesConditions(const Tableau& ta); + // changement de statu des ddl d'une combinaison, en fonction du statut + // de enuta dans chaque noeud, les ddl de la combinaison, prennent le même statut que celui + // de enuta dans chaque noeud. + // cas est la combinaison, + void ChangeStatut(int cas,Enum_ddl enuta); + // changement de statu des ddl d'une combinaison dans chaque noeud, en fonction + // de enubold, les ddl de la combinaison, prennent le même statut que enubold + // cas est la combinaison, + void ChangeStatut(int cas,Enum_boolddl enubold); + + //change le statut de tous les ddl liés à la physique en cours + //par exemple: met à libre ou bloque les ddl liés à la physique en cours + void Libere_Ddl_representatifs_des_physiques(Enum_boolddl enubold); + + // Calcul de l'erreur sur l'ensemble des éléments + // type indique le type d'erreur retenue + // type = 1 : cas d'un calcul aux moindres carrés + // et retour un tableau de tableau de grandeurs sur les maillages en cours + // ret(i) : concerne le maillage i + // ret(i)(1) : somme des erreurs sur l'ensemble des éléments: est homogêne à + // un |delta contrainte| * domaine + // ret(i)(2) : somme de la grandeur de ref du calcul d'erreur sur l'ensemble des + // éléments: est homogêne à une |contrainte| * domaine + // ret(i)(3) : le maxi pour les tous les éléments de |delta contrainte| * domaine + // ret(i)(4) : le maxi pour les tous les éléments de |contrainte| * domaine + Tableau > ErreurSurChaqueElement(int type); + + // lecture de donnée en fonction d'un indicateur : type + // type = 1 , on lit les tenseurs de contraintes + void LectureDonneesExternes(const int type ,const string& nomMaillage); + + // mise en place du travail à t sur les maillages + // indique que l'on va utiliser les ddl en 0, t + // si les grandeurs en tdt existaient, elles sont supprimées + void Travail_t(); + // idem pour un maillage donné de numéro num + void Travail_t(int num); + + // définition des coordonnées à t identiques à ceux à t=0, + void Insert_coord1(); + + // mise en place du travail à t tdt sur les maillages + // indique que l'on va utiliser les ddl en 0, t, tdt + void Travail_tdt(); + + // initialisation des coordonnées à t et tdt aux mêmes valeurs qu'à 0 + // utile quand on veut utiliser les métriques pour un pb non couplés + void Init_Xi_t_et_tdt_de_0() { for (int imail=1;imail<=nbMaillageTotal;imail++) + tabMaillage(imail)->Init_Xi_t_et_tdt_de_0();}; + + // ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage + double Max_var_dep_t_a_tdt() const; + + // ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments pour tous les maillages + double Min_dist2Noeud_des_elements(Enum_dure temps) const ; + + // indique aux éléments un niveau de précision de calcul désiré pour les prochains calculs + // precision = 0 : aucune précision demandée, precision >=0 : précision maximale demandée + void Drapeau_preparation_calcul_precis(int precision); + +// --------- calcul dynamique --------- + // ajout des ddl de vitesse pour tous les maillages + // val_fixe indique si l'on veut des ddl libres ou pas + void Plus_Les_ddl_Vitesse(Enum_boolddl val_fixe); + // ajout des ddl d'accélération pour tous les maillages + // val_fixe indique si l'on veut des ddl libres ou pas + void Plus_Les_ddl_Acceleration(Enum_boolddl val_fixe); + // calcul de la longueur d'arrête d'élément minimal + // divisé par la célérité dans le matériau + double Longueur_arrete_mini_sur_c(Enum_dure temps); + // initialisation éventuelle du bulk viscosity + // choix peut-être égale à 0, 1 ou 2 + void Init_bulk_viscosity(int choix,const DeuxDoubles & coef); + + //----- lecture écriture de restart ----- + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) + void Lecture_base_info(ifstream& ent,const int cas); + // cas donne le niveau de sauvegarde + // = 1 : on sauvegarde tout + // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) + void Ecriture_base_info(ofstream& sort,const int cas); + // sortie du schemaXML: en fonction de enu + void SchemaXML_LesMaillages(ofstream& sort,const Enum_IO_XML enu) const ; + + + // ------ informations utiles par exemples pour la visualisation + // retourne les dimensions minis et maxi suivant les axes du repère + // absolu du maillage numéro nbmail (en faite le calcul est fondé + // uniquement sur la position des noeuds du maillage + // le premier vecteur contient les minimums + // le deuxième vecteur contient les maximums + Tableau Taille_boite(int nbmail); + // dans le cas ou aucun numéro de maillage n'est fournis + // c'est l'encombrement de tous les maillages qui est fourni + Tableau Taille_boite(); + + + // -------- utilitaires de manipulation de maillage + // création de maillage quadratiques incomplets à partir de maillages linéaires. + // En fait il y création de maillages identiques aux maillages déjà existants, les éléments qui sont de types + // linéaires sont remplacés par des éléments quadratiques incomplets correspondants. + // Il y a création de références correspondantes + void CreeMaillagesQuadratiques_a_partir_des_lineaires(LesReferences* lesRef); + // création de maillage quadratiques complets. En fait il y création de maillages identiques aux maillages + // déjà existants, les éléments qui sont de types quadratiques incomplets sont remplacés par des éléments + // quadratiques complets correspondants. + // Il y a création de références correspondantes + void CreeMaillagesQuadratiquesComplets_a_partir_des_incomplets(LesReferences* lesRef); + // création de maillages par extrusion + // Il y a création de références correspondantes + void CreeMaillageExtrusion2D3D(LesReferences* lesRef); + // définition interactive de listes de références + void CreationInteractiveListesRef(LesReferences* lesRef); + // modification de l'orientation d'éléments + void Modif_orientation_element(int cas_orientation,LesReferences* lesRef); + // collapse de noeuds très proche: appartenant à des éléments différents + // rayon : donne la distance maxi entre les noeuds qui doivent être collapsé + void Collapse_noeuds_proches(double rayon, LesReferences* lesRef); + // Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe + void Collapse_element_supperpose(LesReferences* lesRef); + // création d'un nouveau maillage issue de la fusion de maillages existants + // nom_mails_a_fusionner : la liste des maillages à fusionner + // new_mail : le nom du nouveau maillage à construire + // NB: si new_mail correspond à un maillage déjà existant, il y a fusion de ce maillage + // avec les autres, sans création d'un nouveau maillage + void Fusion_maillages(List_io < string >& nom_mails_a_fusionner,const string& new_mail + ,LesReferences* lesRef); + // création d'un nouveau maillage issue d'un maillages existants et d'une ref d'éléments + // le nouveau maillage = les éléments de la ref + void Cree_sous_maillage(int num_mail,LesReferences* lesRef, string nom_ref,const string& new_mail); + // création d'éléments SFE en fonction d'éléments classiques + // il y a création d'un nouveau maillage + void CreationMaillageSFE(); + + // Affiche les donnees des maillages dans des fichiers dont le nom est construit à partir du nom de + // chaque maillage au format ".her" et ".lis" + // le paramètre optionnel indique le numéro du maillage à afficher, s'il vaut -1, on affiche tous les maillages + void Affiche_maillage_dans_her_lis(Enum_dure temps,LesReferences &lesRef,int imail=-1); + + // relocalisation des points milieux des arrêtes des éléments quadratiques + void RelocPtMilieuMailleQuadra(); + + // --- utilitaires pour calculs particuliers------- + // calcul des diverses intégrations: volume et volume + temps, + // alimentation des grandeurs globales associées + void Integration(); + + // calcul des diverses statistiques sur des ref de noeuds et avec éventuellement + // cumul sur le temps + // alimentation des grandeurs globales associées + void CalStatistique(); + + private : + // VARIABLES PROTEGEES : + Tableau tabMaillage ; // tableau de maillages + // liste des noms de maillages associée à un numéro sous forme d'un arbre pour faciliter la recherche + // cette liste est modifiée que par chaque maillage + map < string, int , std::less > mapNomMail; + // const int nbEnreg; // nb de maillage initiaux + int nbEnreg; // nb de maillage initiaux + int nbMaillageTotal; // nb de maillage effectivement en cours + int nbPortion ; // nbPortion = le nombre maxi de maillage enregistrable + // avant une nouvelle allocation dynamique de nbEnreg places supplementaires + UtilLecture * entreePrinc; // acces a la lecture du fichier principal + ParaGlob * paraGlob ; // parametres globaux + LesReferences* lesRef; // references + int domEsclave; // nombre de domaine esclave, lorsqu'il est different de zero + // il indique le nombre de maillage a partir de 1, qui sont esclave + + // ---- stockage des intégrales de volumes sur des références d'éléments ---- + // --- cas des intégrales volumiques: définition du conteneur, il peut également s'agir d'une intégration temporelle en + + // d'où la grandeur courante et celle à t + // 1) intégration de volume uniquement + Tableau integ_vol_typeQuel, integ_vol_typeQuel_t; + Tableau ref_integ_vol; // les références associées + // si la référence est nulle, cela signifie que l'intégrale est figée: sa valeur ne change pas + + // 2) intégration de volume et en temps: donc on commule le delta + Tableau integ_vol_t_typeQuel, integ_vol_t_typeQuel_t; + Tableau ref_integ_vol_t; // les références associées + // si la référence est nulle, cela signifie que l'intégrale est figée: sa valeur ne change pas + + // ---- stockage des statistiques sur des références de noeuds ---- + // --- cas des statistique: définition du conteneur, il peut également s'agir d'un cumul temporelle en + + // d'où la grandeur courante et celle à t + // 1) statistique de ref de noeuds uniquement + Tableau statistique_typeQuel, statistique_typeQuel_t; + Tableau ref_statistique; // les références associées + // si la référence est nulle, cela signifie que la statistique + // est figée: sa valeur ne change pas + + //pour_statistique_de_ddl a la même dimension que ref_statistique + // 1) Dans le cas où ref_statistique(i) est une statistique de Ddl_enum_etendu + // pour_statistique_de_ddl(i) == le Ddl_enum_etendu + // 2) sinon, pour_statistique_de_ddl(i) == NU_DDL + Tableau < Ddl_enum_etendu > pour_statistique_de_ddl; + + // 2) statistique avec cumul en temps: donc on commule le delta + Tableau statistique_t_typeQuel, statistique_t_typeQuel_t; + Tableau ref_statistique_t; // les références associées + // si la référence est nulle, cela signifie que la statistique est figée: sa valeur ne change pas + + //pour_statistique_t_de_ddl a la même dimension que ref_statistique_t + // 1) Dans le cas où ref_statistique_t(i) est une statistique de Ddl_enum_etendu + // pour_statistique_t_de_ddl(i) == le Ddl_enum_etendu + // 2) sinon, pour_statistique_de_ddl(i) == NU_DDL + Tableau < Ddl_enum_etendu > pour_statistique_t_de_ddl; + + // cumule les liste des types de degrés de liberté inconnus, + // qui vont être calculés par la résolution des problèmes + // physiques gérés par les éléments qui existent dans les maillages + // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i + // Si éléments thermiques -> ddl de température + // Si éléments méca + éléments thermiques -> ddl Xi et température + // etc. en fonction des éléments qui existent dans les maillages + // (généré à la lecture du maillage, ce qui permet d'optimiser la consultation par la suite) + list ddl_representatifs_des_physiques; + // idem au niveau des types de problèmes gérés par les éléments + list types_de_problemes; + + // stockage des pointeurd de listes d'element frontiere + Tableau *> listFrontiere; + // idem pour les noeuds des frontières + Tableau *> tt_noeud_front; + // crée et ramene pour tous les maillages, la liste des éléments qui contiennent chaque noeud + // mis à jour lorsque lors de la création des frontières + Tableau < const Tableau > *> tous_indices; + // tableau d'indexage des ddl géré par les noeuds + // t_i_n (i)(j) -> donne les infos pour retrouver le ddl numéro j du cas de charge i + Tableau < Tableau > t_i_n; + // nombre actuellement de cas d'assemblage initialisé + int tab_nb_assemb; + + // METHODES PROTEGEES : + // on s'occupe de mettre à jour les types de pb et les ddl types associés + void Mise_a_jour_type_pb_type_associe_ddl(); + + // met a jour les pointeurs d'assemblage dans les noeuds pour un cas d'assemblage + // a effectuer si l'on a changer de nb de noeuds, de nb de ddl, de nb de maillage + // casAssemb : donne le cas d'assemblage qui est a considérer + // ici, l'assemblage suit l'ordre du tableau de noeud passé en paramètre + // le tableau de noeuds rassemble tous les noeuds des maillages mais avec une numérotation propre + void MiseAJourPointeurAssemblage_interne(const Nb_assemb& nb_casAssemb,Tableau & tab_N_final); + + // remise à jour des tableaux de pointeurs t_i_n uniquement, due à un changement de numéro de noeud + // en fonction d'un changement de num de noeud (mais pas de changement de pointeur d'assemblage + // pour chaque noeud, tab_N_final(i) correspond au noeud qui avait le numéro i ancien + // et qui a maintenant le numéro tab_N_final(i)->Num_noeud() + void MiseAJourTableau_t_i_n(const Nb_assemb& nb_casAssemb,Tableau & tab_N_final); + + + }; + /// @} // end of group + +#endif diff --git a/Maillage/LesMaillages2.cc b/Maillage/LesMaillages2.cc new file mode 100644 index 0000000..7470c62 --- /dev/null +++ b/Maillage/LesMaillages2.cc @@ -0,0 +1,2937 @@ + +// 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 "LesMaillages.h" +#include "ElemMeca.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" +#include "MathUtil.h" +#include "ConstMath.h" +#include "CharUtil.h" +#include "TypeQuelconqueParticulier.h" + +#ifndef SYSTEM_MAC_OS_X_unix + #include "Frontier.h" +#endif + +// --------- calcul dynamique --------- +// ajout des ddl de vitesse pour tous les maillages +// pour tous les noeuds qui ont un ddl de déplacement +// val_fixe indique si l'on veut des ddl libres ou pas +void LesMaillages::Plus_Les_ddl_Vitesse(Enum_boolddl val_fixe) +{ // recup de la dimension + int dimen = ParaGlob::Dimension(); + // recup de la position de VI-1 + int posi = Id_nom_ddl("V1") -1; + // création du tableau de ddl de travail + Tableau ta(dimen); + for (int ii=1; ii<= dimen; ii++) + {//ta(ii) = Enum_ddl(ii+posi); // ERREUR D'AFFECTATION, À VOIRE EN DEBUG OU IL VA + ta(ii) = Ddl (Enum_ddl(ii+posi),0.,val_fixe); // bonne version + }; + // dans le cas où le calcul est axisymétrique + // le dernier ddl en z est mis en HSLIBRE, car on ne le prend pas en compte dans le calcul + // axisymétrique + if (ParaGlob::AxiSymetrie()) + ta(3) = Ddl (Enum_ddl(3+posi),0.,HSLIBRE); // bonne version; + // maintenant on passe en revu les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le déplacement existe + if (noo->Existe_ici(X1)) + noo->PlusTabDdl(ta); + } + }; +}; + + + +// ajout des ddl d'accélération pour tous les maillages +// pour tous les noeuds qui ont un ddl de déplacement +// val_fixe indique si l'on veut des ddl libres ou pas +void LesMaillages::Plus_Les_ddl_Acceleration(Enum_boolddl val_fixe) +{ // recup de la dimension + int dimen = ParaGlob::Dimension(); + // recup de la position de GAMMA1-1 + int posi = Id_nom_ddl("GAMMA1") -1; + // création du tableau de ddl de travail + Tableau ta(dimen); + for (int ii=1; ii<= dimen; ii++) + ta(ii) = Ddl (Enum_ddl(ii+posi),0.,val_fixe); // bonne version + // dans le cas où le calcul est axisymétrique + // le dernier ddl en z est mis en HSLIBRE, car on ne le prend pas en compte dans le calcul + // axisymétrique + if (ParaGlob::AxiSymetrie()) + ta(3) = Ddl (Enum_ddl(3+posi),0.,HSLIBRE); // bonne version; + // maintenant on passe en revu les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on regarde si le déplacement existe + if (noo->Existe_ici(X1)) + noo->PlusTabDdl(ta); + } + } + }; + +// calcul de la longueur d'arrête d'élément minimal +// divisé par la célérité dans le matériau +double LesMaillages::Longueur_arrete_mini_sur_c(Enum_dure temps) + { double dist_ret = ConstMath::tresgrand; // def de la distance de retour + // on balaie les maillages et les éléments + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelementmax = tabMaillage(i1)->Nombre_element(); + for (int i2 = 1; i2 <= nbelementmax; i2++) + { Element & elem = Element_LesMaille(i1,i2); + if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE) + { double dist = ((ElemMeca&) elem).Long_arrete_mini_sur_c(temps); + dist_ret = MiN(dist_ret,dist); + } + } + } + return dist_ret; + }; + +// initialisation éventuelle du bulk viscosity +void LesMaillages::Init_bulk_viscosity(int choix,const DeuxDoubles & coef) + { // on renseigne la classe générique d'éléments mécanique si besoin + // choix peut-être égale à 0, 1 ou 2 + if (choix) + { ElemMeca::ActiveBulkViscosity(choix); // activation du bulk viscosity + ElemMeca::ChangeCoefsBulkViscosity(coef); // passage des coeffs + } + }; + +// -- encore plus générique +// changement de toutes les conditions données (service, variable, fixage ..) +// selon le tableau de ddl passé en paramètre +// par contre les valeurs de ta ne sont pas utilisé donc les valeurs actuelles restent inchangé +void LesMaillages::ChangeToutesLesConditions(const Tableau& ta) +{ // création d'une liste qui contiendra tous les ddl à passer aux noeuds + list liddl; + // on boucle sur le tableau + int taTaille = ta.Taille(); + for (int ita=1;ita<=taTaille;ita++) + { Ddl& taa=ta(ita);Enum_boolddl enub=taa.Retour_Fixe(); + Tableau tenu = TableauTypeDdl(taa.Id_nom()); // récup du tableau d'enum + int tenuTaille = tenu.Taille(); + for (int i=1;i<=tenuTaille;i++) liddl.push_back(Ddl(tenu(i),0.,enub)); + }; + // création du tableau de travail que l'on passera aux noeuds + Tableau tddl(liddl.size()); + list::iterator il,ifin=liddl.end();int iii=1; + for (il=liddl.begin();il!=ifin;il++,iii++) tddl(iii)=(*il); + // maintenant on passe en revue les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + noo->ChangeToutesLesConditions(tddl); + } + } + }; + +// changement de statu des ddl d'une combinaison, en fonction du statut +// de enuta dans chaque noeud, les ddl de la combinaison, prennent le même statut que celui +// de enuta dans chaque noeud. +// cas est la combinaison, +void LesMaillages::ChangeStatut(int cas,Enum_ddl enuta) + {// on passe en revue les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + noo->ChangeStatut(cas,enuta); + } + } + }; + +// changement de statu des ddl d'une combinaison dans chaque noeud, en fonction +// de enubold, les ddl de la combinaison, prennent le même statut que enubold +// cas est la combinaison, +void LesMaillages::ChangeStatut(int cas,Enum_boolddl enubold) + {// on passe en revue les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + noo->ChangeStatut(cas,enubold); + } + } + }; + +//change le statut de tous les ddl liés à la physique en cours +//par exemple: met à libre ou bloque les ddl liés à la physique en cours +void LesMaillages::Libere_Ddl_representatifs_des_physiques(Enum_boolddl enubold) + { // ddl_representatifs_des_physiques représentent tous les ddl de la physique + if (ddl_representatifs_des_physiques.size()) // on ne continue que si c'est diff de 0 + {list ::iterator il,ilfin= ddl_representatifs_des_physiques.end(); + list ::iterator ildebut = ddl_representatifs_des_physiques.begin(); + // on fait un premier balayage, car il s'agit des "types" de ddl mais pas de la liste + // qui elle dépend de la dimension éventuellement + int nbddl = 0; // init + for (il = ildebut;il != ilfin; il++) + nbddl += TableauTypeDdl(*il).Taille(); + // on définit un tableau "ta" pour appeler les noeuds + // qui contient tous les ddl (et pas seulement les types) + Ddl enu((*ildebut),0.0,enubold); // def du premier ddl + Tableau ta(nbddl,enu); int ita=1; + for (il = ildebut;il != ilfin; il++) + {Tableau tddl = TableauTypeDdl(*il); + int ndPlus1 = tddl.Taille() + 1; + for (int i=1;i< ndPlus1;i++,ita++) + ta(ita).Change_nom(tddl(i)); + }; + // on passe en revue les noeuds + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on change les conditions données par ta + noo->ChangeToutesLesConditions(ta); + }; + }; + }; + }; + + +//----- lecture écriture base info ----- +// lecture base info + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) +void LesMaillages::Lecture_base_info(ifstream& ent,const int cas) + { string toto; +// cout << "\n debug **** LesMaillages::Lecture_base_info\n" +// << "\n entr.rdstate() " << ent.rdstate() << flush; + // lecture du nombre de maillage total + ent >> toto >> nbMaillageTotal; +// cout << "\n debug **** LesMaillages::Lecture_base_info\n" +// << " toto= "<< toto << nbMaillageTotal +// << "\n entr.rdstate() " << ent.rdstate() << flush; + + switch (cas) + { case 1 : // ------- on récupère tout ------------------------- + {for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // tout d'abord création du maillage + tabMaillage(i1) = new Maillage (mapNomMail,i1,paraGlob->Dimension()); + // puis lecture + tabMaillage(i1)->Lecture_base_info(ent,cas); + }; + // on s'occupe de mettre à jour les types de pb et les ddl types associés + Mise_a_jour_type_pb_type_associe_ddl(); + break; + } + case 2 : // ----------- on ne récupère que ce qui varie + { for (int i1 = 1; i1<= nbMaillageTotal; i1++) + tabMaillage(i1)->Lecture_base_info(ent,cas); + // ----- cas des grandeurs intégrés éventuelles----- + // utile pour pouvoir post-traiter et également pour le cumul sur le temps + ent >> toto; + if (toto != "int_vol_mail") + { cout << "\nErreur : en lecture de l'entete de l'integration de volume eventuelle" + << " on attendait le mot cle int_vol_mail et on a lu "<< toto <<" !\n"; + cout << "LesMaillages::Lecture_base_info(....)" << flush; + Sortie(1); + }; + int integ_vol_typeQuel_taille = 0; + ent >> integ_vol_typeQuel_taille; + // on boucle sur les grandeurs à lire + // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée + // mais dans ce cas elle ne changera plus pendant le calcul + for (int i=1;i<= integ_vol_typeQuel_taille;i++) + { // on lit l'entête d'un type quelconque + // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes + TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); + TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); + // lecture de l'entête et récup d'enu + // on utilise: avec création, car il peut s'agir d'une intégrale qui n'est plus active + // du coup le tableau existant ne contient pas cette intégrale + EnuTypeQuelParticulier enu_t = + pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + int indice_t = integ_vol_typeQuel_t.Contient(pour_lire_t); + if (indice_t) + {// là il suffit de lire la grandeur associée + ent >> (*integ_vol_typeQuel_t(indice_t).Grandeur_pointee()); + }; + // normalement le cas a tdt est identique + EnuTypeQuelParticulier enu = + pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur + // le test se fait uniquement sur le TypeQuelconque_enum_etendu + // qui est supposé suffisant comme signature + int indice = integ_vol_typeQuel.Contient(pour_lire); + if (indice) + {// là il suffit de lire la grandeur associée + ent >> (*integ_vol_typeQuel(indice).Grandeur_pointee()); + }; + if (!indice) + { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur + // figée, dont la valeur ne changera pas pendant le calcul + // création d'une grandeur associée et lecture des information sur le flot + TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); + // création du type quelconque + TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); + delete grandeur_t; // car il ne sert plus à rien + TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); + // création du type quelconque + TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); + delete grandeur; // car il ne sert plus à rien + + + // maintenant on va mettre à jour le stockage interne + // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue + // à l'initialisation du .info + indice_t = integ_vol_typeQuel_t.Taille()+1; + indice = integ_vol_typeQuel.Taille()+1; + integ_vol_typeQuel_t.Change_taille(indice_t); + integ_vol_typeQuel.Change_taille(indice); + integ_vol_typeQuel(indice) = typQ; + integ_vol_typeQuel_t(indice_t) = typQ_t; + ref_integ_vol.Change_taille(indice);// normalement c'est le même qu'indice_t + // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est + // figé, car aucun domaine d'intégration n'a été définit + ref_integ_vol(indice) = NULL; + }; + // on va créer ou mettre à jour une grandeur globale associée + {TypeQuelconque& TQ_t = integ_vol_typeQuel_t(indice); // pour simplifier + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_typeQuel_t(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + // idem pour la grandeur courante + {TypeQuelconque& TQ = integ_vol_typeQuel(indice); // pour simplifier + // cas des grandeurs à tdt: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_typeQuel(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + // la valeur passée en paramétre est celle de t !! + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); + }; + }; + }; // boucle sur les grandeurs lues + + + // maintenant les intégrales de volume et en temps + ent >> toto; + if (toto != "int_vol_temps_mail") + { cout << "\nErreur : en lecture de l'entete de l'integration de volume et en temps eventuelle" + << " on attendait le mot cle int_vol_temps_mail et on a lu "<< toto <<" !\n"; + cout << "LesMaillages::Lecture_base_info(....)" << flush; + Sortie(1); + }; + int integ_vol_t_typeQuel_taille = 0; + ent >> integ_vol_t_typeQuel_taille; + // on boucle sur les grandeurs à lire + // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée + // mais dans ce cas elle ne changera plus pendant le calcul + for (int i=1;i<= integ_vol_t_typeQuel_taille;i++) + { // on lit l'entête d'un type quelconque + // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes + TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); + TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); + // lecture de l'entête et récup d'enu + // on utilise: avec création, car il peut s'agire d'une intégrale qui n'est plus active + // du coup le tableau exitant ne contient pas cette intégrale + EnuTypeQuelParticulier enu_t = + pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur + // le test se fait uniquement sur le TypeQuelconque_enum_etendu + // qui est supposé suffisant comme signature + int indice_t = integ_vol_t_typeQuel_t.Contient(pour_lire_t); + if (indice_t) + {// là il suffit de lire la grandeur associée + ent >> (*integ_vol_t_typeQuel_t(indice_t).Grandeur_pointee()); + }; + // idem à t + EnuTypeQuelParticulier enu = + pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + int indice = integ_vol_t_typeQuel.Contient(pour_lire); + if (indice) + {// là il suffit de lire la grandeur associée + ent >> (*integ_vol_t_typeQuel(indice).Grandeur_pointee()); + }; + if (!indice) + { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur + // figée, dont la valeur ne changera pas pendant le calcul + // création d'une grandeur associée et lecture des information sur le flot + TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); + // création du type quelconque + TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); + delete grandeur_t; // car il ne sert plus à rien + TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); + // création du type quelconque + TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); + delete grandeur; // car il ne sert plus à rien + // maintenant on va mettre à jour le stockage interne + // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue + // à l'initialisation du .info + indice = integ_vol_t_typeQuel_t.Taille()+1; + integ_vol_t_typeQuel_t.Change_taille(indice); + integ_vol_t_typeQuel.Change_taille(indice); + integ_vol_t_typeQuel(indice) = typQ; + integ_vol_t_typeQuel_t(indice) = typQ_t; + ref_integ_vol_t.Change_taille(indice); + // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est + // figé, car aucun domaine d'intégration n'a été définit + ref_integ_vol_t(indice) = NULL; + }; + // on va créer ou mettre à jour une grandeur globale associée + {TypeQuelconque& TQ_t = integ_vol_t_typeQuel_t(indice); // pour simplifier + TypeQuelconque& TQ = integ_vol_t_typeQuel(indice); // pour simplifier + // transfert des intégrales finalisées + // on considère que les grandeurs à tdt doivent être initialisées à celles de t + (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_t_typeQuel_t(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + // cas des grandeurs à tdt + // integ_vol_t_typeQuel(i) = integ_vol_t_typeQuel_t(i); + + // on va créer ou mettre à jour une grandeur globale associée + {TypeQuelconque& TQ = integ_vol_t_typeQuel(indice); // pour simplifier + // cas des grandeurs à tdt: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_t_typeQuel(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); + }; + }; + }; // boucle sur les grandeurs lues + // déjà fait + // integ_vol_t_typeQuel = integ_vol_t_typeQuel_t; // init + + // ----- cas des statistiques éventuelles----- + // utile pour pouvoir post-traiter et également pour le cumul sur le temps + ent >> toto; + if (toto != "statistique_mail") + { cout << "\nErreur : en lecture de l'entete de statistique eventuelle" + << " on attendait le mot cle statistique_mail et on a lu "<< toto <<" !\n"; + cout << "LesMaillages::Lecture_base_info(....)" << flush; + Sortie(1); + }; + int statistique_typeQuel_taille = 0; + ent >> statistique_typeQuel_taille; + // on boucle sur les grandeurs à lire + // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée + // mais dans ce cas elle ne changera plus pendant le calcul + for (int i=1;i<= statistique_typeQuel_taille;i++) + { // on lit l'entête d'un type quelconque + // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes + TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); + TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); + // lecture de l'entête et récup d'enu + // on utilise: avec création, car il peut s'agir d'une statistique qui n'est plus active + // du coup le tableau existant ne contient pas cette statistique + EnuTypeQuelParticulier enu_t = + pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + int indice_t = statistique_typeQuel_t.Contient(pour_lire_t); + if (indice_t) + {// là il suffit de lire la grandeur associée + ent >> (*statistique_typeQuel_t(indice_t).Grandeur_pointee()); + }; + // normalement le cas a tdt est identique + EnuTypeQuelParticulier enu = + pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur + // le test se fait uniquement sur le TypeQuelconque_enum_etendu + // qui est supposé suffisant comme signature + int indice = statistique_typeQuel.Contient(pour_lire); + if (indice) + {// là il suffit de lire la grandeur associée + ent >> (*statistique_typeQuel(indice).Grandeur_pointee()); + }; + if (!indice) + { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur + // figée, dont la valeur ne changera pas pendant le calcul + // création d'une grandeur associée et lecture des information sur le flot + TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); + // création du type quelconque + TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); + delete grandeur_t; // car il ne sert plus à rien + TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); + // création du type quelconque + TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); + delete grandeur; // car il ne sert plus à rien + + + // maintenant on va mettre à jour le stockage interne + // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue + // à l'initialisation du .info + indice_t = statistique_typeQuel_t.Taille()+1; + indice = statistique_typeQuel.Taille()+1; + statistique_typeQuel_t.Change_taille(indice_t); + statistique_typeQuel.Change_taille(indice); + statistique_typeQuel(indice) = typQ; + statistique_typeQuel_t(indice_t) = typQ_t; + ref_statistique.Change_taille(indice);// normalement c'est le même qu'indice_t + // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est + // figé, car aucune ref de statistique n'a été définie + ref_statistique(indice) = NULL; + }; + // on va créer ou mettre à jour une grandeur globale associée + {TypeQuelconque& TQ_t = statistique_typeQuel_t(indice); // pour simplifier + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans statistique !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&statistique_typeQuel_t(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + // idem pour la grandeur courante + {TypeQuelconque& TQ = statistique_typeQuel(indice); // pour simplifier + // cas des grandeurs à tdt: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans statistique !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&statistique_typeQuel(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + // la valeur passée en paramétre est celle de t !! + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); + }; + }; + }; // boucle sur les grandeurs lues + + // maintenant les statistiques avec cumul en temps + ent >> toto; + if (toto != "statistique_temps_mail") + { cout << "\nErreur : en lecture de l'entete de la statistique avec cumul en temps eventuelle" + << " on attendait le mot cle statistique_temps_mail et on a lu "<< toto <<" !\n"; + cout << "LesMaillages::Lecture_base_info(....)" << flush; + Sortie(1); + }; + int statistique_t_typeQuel_taille = 0; + ent >> statistique_t_typeQuel_taille; + // on boucle sur les grandeurs à lire + // si la grandeur existe déjà, elle est mise à jour, sinon elle est crée + // mais dans ce cas elle ne changera plus pendant le calcul + for (int i=1;i<= statistique_t_typeQuel_taille;i++) + { // on lit l'entête d'un type quelconque + // -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes + TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE); + TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); + // lecture de l'entête et récup d'enu + // on utilise: avec création, car il peut s'agir d'une statistique qui n'est plus active + // du coup le tableau exitant ne contient pas cette statistique + EnuTypeQuelParticulier enu_t = + pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + // là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur + // le test se fait uniquement sur le TypeQuelconque_enum_etendu + // qui est supposé suffisant comme signature + int indice_t = statistique_t_typeQuel_t.Contient(pour_lire_t); + if (indice_t) + {// là il suffit de lire la grandeur associée + ent >> (*statistique_t_typeQuel_t(indice_t).Grandeur_pointee()); + }; + // idem à t + EnuTypeQuelParticulier enu = + pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent); + int indice = statistique_t_typeQuel.Contient(pour_lire); + if (indice) + {// là il suffit de lire la grandeur associée + ent >> (*statistique_t_typeQuel(indice).Grandeur_pointee()); + }; + if (!indice) + { // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur + // figée, dont la valeur ne changera pas pendant le calcul + // création d'une grandeur associée et lecture des information sur le flot + TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent); + // création du type quelconque + TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t); + delete grandeur_t; // car il ne sert plus à rien + TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); + // création du type quelconque + TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); + delete grandeur; // car il ne sert plus à rien + // maintenant on va mettre à jour le stockage interne + // ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue + // à l'initialisation du .info + indice = statistique_t_typeQuel_t.Taille()+1; + statistique_t_typeQuel_t.Change_taille(indice); + statistique_t_typeQuel.Change_taille(indice); + statistique_t_typeQuel(indice) = typQ; + statistique_t_typeQuel_t(indice) = typQ_t; + ref_statistique_t.Change_taille(indice); + // par défaut on met la ref à NULL, ce qui veut dire que la grandeur est + // figé, car aucune ref de noeuds n'a été définie + ref_statistique_t(indice) = NULL; + }; + // on va créer ou mettre à jour une grandeur globale associée + {TypeQuelconque& TQ_t = statistique_t_typeQuel_t(indice); // pour simplifier + TypeQuelconque& TQ = statistique_t_typeQuel(indice); // pour simplifier + // transfert des statistiques finalisées + // on considère que les grandeurs à tdt doivent être initialisées à celles de t + (TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee())); + // cas des grandeurs à t: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + const string* nom_de_ref = g_TG_t->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&statistique_t_typeQuel_t(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t)); + }; + }; + + // on va créer ou mettre à jour une grandeur globale associée + {TypeQuelconque& TQ = statistique_t_typeQuel(indice); // pour simplifier + // cas des grandeurs à tdt: on alimente les grandeurs globales + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans statistique avec cuml en temps !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Lecture_base_info(..."<GrandeurGlobal(*nom_de_ref)); + if (pointe == NULL) + // la grandeur n'existe pas on la définie + ParaGlob::param->Ajout_grandeur_consultable(&statistique_t_typeQuel(indice),*nom_de_ref); + else // sinon on affecte + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + (gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG)); + }; + }; + }; // boucle sur les grandeurs lues + + break; + } + default : + { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n"; + cout << "LesMaillages::Lecture_base_info(....)" + << " cas= " << cas << flush; + Sortie(1); + }; + }; + }; +// écriture base info +// cas donne le niveau de sauvegarde +// = 1 : on sauvegarde tout +// = 2 : on sauvegarde uniquement les données variables (supposées comme telles) +void LesMaillages::Ecriture_base_info(ofstream& sort,const int cas) + { sort << "\n ****les_maillages:_nombre= " << nbMaillageTotal ; + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + tabMaillage(i1)->Ecriture_base_info(sort,cas); + + switch (cas) + { case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- + { // ----- cas des grandeurs intégrés éventuelles----- + // utile pour pouvoir post-traiter et également pour le cumul sur le temps + // 1) les intégrales de volume + sort << "\n\n int_vol_mail "; + int integ_vol_typeQuel_taille = integ_vol_typeQuel.Taille(); + if (integ_vol_typeQuel_taille == 0) + sort << 0; else sort << integ_vol_typeQuel_taille; + sort << " "; + for (int i=1;i<= integ_vol_typeQuel_taille;i++) + // il faut que l'on sauvegarde à t et tdt sinon au restart les grandeurs à tdt n'existe pas + sort << "\n" << integ_vol_typeQuel_t(i) << " "<" + << "\n " + << "\n " + << "\n une suite de maillages " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n "; + // def de Maillage +// SchemaXML_Maillage(sort,niveau); + break; + } + }; + }; + +// ------ informations utiles par exemples pour la visualisation + // retourne les dimensions minis et maxi suivant les axes du repère + // absolu du maillage numéro nbmail (en faite le calcul est fondé + // uniquement sur la position des noeuds du maillage + // le premier vecteur contient les minimums + // le deuxième vecteur contient les maximums +Tableau LesMaillages::Taille_boite(int nbmail) + { + #ifdef MISE_AU_POINT + // vérification que le numéro de maillage est correcte + if (( nbmail <= 0) || (nbmail > nbMaillageTotal)) + { cout << "\n erreur, le numéro de maillage demandé est érroné," + << " nbmail = " << nbmail + << " \n LesMaillages::Taille_boite(int nbmail) " ; + Sortie(1); + } + #endif + return tabMaillage(nbmail)->Taille_boiteMail(); + }; + + // dans le cas ou aucun numéro de maillage n'est fournis + // c'est l'encombrement de tous les maillages qui est fourni +Tableau LesMaillages::Taille_boite() + { if (nbMaillageTotal == 0) + // cas particulier ou aucun maillage n'est définit + { Tableau toto(2); + return toto; + } + // l'objectif est de balayer tous les maillages + // tout d'abord initialisation du tableau de retour sur le premier + // maillage + Tableau tabsortie = tabMaillage(1)->Taille_boiteMail(); + for (int i1 = 2; i1<= nbMaillageTotal; i1++) + { // récupération du tableau calculé + Tableau tabinter = tabMaillage(i1)->Taille_boiteMail(); + // différent tests + int dima = tabsortie(1).Taille(); + for (int it=1;it<=dima;it++) + { if (tabsortie(1)(it) > tabinter(1)(it)) + tabsortie(1)(it) = tabinter(1)(it); + if (tabsortie(2)(it) < tabinter(2)(it)) + tabsortie(2)(it) = tabinter(2)(it); + } + } + // retour + return tabsortie; + }; + + // mise à jour des boites d'encombrements des éléments, qui contiennent des éléments frontières + // et des éléments frontières eux-même +void LesMaillages::Mise_a_jour_boite_encombrement_elem_front(Enum_dure temps) + {for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { // tout d'abord les boites des éléments: on passe en revue tous les éléments + int nbelmax = Nombre_element(i1); + for (int jel = 1; jel <= nbelmax; jel++) + { // récup de l'élément + Element& elem = tabMaillage(i1)->Element_mail(jel); + // on regarde si l'élément contient des éléments frontières + if (elem.Existe_frontiere()) + elem.Boite_encombre_element(temps); + }; + // maintenant on s'occupe des frontières + LaLIST * lisfrontmail = listFrontiere(i1); // pour simplifier + LaLIST ::iterator il,ilfin=lisfrontmail->end(); + for (il=lisfrontmail->begin();il != ilfin; il++) + (*il).Boite_encombrement_frontiere(temps); + }; + }; + +// crée et ramene pour tous les maillages, la liste des éléments qui contiennent chaque noeud +// mis à jour lorsque lors de la création des frontières +const Tableau < const Tableau > *>& LesMaillages::Indice() + { tous_indices.Change_taille(nbMaillageTotal); + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { tous_indices(i1)= &(tabMaillage(i1)->Maillage::Indice());}; + return tous_indices; + }; + +// ----------------------------------------------------- +// | utilitaires de manipulation de maillage |-- +// ----------------------------------------------------- + +// création de maillage quadratiques incomplets à partir de maillages linéaires. +// En fait il y création de maillages identiques aux maillages déjà existants, les éléments qui sont de types +// linéaires sont remplacés par des éléments quadratiques incomplets correspondants. +// Il y a création de références correspondantes +void LesMaillages::CreeMaillagesQuadratiques_a_partir_des_lineaires(LesReferences* lesRef) + { // création de la liste qui sert pour repérer les maillages créés + list tab_lin_vers_comp; + // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter + int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets + for (int im=1;im<=nbMaillageTotal;im++) + if (tabMaillage(im)->Contient_lineaire()) + { nb_final_maillage++; + tab_lin_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage)); + }; + // dans le cas où des maillages linéaires existent, création de nouveaux maillages + nbMaillageTotal = nb_final_maillage; + // on vérifie et augmente éventuellement la taille du nombre de maillage + while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + // maintenant on passe en revue les maillages candidats + list::iterator il,ifin= tab_lin_vers_comp.end(); + for (il=tab_lin_vers_comp.begin();il!=ifin;il++) + { // on commence par créé le futur maillage quadratique à l'identique du maillage linéaire + // original, il y a ici création de nouveau noeud et élément + // on utilise un nouveau nom de maillage construit a partir de l'ancien + string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; + while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { if(ref1->Nbmaille() == (*il).un) + // on a trouvé une référence à considérer + { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille((*il).deux); + list_inter_ref.push_back(ref_nv); + // on intègre la référence dans lesRéférences +// lesRef->Ajout_reference(ref_nv); + } + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques + // complets. Les références sont également transformés en cohérence. + tabMaillage((*il).deux)->Transfo_lin_quadraIncomp(*lesRef); + } + }; + +// création de maillage quadratiques complets à la place des maillages incomplet +// les éléments qui sont de types quadratiques incomplets sont remplacés par des éléments +// quadratiques complets correspondants. +// Il y a création de références correspondantes +void LesMaillages::CreeMaillagesQuadratiquesComplets_a_partir_des_incomplets(LesReferences* lesRef) + { // création de la liste qui sert pour repérer les maillages complets créés + list tab_quadra_inc_vers_comp; + // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter + int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets + for (int im=1;im<=nbMaillageTotal;im++) + if (tabMaillage(im)->Contient_quadratique_incomplet()) + { nb_final_maillage++; + tab_quadra_inc_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage)); + } + // dans le cas où des maillages de quadratiques incomplet existent, création de nouveaux maillages + nbMaillageTotal = nb_final_maillage; + while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + // maintenant on passe en revue les maillages candidats + list::iterator il,ifin= tab_quadra_inc_vers_comp.end(); + for (il=tab_quadra_inc_vers_comp.begin();il!=ifin;il++) + { // on commence par créé le futur maillage complet à l'identique du maillage incomplet + // original, il y a ici création de nouveau noeud et élément + // on utilise un nouveau nom de maillage construit a partir de l'ancien + string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; + while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { if(ref1->Nbmaille() == (*il).un) + // on a trouvé une référence à considérer + { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille((*il).deux); + list_inter_ref.push_back(ref_nv); + // on intègre la référence dans lesRéférences +// lesRef->Ajout_reference(ref_nv); + } + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques + // complets. Les références sont également transformés en cohérence. + tabMaillage((*il).deux)->Transfo_quadraIncomp_quadraComp(*lesRef); + } + }; + +// Affiche les donnees des maillages dans des fichiers dont le nom est construit à partir du nom de +// chaque maillage au format ".her" et ".lis" +// le paramètre optionnel indique le numéro du maillage à afficher, s'il vaut -1, on affiche tous les maillages +void LesMaillages::Affiche_maillage_dans_her_lis(Enum_dure temps,LesReferences &lesRef,int imail) + { if (imail == -1) + {// cas de l'affichage de tous les maillages, on passe en revue les différents maillages + for (int im=1;im<=nbMaillageTotal;im++) + tabMaillage(im)->Affiche_dans_her_lis(lesRef,temps); + } + else + {// cas de l'affichage d'un maillage particulier + if ((imail < 1)||(imail > nbMaillageTotal)) + { cout << "\n erreur dans l'affichage d'un maillage en format .her et .lis" + << "\n le numero propose: " << imail << " de maillage n'existe pas !! " + << "\n LesMaillages::Affiche_maillage_dans_her_lis(LesReferences &lesRef,int imail)"; + Sortie(1); + } + tabMaillage(imail)->Affiche_dans_her_lis(lesRef,temps); + } + }; + +// relocalisation des points milieux des arrêtes des éléments quadratiques +void LesMaillages::RelocPtMilieuMailleQuadra() + { // on passe en revue les différents maillages + for (int im=1;im<=nbMaillageTotal;im++) + tabMaillage(im)->RelocPtMilieuMailleQuadra(); + }; + +// création et ajout d'un nouveau maillage en fonction d'un nom et d'une liste +// d'éléments et de noeuds +// *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments, +// ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé +// >> ramène le numéro du nouveau maillage +int LesMaillages::Creation_nouveau_maillage + (list & li_noeud,list & list_elem,const string& nom_maillage) + { if (ParaGlob::NiveauImpression() >= 4) + cout << " debut de l'ajout d'un nouveau maillage " << flush; + // recherche d'un numéro du maillage + nbMaillageTotal++; + if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + int nbElem= list_elem.size(); + tabMaillage(nbMaillageTotal) = new Maillage (mapNomMail,paraGlob->Dimension() + ,li_noeud,list_elem + ,nbMaillageTotal,nom_maillage); + // indique le nb de maillage pour l'enregistrement des prochaines references + lesRef->NbMaille(nbMaillageTotal); + if (ParaGlob::NiveauImpression() >= 4) + cout << " fin de l'ajout d'un nouveau maillage " << flush; + // retour du numéro de maillage + return nbMaillageTotal; + }; + +// suppression d'un maillage existant +// par défaut, tous les noeuds et éléments du maillage sont supprimés +// si sans_conservation_noeuds_elements est false: les noeuds et les éléments ne sont pas supprimés +// mais ils ne sont plus référencés dans ce maillage ! +void LesMaillages::Suppression_maillage( const string& nom_maillage,const bool sans_conservation_noeuds_elements) +{ // on commence par récupérer le numéro du maillage + int num_mail = NumMaillage(nom_maillage); + if (num_mail != 0 ) // sinon il n'y a rien n'a supprimer + { if (ParaGlob::NiveauImpression() >= 4) + cout << " delet of the mesh " << nom_maillage << flush ; + // on supprime le maillage + // Dans le cas particulier où l'on veut garder les noeuds et éléments, on l'indique au maillage + // avant sa suppression + if(!sans_conservation_noeuds_elements) + tabMaillage(num_mail)->Preparation_destruction_avec_conservation_noeuds_elements(); + delete tabMaillage(num_mail); + // 1) il faut également supprimer les références qui sont relative au maillage que l'on vient de supprimer + // on commence par stocker la liste des ref à supprimer, on ne les supprime pas à la volée + // de manière à ne pas modifier les bornes de l'algo de parcours + // 2) il faut changer de numéro de maillage, toutes les ref qui sont pour les maillages après le maillage supprimé + bool avec_diminution_num_maillage = true; + lesRef->Supprime_tour_lesRef_un_maillage(num_mail,avec_diminution_num_maillage); + // la map des noms + mapNomMail.erase(nom_maillage); + + // -- maintenant il faut que l'on gère tous les tableaux internes qui sont relatifs aux maillages + // on retasse les tableaux + nbMaillageTotal--; + // le tableau de maillage + for (int i = num_mail;i<= nbMaillageTotal;i++) + {tabMaillage(i) = tabMaillage(i+1); + tabMaillage(i)->Change_numero_maillage(i); // changement du numéro de maillage + }; + tabMaillage(nbMaillageTotal+1)=NULL; + // les frontières si elles ont été construite + if (listFrontiere.Taille() != 0) + {for (int i = num_mail;i<= nbMaillageTotal;i++) + {tabMaillage(i) = tabMaillage(i+1); + listFrontiere(i) = listFrontiere(i+1); + tt_noeud_front(i) = tt_noeud_front(i+1); + }; + listFrontiere.Change_taille(nbMaillageTotal); + tt_noeud_front.Change_taille(nbMaillageTotal); + }; + // le nombre de domaine esclave + if (num_mail <= domEsclave ) + // il faut diminuer le nombre d'esclave + domEsclave--; + + }; +}; + + +// création de maillage par extrusion +// Il y a création de références correspondantes +void LesMaillages::CreeMaillageExtrusion2D3D(LesReferences* lesRef) + { // création de la liste qui sert pour repérer les maillages complets créés + list tab_quadra_inc_vers_comp; + // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter + int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets + for (int im=1;im<=nbMaillageTotal;im++) + if (tabMaillage(im)->Contient_quadratique_incomplet()) + { nb_final_maillage++; + tab_quadra_inc_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage)); + } + // dans le cas où des maillages de quadratiques incomplet existent, création de nouveaux maillages + nbMaillageTotal = nb_final_maillage; + while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + // maintenant on passe en revue les maillages candidats + list::iterator il,ifin= tab_quadra_inc_vers_comp.end(); + for (il=tab_quadra_inc_vers_comp.begin();il!=ifin;il++) + { // on commence par créé le futur maillage complet à l'identique du maillage incomplet + // original, il y a ici création de nouveau noeud et élément + // on utilise un nouveau nom de maillage construit a partir de l'ancien + string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; + while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { if(ref1->Nbmaille() == (*il).un) + // on a trouvé une référence à considérer + { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille((*il).deux); + list_inter_ref.push_back(ref_nv); + // on intègre la référence dans lesRéférences +// lesRef->Ajout_reference(ref_nv); + } + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques + // complets. Les références sont également transformés en cohérence. + tabMaillage((*il).deux)->Transfo_quadraIncomp_quadraComp(*lesRef); + } + }; + +// définition interactive de listes de références +void LesMaillages::CreationInteractiveListesRef(LesReferences* lesRef) + { // on récupère le nombre de maillage actuellement actif + int nb_maillages_actifs_initiaux = nbMaillageTotal; + cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; + // on va boucler sur les maillages et définir des ref pour chaque maillages + for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) + tabMaillage(imail)->CreationInteractiveListesRef(lesRef); + }; + +// modification de l'orientation d'éléments +void LesMaillages::Modif_orientation_element(int cas_orientation,LesReferences* lesRef) + { // on récupère le nombre de maillage actuellement actif + int nb_maillages_actifs_initiaux = nbMaillageTotal; + cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; + switch(cas_orientation) + { case 1: case 2: case 3: // cas d'une orientation automatique des maillages: + { // on vérifie et augmente éventuellement la taille du nombre de maillage + while (nbMaillageTotal > nbPortion) + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + + // on va boucler sur les maillages et définir de nouveaux maillages identiques + for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) + { // il y a ici création de nouveau noeud et élément + // on utilise un nouveau nom de maillage construit a partir de l'ancien + int imailnew = imail+nb_maillages_actifs_initiaux; + string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez"; + while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail)); + nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { if(ref1->Nbmaille() == imail) + // on a trouvé une référence à considérer + { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille(imailnew); + list_inter_ref.push_back(ref_nv); + }; + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // on modifie l'orientation du nouveau maillage en fonction du cas + tabMaillage(imailnew)->Modif_orientation_element(cas_orientation,lesRef); + }; + break; + } + case -1: // uniquement vérification + { // on va boucler sur les maillages + for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) + tabMaillage(imail)->Modif_orientation_element(cas_orientation,lesRef); + break; + } + default: + cout << "\n erreur le cas : " << cas_orientation + << " n'est pas actuellement pris en compte" + << "\n LesMaillages::Modif_orientation_element(..."; + Sortie(1); + }; + }; + +// Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe +void LesMaillages::Collapse_element_supperpose(LesReferences* lesRef) +{ // on récupère le nombre de maillage actuellement actif + int nb_maillages_actifs_initiaux = nbMaillageTotal; + cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; + // on vérifie et augmente éventuellement la taille du nombre de maillage + while (nbMaillageTotal > nbPortion) + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + + // on va boucler sur les maillages et définir de nouveaux maillages identiques + for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) + { // il y a ici création de nouveau noeud et élément + // on utilise un nouveau nom de maillage construit a partir de l'ancien + int imailnew = imail+nb_maillages_actifs_initiaux; + string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez"; + while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail)); + nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { if(ref1->Nbmaille() == imail) + // on a trouvé une référence à considérer + { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille(imailnew); + list_inter_ref.push_back(ref_nv); + }; + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // on fusionne les noeuds + tabMaillage(imailnew)->Collapse_element_superpose(lesRef); + }; + +}; + +// collapse de noeuds très proche: appartenant à des éléments différents +// rayon : donne la distance maxi entre les noeuds qui doivent être collapsé +void LesMaillages::Collapse_noeuds_proches(double rayon, LesReferences* lesRef) +{ // on récupère le nombre de maillage actuellement actif + int nb_maillages_actifs_initiaux = nbMaillageTotal; + cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n"; + // on vérifie et augmente éventuellement la taille du nombre de maillage + while (nbMaillageTotal > nbPortion) + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + + // on va boucler sur les maillages et définir de nouveaux maillages identiques + for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++) + { // il y a ici création de nouveau noeud et élément + // on utilise un nouveau nom de maillage construit a partir de l'ancien + int imailnew = imail+nb_maillages_actifs_initiaux; + string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez"; + while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail)); + nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { if(ref1->Nbmaille() == imail) + // on a trouvé une référence à considérer + { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille(imailnew); + list_inter_ref.push_back(ref_nv); + }; + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // on fusionne les noeuds + tabMaillage(imailnew)->Collapse_noeuds_proches(rayon,lesRef); + }; + +}; + +// création d'un nouveau maillage issue de la fusion de maillages existants +// nom_mails_a_fusionner : la liste des maillages à fusionner +// new_mail : le nom du nouveau maillage à construire +// NB: si new_mail correspond à un maillage déjà existant, il y a fusion de ce maillage +// avec les autres, sans création d'un nouveau maillage +void LesMaillages::Fusion_maillages(List_io < string >& nom_mails_a_fusionner,const string& new_mail + ,LesReferences* lesRef) +{ // on va commencer par créer un nouveau maillage + if (ParaGlob::NiveauImpression() >= 4) + cout << " debut d'une operation de fusion de maillage " << flush; + // on regarde s'il s'agit d'une fusion avec un maillage existant ou non: + Maillage* nevez_mail_ = NULL; // est renseigné dans le if suivant + bool creation_nouveau_maillage = false; + if (NumMaillage(new_mail) == 0) + { // le retour est nulle: cas d'un nouveau maillage, on va créer un nouveau maillage + // recherche d'un numéro du maillage + nbMaillageTotal++; + if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + // le premier maillage est vide + int dim = ParaGlob::Dimension(); + tabMaillage(nbMaillageTotal) = new Maillage(mapNomMail,nbMaillageTotal,dim,new_mail); + nevez_mail_ = (tabMaillage(nbMaillageTotal)); // pour simplifier + creation_nouveau_maillage = true; + } + else + { // il s'agit ici d'un maillage qui existe déjà + nevez_mail_ = (tabMaillage(NumMaillage(new_mail))); + }; + // on récupère le maillage de base, qui intègrera les autres + Maillage& nevez_mail = *nevez_mail_; + + // avant de faire l'opération de fusion, on va faire un traitement spécial pour les + // références automatiques E_tout, N_tout, F_tout, A_tout, P_tout, G_tout + {Tableau tab_tout(6); + tab_tout(1) = "E_tout";tab_tout(2) = "N_tout"; tab_tout(3) = "F_tout"; + tab_tout(4) = "A_tout";tab_tout(5) = "P_tout"; tab_tout(6) = "G_tout"; + int idmail = NumMaillage(new_mail); + for (int i=1;i<= 6; i++) + {string& nreftout= tab_tout(i); + if (lesRef->Existe(nreftout,idmail)) + { const Reference& ref1 = lesRef->Trouve(nreftout,idmail); // récup de la ref + Reference* ref2 = ref1.Nevez_Ref_copie(); // on crée une ref identique + string nevez_nom=nreftout+"_1";int num=1; // on cherche un nom qui n'existe pas encore + while (lesRef->Existe(nevez_nom,idmail)) + {nevez_nom += "_"+ChangeEntierSTring(num);num++;}; + ref2->Change_nom(nevez_nom); // change le nom de la nouvelle ref + lesRef->Ajout_reference(ref2); // ajout de la ref + if (ParaGlob::NiveauImpression() > 0) + cout << "\n >>> attention la reference " << nreftout << " du maillage " + << nevez_mail.NomDuMaillage() << " a un nouveau nom "<< nevez_nom; + }; + }; + }; + + // maintenant on va passer en revue tous les maillages à fusionner + List_io < string >::iterator il,ilfin=nom_mails_a_fusionner.end(); + for (il = nom_mails_a_fusionner.begin();il != ilfin;il++) + { // récup du numéro de maillage, + // et éventuellement on passe le maillage identique à new_mail +// debug +//cout << "\n maillage de la liste à fusionner " << (*il) << " newmail= "<& tabN = mail_a_fusion.Tab_noeud(); + int nbN = tabN.Taille();list li_Noe; + for (int i=1;i<=nbN;i++) + li_Noe.push_back(tabN(i)); + // constitution de la liste d'éléments + Tableau& tabE = mail_a_fusion.Tab_element(); + int nbE = tabE.Taille();list li_Elem; + for (int i=1;i<=nbE;i++) + li_Elem.push_back(tabE(i)); + // on récupère les références associées à ce maillage + list lref; // la liste qui contiendra les ref recherchées + const Reference* ref1 = lesRef->Init_et_Premiere(); + // on parcours la liste pour récupérer les ref appartenant au maillage + do { if(ref1->Nbmaille() == num_mail_a_fusion) + // on a trouvé une référence à considérer + {// si l'on est dans le cas de la fusion avec un maillage existant + // on regarde s'il y a déjà une ref avec le même nom dans le maillage + // si oui on change le nom de la ref à ajouter + string ajout="";int num=0; + if (!creation_nouveau_maillage) + {while (lesRef->Existe((ref1->Nom()+ajout),NumMaillage(new_mail))) + {num++;ajout = "_"+ChangeEntierSTring(num); +// debug +//cout << "\n (ref1->Nom()+ajout)" << (ref1->Nom()+ajout) << flush; +// fin debug + + + }; + }; + // on crée la référence à ajouter + Reference* ref2 = ref1->Nevez_Ref_copie(); // on crée une ref identique + ref2->Change_nom(ref1->Nom()+ajout); + lref.push_back(ref2); + // on averti que le nom de la référence a changé + if ((ParaGlob::NiveauImpression() > 0) && (ajout != "")) + cout << "\n >>> attention la reference "<Nom()<<" du maillage " + << mail_a_fusion.NomDuMaillage() << " a un nouveau nom "<< (ref1->Nom()+ajout); +// debug +//cout << "\n ref2= " << ref2->Nom() << " num maille "<< ref2->Nbmaille() << flush; +// fin debug + }; +// debug +//cout << "\n " << ref1->Nom() << " num maille "<< ref1->Nbmaille() << flush; +// fin debug + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + + // appel de la méthode de fusion + nevez_mail.Ajout_elements_et_noeuds(li_Noe,li_Elem,&lref,lesRef); + }; + }; + + if (ParaGlob::NiveauImpression() >= 4) + cout << "\n fin de l'operation de fusion de maillage " << flush; +}; + + +// création d'un nouveau maillage issue d'un maillages existants et d'une ref d'éléments +// le nouveau maillage = les éléments de la ref +void LesMaillages::Cree_sous_maillage(int num_mail,LesReferences* lesRef, string nom_ref,const string& new_mail) +{ // on va commencer par créer un nouveau maillage + if (ParaGlob::NiveauImpression() >= 4) + cout << " debut d'une operation de creation de sous-maillage " << flush; + // on va créer un nouveau maillage + // recherche d'un numéro du maillage + nbMaillageTotal++; + if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + // le premier maillage est vide + int dim = ParaGlob::Dimension(); + // si le nom du nouveau maillage existe déjà, on met nevez en suffixe + string nvnom(new_mail); // init + while (NumMaillage(nvnom)) + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + + // on commence par créé le futur maillage à l'identique du maillage contenant la ref + // originale, il y a ici création de nouveaux noeuds et éléments +// tabMaillage(nbMaillageTotal) = new Maillage(mapNomMail,nbMaillageTotal,dim,nvnom); + tabMaillage(nbMaillageTotal) = new Maillage (mapNomMail,nbMaillageTotal,nvnom,*tabMaillage(nbMaillageTotal-1)); + Maillage* nevez_mail_ = (tabMaillage(nbMaillageTotal)); // pour simplifier + // pour simplifier + Maillage& nevez_mail = *nevez_mail_; + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille(nbMaillageTotal); + list_inter_ref.push_back(ref_nv); + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // puis, pour le nouveau maillage, + // on restreint le maillage aux seuls éléments de la référence passée en paramètre + // toutes les infos relatives à des éléments supprimés, sont également supprimés + nevez_mail.Restreint_sous_maillage(lesRef, nom_ref); + + if (ParaGlob::NiveauImpression() >= 4) + cout << "\n fin de l'operation de creation de sous-maillage " << flush; +}; + +// création d'éléments SFE en fonction d'éléments classiques +void LesMaillages::CreationMaillageSFE() // on passe en revue les différents maillages + { // création de la liste qui sert pour repérer les maillages créés + list tab_tri_vers_sfe; + // tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter + int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets + for (int im=1;im<=nbMaillageTotal;im++) + if (tabMaillage(im)->OKPourTransSfe()) + { nb_final_maillage++; + tab_tri_vers_sfe.push_back(DeuxEntiers(im,nb_final_maillage)); + }; + // dans le cas où des maillages candidats existent, création de nouveaux maillages + nbMaillageTotal = nb_final_maillage; + // on vérifie et augmente éventuellement la taille du nombre de maillage + while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage + { nbPortion = nbPortion+nbEnreg; + tabMaillage.Change_taille(nbPortion); + }; + // maintenant on passe en revue les maillages candidats + list::iterator il,ifin= tab_tri_vers_sfe.end(); + for (il=tab_tri_vers_sfe.begin();il!=ifin;il++) + { // on commence par créer le futur maillage SFE à l'identique du maillage triangulaire + // original, il y a ici création de nouveau noeud et élément + // on utilise un nouveau nom de maillage construit a partir de l'ancien + string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; // init + while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez + // on utilise un nouveau nom de maillage construit a partir de l'ancien + nvnom += "_nevez"; + + tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un)); + // création de références identiques aux cas du maillage initial + const Reference* ref1 = lesRef->Init_et_Premiere(); + list list_inter_ref; // une liste intermédiaire de travail + // l'opération s'effectue en deux temps, car pendant que l'on parcours la liste + // des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours + // 1) donc premier temps on enregistre + do { if(ref1->Nbmaille() == (*il).un) + // on a trouvé une référence à considérer + { // on crée une référence identique + Reference* ref_nv = ref1->Nevez_Ref_copie(); + // on met à jour le numéro de maillage associé + ref_nv->Change_Nbmaille((*il).deux); + list_inter_ref.push_back(ref_nv); + }; + ref1 = lesRef->Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + // 2) deuxième temps on enregistre + list ::iterator kl,klfin=list_inter_ref.end(); + for (kl=list_inter_ref.begin();kl != klfin; kl++) + lesRef->Ajout_reference((*kl)); + // On transforme les éléments triangulaire du nouveau maillage en SFE + // Les références sont conservées, car a priori identiques + tabMaillage((*il).deux)->CreationMaillageSFE(); + } + }; + +// renumérotation des noeuds de tous les maillages en même temps, + prise en compte +// des conditions linéaires qui existent entre les noeuds +// attention, ne peut fonctionner que si les maillages ont des relations entre eux, +//sinon l'arbre de descendance ne sera pas complet !! +// ramène false si rien n'a changé, vrai sinon + // si le pointeur d'assemblage est non nulle, cela veut dire que l'on veut également une mise à jour + // globale des pointeurs d'assemblages (ce qui est différent de la méthode : MiseAJourPointeurAssemblage( + // qui agit maillage après maillage) + // si le pointeur d'assemblage est non nulle et le drapeau: sans_changement_num_noeud = true + // cela signifie que l'on désire uniquement une renumérotation de pointeur sans les noeuds +// ramène dans tous les cas les nouvelles largeurs en ddl +// nouvelles_largeur_en_ddl.un = la largeur totale +// nouvelles_largeur_en_ddl.deux = la demie largeur +// nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis +// uniquement (sans les CLL) + + // ramène dans tous les cas les nouvelles largeurs en ddl + // nouvelles_largeur_en_ddl.un = la largeur totale résultante + // nouvelles_largeur_en_ddl.deux = la demie largeur totale résultante + // nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis + // uniquement (sans les CLL) + // +bool LesMaillages::Renumerotation(LesReferences& lesRef,const Tableau >& tab_condCLL + ,TroisEntiers& nouvelles_largeur_en_ddl + ,const Nb_assemb* nb_casAssemb,bool sans_changement_num_noeud) +{ // pour effectuer la renumérotation il est nécessaire de créer un tableau global de tous les noeuds et + // de tous les éléments, de manière à pouvoir les gérer en même temps + // a1) on calcul les nombres maxi + int nb_noeud = 0; int nb_element = 0; + for (int imail=1;imail<=nbMaillageTotal;imail++) + { nb_noeud += tabMaillage(imail)->Nombre_noeud(); + nb_element += tabMaillage(imail)->Nombre_element(); + }; + // a2) on crée maintenant les éléments frontières car cela utilise les numéros des noeuds, qui vont être changé + // mais ce n'est pas toujours bien de recréer les frontières, car on peut avoir des grandeurs qui dépendent des frontières + // comme par exemple les éléments de contact: si on refait les frontières, il faut refaire les éléments de contact + // or la renumérotation n'a pas à changer les frontières en elles-mêmes + // donc on adopte une création conditionnelle + if ((listFrontiere.Taille() == 0) || (tt_noeud_front.Taille() == 0)) + LesMaillages::CreeElemFront(); // on crée les éléments frontières + + // b) on crée les tableaux + Tableau t_noe(nb_noeud); // le tableau global de noeuds + Tableau t_oldNumNoeud(nb_noeud); // tableau des anciens numéros de noeuds + Tableau t_elem(nb_element); // le tableau global des éléments + // c) on rempli les tableaux en changeant les numéros des noeuds (pour avoir une seule numérotation) + // normalement cela n'influe pas sur les éléments car eux ils contiennent des tableaux de pointeur de noeuds + int numGlobNoeud=1; int numGlobEle = 1; + for (int imil=1;imil<=nbMaillageTotal;imil++) + { int nbn = tabMaillage(imil)->Nombre_noeud(); + Tableau& tab_noeud = tabMaillage(imil)->Tab_noeud(); + for (int inoe = 1; inoe <= nbn; inoe++,numGlobNoeud++) + { t_noe(numGlobNoeud) = tab_noeud(inoe); + t_oldNumNoeud(numGlobNoeud) = tab_noeud(inoe)->Num_noeud(); + t_noe(numGlobNoeud)->Change_num_noeud(numGlobNoeud); + }; + int nb_ele = tabMaillage(imil)->Nombre_element(); + Tableau& tab_element = tabMaillage(imil)->Tab_element(); + for (int iel = 1; iel <= nb_ele; iel++,numGlobEle++) + { t_elem(numGlobEle) = tab_element(iel); + }; + }; + // avant tout changement on calcul la largeur initiale due aux conditions linéaires + // celle-ci n'est valide que dans le cas où tous les noeuds ont des numéros différents + // ce qui est le cas maintenant + int taille_tab_cll = tab_condCLL.Taille(); + int largeur_initiale_CLL = 0; // init + for (int i = 1; i<= taille_tab_cll;i++) + { Tableau & condCLL = tab_condCLL(i); + int taille = condCLL.Taille(); + for (int j=1;j<= taille;j++) + largeur_initiale_CLL=MaX(largeur_initiale_CLL,condCLL(j).DiffMaxiNumeroNoeud()); + }; + if ((ParaGlob::NiveauImpression() > 4) + || ((nb_casAssemb == NULL)&&(ParaGlob::NiveauImpression() > 0)) + ) + { cout << "\n pour l'ensemble des conditions linaires: via une numerotation unique pour tous les maillages, " + << " la 1/2 largeur de bande en noeud initiale est " + << largeur_initiale_CLL << flush; + }; + + + bool nouvelle_numerotation = false; // pour le contrôle de la fin + // on calcul le point de départ + Tableau < LaLIST_io > t_voisin; // def du tableau des voisins des noeuds + list < list < Maillage::Noeud_degre > > lis_descent; // stockage des descendants + bool calcul_ok = false; // init par défaut + Noeud* noe_dep = Maillage::Point_de_depart(t_elem,t_noe,tt_noeud_front,t_voisin,lis_descent,tab_condCLL,calcul_ok); + if (calcul_ok) // on ne continue que si c'est ok + {// on appelle l'algorithme de Cuthill Mac Kee + Tableau tab_N_final = Maillage::Cuthill_Mac_Kee(nb_noeud,noe_dep,t_voisin,lis_descent); + // --- maintenant on regarde l'évolution de la largeur de bande en noeud + // tout d'abord la largeur initiale + int largeur_initiale = Maillage::LargeurBandeEnNoeuds(t_elem); + // on change la numérotation + for (int ia=1;ia <= nb_noeud; ia++) + tab_N_final(ia)->Change_num_noeud(ia); + // nouvelle largeur de bande + int largeur_Cuthill = Maillage::LargeurBandeEnNoeuds(t_elem); + // idem pour les CLL + int largeur_Cuthill_CLL = 0; // init + for (int i = 1; i<= taille_tab_cll;i++) + { Tableau & condCLL = tab_condCLL(i); + int taille = condCLL.Taille(); + for (int j=1;j<= taille;j++) + largeur_Cuthill_CLL=MaX(largeur_Cuthill_CLL,condCLL(j).DiffMaxiNumeroNoeud()); + }; + // on change en numérotation inverse : Cuthill Mac Kee inverse + // car on pense qu'a priori c'est celle-là qui sera la meilleur + ///// Tableau tab_N_inverse(tab_N_final); + for (int ia=1;ia <= nb_noeud; ia++) + {tab_N_final(ia)->Change_num_noeud(1+nb_noeud-ia); + // avec les modifs que j'ai fait après la ligne qui suit ne sert plus ??? + ///// tab_N_inverse(1+nb_noeud-ia) = tab_N_final(ia); + }; + int largeur_Cuthill_inverse = Maillage::LargeurBandeEnNoeuds(t_elem); + // idem pour les CLL + int largeur_Cuthill_inverse_CLL = 0; // init + for (int i = 1; i<= taille_tab_cll;i++) + { Tableau & condCLL = tab_condCLL(i); + int taille = condCLL.Taille(); + for (int j=1;j<= taille;j++) + largeur_Cuthill_inverse_CLL=MaX(largeur_Cuthill_inverse_CLL,condCLL(j).DiffMaxiNumeroNoeud()); + }; + if ((ParaGlob::NiveauImpression() > 3) + || ((nb_casAssemb == NULL)&&(ParaGlob::NiveauImpression() > 0)) + ) + { cout << "\n $$ Premiere etape: optimisation sur l'ensemble des maillages sous forme d'un seul groupe $$ "; + cout << "\n pour l'ensemble des maillages: 1/2 largeur de bande en noeud, initiale= " << largeur_initiale + << "\n partie conditions lineaires initiales : " << largeur_initiale_CLL + << " --> maxi des deux: " << MaX(largeur_initiale_CLL, largeur_initiale) + << " \n apres l'algo de Cuthill Mac Kee= " << largeur_Cuthill + << ", conditions lineaires : " << largeur_Cuthill_CLL + << " --> maxi des deux: " << MaX(largeur_Cuthill_CLL, largeur_Cuthill) + << " \n en Cuthill Mac Kee inverse= " << largeur_Cuthill_inverse + << ", conditions lineaires : " << largeur_Cuthill_inverse_CLL + << " --> maxi des deux: " << MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse)<< flush ; + }; + // normalement le dernier est le meilleur, en tout cas il est meilleur que le cas 2 + + // ----- dernières opérations: on regarde si effectivement il faut appliquer la nouvelle + // ----- numérotation + int demi_largeur_totale=MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse); + + if (MaX(largeur_initiale_CLL, largeur_initiale) + < MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse)) + // if (largeur_initiale < largeur_Cuthill_inverse) + // bizarre, cela veut dire qu'il faut revenir à la forme initiale + { for (int ia=1;ia <= nb_noeud; ia++) + t_noe(ia)->Change_num_noeud(t_oldNumNoeud(ia)); + demi_largeur_totale = MaX(largeur_initiale_CLL, largeur_initiale); + } + else if (MaX(largeur_Cuthill_CLL, largeur_Cuthill) + < MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse) ) + // else if (largeur_Cuthill < largeur_Cuthill_inverse ) + // bizarre, cela veut dire qu'il faut revenir à la forme de Cuthill directe + { nouvelle_numerotation = true; + // on met la numérotation définitive relativement au tableau directe + Tableau num_courant(nbMaillageTotal); // tableau des numéros courant de noeud + // pour chaque maillage + for (int ia=1;ia <= nb_noeud; ia++) + // je ne comprend pas ce que j'ai fait. je modifie en faisant ce que je pense être bon ??? + ////modifié { Noeud* noe = tab_N_final(ia); // pour simplifier + ////modifié int num = (num_courant(noe->Num_Mail())++); + ////modifié noe->Change_num_noeud(num); + ////modifié }; + tab_N_final(ia)->Change_num_noeud(ia); + demi_largeur_totale = MaX(largeur_Cuthill_CLL, largeur_Cuthill); + } + else + // c'est le cas normale + { nouvelle_numerotation=true; + // on met la numérotation définitive relativement au tableau inverse + // là je ne comprend pas ce que j'ai fait, car la numérotation inverse a déjà été faite donc il n'y a rien + // à faire, je comment donc la suite + + //// Tableau num_courant(nbMaillageTotal); // tableau des numéros courant de noeud + //// // pour chaque maillage + //// for (int ia=1;ia <= nb_noeud; ia++) + //// { Noeud* noe = tab_N_inverse(ia); // pour simplifier + //// int num = (num_courant(noe->Num_Mail())++); + //// noe->Change_num_noeud(num); + //// }; + }; + + // on calcule si demandé, la largeur de bande en ddl qui résulte de la nouvelle numérotation + // avant de changer les numéros de noeuds + // et la mise à jour des pointeurs d'assemblages + Tableau tab_N_final_final;// ne sert que pour le cas nb_casAssemb != NULL + if (nouvelle_numerotation && (nb_casAssemb != NULL)) + { // on garde en mémoire la numérotation des noeuds, dans l'ordre de tab_N_final + // car on ne connait pas exactement le cheminement précédent de ce qui est retenue au final + tab_N_final_final.Change_taille(nb_noeud); + for (int i=1;i<=nb_noeud;i++) + tab_N_final_final(tab_N_final(i)->Num_noeud()) = tab_N_final(i); + // on met à jour les pointeurs d'assemblage en suivant le nouvel ordre de noeud + MiseAJourPointeurAssemblage_interne(*nb_casAssemb,tab_N_final_final); + // on calcul la largeur finale + int demi = 0; int total = 0; + int cumule = 0; + // cas des CLL: + for (int i = 1; i<= taille_tab_cll;i++) + { Tableau & condCLL = tab_condCLL(i); + int taille = condCLL.Taille(); + for (int j=1;j<= taille;j++) + condCLL(j).Largeur_Bande(demi,total,*nb_casAssemb); + }; + // on s'occupe des maillages + int demi_pour_mail=0; int total_pour_mail=0; + for (int imil=1;imil<=nbMaillageTotal;imil++) + {int demi_inter=0; int total_inter=0; + tabMaillage(imil)->Largeur_Bande(demi_inter,total_inter,*nb_casAssemb); + demi_pour_mail = MaX(demi_pour_mail,demi_inter); + total_pour_mail =MaX(total_pour_mail,total_inter); + }; + // on garde les maxi + demi = MaX(demi,demi_pour_mail); + total =MaX(total,total_pour_mail); + // enregistrement + nouvelles_largeur_en_ddl.deux = demi; + nouvelles_largeur_en_ddl.un = total; + nouvelles_largeur_en_ddl.trois = demi_pour_mail; + + if (ParaGlob::NiveauImpression() > 2) + cout << "\n $$$ ==>> opti. glob. numerot. $$$ " + << " 1/2 larg. ddl ==> " << demi + << " larg. totale ==> " << total; +//cout << "\n entrer une valeur pour continuer "; +//int toto; cin >> toto; + }; + + // dans le cas d'une nouvelle numérotation + dans le cas où on veut un changement + // de numérotation effectif dans les noeuds + // ->> introduction de la nouvelle numérotation dans les noeuds et mise à jour des reférences + if ((nouvelle_numerotation) && (!sans_changement_num_noeud)) + // il faut donc redéfinir une numérotation pour chaque maillage. Celle-ci + // ne sera pas aussi optimum que dans le cas d'un seul maillage, mais elle devrait + // être meilleure + // -- un tableau d'indice qui donne le nouveau numéro en cours pour chaque maillage + { Tableau num_noeu_par_maillage(nbMaillageTotal,0); + // un nouveau tableau intermédiaire tel que le noeud t_noe_ordonnee(i), a le numéro i + Tableau t_noe_ordonnee(nb_noeud); // le tableau global de noeuds + for (int ia=1;ia <= nb_noeud; ia++) + { Noeud* noe = t_noe(ia); // pour simplifier + t_noe_ordonnee(noe->Num_noeud()) = noe; + }; + // si nouvelle numérotation est vrai, on parcourt le tableau et on renumérote à la volée + // la méthode revient à compresser la numérotation pour chaque maillage de manière a + // rester dans les limites du nombre de noeud pour chaque maillage + for (int ia=1;ia <= nb_noeud; ia++) + { Noeud* noe = t_noe_ordonnee(ia); // pour simplifier + int num_mail = noe->Num_Mail(); + num_noeu_par_maillage(num_mail)++; + ////--debug + //cout << "\n debug LesMaillages::Renumerotation( " + // << "\n num_noeu_par_maillage("<Change_num_noeud(num_noeu_par_maillage(num_mail)); + }; + + // Maintenant on s'occupe des références et de la numérotation définitive + // si on a introduit une nouvelle numérotation + // -- on s'occupe des numéros de référence + // 1) on définit un tableau par maillage qui contient les nouveaux numéros + // t_nv_num(j)(i) est pour le maillage j, le nouveau numéro du noeud + // qui avait auparavant le numéro "i" + Tableau > t_nv_num(nbMaillageTotal); // nouveau num/ au ancien + for (int iml=1; iml<= nbMaillageTotal;iml++) + t_nv_num(iml).Change_taille(tabMaillage(iml)->Nombre_noeud()); // init + for (int ia=1;ia <= nb_noeud; ia++) + { Noeud* noe = t_noe(ia); // pour simplifier, on utilise t_noe et non t_noe_ordonnee + // car ensuite on utilise t_oldNumNoeud qui suit le même ordre que t_noe + // //--debug + // cout << "\n debug LesMaillages::Renumerotation( " + // << "\n noe->Num_Mail()= "<Num_Mail() <<", ia= "<< ia + // << " noe->Num_noeud()= "<Num_noeud() + // << " t_oldNumNoeud(ia)= "<< t_oldNumNoeud(ia) << flush; + ////--- fin debug + t_nv_num(noe->Num_Mail())(t_oldNumNoeud(ia))=noe->Num_noeud(); + }; + // 2) maintenant on change les références + for (int idmail=1;idmail<=nbMaillageTotal;idmail++) + lesRef.Mise_a_jour_ref_noeud(t_nv_num(idmail),idmail); + + // --- on reconstruit les tableaux de pointeurs de noeuds dans chaque maillage + // a) on crée un tableau intermédiaire de tous les tableaux de noeuds + Tableau *> t_t_noeud(nbMaillageTotal); + for (int iml=1; iml<= nbMaillageTotal;iml++) + t_t_noeud(iml) = &(tabMaillage(iml)->Tab_noeud()); // init + // b) on le remplit + for (int ia=1;ia <= nb_noeud; ia++) + { Noeud* noe = t_noe_ordonnee(ia); // pour simplifier + (*t_t_noeud(noe->Num_Mail()))(noe->Num_noeud()) = noe; + }; + }; + + // affichage du résultat et éventuellement deuxième étape concernant le + // changement des pointeurs d'assemblage + if (nouvelle_numerotation) + {if (nb_casAssemb == NULL) // cas sans changement des pointeurs + // si on ne veut pas changer les pointeurs d'assemblage dans la foulée + // on met une information sur la largeur de bande nouvelle, en noeud, + // qui découle de la nouvelle numérotation (et non de l'assemblage) + { + + int largeur_finale_CLL = 0; // init + for (int i = 1; i<= taille_tab_cll;i++) + { Tableau & condCLL = tab_condCLL(i); + int taille = condCLL.Taille(); + for (int j=1;j<= taille;j++) + largeur_finale_CLL=MaX(largeur_finale_CLL,condCLL(j).DiffMaxiNumeroNoeud()); + }; + if (ParaGlob::NiveauImpression() > 0) + { cout << "\n pour l'ensemble des conditions linaires: la 1/2 largeur de bande en noeud, finale est " + << largeur_finale_CLL << flush; + }; + + + + // non c'est débile, car on n'a pas fait de nouvelle numérotation en ddl, donc cela ne sert à rien de les imprimer + // et au niveau de la numérotation en noeud, c'est déja visualisé +/* + int demi = 0; int total = 0; + int cumule = 0; + // on est quand même obligé de considérer un cas d'assemblage, on prend le dernier + // par défaut + // on récupère le nombre actuel de cas d'assemblage + int nb_actuel = tab_nb_assemb; + #ifdef MISE_AU_POINT + if (nb_actuel == 0) + {cout << "\n erreur Renumerotation : pas de cas d'assemblage encore defini !! " + << " la renumerotation n'est pas possible ...."; + Sortie(1); + }; + #endif + Nb_assemb nbAssemble(nb_actuel); + + // cas des CLL: + for (int i = 1; i<= taille_tab_cll;i++) + { Tableau & condCLL = tab_condCLL(i); + int taille = condCLL.Taille(); + for (int j=1;j<= taille;j++) + condCLL(j).Largeur_Bande(demi,total,nbAssemble); + }; + + // on s'occupe des maillages + int demi_pour_mail=0; int total_pour_mail=0; + for (int imil=1;imil<=nbMaillageTotal;imil++) + {int demi_inter=0; int total_inter=0; + tabMaillage(imil)->Largeur_Bande(demi_inter,total_inter,nbAssemble); + demi_pour_mail = MaX(demi_pour_mail,demi_inter); + total_pour_mail =MaX(total_pour_mail,total_inter); + }; + // on garde les maxi + demi = MaX(demi,demi_pour_mail); + total =MaX(total,total_pour_mail); + // enregistrement + nouvelles_largeur_en_ddl.deux = demi; + nouvelles_largeur_en_ddl.un = total; + nouvelles_largeur_en_ddl.trois = demi_pour_mail; + + // affichage du résultat + if (ParaGlob::NiveauImpression() >= 3) + cout << "\n $$$ =>> opti. glob. numerot. $$$ " + << " 1/2 larg. ddl => " << demi + << " larg. totale => " << total + << flush; +*/ + + + + + } + else // sinon c'est le cas où on veut changer les pointeurs d'assemblage + {// deuxième partie pour les pointeurs d'assemblage: + // on doit mettre à jour le tableau t_i_n pour les pointeurs d'assemblage + // concernant uniquement les numéros de noeuds + // --> deux cas suivant que l'on ne veut pas enregistrer la nouvelle numérotation + // des noeuds ou non + if (sans_changement_num_noeud) + { // mise à jour des numéros de noeud, on revient aux numéros initiaux + // on revient au numéro initiaux + for (int i=1;i<=nb_noeud;i++) + t_noe(i)->Change_num_noeud(t_oldNumNoeud(i)); + // pour chaque noeud, tab_N_final(i) correspond au noeud qui avait le numéro i ancien + // et qui a maintenant le numéro tab_N_final(i)->Num_noeud() + // mise à jour de t_i_n + MiseAJourTableau_t_i_n(*nb_casAssemb,tab_N_final_final); + } + else + {MiseAJourTableau_t_i_n(*nb_casAssemb,tab_N_final_final); + }; + }; + } + else + {// on remet néanmoins l'ancienne numérotation, car elle a changé + int nbN = t_noe.Taille(); + for (int i=1;i<=nbN;i++) + t_noe(i)->Change_num_noeud(t_oldNumNoeud(i)); + if (ParaGlob::NiveauImpression() >= 3) + cout << "\n $$$ au final numerot. idem $$$ " << flush; + nouvelle_numerotation = false; + calcul_ok = true; + }; + + }; + // retour + return (calcul_ok && nouvelle_numerotation); + + }; + +// renumérotation des noeuds maillages par maillage, +// === sans prise en compte de conditions linéaires === +// en sortie les maillages sont mis à jour si la nouvelle numérotation conduit à une largeur de bande +// plus faible que la largeur initiale: en noeuds +// ramène: false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure) +// vrai sinon +bool LesMaillages::Renumerotation(LesReferences& lesRef) +{ // on crée les éléments frontières car cela utilise les numéros des noeuds, qui vont être changé + // mais ce n'est pas toujours bien de recréer les frontières, car on peut avoir des grandeurs + // qui dépendent des frontières + // comme par exemple les éléments de contact: si on refait les frontières, + // il faut refaire les éléments de contact + // or la renumérotation n'a pas à changer les frontières en elles-mêmes + // donc on adopte une création conditionnelle + if ((listFrontiere.Taille() == 0) || (tt_noeud_front.Taille() == 0)) + LesMaillages::CreeElemFront(); // on crée les éléments frontières + + // on passe en revue tous les maillages pour une renumérotation individuelle + bool calcul_ok = false; // init par défaut + + Tableau > condCLL; // un tableau vide pour l'appel + for (int imail=1;imail<=nbMaillageTotal;imail++) + { if (ParaGlob::NiveauImpression() > 2) + cout << "\n ===>> traitement du maillage: " << tabMaillage(imail)->NomDuMaillage(); + bool inter = tabMaillage(imail)->Renumerotation(lesRef,condCLL); + calcul_ok = calcul_ok || inter; + }; + + // retour + return calcul_ok ; + }; + +// indique aux éléments un niveau de précision de calcul désiré pour les prochains calculs +// precision = 0 : aucune précision demandée, precision >=0 : précision maximale demandée +void LesMaillages::Drapeau_preparation_calcul_precis(int precision) + {for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbelmax = Nombre_element(i1); + Maillage* maillage = tabMaillage(i1); // pour simplifier + for (int jel = 1; jel <= nbelmax; jel++) + { maillage->Element_mail(jel).Drapeau_preparation_calcul_precis(precision);}; + }; + }; + +// on s'occupe de mettre à jour les types de pb et les ddl types associés +void LesMaillages::Mise_a_jour_type_pb_type_associe_ddl() +{ types_de_problemes.clear(); + ddl_representatifs_des_physiques.clear(); + for (int i = 1; i<= nbMaillageTotal; i++) + { + {//const list & type_pb = (tabMaillage(i))->Types_de_problemes(); // pour simplifier + const Tableau & type_pb = (tabMaillage(i))->Types_de_problemes(); // pour simplifier +// list ::const_iterator il,ilfin=type_pb.end(); +// for (il=type_pb.begin();il != ilfin;il++) + int taill = type_pb.Taille(); + for (int j=1;j<=taill;j++) + if (find(types_de_problemes.begin(),types_de_problemes.end(),type_pb(j)) == types_de_problemes.end()) + types_de_problemes.push_back(type_pb(j));//(*il); + }; + {//const list & type_ddl = (tabMaillage(i))->Ddl_representatifs_des_physiques(); // pour simplifier + //list ::const_iterator il,ilfin=type_ddl.end(); + //for (il=type_ddl.begin();il != ilfin;il++) + const Tableau & type_ddl = (tabMaillage(i))->Ddl_representatifs_des_physiques(); // pour simplifier + int taill = type_ddl.Taille(); + for (int j=1;j<=taill;j++) + if (find(ddl_representatifs_des_physiques.begin(),ddl_representatifs_des_physiques.end() + ,type_ddl(j)) == ddl_representatifs_des_physiques.end()) + ddl_representatifs_des_physiques.push_back(type_ddl(j)); + }; + }; + types_de_problemes.sort(); types_de_problemes.unique(); + ddl_representatifs_des_physiques.sort(); ddl_representatifs_des_physiques.unique(); +}; + + // --- utilitaires pour calculs particuliers------- + +// Tableau integ_vol_typeQuel, integ_vol_typeQuel_t; +// Tableau ref_integ_vol; // les références associées +// // 2) intégration de volume et en temps: donc on commule le delta +// Tableau integ_vol_t_typeQuel, integ_vol_t_typeQuel_t; +// Tableau ref_integ_vol_t; // les références associées +// LesReferences* lesRef; // references + + +// calcul des diverses intégrations: volume et volume + temps, +// alimentation des grandeurs globales associées +void LesMaillages::Integration() +{ // on passe en revue les références de volumes a intégrer +// Tableau ref_integ_vol; // les références associées + + // les références sont ordonnées par apparition dans le fichier .info + // des intégrales, ceci permet de repérer les bonnes grandeurs à cummuler + int taill = ref_integ_vol.Taille(); + for (int rang_integ =1;rang_integ<= taill;rang_integ++) + if (ref_integ_vol(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas + // l'intégrale stockée reste fixe pendant le calcul + { const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol(rang_integ)); + // initialisation du conteneur relatif à chaque ref + TypeQuelconque& TQ = integ_vol_typeQuel(rang_integ); // pour simplifier + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + g_TG->InitParDefaut(); // on initialise le conteneur + + // cumule des valeurs: on récupère les infos à partir des éléments concernés + int ref_Taille=ref->Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref->Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // demande a l'element des infos + const Tableau * tab_Q = poi->Integ_vol_typeQuel(); + const Tableau & index_integ = *(poi->Index_Integ_vol_typeQuel()); + // la grandeur à cumuler c'est celle qui a le bon indexe + int indice = index_integ.Contient(rang_integ); + *(g_TG) += *((*tab_Q)(indice).Grandeur_pointee()); + +// -- les deux lignes d'avant sont a priori équivalentes aux lignes qui suivent +// int nb_integ = tab_Q->Taille(); // le nombre d'intégrale à considérer +// for (int iteg = 1;iteg <= nb_integ;iteg++) +// {if ((index_integ)(iteg)==rang_integ) // si l'index est négatif, on ne cumule pas +// // cela veut aussi dire que l'intégrale est figée +// // sinon si on a le bon index: on cumule l'intégrale +// {*(g_TG) += *((*tab_Q)(iteg).Grandeur_pointee()); +// break; +// }; +// }; + + }; + // maintenant il s'agit d'alimenter les grandeurs globales + + // on récupère le pointeur correspondant à la grandeur correspondant au nom + // de référence + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Integration()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'integration !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::Integration()"<Nom_ref() +// << " :: " << *(g_TG) << flush; +// +//// -- fin debug + + + + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + *(gr_quelc->Grandeur_pointee()) = *(g_TG); + }; + // même chose pour les intégrales en volume et en temps + int taill1 = ref_integ_vol_t.Taille(); + for (int rang_integ =1;rang_integ<= taill1;rang_integ++) + if (ref_integ_vol_t(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas + // l'intégrale stockée reste fixe pendant le calcul + { const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol_t(rang_integ)); + // initialisation du conteneur relatif à chaque ref + TypeQuelconque& TQ = integ_vol_t_typeQuel(rang_integ); // pour simplifier + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + g_TG->InitParDefaut(); // on initialise le conteneur + + // cumule des valeurs: on récupère les infos à partir des éléments concernés + int ref_Taille=ref->Taille(); + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref->Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // demande a l'element des infos + const Tableau * tab_Q = poi->Integ_vol_t_typeQuel(); + const Tableau & index_integ = *(poi->Index_Integ_vol_t_typeQuel()); + // la grandeur à cumuler c'est celle qui a le bon indexe + int indice = index_integ.Contient(rang_integ); + *(g_TG) += *((*tab_Q)(indice).Grandeur_pointee()); + + +// -- les deux lignes d'avant sont a priori équivalentes aux lignes qui suivent +// int nb_integ = tab_Q->Taille(); // le nombre d'intégrale à considérer +// for (int iteg = 1;iteg <= nb_integ;iteg++) +// {if ((index_integ)(iteg)==rang_integ) +// // sinon si on a le bon index: on cumule l'intégrale +// {*(g_TG) += *((*tab_Q)(iteg).Grandeur_pointee()); +// break; +// }; +// }; + }; + // maintenant il s'agit d'alimenter les grandeurs globales + + // on récupère le pointeur correspondant à la grandeur correspondant au nom + // de référence + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans l'integration !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::Integration()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans l'integration !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::Integration()"<Grandeur_pointee()) = *(g_TG); + }; +}; + + +// calcul des diverses statistiques sur des ref de noeuds et avec éventuellement +// cumul sur le temps +// alimentation des grandeurs globales associées +void LesMaillages::CalStatistique() +{ // on passe en revue les références de noeud des statistiques + {// Tableau ref_statistique; // les références associées + int NB_ref = ref_statistique.Taille(); + if (NB_ref) + {// on boucle sur les ref + for (int i_ref =1;i_ref<= NB_ref;i_ref++) + if (ref_statistique(i_ref) != NULL) // si null cela veut que l'on ne fait rien + // la statistique stockée reste fixe pendant le calcul + { const ReferenceNE * ref = ((ReferenceNE *) ref_statistique(i_ref)); + // initialisation du conteneur relatif à chaque ref + TypeQuelconque& TQ = statistique_typeQuel(i_ref); // pour simplifier + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + g_TG->InitParDefaut(); // on initialise le conteneur + + int ref_Taille=ref->Taille(); + int i_mail = ref->Nbmaille(); // le numero du maillage + + Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier + Fonction_nD* fct = gr.Fct(); // récupération d'un pointeur de fonction nD + + // différent choix + if (fct == NULL) + { // cas d'un stockage pour ddl_etendu + Ddl_enum_etendu& ddl_enu_eten = pour_statistique_de_ddl(i_ref);// récup du ddl + // on veut : (1) la somme, (2) la moyenne, (3) le max, (4) le min, (5) le max des | | , (6) le min des | | + // tab_val(k) : la grandeur k + // tab_index(k) : k= 1 -> le numéro du noeud pour le max + // k= 2 -> le numéro du noeud pour le min + // k= 3 -> le numéro du noeud pour le max des | | + // k= 4 -> le numéro du noeud pour le min des | | + + // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) + Vecteur& t10 = (gr.ConteneurVecteur()); + t10(4)=t10(6)=ConstMath::tresgrand; // on met les mini très grand + // t10(i), i=7 à 10 --> correspond aux numéros de noeud, stockés en double au lieu de int + // == tab_index(k) + // ceci pour utiliser uniquement un seul conteneur global + double& tab_pour_MAXI_1 = t10(7); + double& tab_pour_MAXI_2 = t10(8); + double& tab_pour_MAXI_3 = t10(9); + double& tab_pour_MAXI_4 = t10(10); + + // on regarde s'il s'agit d'un ddl pur ou étendu + if (ddl_enu_eten.Nom_vide()) + // cas d'un ddl pur + {// récup de l'énumération + Enum_ddl enu = ddl_enu_eten.Enum(); + // cumule des valeurs: on récupère les infos à partir des noeuds concernés + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage + // récupération du Noeud + Noeud& noe = Noeud_LesMaille(i_mail,nbb); + // récup de la valeur du ddl + double val_du_ddl = 0.; // init + if (noe.Existe_ici(enu)) + {val_du_ddl = noe.Ddl_noeud_tdt(enu).Valeur();} + #ifdef MISE_AU_POINT + else + {if (ParaGlob::NiveauImpression() >= 4) + {if (ParaGlob::Francais()) + {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() + << " n'est pas disponible pour statistique, on met 0 a la place";} + else + {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() + << " is not available for statistic, the value will be 0 ";}; + }; + }; + #endif + // le calcul des grandeurs + t10(1) += val_du_ddl; + t10(2) += 1.; // on s'en sert ici comme compteur + int num_noeud = noe.Num_noeud(); + if (t10(3) < val_du_ddl) + { t10(3) = val_du_ddl; + tab_pour_MAXI_1 = num_noeud; + }; + if (t10(4) > val_du_ddl) + { t10(4) = val_du_ddl; + tab_pour_MAXI_2 = num_noeud; + }; + if (Dabs(t10(5)) < Dabs(val_du_ddl)) + { t10(5) = val_du_ddl; + tab_pour_MAXI_3 = num_noeud; + }; + if (Dabs(t10(6)) > Dabs(val_du_ddl)) + { t10(6) = val_du_ddl; + tab_pour_MAXI_4 = num_noeud; + }; + }; + // calcul de la moyenne + t10(2) = t10(1) / t10(2); + } + else // cas d'un ddl étendu + {// cumule des valeurs: on récupère les infos à partir des noeuds concernés + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage + // récupération du Noeud + Noeud& noe = Noeud_LesMaille(i_mail,nbb); + // récup de la valeur du ddl + double val_du_ddl = 0.; // init + // on examine tout d'abord le cas particulier des positions + bool trouver = false; + // on regarde d'abord s'il s'agit d'une info spécifique au contact + int posi = ddl_enu_eten.Position()-NbEnum_ddl(); + switch (posi) + { case 123: // "X1_t" + { val_du_ddl = noe.Coord1()(1);trouver=true; break;} + case 124: // "X2_t" + { val_du_ddl = noe.Coord1()(2);trouver=true; break;} + case 125: // X3_t + { val_du_ddl = noe.Coord1()(3);trouver=true; break;} + case 126: // X1_t0 + { val_du_ddl = noe.Coord0()(1);trouver=true; break;} + case 127: // X2_t0 + { val_du_ddl = noe.Coord0()(2);trouver=true; break;} + case 128: // X3_t0 + { val_du_ddl = noe.Coord0()(3);trouver=true; break;} + default: ;// rien + }; + // si ce n'était pas un cas particulier on continue la recherche + if (!trouver) + // on regarde si la grandeur existe + {if (noe.Existe_ici_ddlEtendu(ddl_enu_eten)) + {val_du_ddl = noe.DdlEtendue(ddl_enu_eten).ConstValeur();} + #ifdef MISE_AU_POINT + else + {if (ParaGlob::NiveauImpression() >= 4) + {if (ParaGlob::Francais()) + {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() + << " n'est pas disponible pour statistique, on met 0 a la place";} + else + {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() + << " is not available for statistic, the value will be 0 ";}; + }; + }; + #endif + }; + // le calcul des grandeurs + t10(1) += val_du_ddl; + t10(2) += 1.; // on s'en sert ici comme compteur + int num_noeud = noe.Num_noeud(); + if (t10(3) < val_du_ddl) + { t10(3) = val_du_ddl; + tab_pour_MAXI_1 = num_noeud; + }; + if (t10(4) > val_du_ddl) + { t10(4) = val_du_ddl; + tab_pour_MAXI_2 = num_noeud; + }; + if (Dabs(t10(5)) < Dabs(val_du_ddl)) + { t10(5) = val_du_ddl; + tab_pour_MAXI_3 = num_noeud; + }; + if (Dabs(t10(6)) > Dabs(val_du_ddl)) + { t10(6) = val_du_ddl; + tab_pour_MAXI_4 = num_noeud; + }; + }; + // calcul de la moyenne + t10(2) = t10(1) / t10(2); + } + ////------- debug --------- +// cout << "\n debug statistique: "; +// cout << t10; + // + // + ////------- fin debug -------- + + } + else // cas d'un stockage pour fonction nD + { Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier + Fonction_nD* fct = gr.Fct(); // récupération de la fonction nD + // supposons que la fonction nD ramène n valeurs, + // pour chaque valeur on va avoir pour la valeur i : + // ((6*(i-1)+1) la somme, ((6*(i-1)+2) la moyenne, ((6*(i-1)+3) le max, ((6*(i-1)+4) le min, + // ((6*(i-1)+5) -> le numéro du noeud pour le max, ((6*(i-1)+6) -> le numéro du noeud pour le min, + // donc en tout cela donne 6*n valeurs + // ensuite on a: + // (6*n + 1) le max des | |, (6*n + 2) le min des | |, + // (6*n + 3) -> le numéro du noeud pour le max des | | + // (6*n + 4) -> le numéro du noeud pour le min des | | + // d'où un vecteur de taille (6*n + 4) + + // on commence par récupérer les conteneurs des grandeurs à fournir + + List_io & li_enu_scal = fct->Li_enu_etendu_scalaire(); + List_io & li_quelc = fct->Li_equi_Quel_evolue(); + int nb_composante = fct->NbComposante(); + + // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) + Vecteur& t6 = (gr.ConteneurVecteur()); + t6(4)=t6(6)=ConstMath::tresgrand; // on met les mini très grand + + // cumule des valeurs: on récupère les infos à partir des noeuds concernés + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage + // récupération du Noeud + Noeud& noe = Noeud_LesMaille(i_mail,nbb); + + // récupération d'une liste d'info + // le tableau de retour à la taille de li_enu_scal et contient + // les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud + // en fait ici on cumule les ddl pur "et" les ddl_étendue, + // li_quelc : est modifié par les valeurs contenues au noeud + Tableau tab = noe.Valeur_multi_et_Tensorielle(li_enu_scal,li_quelc); + // récup des valeurs de la fonction + Tableau & t_ret = fct->Valeur_FnD_Evoluee(&tab,&li_enu_scal,&li_quelc,NULL,NULL); + int num_noeud = noe.Num_noeud(); + // le calcul des grandeurs sur chaque composante + double norme=0; + for (int i=1;i<= nb_composante;i++) + { int decal = 6*(i-1); + double val_composante = t_ret(i); + t6(decal+1) += val_composante; + t6(decal+2) += 1.; // on s'en sert ici comme compteur + if (t6(decal+3) < val_composante) + { t6(decal+3) = val_composante; + t6(decal+5) = num_noeud; + }; + if (t6(decal+4) > val_composante) + { t6(decal+4) = val_composante; + t6(decal+6) = num_noeud; + }; + norme +=val_composante*val_composante; + }; + // on traite la norme + int decal = 6*nb_composante; + norme = sqrt(norme); + if (t6(decal+1) < norme) + { t6(decal+1) = norme; + t6(decal+3) = num_noeud; + }; + if (t6(decal+2) > norme) + { t6(decal+2) = norme; + t6(decal+4) = num_noeud; + }; + }; + // on calcule les moyennes + for (int i=1;i<= nb_composante;i++) + { int decal = 6*(i-1); + t6(decal+2) = t6(decal+1)/t6(decal+2); + }; + }; + + // maintenant il s'agit d'alimenter les grandeurs globales + + // on récupère le pointeur correspondant à la grandeur correspondant au nom + // de référence + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans le transfert d'une statistique !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::CalStatistique()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans le transfert d'une statistique !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::CalStatistique()"<Grandeur_pointee()) = *(g_TG); + + }; + + }; // fin de la boucle sur les ref + }; + + // idem pour l'accumulation en temps + {// Tableau ref_statistique_t; // les références associées + int NB_ref = ref_statistique_t.Taille(); + if (NB_ref) + {// on boucle sur les ref + for (int i_ref =1;i_ref<= NB_ref;i_ref++) + if (ref_statistique_t(i_ref) != NULL) // si null cela veut que l'on ne fait rien + // la statistique stockée reste fixe pendant le calcul + { const ReferenceNE * ref = ((ReferenceNE *) ref_statistique_t(i_ref)); + // initialisation du conteneur relatif à chaque ref + TypeQuelconque& TQ = statistique_t_typeQuel(i_ref); // pour simplifier + TypeQuelconque& TQ_t = statistique_t_typeQuel_t(i_ref); // le précédent + // le conteneur qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee(); + g_TG->InitParDefaut(); // on initialise le conteneur + + int ref_Taille=ref->Taille(); + int i_mail = ref->Nbmaille(); // le numero du maillage + + Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier + Fonction_nD* fct = gr.Fct(); // récupération d'un pointeur de fonction nD + + // le conteneur à t qui contient le résultat globalisé + TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee(); + Grandeur_Vecteur_Nommer& gr_t = *((Grandeur_Vecteur_Nommer*) g_TG_t); + + // différent choix + if (fct == NULL) + { // cas d'un stockage pour ddl_etendu + Ddl_enum_etendu& ddl_enu_eten = pour_statistique_t_de_ddl(i_ref);// récup du ddl + // on veut : (1) la somme, (2) la moyenne, (3) le max, (4) le min, (5) le max des | | , (6) le min des | | + // tab_val(k) : la grandeur k + // tab_index(k) : k= 1 -> le numéro du noeud pour le max + // k= 2 -> le numéro du noeud pour le min + // k= 3 -> le numéro du noeud pour le max des | | + // k= 4 -> le numéro du noeud pour le min des | | + + // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) + Vecteur& t10 = (gr.ConteneurVecteur()); + t10(4)=t10(6)=ConstMath::tresgrand; // on met les mini très grand + // t10(i), i=7 à 10 --> correspond aux numéros de noeud, stockés en double au lieu de int + // == tab_index(k) + // ceci pour utiliser uniquement un seul conteneur global + double& tab_pour_MAXI_1 = t10(7); + double& tab_pour_MAXI_2 = t10(8); + double& tab_pour_MAXI_3 = t10(9); + double& tab_pour_MAXI_4 = t10(10); + + // on regarde s'il s'agit d'un ddl pur ou étendu + if (ddl_enu_eten.Nom_vide()) + // cas d'un ddl pur + {// récup de l'énumération + Enum_ddl enu = ddl_enu_eten.Enum(); + // cumule des valeurs: on récupère les infos à partir des noeuds concernés + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage + // récupération du Noeud + Noeud& noe = Noeud_LesMaille(i_mail,nbb); + // récup de la valeur du ddl + double val_du_ddl = 0.; // init + // on regarde si la grandeur existe + if (noe.Existe_ici(enu)) + {val_du_ddl = noe.Ddl_noeud_tdt(enu).Valeur();} + #ifdef MISE_AU_POINT + else + {if (ParaGlob::NiveauImpression() >= 4) + {if (ParaGlob::Francais()) + {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() + << " n'est pas disponible pour statistique cumulee, on met 0 a la place";} + else + {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() + << " is not available for statistic cumuled, the value will be 0 ";}; + }; + }; + #endif + // le calcul des grandeurs + t10(1) += val_du_ddl; + t10(2) += 1.; // on s'en sert ici comme compteur + int num_noeud = noe.Num_noeud(); + if (t10(3) < val_du_ddl) + { t10(3) = val_du_ddl; + tab_pour_MAXI_1 = num_noeud; + }; + if (t10(4) > val_du_ddl) + { t10(4) = val_du_ddl; + tab_pour_MAXI_2 = num_noeud; + }; + if (Dabs(t10(5)) < Dabs(val_du_ddl)) + { t10(5) = val_du_ddl; + tab_pour_MAXI_3 = num_noeud; + }; + if (Dabs(t10(6)) > Dabs(val_du_ddl)) + { t10(6) = val_du_ddl; + tab_pour_MAXI_4 = num_noeud; + }; + }; + // calcul de la moyenne + t10(2) = t10(1) / t10(2); + // cumule sur le temps + Vecteur& t10_t = (gr_t.ConteneurVecteur()); + t10(1) += t10_t(1); t10(2) += t10_t(2); + t10(3) += t10_t(3); t10(4) += t10_t(4); + t10(5) += t10_t(5); t10(6) += t10_t(6); + } + else // cas d'un ddl étendu + {// cumule des valeurs: on récupère les infos à partir des noeuds concernés + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage + // récupération du Noeud + Noeud& noe = Noeud_LesMaille(i_mail,nbb); + // récup de la valeur du ddl + double val_du_ddl = 0.; // init + // on examine tout d'abord le cas particulier des positions + bool trouver = false; + // on regarde d'abord s'il s'agit d'une info spécifique au contact + int posi = ddl_enu_eten.Position()-NbEnum_ddl(); + switch (posi) + { case 123: // "X1_t" + { val_du_ddl = noe.Coord1()(1);trouver=true; break;} + case 124: // "X2_t" + { val_du_ddl = noe.Coord1()(2);trouver=true; break;} + case 125: // X3_t + { val_du_ddl = noe.Coord1()(3);trouver=true; break;} + case 126: // X1_t0 + { val_du_ddl = noe.Coord0()(1);trouver=true; break;} + case 127: // X2_t0 + { val_du_ddl = noe.Coord0()(2);trouver=true; break;} + case 128: // X3_t0 + { val_du_ddl = noe.Coord0()(3);trouver=true; break;} + default: ;// rien + }; + // si ce n'était pas un cas particulier on continue la recherche + if (!trouver) + {if (noe.Existe_ici_ddlEtendu(ddl_enu_eten)) + {val_du_ddl = noe.DdlEtendue(ddl_enu_eten).ConstValeur();} + #ifdef MISE_AU_POINT + else + {if (ParaGlob::NiveauImpression() >= 4) + {if (ParaGlob::Francais()) + {cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein() + << " n'est pas disponible pour statistique cumulee, on met 0 a la place";} + else + {cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein() + << " is not available for statistic cumuled, the value will be 0 ";}; + }; + }; + #endif + }; + // le calcul des grandeurs + t10(1) += val_du_ddl; + t10(2) += 1.; // on s'en sert ici comme compteur + int num_noeud = noe.Num_noeud(); + if (t10(3) < val_du_ddl) + { t10(3) = val_du_ddl; + tab_pour_MAXI_1 = num_noeud; + }; + if (t10(4) > val_du_ddl) + { t10(4) = val_du_ddl; + tab_pour_MAXI_2 = num_noeud; + }; + if (Dabs(t10(5)) < Dabs(val_du_ddl)) + { t10(5) = val_du_ddl; + tab_pour_MAXI_3 = num_noeud; + }; + if (Dabs(t10(6)) > Dabs(val_du_ddl)) + { t10(6) = val_du_ddl; + tab_pour_MAXI_4 = num_noeud; + }; + }; + // calcul de la moyenne + t10(2) = t10(1) / t10(2); + // cumule sur le temps + Vecteur& t10_t = (gr_t.ConteneurVecteur()); + t10(1) += t10_t(1); t10(2) += t10_t(2); + t10(3) += t10_t(3); t10(4) += t10_t(4); + t10(5) += t10_t(5); t10(6) += t10_t(6); + }; + // ensuite on cumule sur le temps + + ////------- debug --------- + //cout << "\n debug statistique: "; + //cout << t10; + // + // + ////------- fin debug -------- + + } + else // cas d'un stockage pour fonction nD + { Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier + Fonction_nD* fct = gr.Fct(); // récupération de la fonction nD + // supposons que la fonction nD ramène n valeurs, + // pour chaque valeur on va avoir pour la valeur i : + // ((6*(i-1)+1) la somme, ((6*(i-1)+2) la moyenne, ((6*(i-1)+3) le max, ((6*(i-1)+4) le min, + // ((6*(i-1)+5) -> le numéro du noeud pour le max, ((6*(i-1)+6) -> le numéro du noeud pour le min, + // donc en tout cela donne 6*n valeurs + // ensuite on a: + // (6*n + 1) le max des | |, (6*n + 2) le min des | |, + // (6*n + 3) -> le numéro du noeud pour le max des | | + // (6*n + 4) -> le numéro du noeud pour le min des | | + // d'où un vecteur de taille (6*n + 4) + + // on commence par récupérer les conteneurs des grandeurs à fournir + List_io & li_enu_scal = fct->Li_enu_etendu_scalaire(); + List_io & li_quelc = fct->Li_equi_Quel_evolue(); + int nb_composante = fct->NbComposante(); + + // t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k) + Vecteur& t6 = (gr.ConteneurVecteur()); + t6(4)=t6(6)=ConstMath::tresgrand; // on met les mini très grand + + // cumule des valeurs: on récupère les infos à partir des noeuds concernés + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage + // récupération du Noeud + Noeud& noe = Noeud_LesMaille(i_mail,nbb); + + // récupération d'une liste d'info + // le tableau de retour à la taille de li_enu_scal et contient + // les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud + // en fait ici on cumule les ddl pur "et" les ddl_étendue, + // li_quelc : est modifié par les valeurs contenues au noeud + Tableau tab = noe.Valeur_multi_et_Tensorielle(li_enu_scal,li_quelc); + // récup des valeurs de la fonction + Tableau & t_ret = fct->Valeur_FnD_tab_scalaire(&tab); + int num_noeud = noe.Num_noeud(); + // le calcul des grandeurs sur chaque composante + double norme=0; + for (int i=1;i<= nb_composante;i++) + { int decal = 6*(i-1); + double val_composante = t_ret(i); + t6(decal+1) += val_composante; + t6(decal+2) += 1.; // on s'en sert ici comme compteur + if (t6(decal+3) < val_composante) + { t6(decal+3) = val_composante; + t6(decal+5) = num_noeud; + }; + if (t6(decal+4) > val_composante) + { t6(decal+4) = val_composante; + t6(decal+6) = num_noeud; + }; + norme +=val_composante*val_composante; + }; + // on traite la norme + int decal = 6*nb_composante; + norme = sqrt(norme); + if (t6(decal+1) < norme) + { t6(decal+1) = norme; + t6(decal+3) = num_noeud; + }; + if (t6(decal+2) > norme) + { t6(decal+2) = norme; + t6(decal+4) = num_noeud; + }; + }; + + // on calcule les moyennes et on cumule dans le temps + // pour les composantes i + Vecteur& t6_t = (gr_t.ConteneurVecteur()); + for (int i=1;i<= nb_composante;i++) + { int decal = 6*(i-1); + t6(decal+2) = t6(decal+1)/t6(decal+2); + // le cumul dans le temps + t6(decal+1) += t6_t(decal+1);t6(decal+2) += t6_t(decal+2); + t6(decal+3) += t6_t(decal+3);t6(decal+4) += t6_t(decal+4); + }; + // idem pour les normes + int decal = 6*nb_composante; + t6(decal+1) += t6_t(decal+1) ; t6(decal+2) += t6_t(decal+2); + }; + + // maintenant il s'agit d'alimenter les grandeurs globales + + // on récupère le pointeur correspondant à la grandeur correspondant au nom + // de référence + const string* nom_de_ref = g_TG->Nom_ref(); + #ifdef MISE_AU_POINT + if (nom_de_ref == NULL) + { cout << "\n *** pb dans le transfert d'une statistique cumulee !! " + << " nom_de_ref est nul, on ne peut pas continuer " + << "\n LesMaillages::CalStatistique()"<GrandeurGlobal(*nom_de_ref)); + #ifdef MISE_AU_POINT + if (pointe == NULL) + { cout << "\n *** pb dans le transfert d'une statistique cumulee !! " + << " la variable globale "<< (*nom_de_ref) + << ", n'est pas disponible, on ne peut pas continuer " + << "\n LesMaillages::CalStatistique()"<Grandeur_pointee()) = *(g_TG); + + }; + + }; // fin de la boucle sur les ref + }; + +}; + + // mise à jour des repères d'anisotropie +void LesMaillages::Mise_a_jour_repere_anisotropie + (DiversStockage* divers,LesFonctions_nD* lesFonctionsnD) + { // l'idée est d'éviter de stocker les infos déjà présentes dans DiversStockage ... + // on reprend le caneva de la méthode LesMaillages::Completer + // par contre on considère que tous les dimensionnements sont corrects + // cas de la définition de repère d'anisotropie + int divers_TabRepAnisotrope_Taille=divers->TabRepAnisotrope().Taille(); + for (int ii=1;ii<= divers_TabRepAnisotrope_Taille;ii++) + { string nomRepAnisotrope = (divers->TabRepAnisotrope())(ii).NomRef(); // recup du nom de la ref + const BlocDdlLim& div_TabRepAnisotrope = (divers->TabRepAnisotrope())(ii); + const Reference & refG = lesRef->Trouve(nomRepAnisotrope,div_TabRepAnisotrope.NomMaillage()); // recup de la reference + const ReferenceNE & ref = (ReferenceNE &) refG; + int ref_Taille=ref.Taille(); + // creation d'un bloc general contenant des informations + // n= nombre de string, m nombre de double + BlocGen bloc(5,0) ; // par defaut + string nom_inter("repere_anisotropie_"); + bloc.Change_nom(1,nom_inter); // le mot clé + // ensuite le type l'identificateur de repere + bloc.Change_nom(2,div_TabRepAnisotrope.Nom(2)); + // ensuite le type de repere + bloc.Change_nom(3,div_TabRepAnisotrope.Nom(3)); + // puis la méthode de définition du repère + bloc.Change_nom(4,div_TabRepAnisotrope.Nom(4)); + // un string qui contient le nom de la fonction nD + bloc.Change_nom(5,div_TabRepAnisotrope.Nom(6)); + // puis on alimente les éléments concernés par ces calculs +////--- debug +//cout << "\n -- debug LesMaillages::Completer( "; +//bloc.Affiche(); cout << endl; +////--- fin debug + for (int jj= 1; jj<= ref_Taille; jj++) + {int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage + int nnn = ref.Nbmaille(); // le numero du maillage + // recup de l'element + Element * poi = & Element_LesMaille(nnn,nbb); + // demande a l'element de se completer + poi->Mise_a_jour_repere_anisotropie(bloc,lesFonctionsnD); + }; + }; + + + }; + + + // initialisation par défaut de tous les conteneurs aux noeuds + // de tous les maillages + // contenant li_restreinte_TQ et li_restreinte_ddl + // ces conteneurs sont supposés déjà existés + // typiquement si le conteneurs est un scalaire, on met 0 +void LesMaillages::Init_par_defaut_conteneurs(List_io < TypeQuelconque >& li_restreinte_TQ + ) + {List_io < TypeQuelconque >::iterator il,ilfin=li_restreinte_TQ.end(); + + for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + // on parcours la liste + for (il = li_restreinte_TQ.begin(); il != ilfin;il++) + {TypeQuelconque_enum_etendu enuTypeQuelconque = (*il).EnuTypeQuelconque(); + TypeQuelconque& tyqN = noo->ModifGrandeur_quelconque(enuTypeQuelconque); + tyqN.Grandeur_pointee()->InitParDefaut(); + }; + } + } + }; + +// idem pour une seule grandeur +void LesMaillages::Init_par_defaut_conteneurs(TypeQuelconque_enum_etendu enuTypeQuelconque) + {for (int i1 = 1; i1<= nbMaillageTotal; i1++) + { int nbnoeudmax = tabMaillage(i1)->Nombre_noeud(); + for (int i2 = 1; i2 <= nbnoeudmax; i2++) + { // recup du noeud + Noeud * noo = & Noeud_LesMaille(i1,i2); + TypeQuelconque& tyqN = noo->ModifGrandeur_quelconque(enuTypeQuelconque); + tyqN.Grandeur_pointee()->InitParDefaut(); + + }; + }; + }; + + + + + + + + + + diff --git a/Maillage/Maillage.cc b/Maillage/Maillage.cc new file mode 100755 index 0000000..f67dcd8 --- /dev/null +++ b/Maillage/Maillage.cc @@ -0,0 +1,2649 @@ +// FICHIER : Maillage.cp +// CLASSE : Maillage + +// This file is part of the Herezh++ application. +// +// The finite element software Herezh++ is dedicated to the field +// of mechanics for large transformations of solid structures. +// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) +// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . +// +// Herezh++ is distributed under GPL 3 license ou ultérieure. +// +// Copyright (C) 1997-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 "Maillage.h" +# include +using namespace std; //introduces namespace std +#include +#include "Sortie.h" +#include +#include +#include "List_io.h" +#include "CharUtil.h" +#ifndef SYSTEM_MAC_OS_X_unix + #include "Frontier.h" +#endif +#include "ConstMath.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" +#include "MvtSolide.h" +#include "TypeQuelconqueParticulier.h" + +// CONSTRUCTEURS : +// pour tous les constructeurs: map < string, int , std::less >* lisNomMail, +// est un tableau associatif nom <=> numéro de maillage, qui est utilisé par +// les maillages, mais mis à jour par chaque maillage. +// nom_maill : est facultatif, s'il est différent de ".", il est pris en compte comme nom de maillage + +// Constructeur par defaut +Maillage::Maillage (map < string, int , std::less > & lisNomMail,int nmail,int dim + ,const string& nom_maill): + listeNomMail(lisNomMail),nomDuMaillage(),idmail(nmail),dimension(dim) + ,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front(),indice() + , list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element() + ,ddl_representatifs_des_physiques(),types_de_problemes() + , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif + ,detruire_les_noeuds_et_elements(true) + + { if (nom_maill == ".") + {// tout d'abord on donne un nom par défaut au maillage + nomDuMaillage = "pas_de_nom"; + while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) + { // on cherche un nom quelconque qui n'est pas déjà utilisé + nomDuMaillage += '_'; + }; + } + else // le paramètre de nom de maillage est valide + { nomDuMaillage = nom_maill; + }; + // maintenant on associe le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + }; + +// Constructeur fonction d'une dimension, du nombre de noeuds +// du nombre d'elements, et d'un numero d'identification (le nb de maillage) +Maillage::Maillage (map < string, int , std::less > & lisNomMail + ,int dim,int n_noeud,int n_elt,int nmail,const string& nom_maill): +// Constructeur utile quand la dimension, le nombre de noeuds +// et le nombre d'elements du maillage sont connus + listeNomMail(lisNomMail),tab_noeud(n_noeud),tab_element(n_elt),listFrontiere(),tab_noeud_front() + ,indice(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element() + ,ddl_representatifs_des_physiques(),types_de_problemes() + , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif + ,detruire_les_noeuds_et_elements(true) + +{if (nmail <=0) + { cout << "\nErreur : numero de maillage invalide !\n"; + cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n"; + Sortie(1); + }; + idmail = nmail; + // traitement du nom de maillage + if (nom_maill ==".") + {// on donne un nom par défaut au maillage + nomDuMaillage = "pas_de_nom"; + while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) + { // on cherche un nom quelconque qui n'est pas déjà utilisé + nomDuMaillage += '_'; + }; + } + else // le paramètre de nom de maillage est valide + { nomDuMaillage = nom_maill; + }; + // maintenant on associe le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + + if ( (dim<1) || (dim>3) ) + { cout << "\nErreur : dimension invalide !\n"; + cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n"; + Sortie(1); + }; + if ( n_noeud<=0 ) + { cout << "\nErreur : nombre de noeuds non valide !\n"; + cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n"; + Sortie(1); + }; + if ( n_elt<=0 ) + { cout << "\nErreur : nombre d'elements invalide !\n"; + cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n"; + Sortie(1); + }; + dimension=dim; +}; + + +// Constructeur fonction de la plupart des informations (qui peuvent être vide +// mais doivent être cohérentes) +// *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments, +// ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé +Maillage::Maillage (map < string, int , std::less > & lisNomMail + ,int dim,list & li_noeud, list li_element + ,int nmail,const string& nom_maill ): + listeNomMail(lisNomMail),tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front() + ,indice(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element() + ,ddl_representatifs_des_physiques(),types_de_problemes() + , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif + ,detruire_les_noeuds_et_elements(true) + +{ if (ParaGlob::NiveauImpression() >= 5) + cout << " \n creation du maillage: " << nom_maill << endl; + if (nmail <=0) + { cout << "\nErreur2 : numero de maillage invalide !\n"; + cout << "MAILLAGE::MAILLAGE( ) \n"; + Sortie(1); + }; + // si le numéro de maillage est déjà utilisé, on signale que la place est prise + for (std::map< string, int , std::less >::iterator it=listeNomMail.begin(); + it!=listeNomMail.end(); ++it) + { if ((it->second) == nmail) + { cout << "\n *** erreur: le numero de maillage "<first) + << "\n constructeur: Maillage::Maillage (..."<< flush; + Sortie(1); + }; + }; + // sinon c'est ok + idmail = nmail; + // traitement du nom de maillage + if (nom_maill ==".") + {// on donne un nom par défaut au maillage + nomDuMaillage = "pas_de_nom"; + while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) + { // on cherche un nom quelconque qui n'est pas déjà utilisé + nomDuMaillage += '_'; + }; + } + else // le paramètre de nom de maillage est valide + { nomDuMaillage = nom_maill; + }; + // maintenant on associe le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + + if ( (dim<1) || (dim>3) ) + { cout << "\nErreur2 : dimension invalide !\n"; + cout << "MAILLAGE::MAILLAGE(... \n"; + Sortie(1); + }; + dimension=dim; + // récupération des noeuds + int nbN = li_noeud.size(); + list ::iterator il,ilfin=li_noeud.end(); + Change_nb_noeud(nbN); +// tab_noeud.Change_taille(nbN,NULL); + // on vérifie que la numérotation est correcte pour les noeuds + // c'est-à-dire que tous les numéros peuvent être rangés à suivre + bool numerotation_correcte = true; + for (il=li_noeud.begin();il!=ilfin;il++) + {int nb = (*il)->Num_noeud(); + if (nb<1 || nb > nbN) + {numerotation_correcte=false; + break; + }; + }; + if (numerotation_correcte) + {// on peut y aller sans vérif + for (il=li_noeud.begin();il!=ilfin;il++) + tab_noeud((*il)->Num_noeud()) = *il; + } + else + // on est obligé de changer la numérotation des noeuds + {int nb=1; + for (il=li_noeud.begin();il!=ilfin;il++,nb++) + {tab_noeud(nb) = *il;int nbinit=(*il)->Num_noeud(); + (*il)->Change_num_noeud(nb); + if (ParaGlob::NiveauImpression() > 0) + {cout << "\n warning : le numero initial du noeud " << nbinit << " est remplace par " + << " le numero d'ordre attribue automatiquement par herezh " << nb + << "\n seul ce dernier sera utilise par la suite ! " << endl; + if (ParaGlob::NiveauImpression() > 5) + cout << "\n Maillage::Maillage (map < string, int ,.... " << endl; + }; + }; + }; + // récupération des éléments + int nbE = li_element.size(); + list ::iterator ile,ilefin=li_element.end(); + Change_nb_element(nbE); + // on vérifie que la numérotation est correcte pour les éléments (comme pour les noeuds) + // c'est-à-dire que tous les numéros peuvent être rangés à suivre + numerotation_correcte = true; + for (ile=li_element.begin();ile!=ilefin;ile++) + {int nb = (*ile)->Num_elt(); + if (nb<1 || nb > nbE) + {numerotation_correcte=false; + break; + }; + }; + if (numerotation_correcte) + {// on peut y aller sans vérif + for (ile=li_element.begin();ile!=ilefin;ile++) + tab_element((*ile)->Num_elt()) = *ile; + } + else + // on est obligé de changer la numérotation des éléments + {int nb=1; + for (ile=li_element.begin();ile!=ilefin;ile++,nb++) + {tab_element(nb) = *ile;int nbinit=(*ile)->Num_elt(); + (*ile)->Change_num_elt(nb); + if (ParaGlob::NiveauImpression() > 0) + {cout << "\n warning : le numero initial de l'element " << nbinit << " est remplace par " + << " le numero d'ordre attribue automatiquement par herezh " << nb + << "\n seul ce dernier sera utilise par la suite ! " << endl; + if (ParaGlob::NiveauImpression() > 5) + cout << "\n Maillage::Maillage (map < string, int ,.... " << endl; + }; + }; + }; + // on modifie le numéro de maillage pour les noeuds et éléments + int NBN_P1 = tab_noeud.Taille()+1; + for (int nn=1;nn < NBN_P1;nn++) + tab_noeud(nn)->Change_num_Mail(idmail); + int NBE_P1 = tab_element.Taille()+1; + for (int ne=1;ne < NBE_P1;ne++) + tab_element(ne)->Change_num_maillage(idmail); + + if (ParaGlob::NiveauImpression() >= 5) + cout << " \n fin creation du maillage: " << nom_maill << endl; +}; + +// Constructeur de copie, cependant ici il n'y a pas de création de noeud ni d'élément +// c'est seulement une création de nouveaux conteneurs de pointeurs +// d'autre part le numéro de maillage et le nom de maillage n'est pas valide, il faut +// ensuite les définir +Maillage::Maillage (const Maillage& mail): + listeNomMail(mail.listeNomMail),idmail(mail.idmail),nomDuMaillage(mail.nomDuMaillage),dimension(mail.dimension) + ,tab_noeud(mail.tab_noeud),tab_element(mail.tab_element) + ,listFrontiere(mail.listFrontiere),tab_noeud_front(mail.tab_noeud_front) + ,indice(),list_refIn(),list_refOut(),lesRefin(NULL) + ,mitoyen_de_chaque_element(mail.mitoyen_de_chaque_element) + ,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques) + ,types_de_problemes(mail.types_de_problemes) + , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif + ,detruire_les_noeuds_et_elements(true) + + { // tout d'abord on donne un nom par défaut au maillage + nomDuMaillage = "pas_de_nom"; + while (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) + { // on cherche un nom quelconque qui n'est pas déjà utilisé + nomDuMaillage += '_'; + }; + // maintenant on associe le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + }; + +// Constructeur de copie, avec création de nouveaux noeuds et éléments identiques à ceux passées +// en argument, nmail: donne le numéro du nouveau maillage créée, qui est donc a priori différent +// de celui de mail, idem pour le nom du maillage +// les frontières ne sont pas transmises ni calculées ! ni les normales, +// ni les infos concernant les intégrales (qui sont propres aux maillages existants) +Maillage::Maillage (map < string, int , std::less > & lisNomMail + ,int nmail, const string& nomDu,const Maillage& mail): + listeNomMail(lisNomMail),idmail(nmail),nomDuMaillage(nomDu),dimension(mail.dimension) + ,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front() + ,indice(),list_refIn(),list_refOut(),lesRefin(NULL) + ,mitoyen_de_chaque_element() + ,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques) + ,types_de_problemes(mail.types_de_problemes) + , ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif + ,detruire_les_noeuds_et_elements(true) +{ // on vérifie que le nom de maillage fourni n'existe pas + if (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) + { cout << "\n erreur, le nom de maillage demande existe deja : " << nomDuMaillage + << "\n Maillage::Maillage (....."; + Sortie(1); + }; + // on vérifie que le numéro de maillage proposé est valide + if (idmail <=0) + { cout << "\nErreur : numero de maillage invalide ! = "<< idmail <<"\n"; + cout << "MAILLAGE::MAILLAGE(.... \n"; + Sortie(1); + }; + // maintenant on associe le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + // on s'occupe tout d'abord des noeuds + int nbn = mail.tab_noeud.Taille(); + Change_nb_noeud(nbn); + for (int ino=1;ino<= nbn;ino++) + { tab_noeud(ino) = new Noeud(*(mail.tab_noeud(ino))); + tab_noeud(ino)->Change_num_Mail(nmail); + }; + // maintenant les éléments + int nbe = mail.tab_element.Taille(); + Change_nb_element(nbe); + for (int ie=1;ie<=nbe;ie++) + { tab_element(ie) = mail.tab_element(ie)->Nevez_copie(); +//debug +//tab_element(ie)->Affiche(1); cout << endl; +//fin debug + // on réaffecte les noeuds du maillage + Tableau& ttab = tab_element(ie)->Tab_noeud(); + int ttabtaille=ttab.Taille(); + for (int ine=1;ine<=ttabtaille;ine++) + ttab(ine)=tab_noeud(ttab(ine)->Num_noeud()); + // on change le numéro de maillage + tab_element(ie)->Change_num_maillage(idmail); + }; + // dans le cas où mail.mitoyen_de_chaque_element n'est pas vide, + // on construit le nouveau + if (mail.mitoyen_de_chaque_element.Taille() != 0) + Calcul_tous_les_front_et_leurs_mitoyens(); +}; + +Maillage::~Maillage() +// Destructeur +{ if ( detruire_les_noeuds_et_elements) // cas normal + { for (int i=1;i<= tab_noeud.Taille();i++) + delete tab_noeud(i); + for (int i=1;i<= tab_element.Taille();i++) + delete tab_element(i); + }; + // pas de destruction de tab_noeud_front car ce sont des noeuds de tab_noeud, ils sont déjà détruit + }; + + +void // lecture d'un maillage et def des references s'y rapportant +Maillage::LectureMaillage(UtilLecture * entreePrinc,LesReferences& lesRef) +{ if (ParaGlob::NiveauImpression() >= 5) cout << " debut de lecture de maillage " << endl; + if (ParaGlob::NiveauImpression() >= 6) cout << " lecture du nom de maillage " << endl; + // cas où il y a un nom de maillage + if (strstr(entreePrinc->tablcar,"nom_maillage")!=NULL) + { +// // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant +// listeNomMail.erase(listeNomMail.find(nomDuMaillage)); +// modif le 14 avril 2015 + // non c'est une mauvaise idée, il faut au contraire arrêter le programme et dire qu'il y a + // deux fois le même nom, par contre si le nom de maillage c'est "pas_de_nom" il faut le supprimer + if ((nomDuMaillage == "pas_de_nom") && (listeNomMail.find(nomDuMaillage) != listeNomMail.end())) + listeNomMail.erase(listeNomMail.find(nomDuMaillage)); + + string toto; + *(entreePrinc->entree) >> toto >> nomDuMaillage; + + if (listeNomMail.find(nomDuMaillage) != listeNomMail.end()) + {cout << "\n erreur *** plusieurs maillages ont le meme nom : "<< nomDuMaillage + << " \n revoir les noms de maillage !! " << endl; + Sortie(1); + }; + // maintenant on associe le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + // ensuite lecture de l'entête des noeuds + entreePrinc->NouvelleDonnee(); + if (strstr(entreePrinc->tablcar,"noeuds")==NULL) + { cout << " *** erreur dans la lecture des noeuds " + << " \n LectureMaillage(... " << endl; + entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + } + else + // on définit un nom apriori uniquement dans le cas d'un seul maillage + // sinon c'est une erreur + { if (idmail ==1) + { // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant + listeNomMail.erase(listeNomMail.find(nomDuMaillage)); + nomDuMaillage = "premier_maillage"; + // maintenant on associe le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + } + else + { cout << "\n Erreur dans la lecture du maillage " << idmail <<" ****** "; + cout << "\n il n'y a pas de nom de maillage alors que c'est obligatoire !! " + << " \n LectureMaillage(... " << endl; + entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie (1); + }; + }; + + //------------- lecture des noeuds ------------- + // lecture du nombre de noeud + if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des noeuds " << endl; + entreePrinc->NouvelleDonnee(); + if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre de noeud " << endl ; + int nbNoeud; // nombre de noeud + *(entreePrinc->entree) >> nbNoeud; // lecture dans le flot memoire + if (ParaGlob::NiveauImpression() >= 8) cout << nbNoeud << endl ; + Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud + #ifdef ETUDIANT_LIMITATION + if (nbNoeud > nb_maxi_noeud) + { cout << "\n nombre maxi de noeud autorisé atteind " << nb_maxi_noeud; + Sortie(1); + }; + #endif + // lecture des noeuds + Noeud * ptr; + for (int i=1; i<= nbNoeud; i++) + { entreePrinc->NouvelleDonnee(); + ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage + if (ParaGlob::NiveauImpression() == 10) cout << "n:" << i << " " << flush ; + // lecture du noeud + ptr->Lecture(entreePrinc); + Affectation_noeud(*ptr); + }; + // -------------- lecture des references se rapportant aux noeuds --------- + entreePrinc->NouvelleDonnee(); + if (strstr(entreePrinc->tablcar,"elements")==NULL) + // cas où les références sont mises aprés les noeuds, dans ce cas c'est + // des références de noeud + { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references de noeuds " << endl; + lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds + lesRef.NbMaille(idmail); // indic le numéro de maillage aux références + lesRef.Lecture(*entreePrinc); + }; + + // ------------ lecture des elements ----------- + // lecture du nombre d'element + int nbElement=0; // nombre d'element null par défaut + if (strstr(entreePrinc->tablcar,"elements")!=NULL) // cas avec element + { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des elements du maillage " << endl ; + entreePrinc->NouvelleDonnee(); + if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre d'element " << endl ; + *(entreePrinc->entree) >> nbElement; + if (ParaGlob::NiveauImpression() >= 8) cout << nbElement << endl ; + #ifdef ETUDIANT_LIMITATION + if (nbElement > nb_maxi_element) + { cout << "\n nombre maxi d'element autorise atteind " << nb_maxi_element; + Sortie(1); + }; + #endif + // dimensionnement dynamique du tableau d'elements + Change_nb_element(nbElement); + // Lecture des elements + Element * ptr; + for (int i=1; i<= nbElement; i++) + { // lecture geometrie et interpolation + entreePrinc->NouvelleDonnee(); + if (ParaGlob::NiveauImpression() == 10) cout << "e:" << i << " " << flush ; + // def des énumérations de travail + int num_elt = i; // numéro interne de l'élément + int num_elt_lue; // numéro lue + Enum_geom id_geom; Enum_interpol id_interpol;EnumElemTypeProblem id_typeProb; + // cas d'info annexe + string str_precision(""); // stockage info annexe de choix, initié à rien par défaut + // lectures des infos pour le choix d'un élément + Lecture_info_1element(entreePrinc,num_elt_lue,id_geom,id_interpol,id_typeProb,str_precision); + if (num_elt_lue != num_elt) + { if (ParaGlob::NiveauImpression() > 0) + {cout << "\n warning : le numero de l'element lue " << num_elt_lue << " est different du numero " + << " d'ordre attribue automatiquement par herezh " << num_elt + << "\n seul ce dernier sera utilise pour les resultats ! " << endl; + }; + }; + // ======== choix de l'element ===================================== + // et affectation du pointeur d'element en fonction de id_geom et id_interpol + // le numero d'element : num_elt, est affecte a l'element pointe par ptr + ptr = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision); + if (ptr == NULL) + { // l'operation a echouee + cout << "\n Erreur dans le choix d'element ****** "; + cout << "\n l\'element : " << Nom_interpol(id_interpol) + << " " << Nom_geom(id_geom) + << " n\'est pas present dans le programme ! " << endl; + entreePrinc->MessageBuffer("** lecture d'un element **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie (1); + }; + // lecture des infos particulieres a l'element + Tableau * pt = & tab_noeud; + ptr->LectureDonneesParticulieres(entreePrinc,pt); + Affectation_element(*ptr); + // si c'est le premier élément du premier maillage on regarde s'il s'agit + // d'un élément axisymétrique et on adapte l'espace de travail en conséquence + if ((i==1) && (idmail==1)) + { if (TestEnum_geom_axisymetrique(id_geom)) + ParaGlob::Change_en_AxiSymetrie(); + } + else + {// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent + if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie())) + {cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail + << " nom= " << nomDuMaillage; + if (ParaGlob::AxiSymetrie()) + cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)" + << " et l'element lu est axisymetrique !! "; + else + cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)" + << " et l'element lu n'est pas axisymetrique !! "; + cout << endl; + Sortie (1); + }; + }; + } + } + else + { if (ParaGlob::NiveauImpression() >= 6) + cout << " cas de la lecture d'un maillage SANS elements " << endl; // cas sans element + }; + + // -------------- lecture des references se rapportant aux elements --------- + // ou aux arête ou aux faces et meme eventuellement à des noeuds + if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references apres les elements " << endl ; + entreePrinc->NouvelleDonnee(); + lesRef.NbMaille(idmail); // indic le numéro de maillage aux références + lesRef.Indic("rien_actuellement"); // indic que les prochaines references seront + // a déterminer en fonction du nom de la référence + lesRef.Lecture(*entreePrinc); + // -------------- ajout de références globales --------------------- + // ---- création de la référence de tous les éléments si elle n'existe pas déjà + string etout("E_tout"); + if (!lesRef.Existe(etout,idmail) && (nbElement != 0)) + { // on construit le tableau des numéros des éléments + Tableau tabE(nbElement); for (int i=1;i<=nbElement;i++) tabE(i)=i; + ReferenceNE* retout = new ReferenceNE(tabE,idmail,2,etout);// construction de la référence + lesRef.Ajout_reference(retout); // ajout de la ref, qui est maintenant géré par lesRef + }; + // ---- dans tous les cas on ajoute la référence de tous les noeuds dans le cas où elle n'existe pas + string ntout("N_tout"); + if (!lesRef.Existe(ntout,idmail)) + { // on construit le tableau des numéros de noeuds + Tableau tabN(nbNoeud); for (int i=1;i<=nbNoeud;i++) tabN(i)=i; + ReferenceNE* rtout = new ReferenceNE(tabN,idmail,1,ntout);// construction de la référence + lesRef.Ajout_reference(rtout); // ajout de la ref, qui est maintenant géré par lesRef + }; + if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture de maillage " << endl; + // ----- on s'occupe maintenant de définir les types de pb gérés ------ + Mise_a_jour_type_pb_type_associe_ddl(); +}; + +// lecture et application des opérations d'affinages sur le maillage: ex:déplacement solide +void Maillage::LectureEtApplicationAffinage(UtilLecture * entreePrinc,LesReferences& lesRef) +{ + if (ParaGlob::NiveauImpression() >= 5) cout << " lecture affinage maillage " << endl; + + while ( (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL) + || (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL) + || (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL) + || (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL) + || (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL) + || (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL) + || (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL) + || (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL) + ) + { + // -------------- lecture éventuelle et application de mouvements rigides ------------------ + Lecture_des_mouvements_solides(entreePrinc); + + // --------------- suppression éventuelle des noeuds, non référencés par les éléments ------ + LectureEtSuppressionNoeudNonReferencer(entreePrinc,lesRef); + + // --------------- création éventuelle d'une référence sur les noeuds, non référencés par les éléments ------ + LectureEtCreationRefNoeudNonReferencer(entreePrinc,lesRef); + + // --------------- éventuellement collapse de noeuds proches ------------------------ + LectureEtCollapse_noeuds_proches(entreePrinc,&lesRef); + + // --------------- éventuellement collapse d'éléments supperposés ------------------- + LectureEtCollapse_element_superpose(entreePrinc,&lesRef); + + // -------------- éventuellement suppression d'elements à 2 noeuds, de distances très proches + LectureEtSup_Elem_noeudsConfondu(entreePrinc,&lesRef); + + //---------------- création automatique des références globales de frontière si demandé ---------- + CreationRefFrontiere(entreePrinc,lesRef); + +//----- debug +//{ // on écrit la connection de l'élément 55 +// Element* el = tab_element(55); +// const Tableau& tabi = el->Tab_noeud_const(); +// cout << "\n *** connection de l'element 55: avant renumerotation "; +// for (int i=1;i<=tabi.Taille();i++) cout << " "<Num_noeud(); +// cout << " Maillage::LectureMaillage () " << endl; +//} +//---fin debug + // --------------- renumérotation éventuelle des noeuds ------------------------------------ + LectureEtRenumerotation(entreePrinc,lesRef); +////----- debug +//{ // on écrit la connection de l'élément 55 +// Element* el = tab_element(55); +// const Tableau& tabi = el->Tab_noeud_const(); +// cout << "\n *** connection de l'element 55: après renumerotation "; +// for (int i=1;i<=tabi.Taille();i++) cout << " "<Num_noeud(); +// cout << " Maillage::LectureMaillage () " << endl; +// Sortie(1); +//} +////---fin debug + }; + + // ----------------- vérification que toutes les références de noeuds, d'éléments, d'arêtes et de faces sont valides + // c-a-d se réfèrent à des éléments existants + VerifReference(lesRef); + + if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture affinage maillage " << endl; +}; + +// affichage et definition interactive des commandes +// cas = 1: interactif complet +// cas = 2: entrée uniquement de noms de fichier +// cas = 3: entrée uniquement de l'affinage +void Maillage::Info_commande_Maillages(UtilLecture * entreePrinc,LesReferences& lesRef, int cas) +{ ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier + string rep="o"; + if (cas == 2) + { cout << "\n# voulez-vous inclure un fichier ou continuer sur un exemple (rep o ou ? ou f) ? "; + rep = lect_return_defaut(false,"f"); + }; + + if (((rep == "o") || (rep == "O") ||(rep == "0")) && (cas != 3)) + { cout << "\n non du fichier .her (sans l'extension .her) a inclure ? "; + rep = lect_chaine(); + sort << "\n\n # -- def maillage "; + sort << "\n < " << (rep+".her") ; + cout << "\n un fichier .lis a inclure ? (o ou n (defaut)) "; + rep = lect_return_defaut(false,"n"); + if (rep == "o") + { cout << "\n non du fichier .lis (sans l'extension .lis) a inclure ? "; + rep = lect_chaine(); + sort << "\n < " << (rep+".lis") ; + }; + } + else if ((rep == "?") && (cas != 3)) + { // sinon on continue sur un exemple de maillage + sort << "\n # -- defintion du nom du maillage (facultatif pour le premier maillage " + << "\n # -- qui s'appel par defaut : premier_maillage)" + << "\n" + << "\n nom_maillage plaque_troue # exemple de nom de maillage" + << "\n noeuds ------------ # definition des noeuds"; + + //------------- definition des noeuds ------------- + int dimen = ParaGlob::Dimension(); + #ifdef SYSTEM_MAC_OS_CARBON + int nbNoeud = pow(3,dimen); // nombre de noeud de l'exemple + #else + int nbNoeud = ((int)pow((float)3,(int)dimen)); // nombre de noeud de l'exemple + #endif + + sort << "\n "<< nbNoeud << " NOEUDS # definition du nombre de noeud" + << "\n \n" + << "\n#---------------------------------------------------------------" + << "\n#|NO DU| X | Y | Z |" + << "\n#|NOEUD| | | |" + << "\n#---------------------------------------------------------------"; + + Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud + // définition d'une grille générique de noeuds qui permettra de définir les éléments générique + Tableau tab_coo(nbNoeud); + switch (dimen) + { case 1: + { for (int i=1;i<=3;i++) tab_coo(i) = new Coordonnee((double) i); break;} + case 2: + { int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++,l++) + tab_coo(l) = new Coordonnee((double) i,(double) j); break;} + case 3: + { int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++) for (int k=1;k<=3;k++,l++) + tab_coo(l) = new Coordonnee((double) i,(double) j,(double) k); break;} + }; + // def des noeuds + Noeud * ptr; + for (int i=1; i<= nbNoeud; i++) + { ptr = new Noeud(i,dimension,1); // et attribution du numero de maillage + // def du noeud + ptr->Info_commande_Noeud(entreePrinc,*tab_coo(i),i); + Affectation_noeud(*ptr); + }; + + // -------------- def d'exemples de references se rapportant aux noeuds --------- + sort << "\n# --- reference de noeuds ce trouvant apres la definition des noeuds ---" + << "\n# ( il est possible aussi de definir des references de noeud apres " + << "\n# la definition des elements) " + << "\n# NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres \n"; + lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds + lesRef.NbMaille(idmail); // indic le numéro de maillage aux références + lesRef.Info_commande_lesRef(nbNoeud,0,entreePrinc,1); // def d'exemple des divers refs de noeuds + + // ------------ def d'exemple d'elements ----------- + + int nbElement = 0; // nombre d'element + bool choix_valide=false; + // affichage des types d'élément actuellement disponible selon la dimension + // creation d'un tableau d'éléments + Tableau tab_el = Element::Info_commande_Element(entreePrinc); + int nbele = tab_el.Taille(); + Tableau chooi(nbele,false); // tableau de travail + cout << "\n Donner le type d'element que vous souhaitez utiliser: ? "; + string rep;int num; + while (!choix_valide) + { + try + { // affichage des éléments possibles + // on balaie le tableau des elements enregistre + int undeux=0; + cout << "\n (0) fin \n"; + for (int i=1;i<=nbele;i++) + { cout << " (" << i << ") " << tab_el(i)->Geometrie() <<" "<< tab_el(i)->Interpolation() + <<" "; + undeux++; + if (undeux==2) {cout << "\n";undeux=0;} + }; + rep = lect_return_defaut(false,"0"); + if (rep == "fin_prog") Sortie(1); + num = ChangeEntier(rep); + choix_valide=false; + if (num == 0) + { choix_valide=true;} + else // sinon + { if ((num > 0)&&(num<=nbele)) + {if (chooi(num)) + cout << "\n type d'element deja choisit, recommencer"; + else + chooi(num) = true; + } + else { cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper fin_prog pour arreter le programme"; + } + } + } + catch (ErrSortieFinale) + // cas d'une direction voulue vers la sortie + // on relance l'interuption pour le niveau supérieur + { ErrSortieFinale toto; + throw (toto); + } + catch (...)//(UtilLecture::ErrNouvelleDonnee erreur) + { cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper fin_prog pour arreter le programme"; + choix_valide=false; + } + } //-- fin du while + // on definit le maillage d'essai + // 1- def du nombre d'élément + int ielmax=0; + for (int ie=1;ie<=nbele;ie++) + if (chooi(ie)) ielmax++; + Change_nb_element(ielmax); + // 2- remplissage du tableau d'élément + int iel=1; + for (int ie=1;ie<=nbele;ie++) + if (chooi(ie)) + {tab_element(iel)=tab_el(ie); + tab_element(iel)->Change_num_elt(iel); + tab_el(ie)=NULL; + iel++; + } + // on affiche les éléments + sort << "\n # les elements \n" + << "\n elements ----------"; + sort << "\n " << ielmax << " ELEMENTS"; + + sort << "\n #----------------------------------------------------------------------"; + sort << "\n #| NO | | |"; + sort << "\n #|ELTS | type element | Noeuds |"; + sort << "\n #----------------------------------------------------------------------"; + string ord= "commande"; + Tableau * pt = & tab_noeud; + for (int i=1;i<=ielmax;i++) + tab_element(i)->Info_com_Element(entreePrinc,ord,pt); + sort << "\n \n" ; + + // -------------- def des references se rapportant aux elements --------- + // ou aux arête ou aux faces et meme eventuellement à des noeuds + sort << "\n# --- reference ce trouvant apres la definition des elements ---" + << "\n# NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres " + << "\n# une reference d'element commence par E suivi d'une chaine de caracteres " + << "\n# une reference de face commence par F et une reference d'arrete commence par A \n"; + + lesRef.NbMaille(idmail); // indic le numéro de maillage aux références + lesRef.Info_commande_lesRef(nbNoeud,ielmax,entreePrinc,2); // def d'exemple des divers refs de noeuds + + // effacement des éléments qui ne servent plus + for (int i=1;i<=ielmax;i++) + if (tab_el(i) != NULL) delete tab_el(i); + }; // fin de l'exemple de maillage + + // ---------- définition des affinages éventuelles ---------- +// while ( (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL) +// || (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL) +// || (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL) +// || (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL) +// || (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL) +// || (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL) +// || (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL) +// || (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL) + //On va proposer un menu + while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0")) + { + try + { + cout + << "\n (0 ou f defaut) (fin) " + << "\n (1) mouvement solide " + << "\n (2) suppression des noeuds non reference " + << "\n (3) collapse de noeuds proches " + << "\n (4) collapse d'elements superposes " + << "\n (5) creation de references frontieres " + << "\n (6) renumerotation " + << "\n (7) creation d'une ref sur les noeuds non references " + << "\n (8) suppression des petits elements a 2 ou 3 noeuds 2D " + << "\n (9 ou ? ) informations " + << "\n "; + rep = lect_return_defaut(false,"f"); + if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe + break; + int num = ChangeEntier(rep); + if (Minuscules(rep) == "?") + num = 9; + bool choix_valide=false; + if ((num >= 0)&&(num<=9)) + { choix_valide=true; } + else { cout << "\n Erreur on attendait un entier entre 0 et 9 !!, " + << "\n redonnez une bonne valeur" + << "\n ou taper f ou 0 pour arreter le programme"; + choix_valide=false; + } + switch (num) + { case 0: // sortie + { break;} // normalement cela a déjà été filtré avant + case 1: // mouvement solide + { MvtSolide mvt; // un mouvement par défaut + sort << "\n\n def_mouvement_solide_initiaux_ \n"; + mvt.Info_commande_MvtSolide(sort); + break;} + case 2: // suppression des noeuds non reference + { sort << "\n suppression_noeud_non_references_ "; + break;} + case 3: // collapse de noeuds proches + { sort << "\n fusion_noeuds_proches_ "; + cout << "\n donner la distance en dessous de laquelle on fusionne (un reel) ? "; + double rayon=0.; + rayon = lect_double(); cout << " valeur lue "<< rayon; + sort << rayon << " "; + break;} + case 4: // collapse d'elements superposes + { sort << "\n fusion_elements_superposes_ "; + break;} + case 5: // creation de references frontieres + { sort << "\n def_auto_ref_frontiere_ "; + break;} + case 6: // creation de references frontieres + { sort << "\n renumerotation_des_noeuds_ "; + break;} + case 7: // creation d'une ref sur les noeuds non reference + { sort << "\n creation_ref_noeud_non_references_ "; + break;} + case 8: // suppression des petits elements a 2 ou 3 noeuds 2D + { sort << "\n suppression_elements_2noeuds_tres_proches_ "; + cout << "\n donner la distance entre deux noeuds de l'element en dessous de laquelle on supprime (un reel) ? "; + double rayon=0.; + rayon = lect_double(); cout << " valeur lue "<< rayon; + sort << rayon << " "; + break;} + case 9: // informations + { cout << "\n en dehors de la signification intuitive des differents ordres" + << " pour des informations plus precise il est preferable de se rapporter a la documentation " + << " d'Herezh++, car c'est differents ordres recouvrent des procedures difficiles a " + << " decrire en quelques lignes. "; + break;} + default: + cout << "\n le cas "<::const_iterator il,ilfin=types_de_problemes.end(); +// cout <<"\n types_de_problemes: " << types_de_problemes.size() ; +// for (il=types_de_problemes.begin();il != ilfin;il++) +// NomElemTypeProblem(*il); +// }; + {int tail = types_de_problemes.Taille(); + cout <<"\n types_de_problemes: " << tail ; + for (int i=1;i<=tail;i++) + cout << " "<< NomElemTypeProblem(types_de_problemes(i)); + }; + +// // les ddl associés +// {list ::const_iterator il,ilfin=ddl_representatifs_des_physiques.end(); +// cout <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size(); +// for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++) +// Nom_ddl(*il); +// }; + {int tail = ddl_representatifs_des_physiques.Taille(); + cout <<"\n type_de_ddl_associes: " << tail; + for (int i=1;i<=tail;i++) + cout << " "<< Nom_ddl(ddl_representatifs_des_physiques(i)); + }; + + // cout << "Nombre de degres de liberte : " << Nombre_ddl() << "\n"; + cout << "Nombre de noeuds : " << Nombre_noeud() << "\n"; + cout << "Nombre d'elements : " << Nombre_element() << "\n\n"; + for (int i=1;i<=Nombre_noeud();i++) + // boucle sur les noeuds + { + cout << "\nNoeud " << i << " :\n"; + tab_noeud(i)->Affiche(); + }; + cout << "\n"; + for (int i=1;i<=Nombre_element();i++) + // boucle sur les elements + { + cout << "\nElement " << i << " :\n"; + tab_element(i)->Affiche(ParaGlob::NiveauImpression()); + }; + cout << "\n"; + // renseignement concernant les frontières + int nbmaxiElement = (int) listFrontiere.size(); + cout << "nombre d'element frontiere : " << nbmaxiElement; + cout << "liste : \n"; + LaLIST ::const_iterator ip;int ne; + for (ne=1,ip = listFrontiere.begin();ip != listFrontiere.end(); ip++,ne++) + { // écriture de l'élément courant + cout << ne << " " ; // le numéro + const ElemGeomC0 & geom = (*ip).Eleme()->ElementGeometrique(); + cout << Nom_geom(geom.TypeGeometrie()) << " " ; // la géométrie + cout << Nom_interpol(geom.TypeInterpolation()) << " " ; // l'interpolation + // les noeuds + Tableau tabnoeud = (*ip).Eleme()->TabNoeud(); + int taille = tabnoeud.Taille(); + for (int ine = 1; ine<=taille; ine++) + cout << tabnoeud(ine)->Num_noeud() << " "; + cout << "\n"; + }; + // la liste des noeuds de la frontières, on ne sort que les numéros + cout << " \n liste des numeros de noeud de la frontiere"; + int taal = tab_noeud_front.Taille(); + for (int i=1;i<= taal;i++) + cout << tab_noeud_front(i)->Num_noeud() << " "; + cout << "\n"; +}; + +/*void +Maillage::Affiche (char* nom_fichier) +// Affiche les donnees du maillage dans le fichier nom_fichier +// au format du fichier d'entree ".her" +{ + FILE* fichier; + // ouverture du fichier nom_fichier + if ( (fichier=fopen(nom_fichier,"w"))==NULL ) + { + cout << "ERREUR D'OUVERTURE DU FICHIER :"; + cout << nom_fichier << "\n"; + Sortie(1); + }; + fprintf(fichier,"\n nom_maillage ",nomDuMaillage.c_str()); + fprintf(fichier,"\n\nnoeuds --------\n\n"); + fprintf(fichier,"\t\t%d NOEUDS\n\n",Nombre_noeud()); + // affichage des noeuds : + switch (dimension) + { + case 1 : // cas unidimensionnel + for (int i=1;i<=Nombre_noeud();i++) + { + fprintf(fichier,"\t%d\t%lf\n",Noeud_mail(i).Num_noeud(), + Noeud_mail(i).Coord0()(1)); + }; + break; + case 2 : // cas bidimensionnel + for (int i=1;i<=Nombre_noeud();i++) + { + fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud()); + fprintf(fichier,"%lf\t%lf\n",Noeud_mail(i).Coord0()(1), + Noeud_mail(i).Coord0()(2)); + }; + break; + case 3 : // cas tridimensionnel + for (int i=1;i<=Nombre_noeud();i++) + { + fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud()); + fprintf(fichier,"%lf\t%lf\t%lf\n",Noeud_mail(i).Coord0()(1), + Noeud_mail(i).Coord0()(2),Noeud_mail(i).Coord0()(3)); + }; + break; + default : + cout << "Erreur de dimension\n"; + cout << "MAILLAGE::AFFICHE(char* ) \n"; + Sortie(1); + }; + fprintf(fichier,"\n\nelements --------\n\n"); + fprintf(fichier,"\t\t%d ELEMENTS\n\n",Nombre_element()); + // affichage des elements + for (int i=1;i<=Nombre_element();i++) + { + fprintf(fichier,"\t%d\t",Element_mail(i).Num_elt()); + fprintf(fichier,"%s\t%s\t\t",Element_mail(i).Geometrie(), + Element_mail(i).Interpolation()); + for (int j=1;j<=Element_mail(i).Nombre_noeud();j++) + fprintf(fichier,"%d\t",Element_mail(i).Num_noeud(j)); + fprintf(fichier,"\n"); + }; + fprintf(fichier,"\n\n"); + +}; +*/ + +Maillage& +Maillage::operator= (Maillage& mail) +// Surcharge de l'operateur = : realise l'egalite entre deux maillages +// cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut +// ensuite les définir +{ dimension=mail.dimension; + //nomDuMaillage = mail.nomDuMaillage; + tab_noeud=mail.tab_noeud; + tab_element=mail.tab_element; + listFrontiere=mail.listFrontiere; + tab_noeud_front = mail.tab_noeud_front; + ddl_representatifs_des_physiques = mail.ddl_representatifs_des_physiques; + types_de_problemes = mail.types_de_problemes; + return (*this); +}; + +// test si toutes les informations des maillages sont completes +// = true -> complet +// = false -> incomplet +bool Maillage::Complet() + { bool res = true; + int tab_noeudTaille = tab_noeud.Taille(); + for ( int i=1; i<= tab_noeudTaille;i++) + { // res = res && tab_noeud(i)->TestComplet(); + if(!(tab_noeud(i)->TestComplet())) + { cout << " \n pb au niveau du test du noeud " << tab_noeud(i)->Num_noeud(); + res = false; + }; + }; + int tab_elemTaille = tab_element.Taille(); + for ( int i=1; i<= tab_elemTaille;i++) + {//res = res && tab_element(i)->TestComplet(); + if(!(tab_element(i)->TestComplet())) + {cout << "\n pb au niveau du test de l'element " << tab_element(i)->Num_elt(); + res = false; + }; + }; + // les parties frontières ne sont pas obligatoires + return res; + }; + +// ramene la demi largeur de bande en ddl et la largeur de bande +void Maillage::Largeur_Bande(int& demi, int& total,const Nb_assemb& casAss) + { demi = 0; + int nb_ass = casAss.n; + int tab_elemTaille = tab_element.Taille(); + for (int ne=1;ne<=tab_elemTaille;ne++) + {int tab_eleNbNoeud = tab_element(ne)->Nombre_noeud(); + for (int noe=1; noe<= tab_eleNbNoeud;noe++) +// bug, voic remarque qui suit for ( int no=noe+1; no<=tab_eleNbNoeud;no++) + // l'idée est bonne de commencer à noe+1, mais en fait lorsque l'on a un seul noeud, cela conduit + // a avoir une largeur de bande nulle, donc il faut commencer à noe, et dans ce cas c'est ok + // mais pour les éléments avec plus d'un noeud, on a une boucle supp + for ( int no=noe; no<=tab_eleNbNoeud;no++) + { Noeud & nne = tab_element(ne)->Noeud_elt(noe); + Noeud & nno = tab_element(ne)->Noeud_elt(no); + int di; + if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass)) + di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass) + + nne.NB_ddl_actif_casAssemb(nb_ass); + else + di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass) + + nno.NB_ddl_actif_casAssemb(nb_ass); + if ( di > demi) demi = di; + }; + }; + total = demi * 2 -1; + demi = demi; + }; + +// test pour savoir si tous les coordonnées des noeuds d'un maillage sont imposé +// ramène 1 si tout est fixé, 0 sinon +int Maillage::Tous_Xi_fixes(const Nb_assemb& casAss) const + { int retour = 1; + int nb_ass = casAss.n; + // on va parcourir les noeuds + int tab_noeud_taille= tab_noeud.Taille(); + int dim = ParaGlob::Dimension(); + switch(dim) + {case 3: + {for (int i=1;i<=tab_noeud_taille;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (!( noe.Ddl_fixe(X3) && noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1))) + {retour=0; break;}; + }; + break; + } + case 2: + {for (int i=1;i<=tab_noeud_taille;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (!( noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1))) + {retour=0; break;}; + }; + break; + } + case 1: + {for (int i=1;i<=tab_noeud_taille;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (!( noe.Ddl_fixe(X1))) + {retour=0; break;}; + }; + break; + } + }; +// --- idem mais plus long a priori car contient un switch +// for (int i=1;i<=tab_noeud_taille;i++) +// { Noeud& noe = *tab_noeud(i); // pour simplifier +// switch(dim) +// {case 3: if (!(noe.Ddl_fixe(X3))) {retour=0; break;}; +// case 2: if (!(noe.Ddl_fixe(X2))) {retour=0; break;}; +// case 1: if (!(noe.Ddl_fixe(X1))) {retour=0; break;}; +// }; +// if (!retour) break; +// }; + return retour; + }; + +// création pour chaque noeud de la liste des éléments qui contiennent le noeud +void Maillage::Calcul_indice() +{ // création du tableau indice : pour chaque noeud on regarde quel élément contiend ce noeud +/// les 3/ sont pour la version vector qui marche bien aussi +/// vector > indice(tab_noeud.Taille()); + int tab_noeud_taille= tab_noeud.Taille(); + indice.Change_taille(tab_noeud_taille); + // au cas où le tableau existait auparavant on initialise les éléments du tableau + for (int i=1;i<= tab_noeud_taille;i++) + indice(i).clear(); + // maintenant on passe en revue les éléments + int tabelTaille = tab_element.Taille(); + // indice(i) contiend les numéros d'élément contenant le noeud i + for (int i22 = 1; i22 <= tabelTaille; i22++) + { Element * elem1 = tab_element(i22); // recup de l'element + // récup de son tableau de noeud + Tableau& tabn = elem1->Tab_noeud(); + int tabntaille = tabn.Taille(); + for (int ij=1;ij<= tabntaille;ij++) + {// on balaie ses noeuds +/// indice[(tabn(ij)->Num_noeud())-1].push_back(elem1); + indice((tabn(ij)->Num_noeud())).push_back(elem1); + }; + }; + // on supprime les doublons + for (int i=1;i<=tab_noeud_taille;i++) + { list& intertab = indice(i); // pour allèger l'écriture + intertab.sort(); // on ordonne + intertab.unique(); // on supprime les doublons +/*//-- debug +//{cout << "\n noeud " << i << " taille indice(i) " << intertab.size() ; +// list::iterator ina,infin; +// infin = intertab.end(); +// for (ina = intertab.begin();ina!=infin;ina++) +// {Element * elem2 = *ina; // recup de l'element +// cout << " element " << elem2->Num_elt() << " "; +// }; +// cout << "\n"; +// }; +//-- debug +//{cout << "\n debug ** Maillage::Calcul_indice() "; +// int numnoeud = 104; +// list& intertab = indice(numnoeud); +// list::iterator ina,infin; +// infin = intertab.end(); +// for (ina = intertab.begin();ina!=infin;ina++) +// {Element * elem2 = *ina; // recup de l'element +// cout << " element-- " << elem2->Num_elt() << " "; +// }; +// cout << "\n"< calcul des normales à t=0 +// et ajout conteneur aux noeuds des normales à t = 0 et t +void Maillage::InitNormaleAuxNoeuds() + { // on va parcourir les noeuds et on n'intervient que si le noeud + // appartient à un élément 1D et/ou 2D + int nbNoeud = tab_noeud.Taille(); + int borne_max_nbNoeud = nbNoeud+1; + Coordonnee coor_inter; // coordonnée de travail + Coordonnee premiere_normale;// idem + for (int ine =1; ine < borne_max_nbNoeud;ine++ ) + {// on regarde si le conteneur de la normale existe au noeud + // et création éventuelle + Noeud & noe = *tab_noeud(ine); // pour simplifier + if (!noe.Existe_ici(NN_SURF_t0)) + { Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant + TypeQuelconque typQ4(NN_SURF_t0,EPS11,grandCoordonnee); + noe.AjoutUnTypeQuelconque(typQ4); + }; + // on fait la même chose à t ce qui évitera de tester à la mise à jour + if (!noe.Existe_ici(NN_SURF_t)) + { Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant + TypeQuelconque typQ4(NN_SURF_t,EPS11,grandCoordonnee); + noe.AjoutUnTypeQuelconque(typQ4); + }; + // et on le récupère après création éventuelle + TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t0); + Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee())); + Coordonnee& normale = *gr.ConteneurCoordonnee(); + normale.Zero(); // init + // calcul éventuel du tableau Indice + this->Indice(); + + List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud + List_io < Element*>::iterator il,ilfin = li_elem.end(); + // on balaie les éléments + int nb_normale=0; // le nombre de normales trouvées + for (il = li_elem.begin(); il != ilfin; il++) + {Element& elem = *(*il); + Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); +// if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) + if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces + {int cas = elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter); + if (cas == 0) + {cout << "\n *** erreur, le calcul de la normale n'est pas possible " + << " pour le noeud "<Num_noeud() + << " du maillage " << tab_noeud(ine)->Num_Mail() + << " par rapport a l'element "<< elem.Num_elt() + << " du maillage " << elem.Num_maillage() + << "\n Maillage::MiseAjourNormaleAuxNoeuds() "; + Sortie(1); + } + else if (cas == 2) + {// le calcul n'est pas licite, mais ce n'est pas une erreur + // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien + } + else // sinon c'est ok + {// on peut avoir des directions très proches mais de sens inverse ... ce qui va + // conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire + // s'il est négatif on utilise l'inverse de la normale + // donc en définitif on gardera globalement la direction précédente + if ((normale * coor_inter) > 0.) + {normale += coor_inter;} + else + {normale -= coor_inter;}; + nb_normale++; + }; + }; + }; + if (nb_normale != 0) + {normale /= nb_normale; + // enfin on normalise la normale +////------ debug +//if (normale.Norme() == 0.) +// { +// for (il = li_elem.begin(); il != ilfin; il++) +// {Element& elem = *(*il); +// Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); +// // if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) +// if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces +// {elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter); +// if (coor_inter.Dimension() == 0) +// {cout << "\n *** erreur, le calcul de la normale n'est pas possible " +// << " pour le noeud "<Num_noeud() +// << " du maillage " << tab_noeud(ine)->Num_Mail() +// << " par rapport a l'element "<< elem.Num_elt() +// << " du maillage " << elem.Num_maillage() +// << "\n Maillage::MiseAjourNormaleAuxNoeuds() "; +// Sortie(1); +// } +// else // sinon c'est ok +// {normale += coor_inter; +// nb_normale++; +// }; +// }; +// }; +// +// } +// +//// end debug + normale.Normer(); + // ce qui fini la mise à jour de la normale au noeud + }; + }; + }; + +// calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement +// a priori le calcul s'effectue par une moyenne des normales des éléments qui +// entourent le noeud. +// mise à jour -> mise à jour des normales à t + +void Maillage::MiseAjourNormaleAuxNoeuds() + { // on va parcourir les noeuds et on n'intervient que si le noeud + // appartient à un élément 1D et/ou 2D + int nbNoeud = tab_noeud.Taille(); + int borne_max_nbNoeud = nbNoeud+1; + Coordonnee coor_inter; // coordonnée de travail + for (int ine =1; ine < borne_max_nbNoeud;ine++ ) + {Noeud & noe = *tab_noeud(ine); // pour simplifier + // on récupère la normale au noeud + TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t); + Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee())); + Coordonnee& normale = *gr.ConteneurCoordonnee(); + normale.Zero(); // init + // calcul éventuel du tableau Indice + this->Indice(); + + List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud + List_io < Element*>::iterator il,ilfin = li_elem.end(); + // on balaie les éléments + int nb_normale=0; // le nombre de normales trouvées + for (il = li_elem.begin(); il != ilfin; il++) + {Element& elem = *(*il); + Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); + // if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) + if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces + {int cas = elem.CalculNormale_noeud(TEMPS_t,*tab_noeud(ine),coor_inter); + if (cas == 0) + {cout << "\n *** erreur, le calcul de la normale n'est pas possible " + << " pour le noeud "<Num_noeud() + << " du maillage " << tab_noeud(ine)->Num_Mail() + << " par rapport a l'element "<< elem.Num_elt() + << " du maillage " << elem.Num_maillage() + << "\n Maillage::MiseAjourNormaleAuxNoeuds() "; + Sortie(1); + } + else if (cas == 2) + {// le calcul n'est pas licite, mais ce n'est pas une erreur + // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien + } + else // sinon c'est ok + {normale += coor_inter; + nb_normale++; + }; + }; + }; + if (nb_normale != 0) + {normale /= nb_normale; + // enfin on normalise la normale + normale.Normer(); + }; + // ce qui fini la mise à jour de la normale au noeud + }; + }; + +// mise à jour -> mise à jour des normales à t +// mais ici, on calcule les normales à tdt, et on transfert à t +// cette méthode est utile si on veut utiliser des normales à t pour une valeur +// particulière (transitoire) de la géométrie à tdt +// cf: l'algo non dyna par exempel +void Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T() +{ // on va parcourir les noeuds et on n'intervient que si le noeud + // appartient à un élément 1D et/ou 2D + int nbNoeud = tab_noeud.Taille(); + int borne_max_nbNoeud = nbNoeud+1; + Coordonnee coor_inter; // coordonnée de travail + for (int ine =1; ine < borne_max_nbNoeud;ine++ ) + {Noeud & noe = *tab_noeud(ine); // pour simplifier + // on récupère la normale au noeud + TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t); + Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee())); + Coordonnee& normale = *gr.ConteneurCoordonnee(); + normale.Zero(); // init + // calcul éventuel du tableau Indice + this->Indice(); + + List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud + List_io < Element*>::iterator il,ilfin = li_elem.end(); + // on balaie les éléments + int nb_normale=0; // le nombre de normales trouvées + for (il = li_elem.begin(); il != ilfin; il++) + {Element& elem = *(*il); + Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie()); + // if ((enutygeom == LIGNE) || (enutygeom == SURFACE)) + if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces + {// ici contrairement à la méthode: MiseAjourNormaleAuxNoeuds + // on demande à l'élément de calculer la normale avec la géométrie à tdt + int cas = elem.CalculNormale_noeud(TEMPS_tdt,*tab_noeud(ine),coor_inter); + if (cas == 0) + {cout << "\n *** erreur, le calcul de la normale n'est pas possible " + << " pour le noeud "<Num_noeud() + << " du maillage " << tab_noeud(ine)->Num_Mail() + << " par rapport a l'element "<< elem.Num_elt() + << " du maillage " << elem.Num_maillage() + << "\n Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T() "; + Sortie(1); + } + else if (cas == 2) + {// le calcul n'est pas licite, mais ce n'est pas une erreur + // simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien + } + else // sinon c'est ok + {normale += coor_inter; + nb_normale++; + }; + }; + }; + if (nb_normale != 0) + {normale /= nb_normale; + // enfin on normalise la normale + normale.Normer(); + }; + // ce qui fini la mise à jour de la normale au noeud + }; +}; + +// creation des elements frontiere +void Maillage::CreeElemFront() +{ + // 0- on supprime la liste existante + listFrontiere.erase(listFrontiere.begin(),listFrontiere.end()); + // 1- tout d'abord on crée les éléments frontière dans chaque élément + int tabelTaille = tab_element.Taille(); + // on boucle sur les elements + for (int i2 = 1; i2 <= tabelTaille; i2++) + // création des éléments frontières (on force) + tab_element(i2)->Frontiere(true); + // 2- maintenant on va créé des tableaux permettant d'accélérer l'algorithme final + // pour chaque noeud on regarde quel élément contiend ce noeud + Calcul_indice(); + int tab_noeud_taille= tab_noeud.Taille(); + // indice contiend les numéros d'élément succeptible d'avoir des frontières + // communes + + // 3- maintenant on va de nouveau boucler sur les éléments en regardant + // pour chaque frontière si elle est effectivement recevable c-a-d si + // il n'y a pas deux frontières identiques + Front lili; // un element de référence de frontière courant +// for (int i1 = 1; i1 <= tabelTaille-1; ++i1) + for (int i1 = 1; i1 <= tabelTaille; i1++) + {Element * elem1 = tab_element(i1); // recup de l'element + const Tableau & tab1 = elem1->Frontiere(); // et de ses frontières + int tab1Taille = tab1.Taille(); // frontières +//-- debug +//cout << "\n elem1 " << elem1->Num_elt() << " "; +//--fin debug + // on boucle sur les frontière, qui doivent être repérée par un pointeur non nulle + for (int j1=1;j1<= tab1Taille;j1++) + // on essaie de voir si l'élément j1 est recevable, c-a-d pointeur non nulle + // sinon cela veut dire que la frontière a été supprimer car en double + {ElFrontiere * elfr = tab1(j1); // pour simplifier + // on ne continu que si le pointeur est non nul + if (elfr != NULL) + { + bool res = false; + // si deux éléments frontières sont identiques alors tous leurs noeuds + // sont identiques. En particulier le premier noeud de *elfr est commum + // avec tous les éléments succeptibles de contenir un élément frontière + // identique. On va donc utiliser la liste indice qui contiend cette liste + int numnoeud = (elfr->TabNoeud())(1)->Num_noeud(); +/// vector::iterator ina,infin; +/// vector& intertab = indice[numnoeud-1]; // pour allèger l'écriture + list::iterator ina,infin; + list& intertab = indice(numnoeud); // pour allèger l'écriture + infin = intertab.end(); + // on balaie les élément succeptibles d'avoir des frontières communes + for (ina = intertab.begin();ina!=infin;ina++) + {Element * elem2 = *ina; // recup de l'element + +//-- debug +//cout << " intertab.size() = " << intertab.size(); +//cout << ", elem2 " << elem2->Num_elt() << " "; +//--fin debug + // on ne fait la recherche que pour les éléments différents de elem1 + bool res_ina = false; // init d'un indicateur interne à la boucle j2 qui suit, + if (elem2 != elem1) + { +//------- debug +//cout << "\n debug ** Maillage::CreeElemFront() "; +//elem2->Affiche(); cout << endl; +//---- fin debug + + const Tableau & tab2 = elem2->Frontiere(); // et des éléments + int tab2Taille = tab2.Taille(); // frontières + for (int j2=1;j2<= tab2Taille;++j2) + { // dans le cas où l'élément frontière existe, c'est-à-dire + // qu'il n'a pas été supprimé par un précédent passage + // on le compare + ElFrontiere* tab2j2 = tab2(j2); // pour simplifier + if (tab2j2 != NULL) + {ElFrontiere* p = tab2j2->Oppose(); // variable transitoire + if ((*elfr) == (*p)) + // on a trouve un element qui annule + { res = res_ina = true;// on met l'indicateur + // suppression de l'élément dans la liste + elem2->SupprimeFront(tab2j2); + }; + delete p; // suppression de l'element p transitoire + } + // si il y a eu suppression de l'élément frontière on sort de la boucle + if (res_ina) break; // on sort de la boucle si pas élément de frontière + }; + // si l'on a détecté une égalité on arrète également cette boucle + // après avoir supprimé l'élément frontière + // non, car on pourrait avoir une frontière qui soit commune à plus de 2 éléments + // pour l'instant ce n'est pas le cas, mais par exemple des arrêtes pour les volumes ?? + // if (res) + // { elem1->SupprimeFront(elfr); + // elfr=NULL; + // break; + // } + }; + }; + // en sortie on sauvegarde uniquement si c'est un élément frontière + if (!res) + {// lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1; + int num_dans_le_type = elem1->Num_de_frontiere_dans_le_type(j1); + listFrontiere.push_back(Front(*elfr,elem1,num_dans_le_type)); + } + else // sinon la frontière est commune avec au moins une autre, on l'a supprime + { elem1->SupprimeFront(elfr); + }; + }; // fin du test if (elfr != NULL) + }; // fin de la boucle sur les frontières de elem1 + }// fin de la boucle externe des éléments + + +/* // cas du dernier élément, ses éléments frontières non nuls sont forcément bons +non finalement, cela semble poser des pb sur le dernier élément vu que l'on a mis une procédure d'accélération +pour le calcul des frontières donc on met en stand by pour l'instant, si pas de pb qui apparaissent on supprime + { Element * elem1 = tab_element(tabelTaille); // recup de l'element + const Tableau & tab1 = elem1->Frontiere(); // et des éléments + int tab1Taille = tab1.Taille(); // frontières + for (int j1=1;j1<= tab1Taille;++j1) + // on essaie de voir si l'élément j1 est recevable + { ElFrontiere * elfr = tab1(j1); // pour simplifier + if (elfr != NULL) + {//lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1; + listFrontiere.push_back(Front(elfr,elem1)); + } + } + } + */ + +//Sortie(1); + // effacement du contenu du tableau indice + indice.Libere (); + + //// ---- debug ----- + // vérification que l'on a bien les frontières bien connectées +// cout << " \n debug: Maillage::CreeElemFront()"; +//{ LaLIST ::iterator iF; +// LaLIST ::iterator iFfin = listFrontiere.end(); +// cout << "\n liste des frontières: \n "; +// for (iF = listFrontiere.begin();iF!=iFfin; iF++) +// { Front* elfront = &(*iF); +// Enum_type_geom type_front; // va être modifier par Num_frontiere +// cout << " frontière: " << elfront->Num_frontiere() << " " << elfront->Eleme()->Type_geom_front() +// << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage " +// << elfront->PtEI()->Num_maillage() << " \n "; +// }; +//}; + +// // vérif particulière (a commenter !) +//{ LaLIST ::iterator iF; +// LaLIST ::iterator iFfin = listFrontiere.end(); +// int nbf = 1; +// for (iF = listFrontiere.begin();iF!=iFfin; iF++) +// { Front* fro = &(*iF); +// ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière +// // récup de son tableau de noeud +// Tableau& tabn = efem1->TabNoeud(); +// int tabntaille = tabn.Taille(); +// if (fro->PtEI()->Id_geometrie() == HEXAEDRE) +// {cout << "nbf= " << nbf << ", ele= " << fro->PtEI()->Num_elt() << " : "; +// for (int ij=1;ij<= tabntaille;ij++) +// // on balaie ses noeuds +// cout << tabn(ij)->Num_noeud() << " "; +// cout << endl ; +// nbf++; +// }; +// }; +// +//} +// + //// ---- fin debug ----- + + + + + + // definition des elements mitoyens aux elements de frontiere + MitoyenFront(); + // ==== définition du tableau des noeuds frontières ===== + // 1) on définit un tableau de numéro de noeuds qui sont utilisés + Tableau t_noe(tab_noeud_taille,0); // tous les éléments sont nul + // 2) on balaie les éléments frontières + LaLIST ::iterator li,li_end=listFrontiere.end(); + for (li=listFrontiere.begin();li!=li_end;li++) + { Tableau & tt = (*li).Eleme()->TabNoeud(); + int tt_taille=tt.Taille(); + for (int i=1;i<=tt_taille;i++) + (t_noe(tt(i)->Num_noeud()))++; + }; + // 3) on récupère le nombre de noeud frontière + int nb_n_f=0; + for (int ii=1;ii<= tab_noeud_taille;ii++) + if (t_noe(ii)!=0) nb_n_f++; + // 4) def du tableau final + tab_noeud_front.Change_taille(nb_n_f); + nb_n_f=0; // on se ressert du numéro + for (int ii=1;ii<= tab_noeud_taille;ii++) + {if (t_noe(ii)!=0) {nb_n_f++;tab_noeud_front(nb_n_f)=tab_noeud(ii);};}; + + // dans le cas où les éléments frontières sont des lignes, on les ordonnes + // de manière à former une ligne continue +// OrdonancementDesLigne(); +}; + +// change le nom et le numéro du maillage +void Maillage::ChangeNomNumeroMaillage(const string & nom,int num) + { // on vérifie que le nom de maillage fourni n'existe pas + if (listeNomMail.find(nom) != listeNomMail.end()) + { cout << "\n erreur, le nom de maillage demande existe deja : " << nom + << "\n Maillage::ChangeNomNumeroMaillage(....."; + Sortie(1); + }; + // on met à jour listeNomMail en supprimant le doublet nom <=> numéro existant + listeNomMail.erase(listeNomMail.find(nomDuMaillage)); + nomDuMaillage = nom; // on enregistre le nouveau nom + // on vérifie que le numéro de maillage proposé est valide + if (num <=0) + { cout << "\nErreur : numero de maillage invalide ! = "<< num <<"\n"; + cout << "Maillage::ChangeNomNumeroMaillage(.... \n"; + Sortie(1); + }; + idmail=num; // on enregistre le nouveau numéro + // maintenant on peut associer le nom au numéro dans la map + listeNomMail[nomDuMaillage]=idmail; + }; + +// ramène le numéro du noeud le plus proche du point donné à t=0 +int Maillage::Noeud_le_plus_proche_0(const Coordonnee& M) + { // tout d'abord si le maillage n'a pas de noeud on ramène 0 + int tail_mail = tab_noeud.Taille(); + if (tail_mail == 0) return 0; + // sinon initialisation de la recherche + int num_rech = 1; // choix du premier noeud + // distance avec le noeud + double dist = (tab_noeud(1)->Coord0() - M).Norme(); + // on boucle sur les noeuds + for (int i=2;i<=tail_mail;i++) + { double dista = (tab_noeud(i)->Coord0() - M).Norme(); + if (dista <= dist) + { dist = dista; num_rech = i;}; + }; + // retour + return num_rech; + }; +// ramène le numéro du noeud le plus proche du point donné à t=t +int Maillage::Noeud_le_plus_proche_t(const Coordonnee& M) + { // tout d'abord si le maillage n'a pas de noeud on ramène 0 + int tail_mail = tab_noeud.Taille(); + if (tail_mail == 0) return 0; + // sinon initialisation de la recherche + int num_rech = 1; // choix du premier noeud + // distance avec le noeud + double dist = (tab_noeud(1)->Coord1() - M).Norme(); + // on boucle sur les noeuds + for (int i=2;i<=tail_mail;i++) + { double dista = (tab_noeud(i)->Coord1() - M).Norme(); + if (dista <= dist) + { dist = dista; num_rech = i;}; + }; + // retour + return num_rech; + }; +// ramène le numéro du noeud le plus proche du point donné à t=tdt +int Maillage::Noeud_le_plus_proche_tdt(const Coordonnee& M) + { // tout d'abord si le maillage n'a pas de noeud on ramène 0 + int tail_mail = tab_noeud.Taille(); + if (tail_mail == 0) return 0; + // sinon initialisation de la recherche + int num_rech = 1; // choix du premier noeud + // distance avec le noeud + double dist = (tab_noeud(1)->Coord2() - M).Norme(); + // on boucle sur les noeuds + for (int i=2;i<=tail_mail;i++) + { double dista = (tab_noeud(i)->Coord2() - M).Norme(); + if (dista <= dist) + { dist = dista; num_rech = i;}; + }; + // retour + return num_rech; + }; + + +// ramène le numéro de l'élément qui contiend un point donné et le numéro du point +// d'intégration le plus proche pour les ddl de la liste, (ddl spécifique à l'élément c'est-a-dire +// hors des ddl des noeuds de l'éléments) +// si pas de numéro d'élément ramène un numéro d'élément nulle +// si les numéros de point d'intégration ne sont pas identique pour l'ensemble +// des ddl, pb !!, le numéro du pt integ de retour est alors négatif +// enu_temps: dit si les coordonnées du point M sont à 0 ou t ou tdt +Maillage::NBelemEtptInteg Maillage::Element_le_plus_proche + (Enum_dure enu_temps,const List_io & list_enu + ,const Coordonnee& M) + { Maillage::NBelemEtptInteg ret; + // tout d'abord si le maillage n'a pas d'élément on ramène 0 + int tail_mail = tab_element.Taille();ret.nbElem=0;ret.nbPtInteg=0; + if (tail_mail == 0) { return ret;} + // sinon initialisation de la recherche + // on boucle sur les éléments pour trouver celui qui contiend M + // M peut également être sur la surface de l'élément ce qui est ok également + for (int i=1;i<=tail_mail;i++) + { bool trouve = false; + switch (enu_temps) + { case TEMPS_0 : if(tab_element(i)->Interne_0(M)) trouve = true; break; + case TEMPS_t : if(tab_element(i)->Interne_t(M)) trouve = true; break; + case TEMPS_tdt : if(tab_element(i)->Interne_tdt(M)) trouve = true; break; + }; + if(trouve) + {// on a trouvé un élément on recherche le point le plus près ou est exprimé la grandeur + ret.nbElem = i; + List_io ::const_iterator ii,iide= list_enu.begin(); + List_io ::const_iterator iifin= list_enu.end(); + ret.nbPtInteg = tab_element(i)->PointLePlusPres(enu_temps,(*iide).Enum(),M); + // on vérifie que tous les ddl sont disponibles au pt d'integ + for (ii = iide;ii != iifin; ii++) + if (!(tab_element(i)->Existe_pt_integ (ret.nbPtInteg,(*ii).Enum()))) + { ret.nbPtInteg = -1; return ret;} + // retour normal + return ret; +/* ancienne vérif, pas bonne + // on vérifie que tous les ddl sont de la même famille sinon erreur + for (ii = iide;ii != iifin; ii++) + if (!Meme_famille((*ii).Enum(),(*iide).Enum())) + { ret.nbPtInteg = -1; return ret;} + // retour normal + return ret; + */ + }; + }; + // retour dans le cas où l'on n'a pas trouvé d'élément + ret.nbElem = 0; + ret.nbPtInteg = 0; + return ret; + }; + + +// ramène le numéro de l'élément dont le centre de gravité à t = enu_temps est le plus proche d'un point donné +// Le point peut être n'importe où, en particulier à l'extérieur de la matière +// si pb retour de null +const Element* Maillage::Centre_de_Gravite_Element_le_plus_proche(Enum_dure enu_temps,const Coordonnee& M) +{ Element * el_retour=NULL; + double distance = ConstMath::tresgrand; + int nbelem = tab_element.Taille(); + Coordonnee G(ParaGlob::Dimension()); + // on balaie les éléments + for (int ine = 1; ine <= nbelem; ine++) + {// on commence par calculer le centre de gravité + G.Zero(); + Tableau taN = tab_element(ine)->Tab_noeud(); + int nbn = taN.Taille(); + switch (enu_temps) + { case TEMPS_0: + for (int inn = 1;inn<=nbn;inn++) + {Noeud* noe = taN(inn); + G += noe->Coord0(); + }; + break; + case TEMPS_t: + for (int inn = 1;inn<=nbn;inn++) + {Noeud* noe = taN(inn); + G += noe->Coord1(); + }; + break; + case TEMPS_tdt: + for (int inn = 1;inn<=nbn;inn++) + {Noeud* noe = taN(inn); + G += noe->Coord2(); + }; + break; + }; + G /= nbn; + double new_distance = (M-G).Norme(); + if (new_distance < distance) + {el_retour = tab_element(ine); + distance = new_distance; + }; + }; + + // retour de l'élément + return el_retour; +}; + + +// ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage +double Maillage::Max_var_dep_t_a_tdt() const + { int nbn = tab_noeud.Taille(); double ret=0.; + for (int i=1;i<=nbn;i++) ret=MaX(tab_noeud(i)->Max_var_coor_t_a_tdt(),ret); + return ret; + }; + +// ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments +double Maillage::Min_dist2Noeud_des_elements(Enum_dure temps) const +{ double retour=ConstMath::tresgrand; // init + // on balaie les éléments + int taille_elem = tab_element.Taille(); + for (int i=1; i<=taille_elem;i++) + { const Tableau& tab_N_el = tab_element(i)->Tab_noeud(); + int nbn_loc = tab_N_el.Taille(); + switch (temps) + { case TEMPS_0 : + { for (int in = 1;in<=nbn_loc;in++) + {const Coordonnee& Ci = tab_N_el(in)->Coord0(); + for (int jn = in+1;jn<=nbn_loc;jn++) + {const Coordonnee& Cj = tab_N_el(jn)->Coord0(); + retour = MiN(retour,(Ci-Cj).Max_val_abs()); + }; + }; + break; + } + case TEMPS_t : + { for (int in = 1;in<=nbn_loc;in++) + {const Coordonnee& Ci = tab_N_el(in)->Coord1(); + for (int jn = in+1;jn<=nbn_loc;jn++) + {const Coordonnee& Cj = tab_N_el(jn)->Coord1(); + retour = MiN(retour,(Ci-Cj).Max_val_abs()); + }; + }; + break; + } + case TEMPS_tdt : + { for (int in = 1;in<=nbn_loc;in++) + {const Coordonnee& Ci = tab_N_el(in)->Coord2(); + for (int jn = in+1;jn<=nbn_loc;jn++) + {const Coordonnee& Cj = tab_N_el(jn)->Coord2(); + retour = MiN(retour,(Ci-Cj).Max_val_abs()); + }; + }; + break; + } + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "Maillage::Min_dist2Noeud_des_elements(... \n"; + Sortie(1); + }; + }; + return retour; +}; + +//----- lecture écriture de base info ----- +// lecture base info +// = 1 : on récupère tout +// = 2 : on récupère uniquement les données variables (supposées comme telles) +void Maillage::Lecture_base_info(ifstream& entr,const int cas) +{switch (cas) + { case 1 : // ------- on récupère tout ------------------------- + {// l'id et le nom du maillage et la dimension + int dime; string toto; int idmail_n; string nomDuMaillage_n; + entr >> toto >> idmail_n >> nomDuMaillage_n >> toto >> dime ; + // les types de problèmes associés +// { types_de_problemes.clear(); int nb=0; // init +// entr >> toto >> nb ; string type; +// for (int i=1;i<=nb;i++) +// {entr >> type;types_de_problemes.push_back(Id_nom_ElemTypeProblem(type));}; +// }; + { int nb=0; // init + entr >> toto >> nb ; string type; + types_de_problemes.Change_taille(nb); + for (int i=1;i<=nb;i++) + {entr >> type;types_de_problemes(i)=(Id_nom_ElemTypeProblem(type));}; + }; + // les ddl associés +// { ddl_representatifs_des_physiques.clear(); int nb=0; // init +// entr >> toto >> nb ; string ddl; +// for (int i=1;i<=nb;i++) +// {entr >> ddl;ddl_representatifs_des_physiques.push_back(Id_nom_ddl(ddl));}; +// }; + { int nb=0; // init + entr >> toto >> nb ; string type; + ddl_representatifs_des_physiques.Change_taille(nb); + for (int i=1;i<=nb;i++) + {entr >> type;ddl_representatifs_des_physiques(i)=(Id_nom_ddl(type));}; + }; + + // si le nom de maillage lu est différent de celui existant, + // on supprime le doublet dans la map de gestion et on met à jour + if (nomDuMaillage != nomDuMaillage_n) + { listeNomMail.erase(listeNomMail.find(nomDuMaillage)); + nomDuMaillage = nomDuMaillage_n; + listeNomMail[nomDuMaillage] = idmail_n; + idmail = idmail_n; + } + else + { // sinon on vérifie quand même que le numéro n'a pas changé + if (idmail != idmail_n) + { listeNomMail[nomDuMaillage] = idmail_n; + idmail = idmail_n; + }; + }; + if (dime != dimension) + cout << "\nErreur : valeur de la dimension non coherente avec " + << " l'espace de travail!\n" + << "Maillage::Lecture_base_info(ofstream& sort,int cas)" + << endl; + cout << " === lecture du maillage " << nomDuMaillage << " nb " << idmail << "\n" ; + //------------- lecture des noeuds ------------- + cout << " lecture des noeuds " ; + // le nombre de noeud + int nbNoeud = tab_noeud.Taille(); + entr >> nbNoeud >> toto; + // normalement ici on ne doit pas avoir déjà de noeud + Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud + // lecture des noeuds + Noeud * ptr; + for (int i=1; i<= nbNoeud; i++) + { ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage + ptr->Lecture_base_info(entr,cas); + Affectation_noeud(*ptr); + }; + // ------------ les elements finis ----------- + cout << ", lecture des elements \n" ; + entr >> toto; + // lecture du nombre d'element + int nbElement; + entr >> toto >> nbElement; + // dimensionnement dynamique du tableau d'elements + Change_nb_element(nbElement); + // Lecture des elements + Element * pte; + for (int i=1; i<= nbElement; i++) + { // lecture geometrie et interpolation + Enum_geom id_geom; Enum_interpol id_interpol; + EnumElemTypeProblem id_typeProb;string str_precision; + int num_elt; // donnee dont on ne se sert pas + entr >> toto >> num_elt >> id_geom >> id_interpol >> id_typeProb; + // on regarde le prochain caractère sans changer le flot + /////int cr=entr.peek(); + //--- début du remplacement du peek + char car = Picococar(entr); // = flot.peek(); + // on recupère l'entier correspondant au caractère + int cr = int(car); + //--- fin du remplacement du peek + // on regarde s'il y a une chaine discriminante + if (cr == int('_')) entr >> str_precision; + // ======== choix de l'element ===================================== + // et affectation du pointeur d'element en fonction de id_geom et id_interpol + // le numero d'element : num_elt, est affecte a l'element pointe par ptr + pte = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision); + if (pte == NULL) + { // l'operation a echouee + cout << "\n Erreur dans le choix d'element ****** "; + cout << "\n l\'element : " << Nom_interpol(id_interpol) + << " " << Nom_geom(id_geom) + << " n\'est pas present dans le programme ! " + << "\n Maillage::Lecture_base_info(..." << endl; + Sortie (1); + }; + // lecture des infos particulieres a l'element + Tableau * pt = & tab_noeud; + pte->Lecture_base_info(entr,pt,cas); + Affectation_element(*pte); + // si c'est le premier élément du premier maillage on regarde s'il s'agit + // d'un élément axisymétrique et on adapte l'espace de travail en conséquence + if ((i==1) && (idmail==1)) + { if (TestEnum_geom_axisymetrique(id_geom)) + ParaGlob::Change_en_AxiSymetrie(); + } + else + {// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent + if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie())) + {cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail + << " nom= " << nomDuMaillage; + if (ParaGlob::AxiSymetrie()) + cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)" + << " et l'element lu est axisymetrique !! "; + else + cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)" + << " et l'element lu n'est pas axisymetrique !! "; + cout << endl; + Sortie (1); + }; + }; + } + // ------------ les elements frontières ----------- + // il sont créé par ailleurs si il y en a besoin + break; + } + case 2 : // ----------- lecture uniquement de se qui varie -------------------- + {// le nom du maillage pour vérification +// cout << "\n debug **** Maillage::Lecture_base_info\n" +// << "\n entr.rdstate() " << entr.rdstate() << flush; +//entr.clear(); + string inter,nomDuMail; + entr >> inter >> nomDuMail ; +//string truc; entr >> truc; +// cout << "\n debug **** Maillage::Lecture_base_info\n" +// << " inter=" << inter << " nomDuMaillage= " << nomDuMail +// << " titi= "<< titi << " titi1= "<< titi1 +// << "\n entr.rdstate() " << entr.rdstate() << flush; + + if (nomDuMail != nomDuMaillage) + { cout << "\nErreur : le nom du maillage lu (" << nomDuMail << ") n'est pas identique avec celui en cours (" + << nomDuMaillage << ") !! " + << "\n Maillage::Lecture_base_info(ofstream& sort,int cas)" + << endl; + Sortie (1); + }; + //------------- les noeuds ------------- + // le tableau doit être déjà dimensionné + int nbNoeud = tab_noeud.Taille(); + for (int i=1; i<=nbNoeud;i++) + tab_noeud(i)->Lecture_base_info(entr,cas); + // ------------ les elements finis ----------- + int nbElement = tab_element.Taille(); + Tableau * pt = & tab_noeud; + int nb;string toto; + for (int j=1;j<=nbElement;j++) + {entr >> toto >> nb; // le numéro de l'élément + tab_element(j)->Lecture_base_info(entr,pt,cas); + }; + // ------------ les elements frontières ----------- + // il sont créé par ailleurs si il y en a besoin + break; + } + default : + { cout << "\nErreur : valeur incorrecte du type de lecture !\n"; + cout << "Maillage::Lecture_base_info(ofstream& sort,int cas)" + << " cas= " << cas << endl; + Sortie(1); + }; + }; +}; + +// écriture base info +// = 1 : on sauvegarde tout +// = 2 : on sauvegarde uniquement les données variables (supposées comme telles) +void Maillage::Ecriture_base_info(ofstream& sort,const int cas) +{switch (cas) + { case 1 : // ------- on sauvegarde tout ------------------------- + {// l'id et le nom du maillage et la dimension + sort << "\n num= " << idmail <<" "<< nomDuMaillage <<" " + << "dim= " << dimension; + // les types de problèmes associés +// {list ::iterator il,ilfin=types_de_problemes.end(); +// sort <<"\n types_de_problemes: " << types_de_problemes.size() ; +// for (il=types_de_problemes.begin();il != ilfin;il++) +// sort << NomElemTypeProblem(*il); +// }; + {int tail = types_de_problemes.Taille(); + sort <<"\n types_de_problemes: " << tail ; + for (int i=1;i<=tail;i++) + sort << " "<< NomElemTypeProblem(types_de_problemes(i)); + }; + + // les ddl associés +// {list ::iterator il,ilfin=ddl_representatifs_des_physiques.end(); +// sort <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size(); +// for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++) +// Nom_ddl(*il); +// }; + {int tail = ddl_representatifs_des_physiques.Taille(); + sort <<"\n type_de_ddl_associes: " << tail; + for (int i=1;i<=tail;i++) + sort << " "<< Nom_ddl(ddl_representatifs_des_physiques(i)); + }; + + sort <<"\n"; + //------------- les noeuds ------------- + // le nombre de noeud + int nbNoeud = tab_noeud.Taille(); + sort << nbNoeud << " noeuds \n"; + // sorti des noeuds + for (int i=1; i<=nbNoeud;i++) + tab_noeud(i)->Ecriture_base_info(sort,cas); + // ------------ les elements finis ----------- + sort << "\n --les_elements-- "; + // le nombre d'élément + int nbElement = tab_element.Taille(); + sort <<"\n nombre_d'element " << nbElement ; + // écriture des éléments + for (int j=1;j<=nbElement;j++) + { // tout d'abord les données de différentiation + // numéro geometrie et interpolation + sort << "\n\n element: " << tab_element(j)->Num_elt() << " " + << tab_element(j)->Id_geometrie() << " " + << tab_element(j)->Interpolation() << " " + << tab_element(j)->TypeProblem() << " " + << tab_element(j)->Infos_annexe() << "\n"; + // puis les données de l'élément + tab_element(j)->Ecriture_base_info(sort,cas); + }; + sort << "\n "; + // ------------ les elements frontières ----------- + // ne sont pas sauvegardé car reconstruit à la demande + break; + } + case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- + {// le nom du maillage pour vérification en lecture + sort << "\nnomDuMail= " << nomDuMaillage << "\n"; + //------------- les noeuds ------------- + int nbNoeud = tab_noeud.Taille(); + // sorti des noeuds + for (int i=1; i<=nbNoeud;i++) + tab_noeud(i)->Ecriture_base_info(sort,cas); + // ------------ les elements finis ----------- + int nbElement = tab_element.Taille(); + for (int j=1;j<=nbElement;j++) + {sort << "\n\n element_nb: " << tab_element(j)->Num_elt() << " "; + tab_element(j)->Ecriture_base_info(sort,cas); + }; + // ------------ les elements frontières ----------- + // ne sont pas sauvegardé car reconstruit à la demande + + break; + } + default : + { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n"; + cout << "Maillage::Ecriture_base_info(ofstream& sort,int cas)" + << " cas= " << cas << endl; + Sortie(1); + }; + }; +}; + +// ------ informations utiles par exemples pour la visualisation + // retourne les dimensions minis et maxi suivant les axes du repère + // absolu du maillage (en faite le calcul est fondé + // uniquement sur la position des noeuds du maillage + // le premier vecteur contient les minimums + // le deuxième vecteur contient les maximums +Tableau Maillage::Taille_boiteMail() + { // définition du tableau de retour + Tableau tabret(2); + // cas particulier de maillage vide + int nbNoeud = tab_noeud.Taille(); + if (nbNoeud == 0) + return tabret; + // sinon le cas normal + tabret(1).Change_taille(dimension); + tabret(2).Change_taille(dimension); + // on balaie tous les coordonnées des noeuds pour déterminer les tailles + // maxi et mini + // dans une première étape on regarde s'il existe les coordonnées à t=0 + // t et t+dt, ceci à partir du premier noeud qui sert de test + // on cherche les extrémas + for (int i=1; i<=nbNoeud;i++) + { Coordonnee a0=tab_noeud(i)->Coord0(); + for (int k=1;k<= dimension;k++) + { if (tabret(1)(k) > a0(k)) + tabret(1)(k) = a0(k); + if (tabret(2)(k) < a0(k)) + tabret(2)(k) = a0(k); + } + // dans le cas de coordonnées à t idem + if (tab_noeud(i)->ExisteCoord1()) + {Coordonnee aat=tab_noeud(i)->Coord1(); + for (int k=1;k<= dimension;k++) + { if (tabret(1)(k) > aat(k)) + tabret(1)(k) = aat(k); + if (tabret(2)(k) < aat(k)) + tabret(2)(k) = aat(k); + } + }; + // dans le cas de coordonnées à t+dt idem + if (tab_noeud(i)->ExisteCoord2()) + {Coordonnee aatdt=tab_noeud(i)->Coord2(); + for (int k=1;k<= dimension;k++) + { if (tabret(1)(k) > aatdt(k)) + tabret(1)(k) = aatdt(k); + if (tabret(2)(k) < aatdt(k)) + tabret(2)(k) = aatdt(k); + } + }; + } + + return tabret; + }; + +//========================== fonction protegee ============================= + +// definition des elements mitoyens aux elements de frontiere +// à la fin du programme tous les éléments mitoyens sont stocké dant les éléments front +// la manip est de créer des éléments frontières aux éléments frontières existant +// ensuite deux éléments sont mitoyens s'il ont la même frontière +// à la fin du programme tous les frontières des éléments frontières sont supprimé +void Maillage::MitoyenFront() +{ // le tableau indice_NFr (indice des noeuds frontières) va permettre une recherche plus rapide + // on le construit: + int tab_noeud_taille= tab_noeud.Taille(); + Tableau > indice_NFr(tab_noeud_taille); + // indice_NFr contiend les front succeptible d'avoir des frontières géométriques communes + LaLIST ::iterator iF; + LaLIST ::iterator iFfin = listFrontiere.end(); + for (iF = listFrontiere.begin();iF!=iFfin; iF++) + { Front* fro = &(*iF); + ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière + // récup de son tableau de noeud + Tableau& tabn = efem1->TabNoeud(); + int tabntaille = tabn.Taille(); + for (int ij=1;ij<= tabntaille;ij++) + // on balaie ses noeuds + indice_NFr((tabn(ij)->Num_noeud())).push_back(fro); + }; + // on supprime les doublons + for (int i=1;i<=tab_noeud_taille;i++) + { List_io & intertab = indice_NFr(i); // pour allèger l'écriture + intertab.sort(); // on ordonne + intertab.unique(); // on supprime les doublons + }; + +//-- debug +// cout << "\n maillage " << idmail << "\n"; +// for (int ii=1;ii<= tab_noeud.Taille();ii++) +// {cout << "\n noeud " << ii << "\n"; +// list::iterator ina,infin; +// list& intertab = indice_NFr(ii); // pour allèger l'écriture +// infin = intertab.end(); +// for (ina = intertab.begin();ina!=infin;ina++) +// {Front* elem2 = (*ina); // recup de l'element +// elem2->Affiche(); +// }; +// }; +// cout << endl; +// // Sortie(1); +//--fin debug + + + // on determine les elements front mitoyens a chaque element frontiere, s'ils existent + LaLIST ::iterator iE,jE,iiE; + LaLIST inters; // stockage intermediaire + LaLIST ::iterator iEfin = listFrontiere.end(); + for ( iE = listFrontiere.begin(); iE !=iEfin; iE++) + // pour chaque element on recherche d'autre element ayant des frontieres communes + { // création d'élément frontières secondaires des frontières primaires + Tableau tabi = (*iE).Eleme()->Frontiere(); // frontieres géométriques de iE +// pour le débug cout << "\n on cherche un mitoyen a "; (*iE).Affiche(); + int tabitaille = tabi.Taille(); + for (int i=1;i<= tabitaille;i++) + { ElFrontiere* elfr = tabi(i); +// pour le débug cout << " frontiere : " << i ; + // si deux éléments frontières sont identiques alors tous leurs noeuds + // sont identiques. En particulier le premier noeud de *elfr est commum + // avec tous les éléments succeptibles de contenir un élément frontière + // identique. On va donc utiliser le vector indice_NFr qui contiend cette liste + int numnoeud = (elfr->TabNoeud())(1)->Num_noeud(); + list::iterator ina,infin; + list& intertab = indice_NFr(numnoeud); // pour allèger l'écriture + infin = intertab.end(); + // on balaie les élément succeptibles d'avoir des frontières communes + for (ina = intertab.begin();ina!=infin;ina++) + {Front* elem2 = (*ina); // recup de l'element frontière + // on ne fait la recherche que pour les éléments différent de *iE + if (*elem2!=*iE) + {Tableau tabj = elem2->Eleme()->Frontiere(); // frontieres de ina + int tabjtaille = tabj.Taille(); + for (int j=1;j<= tabjtaille;j++) + { // ElFrontiere * tabjjOppose=(tabj(j)->Oppose()); // element transitoire + if ((*elfr) == *(tabj(j))) // || + // (*(tabi(i)) == *tabjjOppose) ) + // iE et ina ont une frontiere commune, sont donc mitoyen + { //Front pj = &(*(*ina)); + inters.push_back(&(*elem2)); +//-- debug +//{Tableau & toto = elfr->TabNoeud(); cout << "\n premiere frontiere NB: "<< i << ": "; +//for (int ii=1;ii<=toto.Taille();ii++) cout <Num_noeud() << " ";} +//{Tableau & toto = (tabj(j))->TabNoeud(); cout << "\n frontiere mitoyenne NB: "<< j << ": "; +//for (int ii=1;ii<=toto.Taille();ii++) cout <Num_noeud() << " "; } +//cout << "\n "; +//if ((j1==3)&&(j2==6)) +// cout << "on y est "; +//--fin debug +// pour le débug +// cout << "\n on a trouve une frontiere commune "; +// elem2->Affiche(); +// cout << " frontiere commune: noeuds: "; +// Tableau tabno = (tabj(j))->TabNoeud(); +// int nb = tabno.Taille(); +// for (int ijk=1;ijk<=nb; ijk++) +// cout << tabno(ijk)->Num_noeud() << " "; +// fin pour le débug + }; + // delete tabjjOppose; // suppression de l'element transitoire + }; + }; + }; + }; + // fin de la recherche concernant elfr + // on supprime les doublons + inters.sort(); // on ordonne + inters.unique(); // on supprime les doublons + // creation d'un tableau a la place de la liste + Tableau tabb((int) inters.size()); + LaLIST ::iterator ip; int i2; + LaLIST ::iterator ipfin=inters.end(); + LaLIST ::iterator ipdebut=inters.begin(); + for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++) + tabb(i2) = &(*(*ip)); + // def des elements mitoyen + (*iE).DefMitoyen(tabb); +// -- débug --- affichage +//if (inters.size() > 6) +// {cout << "\n nb frontière > 6 "; +// (*iE).Affiche(); +// cout << endl; +// }; +// -- fin débug --- affichage + // on vide la liste + inters.erase(ipdebut,ipfin); + }; +// -- débug --- affichage +// for ( iE = listFrontiere.begin(); iE !=iEfin; iE++) +// (*iE).Affiche(); +// -- fin débug --- affichage + //effacement de tous les éléments frontières secondaires des éléments frontières + // primaires + LaLIST ::iterator iEE; + for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++) + (*iEE).Eleme()->EffaceFrontiere(); + +// -- débug --- affichage +// for ( iE = listFrontiere.begin(); iE !=iEfin; iE++) +// { Tableau & tabi = (*iE).TabMitoyen(); +// int tabitaille = tabi.Taille(); +// for (int i=1;i<= tabitaille;i++) +// { Front* elfr = tabi(i); +// cout << "\n"; +// elfr->Affiche(); +// } +// }; +//// -- fin débug --- affichage +// + + }; + + // dans le cas où les éléments frontières sont des lignes, on les ordonnes + // de manière à former une ligne continue + void Maillage::OrdonancementDesLigne() + {// on définit une liste intermédiaire + LaLIST interlist; + // on commence par le premier élément de la liste et de proche en proche on + // rempli la liste + // on passe en revue les éléments frontières +// LaLIST ::iterator iEE; +// for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++) + // (*iEE).elem->EffaceFrontiere(); + }; + +// definition d'un stockage contenant tous les Front associés à toutes les frontières de tous les éléments +// puis définition des elements mitoyens à ces Front : deux éléments Front sont mitoyens +// s'ils correspondent à des Element différents, et si les frontières associées possèdent les mêmes noeuds +// toutes ces informations sont stockées dans : mitoyen_de_chaque_element (cf. sa description) +void Maillage::Calcul_tous_les_front_et_leurs_mitoyens() +{ // on crée les éléments frontières dans chaque élément + int tabelTaille = tab_element.Taille(); + mitoyen_de_chaque_element.Change_taille(tabelTaille); // dimensionnement + // on boucle sur les elements + for (int i2 = 1; i2 <= tabelTaille; i2++) + { // création des éléments frontières + Element * elem1 = tab_element(i2); + elem1->Frontiere(true); + // puis on crée tous les éléments Front, qui sont alors stockés dans mitoyen_de_chaque_element(i2) + // par contre pour l'instant on n'a pas les mitoyens de calculés + const Tableau & tab1 = elem1->Frontiere(); // et de ses frontières + Tableau & tab_front = mitoyen_de_chaque_element(i2); // pour simplifier + int tab1Taille = tab1.Taille(); // nb de frontières + tab_front.Change_taille(tab1Taille); // dimensionne mitoyen_de_chaque_element(i2) + for (int j=1;j<=tab1Taille;j++) + tab_front(j) = Front(*tab1(j),elem1,j); +//cout << "\n les front"; +//for (int j=1;j<=tab1Taille;j++) +// tab_front(j).Affiche(); + }; + + // on crée des tableaux permettant d'accélérer l'algorithme final + // pour chaque noeud on note quel élément contiend ce noeud + // "indice" contiend les numéros d'élément succeptible d'avoir des frontières communes + Calcul_indice(); + // on va boucler sur les éléments en regardant + // pour chaque frontière si il y a d'autres frontières mitoyennes c-a-d si + // il y a d'autres frontières identiques + for (int i1 = 1; i1 <= tabelTaille; i1++) + {Tableau & tab_front = mitoyen_de_chaque_element(i1); // pour simplifier + int tab1Taille = tab_front.Taille(); // nb de frontières (qui sont déjà stockées) + for (int j1=1;j1<= tab1Taille;j1++) // on boucle sur les frontière de l'élément principale (nb=i1) + // on essaie de voir si l'élément j1 est recevable + {const ElFrontiere * elfr = tab_front(j1).Eleme_const(); // récup de la frontière + // si deux éléments frontières sont identiques alors tous leurs noeuds + // sont identiques. En particulier le premier noeud de *elfr est commum + // avec tous les éléments succeptibles de contenir un élément frontière + // identique. On va donc utiliser la liste indice qui contiend cette liste + int numnoeud = (elfr->TabNoeud_const())(1)->Num_noeud(); + list::iterator ina,infin; + list& intertab = indice(numnoeud); // pour allèger l'écriture + infin = intertab.end(); + LaLIST inters; // stockage intermediaire + // on balaie les élément succeptibles d'avoir des frontières communes + for (ina = intertab.begin();ina!=infin;ina++) + {Element * elem2 = *ina; // recup de l'element + // on ne fait la recherche que pour les éléments différents de elem1 + int num_elem2 = elem2->Num_elt(); + if (num_elem2 != i1) + {// récup des éléments front correspondant à elem2 + Tableau & tab_fro = mitoyen_de_chaque_element(num_elem2); + int tab_fro_taille = tab_fro.Taille(); + for (int j2=1;j2<=tab_fro_taille;j2++) + { // on compare + if ((*tab_fro(j2).Eleme_const()) == (*elfr)) + {// on récupère le Front de l'élément elem2, pour la frontière j2 + Front* front_j2 = &tab_fro(j2); + inters.push_back(front_j2); +//--debug +//tab_front(j1).Affiche(); +//front_j2->Affiche(); +//--fin_debug + }; + }; + }; + }; + + // on supprime les doublons + inters.sort(); // on ordonne + inters.unique(); // on supprime les doublons + // creation d'un tableau a la place de la liste + Tableau tabb((int) inters.size()); + LaLIST ::iterator ip; int i2; + LaLIST ::iterator ipfin=inters.end(); + LaLIST ::iterator ipdebut=inters.begin(); + for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++) + tabb(i2) = &(*(*ip)); + // def des elements mitoyen, stocké dans mitoyen_de_chaque_element(i1) + tab_front(j1).DefMitoyen(tabb); + + }; // fin de la boucle sur les frontières de elem1 + };// fin de la boucle externe des éléments +//--debug +//for (int i=1;i<=mitoyen_de_chaque_element.Taille();i++) +// {cout <<"\n\n **** element: "<& tab_f = mitoyen_de_chaque_element(i); +// for (int j=1;j<=tab_f.Taille();j++) +// tab_f(j).Affiche(); +// } +//--fin debug + // effacement du contenu du tableau indice + indice.Libere (); + +}; + + +// lectures des infos pour le choix d'un élément +void Maillage::Lecture_info_1element(UtilLecture * entreePrinc,int& num_elt,Enum_geom& id_geom + ,Enum_interpol& id_interpol,EnumElemTypeProblem& id_typeProb + ,string& str_precision) + { // mise en place des valeurs par défaut + str_precision = ""; + id_typeProb = MECA_SOLIDE_DEFORMABLE; // type par défaut + // lecture des champs qui doivent être toujours présents + *(entreePrinc->entree) >> num_elt >> id_geom >> id_interpol; + + // cas d'info annexe ou du type de problème + // on regarde le prochain caractère sans changer le flot + /// int cr=(entreePrinc->entree)->peek(); ne marche pas !!! + //--- début du remplacement du peek + char car = Picococar(*(entreePrinc->entree)); // = flot.peek(); + // on recupère l'entier correspondant au caractère + int cr = int(car); + //--- fin du remplacement du peek + // si c'est un chiffre c'est fini pour le choix de l'élément + int zero = int('0'); int neuf = int('9'); +// if ((cr >= int('0'))&&(cr <= int('9'))) return; + if ((cr >= zero)&&(cr <= neuf)) return; + // maintenant on a deux cas, soit des infos annexes ou soit + // la définition du type de pb suivi ou non d'infos annexes + if (cr == int('_')) + // cas où on a des infos annexes de choix + { *(entreePrinc->entree) >> str_precision; + // ensuite il ne doit y avoir que des numéros donc fin + return; + } + // ou on regarde s'il y a définition du type de problème + // qui doit commencer par une lettre + else if ( ((cr >= int('a'))&&(cr<=int('z'))) || + ((cr >= int('A'))&&(cr<=int('Z'))) ) + { *(entreePrinc->entree) >> id_typeProb; + // on regarde s'il y a des infos annexes après le type de problem + if (cr == int('_')) + // cas où on a des infos annexes de choix + { *(entreePrinc->entree) >> str_precision; + // ensuite il ne doit y avoir que des numéros donc fin + return; + } + }; + // sinon c'est le cas qui ne doit pas arriver mais pour éviter des warnings + return; + }; + +// affectation d'un noeud au maillage c-a-d au tableau de pointeur de noeud, +// a condition que la place ne soit pas déjà occupée sinon on change le numéro +// de noeud et on augmente le tableau +void Maillage::Affectation_noeud(Noeud& noeud) + { int nbn = noeud.Num_noeud(); + if (tab_noeud(nbn) == NULL) + {tab_noeud(nbn)=&noeud;} + else + // on augmente la place + {int tail_tab_noeud = tab_noeud.Taille()+1; + tab_noeud.Change_taille(tail_tab_noeud); + noeud.Change_num_noeud(tail_tab_noeud); + tab_noeud(tail_tab_noeud)=&noeud; + if (ParaGlob::NiveauImpression() > 0) + {cout << "\n warning : le numero initial du noeud " << nbn << " est remplace par " + << " le numero d'ordre attribue automatiquement par herezh " << tail_tab_noeud + << "\n seul ce dernier sera utilise par la suite ! " << endl; + if (ParaGlob::NiveauImpression() > 5) + cout << "\n Maillage::Affectation_noeud (Noeud& noeud) " << endl; + }; + }; + }; + +// affectation d'un element au maillage c-a-d au tableau de pointeur d'element, +// a condition que la place ne soit pas déjà occupée sinon on change le numéro +// de l'élément et on augmente le tableau +void Maillage::Affectation_element(Element& element) + { int nbe = element.Num_elt(); + if (tab_element(nbe) == NULL) + {tab_element(nbe)=&element;} + else + // on augmente la place + {int tail_tab_element = tab_element.Taille()+1; + tab_element.Change_taille(tail_tab_element); + element.Change_num_elt(tail_tab_element); + tab_element(tail_tab_element)=&element; + if (ParaGlob::NiveauImpression() > 0) + {cout << "\n warning : le numero initial de l'element " << nbe << " est remplace par " + << " le numero d'ordre attribue automatiquement par herezh " << tail_tab_element + << "\n seul ce dernier sera utilise par la suite ! " << endl; + if (ParaGlob::NiveauImpression() > 5) + cout << "\n Maillage::Affectation_element (Element& element) " << endl; + }; + }; + // on met à jour éventuellement les types de problèmes gérés + EnumElemTypeProblem enu = element.Id_TypeProblem(); + if (!types_de_problemes.Contient(enu)) + {int tail = types_de_problemes.Taille(); + types_de_problemes.Change_taille(tail+1); + types_de_problemes(tail+1) = enu; + ddl_representatifs_des_physiques.Change_taille(tail+1); + switch (enu) + {case MECA_SOLIDE_DEFORMABLE : + ddl_representatifs_des_physiques(tail+1)=X1;break; + case THERMIQUE : + ddl_representatifs_des_physiques(tail+1)=TEMP;break; + default : + cout << "\n***Erreur : pour l'instant le type de probleme: "<) +// les éléments supplémentaires ont un pointeur mis à Null +void Maillage::Change_nb_noeud (int nouveau_nb) +{ int vieille_taille = tab_noeud.Taille(); + tab_noeud.Change_taille(nouveau_nb); + for (int i=vieille_taille+1;i<=nouveau_nb;i++) + tab_noeud(i)=NULL; +}; + +// Modifie le nombre d'elements du maillage (N.B.: Fait appel +// a la methode Change_taille de la classe Tableau) +// les éléments supplémentaires ont un pointeur mis à Null +void Maillage::Change_nb_element (int nouveau_nb) +{ int vieille_taille = tab_element.Taille(); + tab_element.Change_taille(nouveau_nb); + for (int i=vieille_taille+1;i<=nouveau_nb;i++) + tab_element(i)=NULL; +}; + + + + + + + + + + diff --git a/Maillage/Maillage.h b/Maillage/Maillage.h new file mode 100755 index 0000000..9bb4832 --- /dev/null +++ b/Maillage/Maillage.h @@ -0,0 +1,959 @@ +// FICHIER : Maillage.h +// CLASSE : Maillage + +// This file is part of the Herezh++ application. +// +// The finite element software Herezh++ is dedicated to the field +// of mechanics for large transformations of solid structures. +// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) +// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . +// +// Herezh++ is distributed under GPL 3 license ou ultérieure. +// +// Copyright (C) 1997-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: . + +/************************************************************************ + * DATE: 23/01/97 * + * $ * + * AUTEUR: G RIO (mailto:gerardrio56@free.fr) * + * $ * + * PROJET: Herezh++ * + * $ * + ************************************************************************ + * BUT: def de la classe Maillage, * + * Une instance de la classe Maillage est identifiee a partir * + * de la dimension, des tableaux des noeuds et des elements. * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * * + * VERIFICATION: * + * * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * ! ! ! ! * + * $ * + * '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * + * MODIFICATIONS: * + * ! date ! auteur ! but ! * + * ------------------------------------------------------------ * + * $ * + ************************************************************************/ + + +#ifndef MAILLAGE_H +#define MAILLAGE_H + + +#include +#include + + +#include "Noeud.h" +#include "Element.h" +#include "Tableau_T.h" +#include "UtilLecture.h" +#include "Enum_geom.h" +#include "Enum_interpol.h" +#include "LesReferences.h" +#include "Front.h" +#include "LaList.h" +#include "Nb_assemb.h" +#include "Ddl_enum_etendu.h" +#include "Droite.h" +#include "Plan.h" +#include "Sphere.h" +#include "Cylindre.h" +#include "Cercle.h" +#include "Condilineaire.h" +#include "DiversStockage.h" + + +/// @addtogroup Les_Maillages +/// @{ +/// + +//------------------------------------------------------------------ +//! Maillage: un maillage particulier +//------------------------------------------------------------------ +/// \author Gérard Rio +/// \version 1.0 +/// \date 23/01/97 + +class Maillage +{ + public : + friend class LesMaillages; + + // CONSTRUCTEURS : + // pour tous les constructeurs: map < string, int , std::less >* lisNomMail, + // est un tableau associatif nom <=> numéro de maillage, qui est utilisé par + // les maillages, mais mis à jour par chaque maillage. + // nom_maillage : est facultatif, s'il est différent de ".", il est pris en compte + + // Constructeur par defaut + Maillage (map < string, int , std::less > & lisNomMail,int nmail=1,int dim=3 + ,const string& nom_maillage = "."); + + // Constructeur fonction d'une dimension, du nombre de noeuds + // du nombre d'elements, et d'un numero d'identification (le nb de maillage) + Maillage (map < string, int , std::less > & lisNomMail + ,int dim,int n_noeud,int n_elt,int nmail + ,const string& nom_maillage = "."); + + // Constructeur fonction de la plupart des informations (qui peuvent être vide + // mais doivent être cohérentes) + // *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments, + // ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé + Maillage (map < string, int , std::less > & lisNomMail + ,int dim,list & li_noeud, list li_element + ,int nmail + ,const string& nom_maillage = "."); + + // Constructeur de copie, cependant ici il n'y a pas de création de noeud ni d'élément + // c'est seulement une création de nouveaux conteneurs de pointeurs + // cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut + // ensuite les définir + Maillage (const Maillage& mail); + + // Constructeur de copie, avec création de nouveaux noeuds et éléments identiques à ceux passées + // en argument, nmail: donne le numéro du nouveau maillage créée, qui est donc a priori différent + // de celui de mail, idem pour le nom du maillage + // les frontières ne sont pas transmises ni calculées ! + Maillage (map < string, int , std::less > & lisNomMail + ,int nmail, const string& nomDuMaillage, const Maillage& mail); + + // DESTRUCTEUR : + ~Maillage (); + + + // METHODES : + + // lecture de maillages au travers des outils de la classe + // UtilLecture et def des references s'y rapportant + void LectureMaillage(UtilLecture * entreePrinc,LesReferences& lesRef); + // lecture et application des opérations d'affinages sur le maillage: ex:déplacement solide + void LectureEtApplicationAffinage(UtilLecture * entreePrinc,LesReferences& lesRef); + + // ajout d'une liste de noeud à un maillage + // si le numéro de maillage associé au noeud est nul, il est remplacé par celui du maillage + // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a + // création d'un nouveau noeud identique, avec le numéro this + // ajout éventuel d'une liste de référence de noeuds, si celle-ci est non-nulle + // il y a création de nouvelles ref correspondantes au numéro de maillage de this + // et ces références sont rajoutées à lesRef + void Ajout_de_Noeuds(const list & taN,list * lref=NULL,LesReferences* lesRef=NULL ); + // ajout d'une liste d'éléments et de noeud à un maillage + // si le numéro de maillage associé à l'élément ou noeud est nul, il est remplacé par celui du maillage + // si le numéro de maillage est déjà existant et est différent ce celui de this, il y a + // création d'un nouvel item identique, avec le numéro this + // ajout éventuel d'une liste de références associées , si celle-ci est non-nulle + // il y a création de nouvelles ref correspondantes au numéro de maillage de this + // et ces références sont rajoutées à lesRef + // les noeuds qui sont associés aux éléments de taE, doivent faire partie : soit de taN, soit du maillage this + void Ajout_elements_et_noeuds(const list & taN, const list & taE,list * lref,LesReferences* lesRef ); + + // affichage et definition interactive des commandes + // cas = 1: interactif complet + // cas = 2: entrée uniquement de noms de fichier + void Info_commande_Maillages(UtilLecture * entreePrinc,LesReferences& lesRef, int cas); + + // Affiche les donnees du maillage + void Affiche () const ; + + // Affiche les donnees du maillage dans un fichier + // dont le nom est construit à partir du nom du maillage + // au format ".her" et ".lis" + void Affiche_dans_her_lis(LesReferences &lesRef,Enum_dure temps); + + //modification du maillage pour le restreindre aux seuls éléments de la référence passée en paramètre + // toutes les infos relatives à des éléments supprimés, sont également supprimés + void Restreint_sous_maillage(LesReferences* lesRef, string nom_ref); + + // Surcharge de l'operateur = : realise l'egalite de deux maillages + // cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut + // ensuite les définir + Maillage& operator= (Maillage& mail); + + inline int Dimension () const + // Retourne la dimension + { return dimension; }; + + // ramène la liste des problèmes physiques gérés par les éléments du maillage + inline const Tableau & Ddl_representatifs_des_physiques()const + {return ddl_representatifs_des_physiques;}; + + // ramene la liste des degrés de liberté inconnus, associés aux pb + // physiques gérés par les éléments qui existent dans le maillage + // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i + // Si éléments thermiques -> ddl de température + // Si éléments méca + éléments thermiques -> ddl Xi et température + // etc. en fonction des éléments qui existent dans le maillage + inline const Tableau & Types_de_problemes() const + {return types_de_problemes;}; + + inline int Nombre_noeud_elt(int i) const + // Retourne le nombre de noeuds lies au ieme element + { return tab_element(i)->Nombre_noeud(); }; + + inline int Nombre_noeud() const + // Retourne le nombre de noeuds du maillage + { return tab_noeud.Taille(); }; + + inline int Nombre_element() const + // Retourne le nombre d'elements du maillage + { return tab_element.Taille(); }; + + inline Tableau& Tab_noeud() + // Retourne le tableau des noeuds + { return tab_noeud; }; + + inline Tableau& Tab_element() + // Retourne le tableau des elements + { return tab_element; }; + + inline Noeud& Noeud_mail(int i) + // Retourne le ieme noeud Noeud du tableau tab_noeud + { return *tab_noeud(i); }; + + inline Element& Element_mail(int i) + // Retourne le ieme element Element du tableau tab_element + { return *tab_element(i); }; + // idem mais en version constant + inline const Element& Element_mail_const(int i) + { return *tab_element(i); }; + + // test si toutes les informations des maillages sont completes + // = true -> complet + // = false -> incomplet + bool Complet(); + + // ramene la demi largeur de bande en ddl et la largeur de bande + void Largeur_Bande(int& demi, int& total,const Nb_assemb& nb_casAssemb); + + // test pour savoir si tous les coordonnées des noeuds d'un maillage sont imposé + // ramène 1 si tout est fixé, 0 sinon + int Tous_Xi_fixes(const Nb_assemb& casAss) const; + + // calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement + // a priori le calcul s'effectue par une moyenne des normales des éléments qui + // entourent le noeud. + // init -> calcul des normales à t=0 + // et ajout conteneur aux noeuds des normales à t = 0 et t + void InitNormaleAuxNoeuds(); + // mise à jour -> mise à jour des normales à t + void MiseAjourNormaleAuxNoeuds(); + // mise à jour -> mise à jour des normales à t + // mais ici, on calcule les normales à tdt, et on transfert à t + // cette méthode est utile si on veut utiliser des normales à t pour une valeur + // particulière (transitoire) de la géométrie à tdt + // cf: l'algo non dyna par exempel + void MiseAjourNormaleAuxNoeuds_de_tdt_vers_T(); + + // creation des elements frontiere + void CreeElemFront(); + + // ramene un pointeur sur la liste des elements frontieres + inline LaLIST * ListFront() { return &listFrontiere;}; + // ramene le tableau des noeuds de la frontière + Tableau& Tab_noeud_front() {return tab_noeud_front; }; + + // ramene le nom du maillage + string NomDuMaillage() {return nomDuMaillage;}; + + // change le nom et le numéro du maillage + void ChangeNomNumeroMaillage(const string & nom,int num); + + // ramène le numéro du noeud le plus proche du point donné à t=0, + int Noeud_le_plus_proche_0(const Coordonnee& M); + // idem à t + int Noeud_le_plus_proche_t(const Coordonnee& M); + // idem à tdt + int Noeud_le_plus_proche_tdt(const Coordonnee& M); + + // ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage + double Max_var_dep_t_a_tdt() const; + + // ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments + double Min_dist2Noeud_des_elements(Enum_dure temps) const; + + // transfert de grandeurs des points d'intégration aux noeuds + // 1- en entrée les type de ddl internes que l'on veut transférer + // idem pour les type évoluées et les types particuliers + // 2- en entrée: cas qui indique la méthode de transfert à utiliser + // =1 : les valeurs aux noeuds sont obtenue par moyennage des valeurs des pts d'integ les plus près + // des éléments qui entourent le noeud + // on décompose le processus en trois étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois + // le même transfert + + // A) première étape def des conteneurs et c'est tout, la méthode peut donc être utilisée + // pour autre chose. tabQ: permet d'avoir plusieurs listes de TypeQuelconque + // en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur + // est nulle on n'en tient pas compte + void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu + ,const Tableau * >& tabQ); + // B) initialisation des updates sur les noeuds + void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu + ,const Tableau * >& tabQ,int cas); + + // C) exécution du transfert + // transfert incrémental (pour un élément et tous les pt d'integ): + // transfert de ddl de tous les pt d'integ aux noeuds d'un éléments (on ajoute aux noeuds, on ne remplace pas) + // les ddl doivent déjà exister aux noeuds sinon erreur + // il doit s'agir du même type de répartition de pt d'integ pour toutes les grandeurs + void TransfertPtIntegAuNoeud(Element& ele,const List_io < Ddl_enum_etendu >& lietendu + ,const Tableau > & tab_val,int cas) + {ele.TransfertAjoutAuNoeuds(lietendu,tab_val,cas);}; + // idem pour des grandeurs quelconques, transfert de "tous" les points d'intégration en même temps + // ceci pour optimiser, les informations sont ici contenues dans les types quelconques + // liQ_travail: est une liste de travail qui sera utilisée dans le transfert + // - transfert de type quelconque des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds, + // - on ne remplace pas). Les types quelconques doivent déjà exister. + // - un tableau tab_liQ correspondent aux grandeurs quelconque pour tous les pt integ. tab_liQ(i) est associé au pt d'integ i + // - Toutes les listes sont identiques au niveau des descripteurs (types...) ce sont uniquement les valeurs numériques + // - c-a-dire les valeurs associées à TypeQuelconque::Grandeur qui sont différentes (elles sont associées à chaque pt d'integ) + // - liQ_travail: est une liste de travail qui sera utilisée dans le transfert + void TransfertPtIntegAuNoeud(Element& ele,const Tableau >& tab_liQ + ,List_io < TypeQuelconque > & liQ_travail,int cas) + {ele.TransfertAjoutAuNoeuds(tab_liQ,liQ_travail,cas);}; + // D) dernière étape: (par exemple calcul des moyennes en chaque noeuds) + // les résultats sont stockés aux noeuds + void FinTransfertPtIntegAuNoeud(const List_io < Ddl_enum_etendu >& lienu + ,const Tableau * >& tabQ,int cas); + + // ..... cumul et moyenne de grandeurs venant des éléments vers les noeuds (exemple la pression appliquée) ..... + // on décompose le processus en 4 étapes pour éviter d'initialiser plusieurs fois lorque l'on refait à chaque fois + // la même opération (typiquement à chaque incrément) + // on peut utiliser: + // A) AjoutConteneurAuNoeud : pour ajouter des conteneurs ad hoc aux noeuds + // B) InitUpdateAuNoeud: avant le cumul, initialise les conteneurs + // C) Accumul_aux_noeuds : balaie les éléments avec cumul aux noeuds + // D) MoyenneCompteurAuNoeud : effectue les moyennes aux noeuds + + // accumulation aux noeuds de grandeurs venant des éléments vers leurs noeuds (exemple la pression appliquée) + // autres que celles aux pti classiques, mais directements disponibles + // le contenu du conteneur stockées dans liQ est utilisé en variable intermédiaire + void Accumul_aux_noeuds(const List_io < Ddl_enum_etendu >& lietendu + ,List_io < TypeQuelconque > & liQ,int cas) + {int NBE=tab_element.Taille(); + for (int i=1;i<=NBE;i++) + tab_element(i)->Accumul_aux_noeuds(lietendu,liQ,cas); + }; + + // fonctions utilitaires du même genre + + // ajout sur le maillage d'un conteneur particulier quelconque + void AjoutConteneurAuNoeud(TypeQuelconque& tQ); + // ajout sur le maillage d'un ou plusieur ddl_enum_etendu comme conteneur + void AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu); + // initialisation des updates de ddl_étendu uniquement sur les noeuds: on met à 0 les ddl_etendu correspondant, + // les compteurs, comptant le nombre de fois où les noeuds sont modifiés, sont mis à 0 + void InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienu); + // idem pour un seul ddl_etendu + void InitUpdateAuNoeud(const Ddl_enum_etendu & enu); + // moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié) + void MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu); + + // initialisation des coordonnées à t et tdt aux mêmes valeurs qu'à 0 + // utile quand on veut utiliser les métriques pour un pb non couplés + void Init_Xi_t_et_tdt_de_0(); + + // def d'un conteneur pour deux numéros: elem et pti + class NBelemEtptInteg + {public: int nbElem; int nbPtInteg; + // surcharge de l'operator de lecture + friend istream & operator >> (istream & ent, NBelemEtptInteg & de) + { ent >> de.nbElem >> de.nbPtInteg; return ent;}; + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort , const NBelemEtptInteg & de) + { sort << de.nbElem <<" " << de.nbPtInteg << " "; return sort;}; + bool operator < (const NBelemEtptInteg& c) const; bool operator > (const NBelemEtptInteg& c) const; + bool operator == (const NBelemEtptInteg& c) const {return ((nbElem==c.nbElem)&&(nbPtInteg==c.nbPtInteg));}; + bool operator != (const NBelemEtptInteg& c) const {return !((nbElem==c.nbElem)&&(nbPtInteg==c.nbPtInteg));}; + }; + + // def d'un conteneur pour 3 numéros: elem, num face ou arete, et pti + class NBelemFAEtptInteg + {public: int nbElem; int nbFA; int nbPtInteg; + // surcharge de l'operator de lecture + friend istream & operator >> (istream & ent, NBelemFAEtptInteg & de) + { ent >> de.nbElem >> de.nbFA >> de.nbPtInteg; return ent;}; + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream & sort , const NBelemFAEtptInteg & de) + { sort << de.nbElem <<" "<< de.nbFA <<" " << de.nbPtInteg << " "; return sort;}; + bool operator < (const NBelemFAEtptInteg& c) const; bool operator > (const NBelemFAEtptInteg& c) const; + bool operator == (const NBelemFAEtptInteg& c) const {return ((nbElem==c.nbElem)&&(nbFA==c.nbFA)&&(nbPtInteg==c.nbPtInteg));}; + bool operator != (const NBelemFAEtptInteg& c) const {return !((nbElem==c.nbElem)&&(nbFA==c.nbFA)&&(nbPtInteg==c.nbPtInteg));}; + }; + + // ramène le numéro de l'élément qui contiend un point donné et le numéro du point + // d'intégration le plus proche pour les ddl de la liste, (ddl spécifique à l'élément c'est-a-dire + // hors des ddl des noeuds de l'éléments) + // si pas de numéro d'élément ramène un numéro d'élément nulle + // si les numéros de point d'intégration ne sont pas identique pour l'ensemble + // des ddl, pb !!, le numéro du pt integ de retour est alors négatif + // enu_temps: dit si les coordonnées du point M sont à 0 ou t ou tdt + NBelemEtptInteg Element_le_plus_proche + (Enum_dure enu_temps,const List_io & list_enu,const Coordonnee& M); + + // ramène le numéro de l'élément dont le centre de gravité à t = enu_temps est le plus proche d'un point donné + // Le point peut être n'importe où, en particulier à l'extérieur de la matière + // si pb retour de null + const Element* Centre_de_Gravite_Element_le_plus_proche(Enum_dure enu_temps,const Coordonnee& M); + + // ramène pour chaque noeud, la liste des éléments qui contiennent le noeud + // si le tableau n'existe pas, il est construit, sinon uniquement un retour + // et la miss à jour est uniquement faite lors de la création des frontières + const Tableau >& Indice() + {if (indice.Taille() == 0) Calcul_indice(); + return indice; }; + + //----- lecture écriture dans base info ----- + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) + void Lecture_base_info(ifstream& ent,const int cas); + // cas donne le niveau de sauvegarde + // = 1 : on sauvegarde tout + // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) + void Ecriture_base_info(ofstream& sort,const int cas); + // sortie du schemaXML: en fonction de enu + static void SchemaXML_Maillages(ofstream& sort,const Enum_IO_XML enu) ; + + // ------ informations utiles par exemples pour la visualisation + // retourne les dimensions minis et maxi suivant les axes du repère + // absolu du maillage (en faite le calcul est fondé + // uniquement sur la position des noeuds du maillage + // le premier vecteur contient les minimums + // le deuxième vecteur contient les maximums + Tableau Taille_boiteMail(); + + // --------- utilitaires de manipulation de maillage + // test pour savoir si le maillage contiend des éléments à interpolation linéaire + bool Contient_lineaire(); + // test pour savoir si le maillage contiend des éléments à interpolation quadratique incomplète + bool Contient_quadratique_incomplet(); + // transformation des éléments linéaires du maillage en quadratiques. + // les éléments linéaires sont supprimés, + // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! + // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage + void Transfo_lin_quadraIncomp(LesReferences &lesRef); + // transformation des éléments quadratiques incomplet du maillage en quadratiques complets. + // les éléments incomplets sont supprimée, + // Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! + // il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage + void Transfo_quadraIncomp_quadraComp(LesReferences &lesRef); + // relocalisation des points milieux des arrêtes des éléments quadratiques + void RelocPtMilieuMailleQuadra(); + // définition interactive de listes de références + void CreationInteractiveListesRef(LesReferences* lesRef); + // modification de l'orientation d'éléments + void Modif_orientation_element(int cas_orientation,LesReferences* lesRef); + // Lecture et Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe + void LectureEtCollapse_element_superpose(UtilLecture * entreePrinc,LesReferences* lesRef); + // Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe + void Collapse_element_superpose(LesReferences* lesRef); + // Lecture et collapse de noeuds très proche: appartenant à des éléments différents + void LectureEtCollapse_noeuds_proches(UtilLecture * entreePrinc, LesReferences* lesRef); + // collapse de noeuds très proche: appartenant à des éléments différents + // rayon : donne la distance maxi entre les noeuds qui doivent être collapsé + void Collapse_noeuds_proches(double rayon, LesReferences* lesRef); + // Lecture et suppression d'elements à 2 noeuds, de distances très proches + void LectureEtSup_Elem_noeudsConfondu(UtilLecture * entreePrinc, LesReferences* lesRef); + // suppression d'elements à 2 noeuds, de distances très proches + // rayon : donne la distance maxi entre les noeuds + void Sup_Elem_noeudsConfondu(double rayon, LesReferences* lesRef); + // création d'éléments SFE en fonction d'éléments classiques + void CreationMaillageSFE(); + // test pour savoir si le maillage est ok pour être transformée en sfe + bool OKPourTransSfe(); + // lecture et suppression éventuelle des noeuds, non référencés par les éléments et les références + void LectureEtSuppressionNoeudNonReferencer(UtilLecture * entreePrinc,LesReferences& lesRef); + // uniquement suppression éventuelle des noeuds, non référencés par les éléments et les références + void SuppressionNoeudNonReferencer(LesReferences& lesRef); + // Affichage des noeuds, non référencés par les éléments + void AffichageNoeudNonReferencer(); + + // lecture et création éventuelle d'une ref sur les noeuds, non référencés par les éléments + void LectureEtCreationRefNoeudNonReferencer(UtilLecture * entreePrinc,LesReferences& lesRef); + // création éventuelle d'une référence sur les noeuds, non référencés par les éléments + void CreationRefNoeudNonReferencer(LesReferences& lesRef); + // vérification que toutes les références de noeuds, d'éléments, d'arêtes et de faces sont valides + // c-a-d se réfèrent à des éléments existants + void VerifReference(LesReferences& lesRef); + // lecture et renumérotation éventuelle des noeuds + void LectureEtRenumerotation(UtilLecture * entreePrinc,LesReferences& lesRef); + // renumérotation des noeuds du maillage, en fonction de conditions linéaires éventuelles + // ramène false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure), vrai sinon + bool Renumerotation(LesReferences& lesRef,const Tableau >& condCLL); + // création automatique des références globales de frontière si demandé dans le .info + void CreationRefFrontiere(UtilLecture * entreePrinc,LesReferences& lesRef); + // demande de création automatique des références globales de frontière + void CreationRefFrontiere(LesReferences& lesRef); + // force la mise à une valeur d'un ddl (ou de la liste de ddl fonction de la dimention) particulier, quelques soit son activité + // si fonction_de_la_dimension = true : c'est toute les ddl fct de la dimension qui sont mis à la valeur + void Force_Ddl_aux_noeuds_a_une_valeur(Enum_ddl enu, const double& val,Enum_dure temps, bool fonction_de_la_dimension); + // mise à zéro de dd_enum_etendu aux noeuds : force la mise à une valeur à 0 + void Force_Ddl_etendu_aux_noeuds_a_zero(const Tableau& tab_enu); + + + protected : + int idmail ; // numero de maillage + string nomDuMaillage; + // liste communes de tous les noms de maillages associée à un numéro + // sous forme d'un arbre pour faciliter la recherche + // cette liste n'est modifiée que par chaque maillage + map < string, int , std::less >& listeNomMail; + int dimension; // dimension du maillage + Tableau tab_noeud; // tableau des noeuds du maillage + Tableau tab_element; // tableau des elements du maillage + // list des elements frontieres du maillage, c-a-d des frontières uniques + LaLIST listFrontiere; + // tableau des noeuds des éléments frontières + Tableau tab_noeud_front; + // tableau utilitaire: + // indice(i) contient la liste des éléments qui contiennent le noeud i + Tableau > indice; + // pour chaque élément "i" , mitoyen_de_chaque_element(i)(j) contient l'élément Front + // qui décrit la frontière "j" de l'élément et dedans, les éléments mitoyens de cette frontière + // appartenant à d'autres éléments (ce tableau est construit par la méthode : Mitoyen()) + Tableau < Tableau > mitoyen_de_chaque_element; + + // définie la liste des types de degrés de liberté inconnus, qui vont être calculés par la résolution des problèmes + // physiques gérés par les éléments qui existent dans le maillages + // Si éléments mécaniques -> ddl Xi voir Vi et gamma_i + // Si éléments thermiques -> ddl de température + // Si éléments méca + éléments thermiques -> ddl Xi et température + // etc. en fonction des éléments qui existent dans les maillages + // (généré à la lecture du maillage, ce qui permet d'optimiser la consultation par la suite) + Tableau ddl_representatifs_des_physiques; + // idem au niveau des types de problèmes gérés par les éléments + Tableau types_de_problemes; + + //indicateur uniquement utilisé pour la destruction, par défaut est toujours vrai + // via la méthode Preparation_destruction_avec_conservation_noeuds_elements(), on peut le modifier + bool detruire_les_noeuds_et_elements; + +// -- variables internes utilisées par Orientation_elements_mitoyens_recursif + // tab_sens_element(i) : = 1 au début, puis vaut -1 si le sens de l'élément i à été changé + Tableau tab_sens_element; // pendant les différents appels de Orientation_elements_mitoyens_recursif + // - on définit un tableau d'indicateur, permettant de savoir si un élément a été traité ou pas + // une fois qu'un élément a été traité: a) on ne permet plus son changement de sens + // b) de plus dans le cas d'une suite d'appels récursif, il n'est plus retenue pour les nouvelles listes + Tableau ind_elem; // def et init à 0, c-à-d non traité + +// -- fin variables internes utilisées par Orientation_elements_mitoyens_recursif + + // METHODES PROTEGEES : + + // cas particulier de destruction, sans suppression des noeuds et éléments + // l'utilisation de la méthode suivante, permet ensuite de supprimer le maillage + // tout en évitant la destruction des noeuds internes et éléments internes + // à utiliser avec précaution, intéressant si l'on veut créer un nouveau maillage + // avec les noeuds et éléments de ce maillage + void Preparation_destruction_avec_conservation_noeuds_elements() + { detruire_les_noeuds_et_elements = false; }; + + // change le numéro de maillage + void Change_numero_maillage(int new_num); + + // definition des elements mitoyens aux elements de frontiere + // à la fin du programme tous les éléments mitoyens sont stocké dant les éléments + // Front et non les éléments frontières qui eux sont supprimés + void MitoyenFront(); + // création pour chaque noeud de la liste des éléments qui contiennent le noeud + void Calcul_indice(); + + // definition d'un stockage contenant tous les Front associés à toutes les frontières de tous les éléments + // puis définition des elements mitoyens à ces Front : deux éléments Front sont mitoyens + // s'ils correspondent à des Element différents, et si les frontières associées possèdent les mêmes noeuds + // toutes ces informations sont stockées dans : mitoyen_de_chaque_element (cf. sa description) + void Calcul_tous_les_front_et_leurs_mitoyens(); + + // dans le cas où les éléments frontières sont des lignes, on les ordonnes + // de manière à former une ligne continue + void OrdonancementDesLigne(); + // lectures des infos pour le choix d'un élément + void Lecture_info_1element(UtilLecture * entreePrinc,int& num_elt,Enum_geom& id_geom + ,Enum_interpol& id_interpol,EnumElemTypeProblem& id_typeProb + ,string& discriminant); + // lecture des mouvements solides si nécessaire + void Lecture_des_mouvements_solides(UtilLecture * entreePrinc); + + // une classe de travail qui sert pour pouvoir classer les noeuds par leur position géométrique initiale + // deux élément sont identiques si leur position initiale sont identique + // a >= b si : soit a.x >= b.x, ou a.x==b.x et a.y >= b.y, ou a.x==b.x et a.y == b.y et a.z >= b.z + class PosiEtNoeud + { public: + Noeud * noe; // le noeud + Element * el; // l'élément auquel il est rattaché + // -------- constructeur ------------ + PosiEtNoeud() : noe(NULL),el(NULL) {}; // constructeur par défaut + PosiEtNoeud(Noeud * no,Element * e) : noe(no),el(e) {}; // constructeur normal + PosiEtNoeud(const PosiEtNoeud& po) : noe(po.noe),el(po.el) {}; // constructeur de copie + //------ surcharges qui ne travaillent que sur la position -------- + PosiEtNoeud& operator= (const PosiEtNoeud& po); // affectation + bool operator == (const PosiEtNoeud& po) const ; // test d'égalité + bool operator != (const PosiEtNoeud& po) const ; // test d'inégalité + bool operator < (const PosiEtNoeud& po) const ; // relation d'ordre + bool operator <= (const PosiEtNoeud& po) const ; // relation d'ordre + bool operator > (const PosiEtNoeud& po) const ; // relation d'ordre + bool operator >= (const PosiEtNoeud& po) const ; // relation d'ordre + }; + + // fonctions simples ayant pour but de bien repérer des opérations dangereuses + + // affectation d'un noeud au maillage c-a-d au tableau de pointeur de noeud, + // a condition que la place ne soit pas déjà occupée sinon on change le numéro + // de noeud et on augmente le tableau + void Affectation_noeud (Noeud& noeud); + + // affectation d'un element au maillage c-a-d au tableau de pointeur d'element, + // a condition que la place ne soit pas déjà occupée sinon on change le numéro + // de l'élément et on augmente le tableau + void Affectation_element (Element& element); + + // Modifie le nombre de noeuds du maillage (N.B.: Fait appel + // a la methode Change_taille de la classe Tableau) + // les éléments supplémentaires ont un pointeur mis à Null + void Change_nb_noeud (int nouveau_nb); + + // Modifie le nombre d'elements du maillage (N.B.: Fait appel + // a la methode Change_taille de la classe Tableau) + // les éléments supplémentaires ont un pointeur mis à Null + void Change_nb_element (int nouveau_nb); + + // ** pour l'instant ne fonctionne que pour les éléments surfaces + // orientation automatique des éléments mitoyens, à l'élément num_elem, et ensuite + // récursivement à tous les éléments mitoyens des mitoyens jusqu'à ce que la chaine s'arrête + // L'ensemble des éléments est alors groupé dans une référence qui est construit à partir du numéro num_elem + // et qui est ajouté aux refs déjà existantes + // ensuite, le programme passe en revue les éléments restants, et regarde s'ils font parti + // d'un ensemble homogène orienté, si non, ramène la liste des éléments hors ensemble orienté + // *** ne concerne que les éléments surfaces, les autres sont ignorés + // ind_elem(i) : (tableau interne) indique si l'élément i a été traité (=true) ou non (=false) + // ind_elem: est pris en compte puis mis à jour par le programme, c-a-d que les nouveaux éléments orienté + // passe de false à true, par contre tous les éléments déjà à true, ne sont pas pris en compte dans le traitement + // angle_maxi : angle maximum entre deux éléments, au dessus duquel on considère qu'il y a une rupture de la mitoyenneté + // nom_ref : s'il est différent de "_", donne le nom de base voulu à la série de référence qui va être construite + // inverse : indique si l'on souhaite partir d'une orientation inverse de celle existante avant application de l'algo + // ceci pour l'élément de départ: au premier appel, l'opération est toujours possible, ensuite cela dépend + // si l'élément trouvé a déjà été traité ou pas + // recursiv : indique si l'on se situe dans une suite récursive d'appel de la méthode + // si oui, seule les éléments non déjà pris en compte dans les appels précédents, sont examiné + // c'est ind_elem qui permet de s'en assurer + // si non: cas par exemple d'un angle_maxi qui change, on réexamine tous les éléments, cependant + // la ré_orientation éventuelle n'est faite qu'une seule fois (toujours via ind_elem) + list Orientation_elements_mitoyens_recursif(bool recursif,string& nom_ref,int num_elem + , LesReferences& lesRef,double& angle_maxi,bool inverse); + // méthode pour initialiser les différents tableaux utilisés par Orientation_elements_mitoyens_recursif + void Init_Orientation_elements_mitoyens_recursif(); + + // méthode pour orienter des éléments en fonction d'un rayon: AG, A étant un point donné, G étant le centre de + // gravité d'une facette + // A : coordonnée d'un point, si indic_G(i) est true, alors A(i) est remplacé par la coordonnée G(i) du centre + // de gravité de la facette + // zone_a_traiter: le nom de la référence des éléments a traiter + // inverse : si true, l'orientation des normales des facettes est identique à celles de AG, sinon c'est l'inverse + + void Orientation_via_rayon(const Tableau & indic_G,const Coordonnee & A + ,const string& zone_a_traiter, LesReferences& lesRef, bool inverse); + + // ------- pour la définition interactive de liste de ref ------------- + // def d'un conteneur pour deux numéros: nb element nb face + class NBelemEtFace {public: int nbElem; int nbFace; + bool operator < (const NBelemEtFace& c) const; bool operator > (const NBelemEtFace& c) const; + bool operator == (const NBelemEtFace& c) const {return ((nbElem==c.nbElem)&&(nbFace==c.nbFace));}; + bool operator != (const NBelemEtFace& c) const {return !((nbElem==c.nbElem)&&(nbFace==c.nbFace));}; + }; + // def d'un conteneur pour deux numéros: nb element nb arête + class NBelemEtArete {public: int nbElem; int nbArete; + bool operator < (const NBelemEtArete& c) const; bool operator > (const NBelemEtArete& c) const; + bool operator == (const NBelemEtArete& c) const {return ((nbElem==c.nbElem)&&(nbArete==c.nbArete));}; + bool operator != (const NBelemEtArete& c) const {return !((nbElem==c.nbElem)&&(nbArete==c.nbArete));}; + }; + + // calcul des listes de références en fonction de la demande: + // list_nomReference: contient les types de refs que l'on veut + // list_methode: contient la ou les méthodes que l'on veut utiliser + // cas 1D + void CalculListRef_1D(list& list_nomReference,LesReferences* lesRef,list& list_methode + ,const Enum_ddl & enu_ddl); + // cas 2D + void CalculListRef_2D(list& list_nomReference,LesReferences* lesRef,list& list_methode + ,const Enum_ddl & enu_ddl); + // cas 3D + void CalculListRef_3D(list& list_nomReference,LesReferences* lesRef,list& list_methode + ,const Enum_ddl & enu_ddl); + // les méthodes de bases + // fonction générique pour des condition PresDe + void PresDe(const list& list_nomReference, list & list_noeud_restant + ,list & list_element_restant,const Enum_ddl& enu_ddl + ,list & list_elemPtin_restant,bool& premLpti + ,list & list_elemFace_restant,bool& premLface + ,list & list_elemArrete_restant,bool& premLarrete); + // fonction générique pour des condition "tout dedans" + void ToutDedans(const list& list_nomReference, list & list_noeud_restant + ,list & list_element_restant,const Enum_ddl& enu_ddl + ,list & list_elemPtin_restant,bool& premLpti + ,list & list_elemFace_restant,bool& premLface + ,list & list_elemArrete_restant,bool& premLarrete); + // constitution des références + void EnregRef(const list& list_nomReference,list & list_noeud_restant + ,list & list_elemPtin_restant,list & list_element_restant + ,list & list_elemFace_restant,list & list_elemArrete_restant + ,LesReferences* lesRef); + // définition des fonctions conditions + // def de data internes qui servent pour les fonctions init et exe: dimensionnées dans init, utilisé dans exe + // donc: init et exe doivent être utilisé absolument à suivre + Tableau t_poi; + Tableau t_droit; + Tableau t_para; + Tableau t_plan; + Tableau t_sphere; + Tableau t_cylindre; + Tableau t_cercle; + // cas de croisement avec des références existantes: def de variables de passage pour InRef et OutRef + // les pointeurs qui suivent ne servent pas à créer des refs, mais uniquement a récupérer les adresses + list list_refIn; + list list_refOut; + LesReferences* lesRefin; // variable utilisée uniquement pour le passage d'info à + // ,InitInRef(), ExeInRef (), InitOutRef(), ExeOutRef() + + // tout d'abord les pointeurs de fonctions en cours + // - pour les conditions Presde + // acquisition interactive des paramètres de la condition + void (Maillage::*initConditionPresDe) (double& dist); + // exécution de la condition : ramène true si ok, false sinon + bool (Maillage::*ExeConditionPresDe) (const double& dist,const Coordonnee& M)const; + // - pour les condition ToutDedans + // acquisition interactive des paramètres de la condition + void (Maillage::*initConditionToutDedans) (); + // exécution de la condition : ramène true si ok, false sinon + bool (Maillage::*ExeConditionToutDedans) (const Tableau & tab_M)const; + + + // recherche près d'un point + // def interactive du point et de la distance + void InitPresPoint(double& dist); + // exécution de la condition + bool ExePresPoint(const double& dist,const Coordonnee& M) const; + + // recherche d'un coté d'un point (en 1D) + void InitCotePoint(); + // ramène true si tous les points sont du même coté que t_poi(1) + bool ExeCotePoint(const Tableau & t_M)const; + + // recherche entre deux points (1D) + void InitEntrePoint(); + // ramène true si tous les points sont entre t_poi(1) et t_poi(2) + bool ExeEntrePoint(const Tableau & t_M)const; + + // recherche entre deux points (1D) _avec_distance + void InitEntrePoint_avec_distance(); + // ramène true si tous les points sont entre t_poi(1) et t_poi(2) + bool ExeEntrePoint_avec_distance(const Tableau & t_M)const; + + // recherche près d'une ligne + void InitPresLigne(double& dist); + bool ExePresLigne(const double& dist,const Coordonnee& M)const; + + // dans le cas particulier d'une ligne, on peut ordonner certaines listes résultantes / à la lignes + // il s'agit des noeuds et des pt d'integ: on les ordonnes par rapport à leurs projections sur la lignes + void InitOrdonneLigne(); + void OrdonneLigne(list & list_noeud_restant,list & list_elemPtin_restant + ,const Enum_ddl& enu_ddl); + + // recherche près d'un cercle + void InitPresCercle(double& dist); + bool ExePresCercle(const double& dist,const Coordonnee& M)const; + + // recherche près d'un plan + void InitPresPlan(double& dist); + bool ExePresPlan(const double& dist,const Coordonnee& M)const; + + // recherche près d'un cylindre + void InitPresCylindre(double& dist); + bool ExePresCylindre(const double& dist,const Coordonnee& M)const; + + // recherche près d'une sphere + void InitPresSphere(double& dist); + bool ExePresSphere(const double& dist,const Coordonnee& M)const; + + // recherche d'un coté d'un plan + void InitCotePlan(); + // ramène true si tous les points sont du même coté que t_poi(1) du plan + bool ExeCotePlan(const Tableau & t_M)const; + + // condition entre plans // + void InitEntrePlan(); + // ramène true si tous les points sont entre les deux plans + bool ExeEntrePlan(const Tableau & t_M)const; + + // condition entre plans _avec_distance // + void InitEntrePlan_avec_distance(); + // ramène true si tous les points sont entre les deux plans + bool ExeEntrePlan_avec_distance(const Tableau & t_M)const; + + // condition dans ou dehors un cylindre + void InitDansCylindre(); + // ramène true si tous les points sont dans le cylindre + bool ExeDansCylindre(const Tableau & t_M)const; + // ramène true si tous les points sont à l'extérieur du cylindre + bool ExeOutCylindre(const Tableau & t_M)const; + + // condition entre deux cylindre + void InitEntreCylindre(); + // ramène true si tous les points sont entre les deux cylindres + bool ExeEntreCylindre(const Tableau & t_M)const; + + // condition dans ou dehors d'une sphére + void InitDansSphere(); + // ramène true si tous les points sont dans la sphère + bool ExeDansSphere(const Tableau & t_M)const; + // ramène true si tous les points sont à l'extérieur de la sphère + bool ExeOutSpheres(const Tableau & t_M)const; + + // condition entre deux spheres concentriques + void InitEntreSpheres(); + // ramène true si tous les points sont entre les deux sphères + bool ExeEntreSpheres(const Tableau & t_M)const; + + // condition du même coté d'une droite (en 2D seulement) + void InitCoteDroite(); + // ramène true si tous les points sont du même coté que t_poi(1) de la droite (en 2D uniquement) + bool ExeCoteDroite(const Tableau & t_M)const; + + // condition entre 2 droites (en 2D seulement) + void InitEntreDroite(); + // ramène true si tous les points sont entre les 2 droites (en 2D uniquement) + bool ExeEntreDroite(const Tableau & t_M)const; + + // condition entre 2 droites (en 2D seulement) _avec_distance + void InitEntreDroite_avec_distance(); + // ramène true si tous les points sont entre les 2 droites (en 2D uniquement) + bool ExeEntreDroite_avec_distance(const Tableau & t_M)const; + + // condition dans ou dehors un cercle (en 2D seulement) + void InitDansCercle(); + // ramène true si tous les points sont dans le cercle + bool ExeDansCercle(const Tableau & t_M)const; + // ramène true si tous les points sont à l'extérieur du cercle + bool ExeOutCercle(const Tableau & t_M)const; + + // condition entre cercles concentriques (en 2D seulement) + void InitEntreCercles(); + // ramène true si tous les points sont entre les deux cercles concentriques + bool ExeEntreCercles (const Tableau & t_M)const; + + // acquisition d'un plan + Plan Acquisition_interactive_plan(); + + // acquisition d'un point + Coordonnee Acquisition_interactive_point(); + + // acquisition d'une droite + Droite Acquisition_interactive_droite(); + + // acquisition d'un vecteur=direction + Coordonnee Acquisition_interactive_vecteur(); + + // condition d'appartenance à une référence existante + void InitInRef(); + // condition d'exclusion à une référence existante + void InitOutRef(); + // ---- mise en place de la condition d'appartenance ou d'exclusion à des références existantes + // contrairement aux autres conditions, cette condition est prise en compte au moment de la création finale + // de la référence dans la méthode : EnregRef, via les méthodes du 2) + // 1) une fonction qui ne fait rien, mais est là pour que le tout fonctionne normalement + bool Exe_In_out_avecRefExistantes(const Tableau & t_M)const; // ne fait rien + // 2) fonctions qui réellement font quelque chose: utilisées dans la méthode EnregRef + void Exe_In_out_avecRefExistantes_N(list & list_noeud_restant); + void Exe_In_out_avecRefExistantes_E(list & list_element_restant); + void Exe_In_out_avecRefExistantes_G(list & list_elemPtin_restant); + void Exe_In_out_avecRefExistantes_F(list & list_elemFace_restant); + void Exe_In_out_avecRefExistantes_A(list & list_elemArrete_restant); +// void InterOuDiff_avecRefExistantes(const Tableau & t_M)const; + + //-------------------- méthodes particulières pour l'optimisation de largeur de bande ------------------------ + + // une classe intermédiaire pour pouvoir classer les noeuds en fonction du degré + class Noeud_degre + { public: Noeud* noe; int degre; + Noeud_degre (): noe(NULL), degre(0) {}; + Noeud_degre (Noeud* no,int deg): noe(no),degre(deg) {}; + Noeud_degre (const Noeud_degre& no ): noe(no.noe), degre(no.degre) {}; + ~Noeud_degre() {}; + bool operator > (const Noeud_degre& a) const { return (this->degre > a.degre);}; + bool operator >= (const Noeud_degre& a) const { return (this->degre >= a.degre);}; + bool operator < (const Noeud_degre& a) const { return (this->degre < a.degre);}; + bool operator <= (const Noeud_degre& a) const { return (this->degre <= a.degre);}; + Noeud_degre& operator= (const Noeud_degre& de) { degre = de.degre; noe = de.noe; return (*this);}; + }; + + // méthode static: c-a-d indépendante des données du maillage (elle est générale) + // calcul du point de départ, en fonction de conditions linéaires éventuelles + // il y a également calcul des voisins et de la descendance du noeud de retour + // s'il y a un pb, calcul_ok en retour est false + static Noeud* Point_de_depart(const Tableau& tab_elem + ,const Tableau& tab_noe + ,const Tableau *> tt_noeud_front + ,Tableau < LaLIST_io >& t_voisin + , list < list < Noeud_degre > > & lis_descent + ,const Tableau >& condCLL,bool& calcul_ok); + + // méthode static: c-a-d indépendante des données du maillage (elle est générale) + // calcul des voisins de tous les noeuds du maillage en fonction des éléments et de conditions + // linéaires éventuelles, + // en entrée/sortie t_voisin + // restriction: il faut que tab_noe contienne tous les noeuds référencés dans tab_elem et tt_t_condCLL + // s'il y a un pb, calcul_ok en retour est false + static Tableau < LaLIST_io >& Voisins(const Tableau& tab_elem + ,const Tableau& tab_noe + ,Tableau < LaLIST_io >& t_voisin + ,const Tableau >& t_t_condCLL,bool& calcul_ok); + + // méthode static: c-a-d indépendante des données du maillage (elle est générale) + // calcul de la descendance d'un noeud noeu, + // on considère que les voisins sont dèjà correctement définis + // en entrée la liste qui est modifiée en interne et retournée en sortie + // le premier élément de la liste c'est la dernière descendance + // s'il y a un pb, calcul_ok en retour est false + static list < list < Noeud_degre > > & Descendance (const int& taille_tabnoeud + ,Noeud * noeu, Tableau < LaLIST_io >& t_voisin + , list < list < Noeud_degre > > & lient,bool& calcul_ok); + // méthode static: c-a-d indépendante des données du maillage (elle est générale) + // algorithme de Cuthill Mac Kee directe + // noeu : le noeud de départ + // lis_descent : les descendants de noeu, qui va être modifié dans le processus + // ramène une nouvelle numérotation (mais les numéros internes des noeuds ne sont pas changé + static Tableau Cuthill_Mac_Kee(const int& taille_tabnoeud,Noeud * noeu + ,Tableau < LaLIST_io >& t_voisin + , list < list < Noeud_degre > >& lis_descent); + // méthode static: c-a-d indépendante des données du maillage (elle est générale) + // calcul de la largeur de bande en noeuds + static int LargeurBandeEnNoeuds(const Tableau& tab_elem); + + // on s'occupe de mettre à jour les types de pb et les ddl types associés + void Mise_a_jour_type_pb_type_associe_ddl(); + + +}; +/// @} // end of group + +#endif diff --git a/Maillage/Maillage2.cc b/Maillage/Maillage2.cc new file mode 100644 index 0000000..06a775f --- /dev/null +++ b/Maillage/Maillage2.cc @@ -0,0 +1,1783 @@ +// FICHIER : Maillage.cp +// CLASSE : Maillage + +// This file is part of the Herezh++ application. +// +// The finite element software Herezh++ is dedicated to the field +// of mechanics for large transformations of solid structures. +// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) +// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . +// +// Herezh++ is distributed under GPL 3 license ou ultérieure. +// +// Copyright (C) 1997-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 "Maillage.h" +# include +using namespace std; //introduces namespace std +#include +#include "Sortie.h" +#include +#include +#include "List_io.h" +#include "CharUtil.h" +#ifndef SYSTEM_MAC_OS_X_unix + #include "Frontier.h" +#endif +#include "ConstMath.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" +#include "Util.h" +#include "MvtSolide.h" + + +// --------- utilitaires de manipulation de maillage + // test pour savoir si le maillage contiend des éléments à interpolation linéaire +bool Maillage::Contient_lineaire() + { // on balaie les éléments + int taille_elem = tab_element.Taille(); + for (int i=1; i<=taille_elem;i++) + { Enum_interpol eninter = tab_element(i)->Id_interpolation(); + // LINEAIRE indique que l'on a une interpolation linéaire + if (eninter == LINEAIRE) return true; + } + // sinon pas d'élément incomplet quadratique + return false; + }; +bool Maillage::Contient_quadratique_incomplet() + { // on balaie les éléments + int taille_elem = tab_element.Taille(); + for (int i=1; i<=taille_elem;i++) + { Enum_interpol eninter = tab_element(i)->Id_interpolation(); + // QUADRATIQUE indique que l'on a une interpolation quadratique incomplète + // alors que QUADRACOMPL indique que c'est quadratique complet + if (eninter == QUADRATIQUE) return true; + } + // sinon pas d'élément incomplet quadratique + return false; + }; + +// transformation des éléments linéaires du maillage en quadratiques. +// les éléments linéaires sont supprimés, +// Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! +// il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage +void Maillage::Transfo_lin_quadraIncomp(LesReferences &lesRef) + {list nv_remplace; + list li_nv_noeud; + list li_bornes; + // 1) on balaie les éléments + int nbnt=tab_noeud.Taille(); // le nombre de noeud total (évolue pendant la transformation) + // nbnt permet à Construct_from_imcomplet de donner des numéros de noeud licite, en particulier + // permet d'éviter que deux noeuds aient le même numéro + int taille_elem = tab_element.Taille(); + for (int i=1; i<=taille_elem;i++) + { Enum_interpol eninter = tab_element(i)->Id_interpolation(); + // LINEAIRE indique que l'on a une interpolation linéaire + if (eninter == LINEAIRE) + {// 2) on a trouvé un linéaire + // on crée un quadratique incomplet de même type + Element * elem = tab_element(i); // pour simplifier + Element::Signature signa = elem->Signature_element(); + // on change l'interpolation + signa.id_interpol=QUADRATIQUE; + // on crée le nouvel élément quadratique avec le même numéro que le linéaire (car il le remplacera + // par la suite) + Element* elem2= Element::Choix_element(elem->Num_maillage(),elem->Num_elt(),signa); + if (elem2 == NULL) + { cout << "\n erreur de creation d'un element quadratique incomplet a partir d'un lineaire" + << "\n signature du lineaire: interpolation " << Nom_interpol(signa.id_interpol) + << " geometrie: " << Nom_geom(signa.id_geom) << " problem: " << NomElemTypeProblem(signa.id_problem) + << " infos_annexes: " << signa.infos_annexes + << "\n Maillage::Transfo_lin_quadraIncomp(..."; + Sortie(1); + } + // 3) on demande à l'élément de définir ses noeuds, d'une part à partir des noeuds + // déjà existants de l'élément linéaire, et d'autre part à partir de nouveaux noeuds + // construit à partir de l'interpolation initiale linéaire. + // on fournit également le premier numéro -1 du nouveau noeud + list li_bo; // les bornes pour la renumérotation + list l_nv_noe = elem2->Construct_from_lineaire(*elem,li_bo,nbnt); + nbnt += l_nv_noe.size(); + // 4) on ajoute les nouveaux noeuds + list ::iterator lni,lnifin=l_nv_noe.end(); + for (lni=l_nv_noe.begin();lni!=lnifin;lni++) + {li_nv_noeud.push_back(Maillage::PosiEtNoeud(*lni,elem2)); + } + list ::iterator pni,pnifin=li_bo.end(); + for (pni=li_bo.begin();pni!=pnifin;pni++) + {li_bornes.push_back(*pni); + } + // 5) on enregistre l'élément linéaire et on le remplace par le quadratique dans + // la liste d'élément + nv_remplace.push_back(elem); + tab_element(i) = elem2; + } + } + + // 6) on supprime les doublons dans la liste des noeuds en réaffectant les bons pointeurs dans les éléments +// li_nv_noeud.sort(); // ordonne la liste + // suppression des doublons et réaffectation des pointeurs de noeuds supprimés dans les éléments + if (li_nv_noeud.size() != 1) + {list ::iterator lili,lilifin = li_nv_noeud.end(); + list ::iterator lila = li_nv_noeud.begin();lili=lila; lili++; + list ::iterator pili,pilifin = li_bornes.end(); + list ::iterator pila = li_bornes.begin();pili=pila; pili++; + do + { if (*lila == *lili) + { //cas de deux noeuds identiques, on réaffecte le pointeur de noeud dans l'élément + (*lila).el->Reaffectation_pointeur_noeud((*lila).noe,(*lili).noe); + // on supprime le noeud doublon + delete (*lila).noe; + // on supprime les éléments de la liste + li_nv_noeud.erase(lila); li_bornes.erase(pila); + } + lila = lili; lili++; + pila = pili; pili++; + } while (lili!= lilifin); + } + // 7) insertion des nouveaux noeuds dans le tableau définitif et renumérotation + // a) on commence par définir une liste de noeud, équivalente au tableau tab_noeud + List_io li_no; + int nbn = tab_noeud.Taille(); + // petite vérif: il faut que le maillage contienne au moins un noeud + #ifdef MISE_AU_POINT + if (nbn == 0) + { cout << "\n erreur le maillage contiend 0 noeud en propre, ce qui est insufisent pour la routine" + << "\n list Maillage::Transfo_quadraIncomp_quadraComp()"; + Sortie(1); + } + #endif + // b) on définit un tableau de listes de pointeurs de noeud + Tableau > tab_ln(nbn); + // c) on remplit chaque liste des noeuds qu'il faudrait ajouter pour avoir une bonne numérotation + list ::iterator lili,lilifin = li_nv_noeud.end(); + list ::iterator pilifin = li_bornes.end(); + list ::iterator pili = li_bornes.begin(); + for (lili=li_nv_noeud.begin();lili != lilifin; lili++,pili++) + { // récup de la position moyenne d'insertion et remplissage de la liste correspondante + // cout << "\n un= " << (*pili).un << "deux= " << (*pili).deux ; + int bi=( (*pili).un + (*pili).deux ) / 2; // division entière + // cout << " bi= " << bi << endl; + tab_ln(bi).push_back((*lili).noe); + } + // d) on définit un nouveau tableau de noeud qui comprend les anciens et les nouveaux noeuds, ordonnées + int nbn_nv = nbn+li_nv_noeud.size(); + Tableau tab_noe_nv(nbn_nv); + // définition également d'un tableau d'indiçage inverse + Tableau indic(nbn); + int ino=0; + for (int ivo=1;ivo<= nbn;ivo++) + { // tout d'abord le noeud ancien + ino++; tab_noe_nv(ino)=tab_noeud(ivo); + indic(ivo)=ino; + // puis éventuellement les noeuds à intercaler + List_io& li_ln = tab_ln(ivo); // pour simplifier + if (li_ln.size() != 0) + { List_io::iterator iln,iln_end=li_ln.end(); + for (iln=li_ln.begin(); iln != iln_end; iln++) + { ino++; tab_noe_nv(ino)=*iln;}; + } + } + tab_noeud = tab_noe_nv; // remplacement du tableau du maillage + // e) on renumérote les différents noeuds + for (int j=1;j<= nbn_nv;j++) tab_noeud(j)->Change_num_noeud(j); + // 7) modification des références sur les noeuds + // a) on passe en revue les références et on sélectionne les références relatives aux noeuds + // de l'ancien maillage + const Reference* ref1 = lesRef.Init_et_Premiere(); + do { if((ref1->Nbmaille() == idmail) && (ref1->Indic() == 1)) + // on a trouvé une référence de noeud à considérer + { ReferenceNE * refNE = ( ReferenceNE *) ref1; // pour simplifier + int nb_num=refNE->Taille(); + for (int it= 1;it<=nb_num;it++) + refNE->Change_num_dans_ref(it,indic(refNE->Numero(it))); + } + ref1 = lesRef.Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + + cout << "\n *** attention les references generes ici ne sont pas bonnes !! , seul le maillage est " + << " actuellement correcte "; + + // 8) suppression des éléments linéaires qui n'ont plus lieu d'être + list ::iterator lele,lelefin=nv_remplace.end(); + for (lele=nv_remplace.begin();lele!=lelefin;lele++) + delete (*lele); + // 9) rien à faire sur les références d'élément, ou de face d'élément ou d'arrête d'élément + // car d'une part les nouveaux éléments ont le même numéro que les anciens, et d'autre part + // le fait de passer en élément complet ne modifie pas les arrêtes ou faces + }; + +// transformation des éléments quadratiques incomplet du maillage en quadratiques complets. +// les éléments incomplets sont supprimée, +// Important: dans la procédure de renumérotation, la routine modifie la numérotation initiale des noeuds !! +// il y a également création de référence adaptée au nouveau maillage en cohérence avec l'ancien maillage + void Maillage::Transfo_quadraIncomp_quadraComp(LesReferences &lesRef) + {list nv_remplace; + list li_nv_noeud; + list li_bornes; + // 1) on balaie les éléments + int nbnt=tab_noeud.Taille(); // le nombre de noeud total (évolue pendant la transformation) + // nbnt permet à Construct_from_imcomplet de donner des numéros de noeud licite, en particulier + // permet d'éviter que deux noeuds aient le même numéro + int taille_elem = tab_element.Taille(); + for (int i=1; i<=taille_elem;i++) + { Enum_interpol eninter = tab_element(i)->Id_interpolation(); + // QUADRATIQUE indique que l'on a une interpolation quadratique incomplète + // alors que QUADRACOMPL indique que c'est quadratique complet + if (eninter == QUADRATIQUE) + {// 2) on a trouvé un quadratique incomplet + // on crée un quadratique complet de même type + Element * elem = tab_element(i); // pour simplifier + Element::Signature signa = elem->Signature_element(); + // on change l'interpolation + signa.id_interpol=QUADRACOMPL; + // on crée le nouvel élément complet avec le même numéro que l'incomplet (car il le remplacera + // par la suite) + Element* elem2= Element::Choix_element(elem->Num_maillage(),elem->Num_elt(),signa); + if (elem2 == NULL) + { cout << "\n erreur de creation d'un element quadratique complet a partir d'un incomplet" + << "\n signature du quadratique incomplet: interpolation " << Nom_interpol(signa.id_interpol) + << " geometrie: " << Nom_geom(signa.id_geom) << " problem: " << NomElemTypeProblem(signa.id_problem) + << " infos_annexes: " << signa.infos_annexes + << "\n Maillage::Transfo_quadraIncomp_quadraComp(..."; + Sortie(1); + } + // 3) on demande à l'élément de définir ses noeuds, d'une part à partir des noeuds + // déjà existants de l'élément incomplet, et d'autre part à partir de nouveaux noeuds + // construit à partir de l'interpolation initiale incomplète. + // on fournit également le premier numéro -1 du nouveau noeud + list li_bo; // les bornes pour la renumérotation + list l_nv_noe = elem2->Construct_from_imcomplet(*elem,li_bo,nbnt); + nbnt += l_nv_noe.size(); + // 4) on ajoute les nouveaux noeuds + list ::iterator lni,lnifin=l_nv_noe.end(); + for (lni=l_nv_noe.begin();lni!=lnifin;lni++) + {li_nv_noeud.push_back(Maillage::PosiEtNoeud(*lni,elem2)); + } + list ::iterator pni,pnifin=li_bo.end(); + for (pni=li_bo.begin();pni!=pnifin;pni++) + {li_bornes.push_back(*pni); + } + // 5) on enregistre l'élément incomplet et on le remplace par le complet dans + // la liste d'élément + nv_remplace.push_back(elem); + tab_element(i) = elem2; + } + } + + // 6) on supprime les doublons dans la liste des noeuds en réaffectant les bons pointeurs dans les éléments +// non car cela ne sert à rien et il faudrait également traiter li_bornes li_nv_noeud.sort(); // ordonne la liste + // suppression des doublons et réaffectation des pointeurs de noeuds supprimés dans les éléments + if (li_nv_noeud.size() != 1) + {list ::iterator lili,lilifin = li_nv_noeud.end(); + list ::iterator lila = li_nv_noeud.begin();lili=lila; lili++; + list ::iterator pili,pilifin = li_bornes.end(); + list ::iterator pila = li_bornes.begin();pili=pila; pili++; + do + { if (*lila == *lili) + { //cas de deux noeuds identiques, on réaffecte le pointeur de noeud dans l'élément + (*lila).el->Reaffectation_pointeur_noeud((*lila).noe,(*lili).noe); + // on supprime le noeud doublon + delete (*lila).noe; + // on supprime les éléments de la liste + li_nv_noeud.erase(lila); li_bornes.erase(pila); + } + lila = lili; lili++; + pila = pili; pili++; + } while (lili!= li_nv_noeud.end()); + }; +////------ debug +//{ +//cout << "\n debug: Maillage::Transfo_quadraIncomp_quadraComp "; +//list ::iterator pili = li_bornes.begin(); +//int i=1; +//for (pili;pili != li_bornes.end();pili++,i++) +// cout << "\n borne "<< i <<": " << *pili; +//cout << endl; +//}; +////----- fin debug + + + + // 7) insertion des nouveaux noeuds dans le tableau définitif et renumérotation + // a) on commence par définir une liste de noeud, équivalente au tableau tab_noeud + List_io li_no; + int nbn = tab_noeud.Taille(); + // petite vérif: il faut que le maillage contienne au moins un noeud + #ifdef MISE_AU_POINT + if (nbn == 0) + { cout << "\n erreur le maillage contiend 0 noeud en propre, ce qui est insufisent pour la routine" + << "\n list Maillage::Transfo_quadraIncomp_quadraComp()"; + Sortie(1); + } + #endif + // b) on définit un tableau de listes de pointeurs de noeud + Tableau > tab_ln(nbn); + // c) on remplit chaque liste des noeuds qu'il faudrait ajouter pour avoir une bonne numérotation + list ::iterator lili,lilifin = li_nv_noeud.end(); + list ::iterator pilifin = li_bornes.end(); + list ::iterator pili = li_bornes.begin(); + for (lili=li_nv_noeud.begin();lili != lilifin; lili++,pili++) + { // récup de la position moyenne d'insertion et remplissage de la liste correspondante + int bi=( (*pili).un + (*pili).deux ) / 2; // division entière +////------ debug +//{ +//cout << "\n debug: Maillage::Transfo_quadraIncomp_quadraComp "; +// cout << "\n bornes : " << *pili << endl; +//}; +////----- fin debug + tab_ln(bi).push_back((*lili).noe); + }; + // d) on définit un nouveau tableau de noeud qui comprend les anciens et les nouveaux noeuds, ordonnées + int nbn_nv = nbn+li_nv_noeud.size(); + Tableau tab_noe_nv(nbn_nv); + // définition également d'un tableau d'indiçage inverse + Tableau indic(nbn); + int ino=0; + for (int ivo=1;ivo<= nbn;ivo++) + { // tout d'abord le noeud ancien + ino++; tab_noe_nv(ino)=tab_noeud(ivo); + indic(ivo)=ino; + // puis éventuellement les noeuds à intercaler + List_io& li_ln = tab_ln(ivo); // pour simplifier + if (li_ln.size() != 0) + { List_io::iterator iln,iln_end=li_ln.end(); + for (iln=li_ln.begin(); iln != iln_end; iln++) + { ino++; tab_noe_nv(ino)=*iln;}; + } + } + tab_noeud = tab_noe_nv; // remplacement du tableau du maillage + // e) on renumérote les différents noeuds + for (int j=1;j<= nbn_nv;j++) tab_noeud(j)->Change_num_noeud(j); + // 7) modification des références sur les noeuds + // a) on passe en revue les références et on sélectionne les références relatives aux noeuds + // de l'ancien maillage + const Reference* ref1 = lesRef.Init_et_Premiere(); + do { if((ref1->Nbmaille() == idmail) && (ref1->Indic() == 1)) + // on a trouvé une référence de noeud à considérer + { ReferenceNE * refNE = ( ReferenceNE *) ref1; // pour simplifier + int nb_num=refNE->Taille(); + for (int it= 1;it<=nb_num;it++) + refNE->Change_num_dans_ref(it,indic(refNE->Numero(it))); + } + ref1 = lesRef.Reference_suivante(); // la référence suivante + } while (ref1 != NULL); + + // 8) suppression des élément incomplet qui n'ont plus lieu d'être + list ::iterator lele,lelefin=nv_remplace.end(); + for (lele=nv_remplace.begin();lele!=lelefin;lele++) + delete (*lele); + // 9) rien à faire sur les références d'élément, ou de face d'élément ou d'arrête d'élément + // car d'une part les nouveaux éléments ont le même numéro que les anciens, et d'autre part + // le fait de passer en élément complet ne modifie pas les arrêtes ou faces + }; + +// Affiche les donnees du maillage dans un fichier +// dont le nom est construit à partir du nom du maillage +// au format ".her" et ".lis" +void Maillage::Affiche_dans_her_lis(LesReferences &lesRef,Enum_dure temps) + { + //------------- écriture du .her ------------- + // ouverture du fichier pour les noeuds + char nomm[132]; + char*fileName = nomm; + strcpy(fileName, nomDuMaillage.c_str()); + ofstream * sur_sort = new ofstream (strcat(fileName,".her")); + ofstream & sort = * sur_sort; + if(!(sort.is_open())) + // le fichier ne peut être ouvert, message d'erreur + { cout << "\n erreur en ouverture pour l'ecriture du fichier " << fileName << "\n" + << " Maillage::Affiche_dans_her_lis(.... " << endl; + Sortie(1); + }; + // écriture de l'entete + sort << "\n ###########################################################################" + << "\n # ecriture automatique d'un maillage au format .her, par Herezh++ #" + << "\n ###########################################################################" + << "\n # version: " << ParaGlob::NbVersion() << "\n \n \n "; + // écriture du nom du maillage + sort << "\n nom_maillage " << nomDuMaillage << " # nom du maillage" + << "\n" + << "\n noeuds ------------ # definition des noeuds"; + int dimen = ParaGlob::Dimension(); + // l'entete des noeuds + int nbn = tab_noeud.Taille(); + sort << "\n "<< nbn << " NOEUDS # definition du nombre de noeuds" + << "\n \n" + << "\n#---------------------------------------------------------------" + << "\n#|NO DU| X | Y | Z |" + << "\n#|NOEUD| | | |" + << "\n#---------------------------------------------------------------" + << "\n"; + // écriture des noeuds + double sero = 0.; + for (int ine=1;ine<=nbn; ine++) + { sort << "\n" << setw (6) << ine <<" "; + Coordonnee co; + switch (temps) + { + case TEMPS_0 : co=tab_noeud(ine)->Coord0(); break; + // si les noeuds n'ont pas bougés on sort les coordonnées à 0 + case TEMPS_t : + { if (tab_noeud(ine)->ExisteCoord1()) + { co=tab_noeud(ine)->Coord1(); } + else co=tab_noeud(ine)->Coord0(); + break; + } + case TEMPS_tdt : + { if (tab_noeud(ine)->ExisteCoord2()) + { co=tab_noeud(ine)->Coord2(); } + else co=tab_noeud(ine)->Coord0(); + break; + } + default : + cout << "\nErreur : valeur incorrecte du type Enum_dure !\n"; + cout << "Maillage::Affiche_dans_her_lis(.. \n"; + Sortie(1); + }; + #ifndef ENLINUX_STREAM + sort.setf(ios_base::scientific); + #else + sort.setf(ios::scientific); + #endif + for (int j=1;j<=3;j++) + if (j<=dimen) + sort << setw (18) << setprecision(ParaGlob::NbdigdoCA()) <Signature_element(); + sort << Nom_geom(sign.id_geom) << " " << Nom_interpol(sign.id_interpol) + << " " << sign.infos_annexes << " "; + Tableau& tab_n = tab_element(ie)->Tab_noeud(); + int taille_tab_n = tab_n.Taille(); + for (int ite=1;ite<=taille_tab_n;ite++) + sort << tab_n(ite)->Num_noeud() << " "; + } + // quelques lignes blanches à la fin du fichier + sort << "\n \n \n"; + // fermeture du fichier + delete sur_sort; + + //------------- écriture du .lis ------------- + + // Affiche les donnees des références pour le maillage imail dans un fichier + // dont le nom est construit à partir du nom du maillage au format ".lis" + lesRef.Affiche_dans_lis(nomDuMaillage,idmail); + + }; + + +//modification du maillage pour le restreindre aux seuls éléments de la référence passée en paramètre +// toutes les infos relatives à des éléments supprimés, sont également supprimés +void Maillage::Restreint_sous_maillage(LesReferences* lesRef, string nom_ref) + { // on définit un tableau d'indicateur donnant les éléments non référencés + Tableau tab_el_non_referencer(tab_element.Taille(),true); // par défaut on ne conserve pas + // on définit un tableau d'indicateur donnant les noeuds non référencés + Tableau tab_noe_non_referencer(tab_noeud.Taille(),true); + // récup de la référence des éléments + const ReferenceNE & ref =((ReferenceNE &) lesRef->Trouve(nom_ref,idmail)); + if (ref.Indic() != 2) + {cout << "\n *** erreur: la reference "< 2) + cout << "\n Maillage::Restreint_sous_maillage(... "; + Sortie(1); + }; + // récup du tableau d'éléments de la référence + const Tableau& tab_E_ref = ref.Tab_num(); + // on marque les éléments à conserver ainsi que les noeuds + // qui appartiennent à des éléments à conserver + int nb_el = tab_E_ref.Taille(); + for (int i=1;i<=nb_el;i++) + {tab_el_non_referencer(tab_E_ref(i)) = false; + Element * el = tab_element(tab_E_ref(i)); + const Tableau& tab_noeu = el->Tab_noeud_const(); + int nb_noe = tab_noeu.Taille(); + for (int noe = 1;noe <= nb_noe; noe++) + tab_noe_non_referencer(tab_noeu(noe)->Num_noeud())=false; + }; + // suppression des éléments non référencés + int NBE=tab_element.Taille(); + for (int i=1;i<=NBE;i++) + if (tab_el_non_referencer(i)) + delete tab_element(i); + // suppression des noeuds non référencés + int NBN = tab_noeud.Taille(); + int nb_noeud_final = 0; // init + for (int i=1;i<= NBN;i++) + if (tab_noe_non_referencer(i)) + {delete tab_noeud(i);} + else {nb_noeud_final++;}; // sinon on compte + + // on redimentionne et réafecte le tableau de noeuds + Tableau tab_old_noe = tab_noeud; // sauvegarde de l'ancien tableau + // nv_tab est tel que : nv_tab_noe(i) est le nouveau numéro qui avait auparavant le numéro "i" + Tableau nv_tab_noe(NBN); + tab_noeud.Change_taille(nb_noeud_final); + int indice_noeu=1; // pour parcourir le tableau final de noeud + for (int i=1;i<=NBN;i++) + if (!tab_noe_non_referencer(i)) + {tab_noeud(indice_noeu) = tab_old_noe(i); + nv_tab_noe(i)=indice_noeu; + tab_noeud(indice_noeu)->Change_num_noeud(indice_noeu); + indice_noeu++; + }; + + + // on redimentionne et réafecte le tableau d'élément + Tableau tab_old_El = tab_element; // sauvegarde de l'ancien tableau + // nv_tab est tel que : nv_tab_ele(i) est le nouveau numéro qui avait auparavant le numéro "i" + Tableau nv_tab_ele(NBE); + tab_element.Change_taille(nb_el); + int indice_ele=1; // pour parcourir le tableau final d'élément + for (int i=1;i<=NBE;i++) + if (!tab_el_non_referencer(i)) + {tab_element(indice_ele) = tab_old_El(i); + nv_tab_ele(i)=indice_ele; + tab_element(indice_ele)->Change_num_elt(indice_ele); + indice_ele++; + }; + + // on s'occupe maintenant des références + lesRef->Mise_a_jour_ref_element(nv_tab_ele,idmail,tab_el_non_referencer); + lesRef->Mise_a_jour_ref_noeud(nv_tab_noe,idmail,tab_noe_non_referencer); + // toilettage final + listFrontiere.clear();tab_noeud_front.Change_taille(0);indice.Change_taille(0); + mitoyen_de_chaque_element.Change_taille(0); + }; + + +// relocalisation des points milieux des arrêtes des éléments quadratiques +void Maillage::RelocPtMilieuMailleQuadra() + { // on passe en revue les différents éléments pour voir s'il ont une arrête quadratique + int nbe = tab_element.Taille(); + for (int ne=1;ne<=nbe;ne++) + { // récup de l'élément géométrique + const ElemGeomC0& elgeom = tab_element(ne)->ElementGeometrique_const(); + // récup du nombre de segment + int nbse= elgeom.NbSe(); + // on boucle sur les segments pour voir s'il y a un quadratique + for (int iseg=1;iseg<=nbse;iseg++) + { ElemGeomC0 const & elseg = elgeom.ElemSeg(iseg); + if (elseg.TypeInterpolation() == QUADRACOMPL) + { // récup de la connection des noeuds des arêtes par rapport a ceux de l'element + Tableau > const & nonStout = elgeom.NonS(); + Tableau const & nonS = nonStout(iseg); + Tableau& t_noeud = tab_element(ne)->Tab_noeud(); + Noeud & N1=*t_noeud(nonS(1));Noeud & N2=*t_noeud(nonS(2));Noeud & N3=*t_noeud(nonS(3)); + // ------------- étape de modification du noeud milieu ----------------------- + Coordonnee M01= N1.Coord0();Coordonnee M02= N2.Coord0();Coordonnee M03= N3.Coord0(); + Coordonnee M1M3=(M03-M01);Coordonnee M1M2=(M02-M01);Coordonnee M2M3=(M03-M02); + double d12=M1M2.Norme();double d13=M1M3.Norme();double d23=M2M3.Norme(); + if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit)) + { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant 0" + << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment" + << "\n Maillage::RelocPtMilieuMailleQuadra()"; + N1.Affiche(); N2.Affiche(); N3.Affiche(); + break; + } + Coordonnee U=M1M3/d13; + // le vecteur normal à U + int dim = ParaGlob::Dimension(); Coordonnee V(dim); + double sinusangle; + switch (dim) + { case 1: // ici il suffit de prendre le point milieu + { sinusangle=0.; break;} + case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;} + case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2); + if (sinusangle > ConstMath::unpeupetit) + { W.Normer(); V = Util::ProdVec_coor(W,U);} + break; + } + }; + // on vérifie que les 3 points ne sont pas naturellement alignés + if (sinusangle > ConstMath::unpeupetit) + // cas où l'on peut considérer une base locale + { + double N1H = M1M2*U; double HN2 = M1M2*V; + double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H)); + Coordonnee P = M01 + p1 * U + p2 * V;; + N2.Change_coord0(P); break; + } + else + // cas où les 3 points sont originalement alignés + { Coordonnee milieu = (M01+M03)/2.; + N2.Change_coord0(milieu); break; + } + // +++++++ si les coordonnées à t existent, même traitement + if (N1.ExisteCoord1()) + { M01= N1.Coord1();M02= N2.Coord1();M03= N3.Coord1(); + M1M3=(M03-M01); M1M2=(M02-M01); M2M3=(M03-M02); + d12=M1M2.Norme(); d13=M1M3.Norme(); d23=M2M3.Norme(); + if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit)) + { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant t" + << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment" + << "\n Maillage::RelocPtMilieuMailleQuadra()"; + N1.Affiche(); N2.Affiche(); N3.Affiche(); + break; + } + U=M1M3/d13; + // le vecteur normal à U + switch (dim) + { case 1: // ici il suffit de prendre le point milieu + { sinusangle=0.; break;} + case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;} + case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2); + if (sinusangle > ConstMath::unpeupetit) + { W.Normer(); V = Util::ProdVec_coor(W,U);} + break; + } + }; + // on vérifie que les 3 points ne sont pas naturellement alignés + if (sinusangle > ConstMath::unpeupetit) + // cas où l'on peut considérer une base locale + { + double N1H = M1M2*U; double HN2 = M1M2*V; + double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H)); + Coordonnee P = M01 + p1 * U + p2 * V;; + N2.Change_coord1(P); break; + } + else + // cas où les 3 points sont originalement alignés + { Coordonnee milieu = (M01+M03)/2.; + N2.Change_coord1(milieu); break; + } + } + // +++++ si les coordonnées à t existent, même traitement + if (N1.ExisteCoord2()) + { M01= N1.Coord2();M02= N2.Coord2();M03= N3.Coord2(); + M1M3=(M03-M01); M1M2=(M02-M01); M2M3=(M03-M02); + d12=M1M2.Norme(); d13=M1M3.Norme(); d23=M2M3.Norme(); + if ((d12 < ConstMath::unpeupetit) || (d13 < ConstMath::unpeupetit) || (d23 < ConstMath::unpeupetit)) + { cout << "\n erreur deux des trois points du segment quadratique sont confondu a l'instant tdt" + << "\n il n'est pas possible d'effectuer la relocalisation du noeud milieu pour ce segment" + << "\n Maillage::RelocPtMilieuMailleQuadra()"; + N1.Affiche(); N2.Affiche(); N3.Affiche(); + break; + } + U=M1M3/d13; + // le vecteur normal à U + switch (dim) + { case 1: // ici il suffit de prendre le point milieu + { sinusangle=0.; break;} + case 2 : {V(1) = -U(2); V(2)=U(1);sinusangle = Util::Determinant(U,M1M2);break;} + case 3 : {Coordonnee W = Util::ProdVec_coor(U,M1M2); sinusangle = Util::Determinant(U,M1M2); + if (sinusangle > ConstMath::unpeupetit) + { W.Normer(); V = Util::ProdVec_coor(W,U);} + break; + } + }; + // on vérifie que les 3 points ne sont pas naturellement alignés + if (sinusangle > ConstMath::unpeupetit) + // cas où l'on peut considérer une base locale + { + double N1H = M1M2*U; double HN2 = M1M2*V; + double p1 = d13/2.; double p2 = d13*d13*HN2/(4.*N1H*(d13-N1H)); + Coordonnee P = M01 + p1 * U + p2 * V;; + N2.Change_coord2(P); break; + } + else + // cas où les 3 points sont originalement alignés + { Coordonnee milieu = (M01+M03)/2.; + N2.Change_coord2(milieu); break; + } + } + // ------------- fin de l'étape de modification du noeud milieu - -------------- + } + } + } + }; + +// sortie du schemaXML: en fonction de enu +void Maillage::SchemaXML_Maillages(ofstream& sort,const Enum_IO_XML enu) + { switch (enu) + {case XML_TYPE_GLOBAUX: + {// on définit des types pour un maillage + Noeud::SchemaXML_Noeud(sort,enu); + // def du type maillage + sort << "\n " + << "\n " + << "\n un nom de maillage, des noeuds, des references de noeuds," + << "\n des elements, des references d'elements " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n "; + + + + /* << "\n " + << "\n " + << "\n " */ + + sort << "\n " + << "\n "; + break; + } + case XML_IO_POINT_INFO: + {// cas de la définition d'un maillage +/* sort << "\n " + << "\n " + << "\n " + << "\n un nom de maillage, des noeuds, des references de noeuds," + << "\n des elements, des references d'elements " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n "*/ + + + + /* << "\n " + << "\n " + << "\n " */ + + /* sort << "\n " + << "\n " + << "\n ";*/ + // def de Maillage +// SchemaXML_Maillage(sort,niveau); + break; + } + }; + }; + +//---------------------- class de travail --------------------------- + +// classe de travail qui sert pour pouvoir classer les noeuds par leur position géométrique initiale +// deux élément sont identiques si leur position initiale sont identique +// a >= b si : soit a.x >= b.x, ou a.x==b.x et a.y >= b.y, ou a.x==b.x et a.y == b.y et a.z >= b.z + +Maillage::PosiEtNoeud& Maillage::PosiEtNoeud::operator= (const Maillage::PosiEtNoeud& po) // affectation + { noe=po.noe; return *this;}; + +bool Maillage::PosiEtNoeud::operator == (const Maillage::PosiEtNoeud& po) const // test d'égalité + { if ((noe->Coord0()-po.noe->Coord0()).Norme() <= ConstMath::unpeupetit) return true; else return false; }; + +bool Maillage::PosiEtNoeud::operator != (const Maillage::PosiEtNoeud& po) const // test d'inégalité + { if (noe->Coord0() != po.noe->Coord0()) return true; else return false; }; + +bool Maillage::PosiEtNoeud::operator < (const Maillage::PosiEtNoeud& po) const // relation d'ordre + { Coordonnee co1=noe->Coord0(); Coordonnee co2=po.noe->Coord0(); + switch (co1.Dimension()) + { case 1: return (co1(1) < co2(1));break; + case 2: {if (co1(1) < co2(1)) return true; + else if (co1(1) == co2(1)) + { return (co1(2) < co2(2));} + else return false; + break;} + case 3: {if (co1(1) < co2(1)) return true; + else if (co1(1) == co2(1)) + { if (co1(2) < co2(2)) return true; + else if (co1(2) == co2(2)) + { return (co1(3) < co2(3));} + else false; + } + return false; + break; + } + default: + { cout << "\n erreur le cas différent de 1 2 3 n'est pas admissible ici= " << co1.Dimension() + << "\n bool Maillage::PosiEtNoeud::operator < (co... "; + Sortie(1); + } + }; + Sortie(1); // ne doit jamais passer ici !! + return false; + }; + +bool Maillage::PosiEtNoeud::operator <= (const Maillage::PosiEtNoeud& po) const // relation d'ordre + { Coordonnee co1=noe->Coord0(); Coordonnee co2=po.noe->Coord0(); + switch (co1.Dimension()) + { case 1: return (co1(1) <= co2(1));break; + case 2: {if (co1(1) < co2(1)) return true; + else if (co1(1) == co2(1)) + { return (co1(2) <= co2(2));} + else return false; + break;} + case 3: {if (co1(1) < co2(1)) return true; + else if (co1(1) == co2(1)) + { if (co1(2) < co2(2)) return true; + else if (co1(2) == co2(2)) + { return (co1(3) <= co2(3));} + else false; + } + return false; + break; + } + default: + { cout << "\n erreur le cas différent de 1 2 3 n'est pas admissible ici= " << co1.Dimension() + << "\n bool Maillage::PosiEtNoeud::operator <= (co... "; + Sortie(1); + } + }; + Sortie(1); // ne doit jamais passer ici !! + return false; + }; + +bool Maillage::PosiEtNoeud::operator > (const Maillage::PosiEtNoeud& po) const // relation d'ordre + { return !(*this <= po);}; + +bool Maillage::PosiEtNoeud::operator >= (const Maillage::PosiEtNoeud& po) const // relation d'ordre + { return !(*this < po);}; + +// transfert de grandeurs des points d'intégration aux noeuds +// 1- en entrée les type évolués et quelconques que l'on veut transférer +// 2- en entrée: cas qui indique la méthode de transfert à utiliser +// =1 : les valeurs aux noeuds sont obtenue par moyennage +// des valeurs des pts d'integ les plus près +// des éléments qui entourent le noeud +// on décompose le processus en 3 étapes pour éviter d'initialiser plusieurs +// fois lorque l'on refait à chaque fois +// le même transfert + +// A) première étape def des conteneurs et c'est tout, la méthode peut donc être utilisée +// pour autre chose. tabQ: permet d'avoir plusieurs listes de TypeQuelconque +// en entrée: tabQ doit-être de dimension 2, donc pointe sur 2 listes, si un des pointeur +// est nulle on n'en tient pas compte +void Maillage::AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu + ,const Tableau * >& tabQ) +{ // on crée des tableaux pour optimiser le nombre d'appel aux fonctions d'ajout de grandeur aux noeuds + // 1) cas des Ddl_enum_etendu + Tableau tab_ddlEnuEtendu(lienu.size()); + {List_io < Ddl_enum_etendu >::const_iterator ilienu,ilienufin = lienu.end(); + int indice = 1; + for (ilienu = lienu.begin();ilienu != ilienufin; ilienu++,indice++) + tab_ddlEnuEtendu(indice) = (*ilienu); + }; + // 2) cas des grandeurs quelconques + Tableau < TypeQuelconque > tabglobQ; + int ttai = 0; + if (tabQ(1) != NULL) ttai += tabQ(1)->size(); + if (tabQ(2) != NULL) ttai += tabQ(2)->size(); + tabglobQ.Change_taille(ttai); + int indice = 1; + if (tabQ(1) != NULL) + {List_io < TypeQuelconque >::const_iterator itabQ,itabQfin = tabQ(1)->end(); + for (itabQ = tabQ(1)->begin();itabQ != itabQfin; itabQ++,indice++) + {tabglobQ(indice).ChangeGrandeur(*itabQ); // on commence par changer la grandeur + tabglobQ(indice) = (*itabQ); // et on affecte + }; + }; + if (tabQ(2) != NULL) + {List_io < TypeQuelconque >::const_iterator itabQ,itabQfin = tabQ(2)->end(); + for (itabQ = tabQ(2)->begin();itabQ != itabQfin; itabQ++,indice++) + {tabglobQ(indice).ChangeGrandeur(*itabQ); // on commence par changer la grandeur + tabglobQ(indice) = (*itabQ); // et on affecte + }; + }; + + int nbN=tab_noeud.Taille(); + // on met à jour les noeuds + for(int i=1;i<=nbN;i++) + { // Pour les grandeurs ddl étendu on les ajoutes aux noeuds si ce n'est pas déjà fait + tab_noeud(i)->AjoutTabDdl_etendu(tab_ddlEnuEtendu); + // on ajoute également les différents types quelconques aux noeuds + tab_noeud(i)->AjoutTabTypeQuelconque(tabglobQ); + // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté + tab_noeud(i)->Mise_non_update_Ddl_etendu(); + tab_noeud(i)->Mise_non_update_grandeurs_quelconques(); + }; +}; + +// B) initialisation des updates sur les noeuds +void Maillage::InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienetendu + ,const Tableau * >& tabQ, int ) + {int nbN=tab_noeud.Taille(); + List_io ::const_iterator iliet,ilietfin = lienetendu.end(); + List_io ::const_iterator iliGQ,iliGQfin; + // on met à jour tous les noeuds + for(int inoeud=1;inoeud<=nbN;inoeud++) + {for (iliet = lienetendu.begin();iliet != ilietfin; iliet++) + {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); + // on initialise la grandeur pointée: + dd.Valeur()=0.; + // mise à 0 du nombre d'appel + tab_noeud(inoeud)->Mise_non_update_Ddl_etendu(*iliet); + }; + for (int iQu=1;iQu<=tabQ.Taille();iQu++) + {if (tabQ(iQu) != NULL) + {iliGQfin = tabQ(iQu)->end(); + for (iliGQ = tabQ(iQu)->begin();iliGQ != iliGQfin; iliGQ++) + {TypeQuelconque& tq = tab_noeud(inoeud)->ModifGrandeur_quelconque((*iliGQ).EnuTypeQuelconque()); + TypeQuelconque::Grandeur & grandeur = *(tq.Grandeur_pointee()); + // on initialise la grandeur pointée: + grandeur *= 0.; + // mise à 0 du nombre d'appel + tab_noeud(inoeud)->Mise_non_update_grandeurs_quelconques((*iliGQ).EnuTypeQuelconque()); + }; + } + }; + }; + }; + +// D) dernière étape: (par exemple calcul des moyennes en chaque noeuds) +void Maillage::FinTransfertPtIntegAuNoeud + (const List_io < Ddl_enum_etendu >& lienetendu,const Tableau * >& tabQ,int cas) +{switch(cas) + { case 1: // cas du transfert par moyennage + { int nbN=tab_noeud.Taille(); + List_io ::const_iterator iliet,ilietfin = lienetendu.end(); + List_io ::const_iterator iliGQ,iliGQfin; + // on passe en revue les grandeurs aux noeuds, et on les moyennes + for(int inoeud=1;inoeud<=nbN;inoeud++) + { // .. pour les ddl étendus .. + for (iliet = lienetendu.begin();iliet != ilietfin; iliet++) + {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); + // on modifie la grandeur pointée: -1 car ici on vient d'appeler + // ModifDdl_etendu qui comptabilise un appel de + + // dd.Valeur()/=(tab_noeud(inoeud)->DdlEtendue_update(*iliet)-1); + int nbappel = MaX((tab_noeud(inoeud)->DdlEtendue_update(*iliet)-1),1); + dd.Valeur()/=nbappel; + }; + // .. pour les grandeurs quelconques .. + for (int iQu=1;iQu<=tabQ.Taille();iQu++) + {if (tabQ(iQu) != NULL) + {iliGQfin = tabQ(iQu)->end(); + for (iliGQ = tabQ(iQu)->begin();iliGQ != iliGQfin; iliGQ++) + {TypeQuelconque_enum_etendu enuQ = (*iliGQ).EnuTypeQuelconque(); + TypeQuelconque& tq = tab_noeud(inoeud)->ModifGrandeur_quelconque(enuQ); + TypeQuelconque::Grandeur & grandeur = *(tq.Grandeur_pointee()); + // on modifie les grandeurs pointées: -1 car ici on vient d'appeler + // ModifGrandeur_quelconque qui comptabilise un appel de + + grandeur /= MaX((tab_noeud(inoeud)->Grandeur_quelconque_update(enuQ)-1),1); +//--- debug +//if (iliGQ == tabQ(iQu)->begin()) +// cout << " noeud " << inoeud << " grandeur " << grandeur << endl; +//--- fin debug + }; + } + }; + }; + break; + } + default : + cout << "\n *** cas non implante, cas = " << cas + << "\n FinTransfertPtIntegAuNoeud(... "; + Sortie(1); + }; + +}; + +// fonctions utilitaires du même genre + +// ajout sur le maillage d'un conteneur particulier quelconque +void Maillage::AjoutConteneurAuNoeud(TypeQuelconque& tQ) +{ int nbN=tab_noeud.Taille(); + // on met à jour les noeuds + for(int i=1;i<=nbN;i++) + { // on ajoute le type quelconque au noeud + tab_noeud(i)->AjoutUnTypeQuelconque(tQ); + // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté + tab_noeud(i)->Mise_non_update_grandeurs_quelconques(); + }; +}; + +// ajout sur le maillage d'un ou plusieur ddl_enum_etendu comme conteneur +void Maillage::AjoutConteneurAuNoeud(const List_io < Ddl_enum_etendu >& lienu) +{ // on crée des tableaux pour optimiser le nombre d'appel aux fonctions d'ajout de grandeur aux noeuds + // 1) cas des Ddl_enum_etendu + Tableau tab_ddlEnuEtendu(lienu.size()); + {List_io < Ddl_enum_etendu >::const_iterator ilienu,ilienufin = lienu.end(); + int indice = 1; + for (ilienu = lienu.begin();ilienu != ilienufin; ilienu++,indice++) + tab_ddlEnuEtendu(indice) = (*ilienu); + }; + + int nbN=tab_noeud.Taille(); + int nb_ienu = lienu.size(); + // on met à jour les noeuds + for(int i=1;i<=nbN;i++) + { // Pour les grandeurs ddl étendu on les ajoutes aux noeuds si ce n'est pas déjà fait + tab_noeud(i)->AjoutTabDdl_etendu(tab_ddlEnuEtendu); + // on met à jour le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté + for (int idee=1; idee <= nb_ienu; idee++) + tab_noeud(i)->Mise_non_update_Ddl_etendu(tab_ddlEnuEtendu(idee)); + }; +}; + +// initialisation des updates de ddl_étendu uniquement sur les noeuds: on met à 0 les ddl_etendu correspondant, +// les compteurs, comptant le nombre de fois où les noeuds sont modifiés, sont mis à 0 +void Maillage::InitUpdateAuNoeud(const List_io < Ddl_enum_etendu >& lienetendu) + {int nbN=tab_noeud.Taille(); + List_io ::const_iterator iliet,ilietfin = lienetendu.end(); + // on met à jour tous les noeuds + for(int inoeud=1;inoeud<=nbN;inoeud++) + {for (iliet = lienetendu.begin();iliet != ilietfin; iliet++) + {Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(*iliet); + // on initialise la grandeur pointée: + dd.Valeur()=0.; + }; + // on met à 0 le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté + tab_noeud(inoeud)->Mise_non_update_Ddl_etendu(); + }; + }; + +// initialisation des updates d'un seul ddl_étendu uniquement sur les noeuds: on met à 0 le ddl_etendu correspondant, +// le compteur, comptant le nombre de fois où le noeud est modifié, est mis à 0 +void Maillage::InitUpdateAuNoeud(const Ddl_enum_etendu & enetendu) + {int nbN=tab_noeud.Taille(); + // on met à jour tous les noeuds + for(int inoeud=1;inoeud<=nbN;inoeud++) + { // on initialise la grandeur pointée: + (tab_noeud(inoeud)->ModifDdl_etendu(enetendu)).Valeur()=0.; + // on met à 0 le tableau d'indice de noeud, qui donne le nombre de fois où chaque noeud à été updaté + tab_noeud(inoeud)->Mise_non_update_Ddl_etendu(); + }; + }; + +// moyenne des valeurs aux noeuds (en fonction du nombre ou le noeud a été modifié) +void Maillage::MoyenneCompteurAuNoeud(const Ddl_enum_etendu & enu) +{ int nbN=tab_noeud.Taille(); + // on passe en revue les grandeurs aux noeuds, et on les moyennes + for(int inoeud=1;inoeud<=nbN;inoeud++) + { Ddl_etendu& dd = tab_noeud(inoeud)->ModifDdl_etendu(enu); + // on modifie la grandeur pointée: -1 car ici on vient d'appeler + // ModifDdl_etendu qui comptabilise un appel de + + int nbappel = (tab_noeud(inoeud)->DdlEtendue_update(enu)-1); + dd.Valeur()/=nbappel; + }; +}; + +// initialisation des coordonnées à t et tdt aux mêmes valeurs qu'à 0 +// utile quand on veut utiliser les métriques pour un pb non couplés +void Maillage::Init_Xi_t_et_tdt_de_0() +{ int nbN=tab_noeud.Taille(); + // on passe en revue les grandeurs aux noeuds, et on les moyennes + for(int inoeud=1;inoeud<=nbN;inoeud++) + { Noeud & noe = *tab_noeud(inoeud); + const Coordonnee& co1 = noe.Coord0(); + noe.Change_coord1(co1); + noe.Change_coord2(co1); + }; +}; + +// lecture des mouvements solides si nécessaire +void Maillage::Lecture_des_mouvements_solides(UtilLecture * entreePrinc) + { // on définit un mouvement solide (vide par défaut) + MvtSolide mvtsolide; + if (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL) // cas de mouvements initiaux initiaux + { if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ; + entreePrinc->NouvelleDonnee(); // on passe le mot clé + }; + // lecture éventuelle des mouvements solides + mvtsolide.Lecture_mouvements_solides(entreePrinc); + // traitement au cas où il y a eu lecture de mouvements non nul + if (mvtsolide.ExisteMvtSolide()) + { if (ParaGlob::NiveauImpression() >= 6) + cout << " traitement des mouvements solides initiaux sur le maillage " << endl ; + // on passe le mot clé de fin de mouvement solides pour les lectures suivantes + entreePrinc->NouvelleDonnee(); + + // --- dans le cas où il y a des centres de rotation qui sont des positions de noeud, on renseigne + // a) récupération des centres de rotation noeud, éventuellement + const list & lis_centre_noeud = mvtsolide.Liste_ident_centreNoeud(); + if (lis_centre_noeud.size() != 0) + { list ::const_iterator ict,ictfin=lis_centre_noeud.end(); + list list_coor; // liste des coordonnées des noeuds centre de rotation + for (ict = lis_centre_noeud.begin();ict!=ictfin;ict++) + { // a priori ne concerne que le maillage en question + if (((*ict).nom == "")|| ((*ict).nom == nomDuMaillage)) + // cas normal + { int num_noeud = (*ict).n; + if ((num_noeud < 0) || (num_noeud > tab_noeud.Taille())) + { cout << "\n *** erreur sur le numero de noeud de centre de rotation = "<< num_noeud + << " on ne peut pas appliquer la rotation " << endl; + if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ; + }; + list_coor.push_back(tab_noeud(num_noeud)->Coord0()); // on récupère les coordonnées initiales + } + else // cas où il s'agit d'un autre maillage, pour l'instant non pris en compte + { cout << "\n *** erreur sur le numero de noeud concerne un autre maillage = "<< (*ict).nom + << " cette option n'est pas prise en compte " << endl; + if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des mouvements solides initiaux " << endl ; + }; + }; + // b) maintenant on passe l'info au mouvement solide + mvtsolide.RenseigneCentreNoeud(list_coor); + }; + int nbnoeud = tab_noeud.Taille(); + Coordonnee point_inter; + for (int ne=1;ne<=nbnoeud;ne++) + { point_inter = tab_noeud(ne)->Coord0(); // récupération des coordonnées initiales + mvtsolide.AppliqueMvtSolide(point_inter); // on applique le mouvement solide + tab_noeud(ne)->Change_coord0(point_inter); // on met à jour les nouvelles coordonnées + }; + }; + }; + +// ajout d'une liste de noeud à un maillage +// si le numéro de maillage associé au noeud est nul, il est remplacé par celui du maillage +// si le numéro de maillage est déjà existant et est différent ce celui de this, il y a +// création d'un nouveau noeud identique, avec le numéro this +// ajout éventuel d'une liste de référence de noeuds, si celle-ci est non-nulle +// il y a création de nouvelles ref correspondantes au numéro de maillage de this +// et ces références sont rajoutées à lesRef +void Maillage::Ajout_de_Noeuds(const list & lisN, list * lref,LesReferences* lesRef ) +{ // on change de taille du tableau de noeud et on ajoute les noeuds passés en paramètre + int nbN = tab_noeud.Taille(); + int nb_lisN = lisN.size(); + tab_noeud.Change_taille(nbN+nb_lisN); + list::const_iterator il,ilfin=lisN.end(); + // on définit un tableau indiquant les nouveaux numéros indicés par les anciens + // t_new_num(i) : = le numéro du nouveau noeud correspondant au noeud initial i + int taille_maxi = 0; + for(il=lisN.begin();il!=ilfin;il++) // un premier passage pour avoir la dimension maxi du tableau + if ((*il)->Num_noeud() > taille_maxi) + taille_maxi = (*il)->Num_noeud(); + Tableau t_new_num(taille_maxi,0); // les données du tableau sont initialisées à 0 + + int i=1; + for(il=lisN.begin();il!=ilfin;il++,i++) + { int ancien_num = (*il)->Num_noeud(); + if (((*il)->Num_Mail() != 0) && ((*il)->Num_Mail() != idmail)) + { // on crée un nouveau noeud identique + Noeud* new_noe = new Noeud(*(*il)); + // on change les numéros de noeud et de maillage + new_noe->Change_num_noeud(i+nbN); + new_noe->Change_num_Mail(idmail); + // affectation + tab_noeud(i+nbN) = new_noe; + } + else // sinon cela signifie que le noeud n'appartient pas pour l'instant à un maillage + { // on change les numéros de noeud et de maillage + (*il)->Change_num_noeud(i+nbN); + (*il)->Change_num_Mail(idmail); + // affectation + tab_noeud(i+nbN) = (*il); + }; + // on enregistre le nouveau num que si l'ancien est non nul + if (ancien_num != 0) + t_new_num(ancien_num) = i+nbN; + }; + // cas de la présence d'une liste de référence éventuellement à ajouter + if (lref != NULL) + { + #ifdef MISE_AU_POINT + if (lesRef == NULL) + { cout << "\n erreur le conteneur de reference n'est pas defini " + << "\n Maillage::Ajout_de_Noeuds(... "; + Sortie(1); + }; + #endif + // on va passer en revue la liste des références à ajouter + list::const_iterator im,imfin = lref->end(); + for (im=lref->begin();im!=imfin;im++) + { if ((*im)->Indic() == 1) + {const ReferenceNE & refN = *((ReferenceNE *) (*im)); + // on va contruire une nouvelle référence ad hoc: + string nouveau_nom = (refN.Nom()); + // on regarde s'il y a déjà une ref avec le même nom dans le maillage + // si oui on change le nom de la ref à ajouter + string ajout="";int num=0; + while (lesRef->Existe((refN.Nom()+ajout),idmail)) + {num++;ajout = "_"+ChangeEntierSTring(num);}; + if (ajout != "") + { nouveau_nom += ajout; + if (ParaGlob::NiveauImpression() > 0) + cout << "\n >>> attention la reference "< tt = refN.Tab_num(); // on récupère une copie du tableau de ref + // on le met à jour / aux nouveaux numéros + int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref + for (int k=1;k<= tai; k++) + {if (t_new_num(k) != 0) + { kn++; + tt(kn) = t_new_num(k); // cas où effectivement on a rajouté un noeud qui était déjà référencé + // dans l'ancienne référence + } + else + {if (ParaGlob::NiveauImpression() > 0) + cout << "\n le noeud "<Ajout_reference(newref); + }; + }; + + }; + }; +}; + +// ajout d'une liste d'éléments et de noeud à un maillage +// si le numéro de maillage associé à l'élément ou noeud est nul, il est remplacé par celui du maillage +// si le numéro de maillage est déjà existant et est différent ce celui de this, il y a +// création d'un nouvel item identique, avec le numéro this +// ajout éventuel d'une liste de références associées , si celle-ci est non-nulle +// il y a création de nouvelles ref correspondantes au numéro de maillage de this +// et ces références sont rajoutées à lesRef +// les noeuds qui sont associés aux éléments de lisE, doivent faire partie : soit de lisN, soit du maillage this +void Maillage::Ajout_elements_et_noeuds + (const list & lisN, const list & lisE,list * lref,LesReferences* lesRef ) +{ // -- on commence par ajouter les noeuds en gardant une trace du type d'ajout + + // on change de taille du tableau de noeud et on ajoute les noeuds passés en paramètre + int nbN = tab_noeud.Taille(); + int nb_lisN = lisN.size(); + tab_noeud.Change_taille(nbN+nb_lisN); + list::const_iterator il,ilfin=lisN.end(); + // on définit un tableau indiquant les nouveaux numéros indicés par les anciens + // t_new_num(i) : = le numéro du nouveau noeud correspondant au noeud initial i + int taille_maxi = 0; + for(il=lisN.begin();il!=ilfin;il++) // un premier passage pour avoir la dimension maxi du tableau + if ((*il)->Num_noeud() > taille_maxi) + taille_maxi = (*il)->Num_noeud(); + Tableau t_new_num(taille_maxi,0); // les données du tableau sont initialisées à 0 + + list li_nevez_noeud; // la liste des nouvelles positions de noeuds + int i=1; + for(il=lisN.begin();il!=ilfin;il++,i++) + { int ancien_num = (*il)->Num_noeud(); + if (((*il)->Num_Mail() != 0) && ((*il)->Num_Mail() != idmail)) + { // on crée un nouveau noeud identique + Noeud* new_noe = new Noeud(*(*il)); + // on change les numéros de noeud et de maillage + new_noe->Change_num_noeud(i+nbN); + new_noe->Change_num_Mail(idmail); + // affectation + tab_noeud(i+nbN) = new_noe; + li_nevez_noeud.push_back(new_noe); + } + else // sinon cela signifie que le noeud n'appartient pas pour l'instant à un maillage + { // on change les numéros de noeud et de maillage + (*il)->Change_num_noeud(i+nbN); + (*il)->Change_num_Mail(idmail); + // affectation + tab_noeud(i+nbN) = (*il); + li_nevez_noeud.push_back((*il)); + }; + // on enregistre le nouveau num que si l'ancien est non nul + // sinon + if (ancien_num != 0) + t_new_num(ancien_num) = i+nbN; + }; + + // -- puis on s'occupe des éléments + + + // on change de taille du tableau d'éléments et on ajoute les éléments passés en paramètre + int nbE = tab_element.Taille(); + int nb_lisE = lisE.size(); + tab_element.Change_taille(nbE+nb_lisE); + list::const_iterator ie,iefin=lisE.end(); + // on définit un tableau indiquant les nouveaux numéros indicés par les anciens + // t_new_num_elem(i) : = le numéro du nouvel élément correspondant à l'élément initial i + taille_maxi = 0; + for(ie=lisE.begin();ie!=iefin;ie++) // un premier passage pour avoir la dimension maxi du tableau + if ((*ie)->Num_elt_const() > taille_maxi) + taille_maxi = (*ie)->Num_elt_const(); + Tableau t_new_num_elem(taille_maxi,0); // les données du tableau sont initialisées à 0 + + i=1; + for(ie=lisE.begin();ie!=iefin;ie++,i++) + { int num_elt = i+nbE; // numéro interne de l'élément + int ancien_num = (*ie)->Num_elt_const(); + Element* new_elem = NULL; // sera affecté dans le if qui suit + if (((*ie)->Num_maillage() != 0) && ((*ie)->Num_maillage() != idmail)) + { Element::Signature signa = (*ie)->Signature_element(); // récupération de la signature de l'élément + // on crée un nouveau element identique + new_elem = Element::Choix_element(idmail,num_elt,signa); + if (new_elem == NULL) + { // l'operation a echouee + cout << "\n Erreur dans la creation d'un nouvel element ****** "; + cout << "\n element : " << Nom_interpol(signa.id_interpol) + << " " << Nom_geom(signa.id_geom) + << "\n Maillage::Ajout_elements_et_noeuds(... " << endl; + Sortie (1); + }; + // on affecte les données internes + (*new_elem) = (*(*ie)); + // il faut de nouveau définir les numéros de maillage et d'élément + new_elem->Change_num_elt(num_elt); + new_elem->Change_num_maillage(idmail); + } + else // sinon cela signifie que l'éléments n'appartient pas pour l'instant à un maillage + { // on change les numéros d'élément et de maillage, et peut directement l'affecté + (*ie)->Change_num_elt(num_elt); + (*ie)->Change_num_maillage(idmail); + new_elem = (*ie); + }; + + // maintenant on va s'occuper de la connexion + Tableau& t_n_elem = new_elem->Tab_noeud(); + int nbnoe = t_n_elem.Taille(); + for (int inoe = 1; inoe <= nbnoe; inoe++) + {// on regarde si le noeud fait partie de la liste des noeuds en entrée + // ou alors, qu'il utilise les noeuds existants + bool fait_partie = false; + list::iterator it=li_nevez_noeud.begin(); + for(il=lisN.begin();il!=ilfin;il++,it++) + if ((*il) == t_n_elem(inoe)) + { fait_partie = true; break;}; + // deux cas + if (fait_partie) + // on réaffecte + {t_n_elem(inoe)=(*it);} + else // sinon cela signifie que l'on utilise les noeuds existants + // on vérifie qu'il s'agit bien de noeud existant + { bool verif = false; + for (int j=1;j<= nbN;j++) // on boucle jusqu'à nbN = le nombre initial de noeud + if (tab_noeud(j) == t_n_elem(inoe)) + {verif = true; break;}; + if (!verif) + { cout << "\n erreur, la connexion de l'element a ajouter n'est pas recevable " + << " le noeud "<Num_noeud()<< " de l'element " + << new_elem->Num_elt() << " n'existe pas dans le maillage initial " + << "\n Maillage::Ajout_elements_et_noeuds(... " << endl; + Sortie (1); + }; + } + }; + // arrivée ici c'est que tout est ok, on ajoute l'élément + tab_element(nbE+i)=new_elem; + // on enregistre le nouveau num que si l'ancien est non nul + if (ancien_num != 0) + t_new_num_elem(ancien_num) = nbE+i; + }; + + + // cas de la présence d'une liste de référence éventuellement à ajouter + if (lref != NULL) + { + #ifdef MISE_AU_POINT + if (lesRef == NULL) + { cout << "\n erreur le conteneur de reference n'est pas defini " + << "\n Maillage::Ajout_de_Noeuds(... "; + Sortie(1); + }; + #endif + // on va passer en revue la liste des références à ajouter + list::const_iterator im,imfin = lref->end(); + for (im=lref->begin();im!=imfin;im++) + {int indic = (*im)->Indic(); // pour simplifier + switch (indic) + {case 1: // cas d'une ref de noeuds + {const ReferenceNE & refN = *((ReferenceNE *) (*im)); + // on va contruire une nouvelle référence ad hoc: + string nouveau_nom = (refN.Nom()); + // on regarde s'il y a déjà une ref avec le même nom dans le maillage + // si oui on change le nom de la ref à ajouter + string ajout="";int num=0; + while (lesRef->Existe((refN.Nom()+ajout),idmail)) + {num++;ajout = "_"+ChangeEntierSTring(num);}; + if (ajout != "") + { nouveau_nom += ajout; + if (ParaGlob::NiveauImpression() > 0) + cout << "\n >>> attention la reference "< tt = refN.Tab_num(); // on récupère une copie du tableau de ref + Tableau tt_new = tt; // le nouveau tableau + // on le met à jour / aux nouveaux numéros + int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref + for (int k=1;k<= tai; k++) + {if (t_new_num(tt(k)) != 0) + { kn++; + tt_new(kn) = t_new_num(tt(k)); // cas où effectivement on a rajouté un noeud qui était déjà référencé + // dans l'ancienne référence + } + else + {if (ParaGlob::NiveauImpression() > 0) + cout << "\n le noeud "<Ajout_reference(newref); + }; + break; + } + case 2: // cas d'une ref d'éléments + {const ReferenceNE & refE = *((ReferenceNE *) (*im)); + // on va contruire une nouvelle référence ad hoc: + string nouveau_nom = (refE.Nom()); + // on regarde s'il y a déjà une ref avec le même nom dans le maillage + // si oui on change le nom de la ref à ajouter + string ajout="";int num=0; + while (lesRef->Existe((refE.Nom()+ajout),idmail)) + {num++;ajout = "_"+ChangeEntierSTring(num);}; + if (ajout != "") + { nouveau_nom += ajout; + if (ParaGlob::NiveauImpression() > 0) + cout << "\n >>> attention la reference "< tt = refE.Tab_num(); // on récupère une copie du tableau de ref + // on le met à jour / aux nouveaux numéros + int tai = tt.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref + Tableau tt_new = tt; // le nouveau tableau + for (int k=1;k<= tai; k++) + {if (t_new_num_elem(tt(k)) != 0) + { kn++; + tt_new(kn) = t_new_num_elem(tt(k)); // cas où effectivement on a rajouté un élément qui était déjà référencé + // dans l'ancienne référence + } + else + {if (ParaGlob::NiveauImpression() > 0) + cout << "\n l'element "<Ajout_reference(newref); + }; + break; + } + case 3: case 4: case 5: case 6:// cas des autres refs: exemple surfaces + {const ReferenceAF & refAF = *((ReferenceAF *) (*im)); + // on va contruire une nouvelle référence ad hoc: + string nouveau_nom = (refAF.Nom()); + // on regarde s'il y a déjà une ref avec le même nom dans le maillage + // si oui on change le nom de la ref à ajouter + string ajout="";int num=0; + while (lesRef->Existe((refAF.Nom()+ajout),idmail)) + {num++;ajout = "_"+ChangeEntierSTring(num);}; + if (ajout != "") + { nouveau_nom += ajout; + if (ParaGlob::NiveauImpression() > 0) + cout << "\n >>> attention la reference "< te = refAF.Tab_Elem(); // on récupère une copie du tableau des éléments + Tableau te_new = te; // le nouveau tableau + // apriori seules les numéros d'élément sont succeptible d'avoir changé, les numéros + // locaux: surface, arête, noeuds relatifs à l'éléments, et pti restent inchangé + // par contre ils peuvent être supprimés si le num d'élément est supprimé + Tableau tl = refAF.Tab_FA(); // on récupère une copie du tableau des num locaux + + // on met à jour le tableau de d'éléments / aux nouveaux numéros + int tai = te.Taille();int kn=0; // kn c'est le pointeur dans la nouvelle ref + for (int k=1;k<= tai; k++) + {if (t_new_num_elem(te(k)) != 0) + { kn++; + te_new(kn) = t_new_num_elem(te(k)); // cas où effectivement on a rajouté un élément qui était déjà référencé + // dans l'ancienne référence + tl(kn) = tl(k); // normalement k est > kn, donc cela revient à décaler + // en ne gardant que les termes viables + } + else + {if (ParaGlob::NiveauImpression() > 0) + cout << "\n l'element "<Ajout_reference(newref); + }; + break; + } + }; + }; + }; + // -------------- ajout de références globales si elles n'existent pas --------------------- + // ---- mise à jour de la référence de tous les éléments si elle n'existe pas déjà + int nbElement = tab_element.Taille(); + string etout("E_tout"); + if (lesRef->Existe(etout,idmail)) + lesRef->SupprimeReference("E_tout",idmail); // on supprime la référence E_tout + // on construit le tableau des numéros des éléments + Tableau tabE(nbElement); for (int i=1;i<=nbElement;i++) tabE(i)=i; + ReferenceNE* retout = new ReferenceNE(tabE,idmail,2,etout);// construction de la référence + lesRef->Ajout_reference(retout); // ajout de la ref, qui est maintenant géré par lesRef + + // ---- dans tous les cas on ajoute ou modifie la référence de tous les noeuds + string ntout("N_tout"); + int nbNoeud = tab_noeud.Taille(); + if (lesRef->Existe(ntout,idmail)) + lesRef->SupprimeReference("N_tout",idmail); // on supprime la référence N_tout + // on construit le tableau des numéros de noeuds + Tableau tabN(nbNoeud); for (int i=1;i<=nbNoeud;i++) tabN(i)=i; + ReferenceNE* rtout = new ReferenceNE(tabN,idmail,1,ntout);// construction de la référence + lesRef->Ajout_reference(rtout); // ajout de la ref, qui est maintenant géré par lesRef +//debug +//cout << "\n nbElement " << nbElement << ", nbNoeud "<< nbNoeud << endl; +// fin debug + + +}; + + +// force la mise à une valeur d'un ddl (ou de la liste de ddl fonction de la dimention) particulier, quelques soit son activité +// si fonction_de_la_dimension = true : c'est toute les ddl fct de la dimension qui sont mis à la valeur +void Maillage::Force_Ddl_aux_noeuds_a_une_valeur(Enum_ddl enu, const double& val,Enum_dure temps, bool fonction_de_la_dimension) +{ + int nbnoeud = tab_noeud.Taille(); + int dima = ParaGlob::Dimension(); + switch (temps) + {case TEMPS_0: + { if (!(fonction_de_la_dimension) || !FoncDim(enu)) + {for (int i=1;i<= nbnoeud;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (noe.Existe_ici(enu)) // on intervient que si le ddl existe + noe.Change_val_0(enu,val); + }; + } + else + {for (int i=1;i<= nbnoeud;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (noe.Existe_ici(enu)) // on intervient que si le ddl existe + { switch (dima) + { case 3: noe.Change_val_0(Enum_ddl(enu+2),val); + case 2: noe.Change_val_0(Enum_ddl(enu+1),val); + case 1: noe.Change_val_0(Enum_ddl(enu),val); + }; + }; + }; + }; + break; + } + case TEMPS_t: + { if (!(fonction_de_la_dimension) || !FoncDim(enu)) + {for (int i=1;i<= nbnoeud;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (noe.Existe_ici(enu)) // on intervient que si le ddl existe + noe.Change_val_t(enu,val); + }; + } + else + {for (int i=1;i<= nbnoeud;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (noe.Existe_ici(enu)) // on intervient que si le ddl existe + { switch (dima) + { case 3: noe.Change_val_t(Enum_ddl(enu+2),val); + case 2: noe.Change_val_t(Enum_ddl(enu+1),val); + case 1: noe.Change_val_t(Enum_ddl(enu),val); + }; + }; + }; + }; + break; + } + case TEMPS_tdt: + { if (!(fonction_de_la_dimension) || !FoncDim(enu)) + {for (int i=1;i<= nbnoeud;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (noe.Existe_ici(enu)) // on intervient que si le ddl existe + noe.Change_val_tdt(enu,val); + }; + } + else + {for (int i=1;i<= nbnoeud;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (noe.Existe_ici(enu)) // on intervient que si le ddl existe + { switch (dima) + { case 3: noe.Change_val_tdt(Enum_ddl(enu+2),val); + case 2: noe.Change_val_tdt(Enum_ddl(enu+1),val); + case 1: noe.Change_val_tdt(Enum_ddl(enu),val); + }; + }; + }; + }; + break; + } + }; + +}; + + +// mise à zéro de dd_enum_etendu aux noeuds : force la mise à une valeur à 0 +void Maillage::Force_Ddl_etendu_aux_noeuds_a_zero(const Tableau& tab_enu) +{ + int nbnoeud = tab_noeud.Taille(); + int nb_enu = tab_enu.Taille(); + for (int i=1;i<=nb_enu;i++) + {const Ddl_enum_etendu& enu = tab_enu(i); + for (int i=1;i<= nbnoeud;i++) + { Noeud& noe = *tab_noeud(i); // pour simplifier + if (noe.Existe_ici_ddlEtendu(enu)) // on intervient que si le ddl existe + noe.ModifDdl_etendu(enu).Valeur() = 0.; + }; + }; + +}; + + +// on s'occupe de mettre à jour les types de pb et les ddl types associés +void Maillage::Mise_a_jour_type_pb_type_associe_ddl() +{ //types_de_problemes.clear(); + //ddl_representatifs_des_physiques.clear(); +// types_de_problemes.Libere();ddl_representatifs_des_physiques.Libere(); +// int nbElement = tab_element.Taille(); +//string titi; +//cout << "\n nbElement "<> titi; +// // on définit un tableau intermédiaire +// int nombre_de_EnumElemTypeProblem = Nombre_de_EnumElemTypeProblem(); +//cout << "\n nombre_de_EnumElemTypeProblem "<> titi; +// Tableau < int> types_de_problemes_actif(nombre_de_EnumElemTypeProblem,0); +// types_de_problemes_actif(1)=1; +//cout << "\n taill "<> titi; +//cout << "\n types_de_problemes_actif(1) "<> titi; +// +// for (int i;i<=nbElement;i++) +// {Element& ele = *tab_element(i); +//cout << "\n i"<> titi; +//ele.Affiche(); +//cout << "\n i"<> titi; +// EnumElemTypeProblem enu = ele.Id_TypeProblem(); +//cout << "\n i"<> titi; +//int truc =enu; +//cout << "\n enu= "<> titi; +//cout << "\n types_de_problemes_actif(1) "<> titi; +//types_de_problemes_actif(1) = 1; +//cout << "\n types_de_problemes_actif(1) "<> titi; +//types_de_problemes_actif(int(enu)) = 1; +//cout << "\n types_de_problemes_actif(1) "<> titi; +// // types_de_problemes_actif(truc) = 1; // on rend actif l'élément du tableau +// }; +//cout << "\n une valeur ? "; +//cin >> titi; +// // maintenant on regarde le nombre de pb actif +// int nb_pb = 0; // init +// for (int i=1;i<=nombre_de_EnumElemTypeProblem;i++) +// if (types_de_problemes_actif(i)) nb_pb++; +//cout << "\n une valeur ? "; +//cin >> titi; +// // on redimentionne et on rempli +// types_de_problemes.Change_taille(nb_pb); +//cout << "\n une valeur ? "; +//cin >> titi; +// nb_pb = 0; // init +// for (int i=1;i<=nombre_de_EnumElemTypeProblem;i++) +// if (types_de_problemes_actif(i)) +// {nb_pb++;types_de_problemes(nb_pb)=EnumElemTypeProblem(i);}; +//cout << "\n une valeur ? "; +//cin >> titi; +// +// +////cout << "\n enu"<> titi; +//// bool trouve = false; +//// list ::iterator il,ilfin=types_de_problemes.end(); +////if (!types_de_problemes.empty()) +////cout << "\n ilfin il begin " << (*types_de_problemes.begin())<< " une valeur ? "; +////cin >> titi; +//// for (il=types_de_problemes.begin();il != ilfin; il++) +//// {cout << "\n "<> titi; +//// +//// if ((*il)==enu) {trouve = true; break;}; +//// }; +//// if (find(types_de_problemes.begin(),types_de_problemes.end(),enu) == types_de_problemes.end()) +//// if (!trouve) +////EnumElemTypeProblem tutu = MECA_SOLIDE_DEFORMABLE; +// // { types_de_problemes.push_back(tutu);}; +//// +//// int taill = types_de_problemes.Taille(); +//// for (int j=1;j<=taill;j++) +//// if (types_de_problemes(j) == enu) +//// { types_de_problemes.Change_taille(taill+1); +//// types_de_problemes(taill+1)=enu; +//// break; +//// }; +//// }; +//// inter.sort(); inter.unique(); +//// types_de_problemes = inter; +// // on parcours les types de pb pour attribuer les types de ddl +//// list ::iterator il,ilfin=types_de_problemes.end(); +//// for (il=types_de_problemes.begin();il != ilfin;il++) +//// +//// { switch (types_de_problemes(j)) +//// {case MECA_SOLIDE_DEFORMABLE : +//// ddl_representatifs_des_physiques.push_back(X1);break; +//// case THERMIQUE : +//// ddl_representatifs_des_physiques.push_back(TEMP);break; +//// default : +//// cout << "\n***Erreur : pour l'instant le type de probleme: "<. +// +// 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 "Maillage.h" +# include +using namespace std; //introduces namespace std +#include +#include "Sortie.h" +#include +#include +#include "List_io.h" +#include "CharUtil.h" +#ifndef SYSTEM_MAC_OS_X_unix + #include "Frontier.h" +#endif +#include "ConstMath.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" +#include "Util.h" +#include "MvtSolide.h" +#include "Basiques.h" +#include + + +// définition interactive de listes de références +void Maillage::CreationInteractiveListesRef(LesReferences* lesRef) + { string reponse=""; + bool fr = ParaGlob::Francais(); // pour simplifier + while ((reponse != "f")&&(reponse != "fi")&&(reponse != "fin")) + { // def de la liste des types de références voulues + list list_typeReference; + Enum_ddl enu_ddl; // associé aux pt d'integ nécessite un enuméré associé + list ::iterator it; + string typeReference=""; + while (!((typeReference == "f")||(typeReference == "fi")||(typeReference == "fin"))) + {// on initialise les listes de ref utilisées pour la def des nouvelles ref + // de manière à ne pas utiliser les refs déjà définies + list_refIn.clear(); + list_refOut.clear(); +// debug +// cout << "\n effacement de list_refIn et list_refOut " << endl; +// fin debug + + // affichage du menu du type de référence voulu + if (list_typeReference.size()!= 0) + { if (fr) {cout << "\n type actuellement enregistre ";} + else {cout << "\n type(s) already read ";}; + for (it=list_typeReference.begin();it!=list_typeReference.end();it++) + cout << " " << *it; + }; + if (fr) + {cout << "\n ref de noeuds (rep no) " + << "\n ref d'elements (rep el) " + << "\n ref de faces (rep fa) " + << "\n ref d'arretes (rep ar) " + << "\n ref de pt d'integration d'element (rep pt) " + << "\n toutes les ref de frontiere (rep tfr) " + << "\n effacer la liste actuelle (rep ef) " + << "\n fin def des types de ref voulu (rep f) " + << "\n reponses : (il peut y en avoir plusieurs differentes) "; + } + else + {cout << "\n reference of nodes (rep no) " + << "\n reference of elements (rep el) " + << "\n reference of facets (rep fa) " + << "\n reference of edges (rep ar) " + << "\n reference of integration points (rep pt) " + << "\n all the references of the boundary (rep tfr) " + << "\n deletion of the registered references (rep ef) " + << "\n end of the def of the type of ref (rep f) " + << "\n answer : (you can set several different ) "; + }; + + typeReference=lect_return_defaut(false,"f"); + if ((typeReference=="no")||(typeReference=="el")||(typeReference=="fa") + ||(typeReference=="ar")||(typeReference=="pt")) + { if (find(list_typeReference.begin(),list_typeReference.end(),typeReference) == list_typeReference.end()) + {list_typeReference.push_back(typeReference);} + else + {if (fr){cout << "\n type deja enregistre !! on n'en tient pas compte ";} + else {cout << "\n ype already registered !! we don't consider this choice ";}; + }; + } + else if (typeReference=="tfr") + {// là on crée directement les références et on continue + CreationRefFrontiere(*lesRef); +////--- debug +//cout << "\n debug Maillage::CreationInteractiveListesRef( "; +//lesRef->Affiche(1); +// +////--- fin debug + } + else if (typeReference=="ef") + list_typeReference.erase(list_typeReference.begin(),list_typeReference.end()); + else if ((typeReference == "f")||(typeReference == "fi")||(typeReference == "fin")) + { // fin demandé: on ne fait rien + } + else + {if (fr){cout << "\n mauvais choix lu : " << typeReference << ", verifiez la syntaxe et recommencez ";} + else {cout << "\n bad choice : " << typeReference << ", check your answer ";} + }; + }; + // définition du nom des références + string nomref; string rep = ""; + bool existe_demande_pti = false; + if (fr){cout << "\n \n ---- acquisition des noms de references ---- ";} + else {cout << "\n \n ---- reading of the reference names ---- ";} + list list_nomReference; + list ::iterator il, ilfin = list_typeReference.end(); + + // si la liste est non vide on continue + if ( list_typeReference.size()!= 0) + {while ((rep != "f")&&(rep != "fi")&&(rep != "fin")) + { // affichage du menu du type de référence voulu + list ::iterator il; + if (list_typeReference.size()!= 0) + { if (fr){cout << "\n liste de nom de reference actuellement enregistre ";} + else {cout << "\n list of the already registered reference names ";} + for (il=list_nomReference.begin();il!=list_nomReference.end();il++) + cout << " " << *il; + }; + for (il = list_typeReference.begin();il != ilfin; il++) + {if (*il == "no") + { bool nom_correcte = false; + while (!nom_correcte) + {if (fr){cout << "\n nom de la reference de noeud ? ";}else{cout << "\n name of the node reference ? ";}; + nomref= lect_chaine(); + nomref = "N_"+nomref; + if (!(lesRef->Existe(nomref,idmail))) + {list_nomReference.push_back(nomref); + nom_correcte=true; + } + else + { if (fr){cout << "\n la reference " << nomref << " existe deja, choissez un autre nom ";} + else {cout << "\n the reference " << nomref << " already exists, choose another name ";}; + }; + }; // fin du while + } + else if (*il == "el") + { bool nom_correcte = false; + while (!nom_correcte) + {if (fr){cout << "\n nom de la reference d'element ? "; nomref= lect_chaine();} + else {cout << "\n name of the element reference ? "; nomref= lect_chaine();}; + nomref = "E_"+nomref; + if (!(lesRef->Existe(nomref,idmail))) + {list_nomReference.push_back(nomref); + nom_correcte=true; + } + else + { if (fr){cout << "\n la reference " << nomref << " existe deja, choissez un autre nom ";} + else {cout << "\n the reference " << nomref << " already exists, choose another name ";}; + }; + }; // fin du while + } + else if (*il == "fa") + { bool nom_correcte = false; + while (!nom_correcte) + {if (fr){cout << "\n nom de la reference de face ? "; nomref= lect_chaine();} + else {cout << "\n name of the facet reference ? "; nomref= lect_chaine();}; + nomref = "F_"+nomref; + if (!(lesRef->Existe(nomref,idmail))) + {list_nomReference.push_back(nomref); + nom_correcte=true; + } + else + { if (fr){cout << "\n la reference " << nomref << " existe deja, choissez un autre nom ";} + else {cout << "\n the reference " << nomref << " already exists, choose another name ";}; + }; + }; // fin du while + } + else if (*il == "ar") + { bool nom_correcte = false; + while (!nom_correcte) + {if (fr){cout << "\n nom de la reference d'arrete ? "; nomref= lect_chaine();} + else {cout << "\n name of the edge reference ? "; nomref= lect_chaine();}; + nomref = "A_"+nomref; + if (!(lesRef->Existe(nomref,idmail))) + {list_nomReference.push_back(nomref); + nom_correcte=true; + } + else + { if (fr){cout << "\n la reference " << nomref << " existe deja, choissez un autre nom ";} + else {cout << "\n the reference " << nomref << " already exists, choose another name ";}; + }; + }; // fin du while + } + else if (*il == "pt") + { bool nom_correcte = false; + while (!nom_correcte) + {if (fr){cout << "\n nom de la reference de point d'integration ? " << endl; } + else {cout << "\n name of integration point reference ? "<< endl;}; + nomref= lect_chaine(); + string nomddl=""; + nomref = "G_"+nomref; + if (!(lesRef->Existe(nomref,idmail))) + {list_nomReference.push_back(nomref); + while (!ExisteEnum_ddl(nomddl)) + { if (fr) {cout << "\n donnez un nom d'un ddl de base associe aux points d'integration "; + cout << "\n liste de ddl possible : " << endl;} + else {cout << "\n give a dof name associated to this integration point "; + cout << "\n list of possible dof : " << endl;}; + for (int i=1;i::iterator il, ilfin = list_typeReference.end(); + for (il = list_typeReference.begin(); il!=ilfin;il++) + {if (*il == "pt") + while ((dem != "f")&&(dem != "fi")&&(dem != "fin")) + { List_io li_inter; li_inter.push_back(Ddl_enum_etendu(enu_ddl)); // liste de travail + + if (fr){cout << "\n ---- information concernant les pt d'integ existant ------ " + << "\n les coor d'un pt d'integ d'un ele choisit par numero (elem+integ) (rep chnbe ) " + << "\n les coor d'un pt d'integ d'un ele choisit le plus pres de (rep npres ) " + << "\n tous les coor des pt d'integ d'un elem choisit par numero (rep lespti ) " + << "\n fin (f )" << endl; + } + else {cout << "\n -- information concerning the existing integration points ------ " + << "\n the coord of an integ pt, choosen by its number+elem number (rep chnbe ) " + << "\n the coordinates of an integ pt, choosen with a nearest point (rep npres ) " + << "\n all the coord of an integ pt of an elem, choosen by its elem number (rep lespti ) " + << "\n end (f )" << endl; + }; + dem= lect_return_defaut(false,"f"); + int nbe, nbpti; + if (dem == "chnbe") + { if (fr){cout << "\n num element ? " << endl;}else{cout << "\n element number ? " << endl;}; + nbe=(int)lect_double(); + if ((nbe > 0) || (nbe <= tab_noeud.Taille())) + {if (fr){cout << "\n num pt integ ? " << endl;}else{cout << "\n integretion number ? " << endl;}; + nbpti=(int)lect_double(); + // vérification de l'existence d'un point d'intégration correspondant à un ddl + bool erreur=false; + if (tab_element(nbe)->Existe_pt_integ (nbpti,enu_ddl)) + { Coordonnee M = tab_element(nbe)->CoordPtInteg(TEMPS_0 ,enu_ddl,nbpti,erreur); + if (!erreur) + {cout << "\n " << M << "\n ";} + else {if (fr){cout << "\n ** erreur en sortie du point ?? " << endl;} + else{cout << "\n ** error in output of the point ?? " << endl;}; + }; + } + else + {if (fr){cout << " num de pt d'integ non correcte, recommencez !" << endl;} + else {cout << " bad number of integ pt, start again !" << endl;}; + }; + } + else {if (fr){cout << " num d'element non correcte, recommencez !"<< endl;} + else {cout << " bad number of element, start again !" << endl;}; + }; + } + else if (dem == "npres") + { int dima = ParaGlob::Dimension(); + Coordonnee xi(dima); + if (fr){cout << "\n coordonnee d'un point dans la matiere !! ("<< dima <<" nombre(s)) ? ";} + else {cout << "\n coordinate of a point in the material !! ("<< dima <<" number(s)) ? ";}; + for(int j=1;j<=dima;j++) cin >> xi(j); + std::cin.ignore( std::numeric_limits::max(), '\n' );// purge de cin + Maillage::NBelemEtptInteg nu = Element_le_plus_proche(TEMPS_0,li_inter,xi); + bool erreur=false; + if (nu.nbElem != 0) + { Coordonnee M = tab_element(nu.nbElem)->CoordPtInteg(TEMPS_0 ,enu_ddl,nu.nbPtInteg,erreur); + if (!erreur) + {cout << "\n element: " < 0) || (nbe <= tab_noeud.Taille())) + { int nbpti = tab_element(nbe)->NbPtInteg(enu_ddl); + bool erreur=false; + for (int i=1;i<=nbpti;i++) + cout << "\n pti "<CoordPtInteg(TEMPS_0 ,enu_ddl,i,erreur) + << "\n "; + } + else {if (fr){cout << " num d'element non correcte, recommencez !";} + else {cout << " wrong number of element, try again !";} + }; + } + else if (dem == "f") {} + else + {if (fr){cout << "\n syntaxe non correcte recommencez ! ";} + else {cout << "\n wrong syntaxes, try again ! ";} + }; + }; //-- fin du while + }; //-- fin de la boucle sur les type de ref + }; // -- fin du if demande pti + + // def de la méthode pour définir la liste d'éléments associé à la référence + string methode=""; + list list_methode; + int dima = ParaGlob::Dimension(); + + while ((methode != "f")&&(methode != "fi")&&(methode != "fin")) + {// affichage du menu du type de référence voulu + switch (dima) + {case 3: + if (fr) + {cout << "\n pres d'un plan (rep pres_plan) " + << "\n d'un cote du plan (rep cote_plan) " + << "\n entre deux plans // (rep entre_plans) " + << "\n entre plan // +- distance (rep entre_plans_dist) " + << "\n pres d'un cylindre (rep pres_cylindre) " + << "\n a l'interieur d'un cylindre (rep in_cylindre) " + << "\n a l'exterieur cylindre (rep ex_cylindre) " + << "\n entre deux cylindres // (rep entre_cylindres) " + << "\n pres d'une sphere (rep pres_sphere) " + << "\n dans une sphere (rep in_sphere) " + << "\n a l'exterieur d'une sphere (rep ex_sphere) " + << "\n entre deux spheres concentriques (rep entre_spheres) " + << "\n entre deux spheres concentriques (rep entre_spheres) " +// << "\n pres d'un parallelepipede (rep pres_para) " +// << "\n dans une parallelepipede (rep in_para) " +// << "\n a l'exterieur d'une parallelepipede (rep ex_para) " +// << "\n entre deux parallelepipedes (rep entre_para) " + << "\n pres d'un point (rep pres_point) " + << "\n pres d'une droite (rep pres_droite) " + << "\n pres d'un cercle (rep pres_cercle) " + << "\n addition d'une ref deja existante (rep in_ref) " + << "\n hors une ref dejà existante (rep out_ref) " + << "\n ordonner N et ptint / project sur une droite (rep ord_droite ) "; + break; + } + else + {cout << "\n near a plane (rep pres_plan) " + << "\n on one side of a plane (rep cote_plan) " + << "\n between two planes // (rep entre_plans) " + << "\n between plane // +- distance (rep entre_plans_dist) " + << "\n near a cylinder (rep pres_cylindre) " + << "\n inside a cylinder (rep in_cylindre) " + << "\n outside a cylinder (rep ex_cylindre) " + << "\n between two cylinders // (rep entre_cylindres) " + << "\n near a sphere (rep pres_sphere) " + << "\n into a sphere (rep in_sphere) " + << "\n outside a sphere (rep ex_sphere) " + << "\n between two concentric spheres (rep entre_spheres) " +// << "\n pres d'un parallelepipede (rep pres_para) " +// << "\n dans une parallelepipede (rep in_para) " +// << "\n a l'exterieur d'une parallelepipede (rep ex_para) " +// << "\n entre deux parallelepipedes (rep entre_para) " + << "\n near a point (rep pres_point) " + << "\n near a line (rep pres_droite) " + << "\n near a cercle (rep pres_cercle) " + << "\n addition of an already existing reference (rep in_ref) " + << "\n outside to an already existing reference (rep out_ref) " + << "\n sort N and Gauss points / projection on a line (rep ord_droite ) "; + break; + } + case 2: + if (fr) + { cout << "\n pres d'un point (rep pres_point) " + << "\n pres d'une droite (rep pres_droite) " + << "\n d'un cote d'une droite (rep cote_droite) " + << "\n entre deux droites // (rep entre_droites) " + << "\n entre droite // +- distance (rep entre_droites_dist) " + << "\n pres d'un cercle (rep pres_cercle) " + << "\n a l'interieur d'un cercle (rep in_cercle) " + << "\n a l'exterieur d'un cercle (rep ex_cercle) " + << "\n entre deux cercles concentriques (rep entre_cercles) " + << "\n addition d'une ref deja existante (rep in_ref) " + << "\n hors une ref dejà existante (rep out_ref) " + << "\n ordonner N et ptint / project sur une droite (rep ord_droite ) "; + // << "\n pres d'un rectangle (rep pres_rec) " + // << "\n a l'interieur d'un rectangle (rep in_rec) " + // << "\n a l'exterieur d'un rectangle (rep ex_rec) " + // << "\n entre deux rectangles (rep entre_rec) "; + break; + } + else + { cout << "\n near a point (rep pres_point) " + << "\n near a line (rep pres_droite) " + << "\n on one side of a line (rep cote_droite) " + << "\n between two lines // (rep entre_droites) " + << "\n between line // +- distance (rep entre_droites_dist) " + << "\n near a cercle (rep pres_cercle) " + << "\n inside a cercle (rep in_cercle) " + << "\n outside a cercle (rep ex_cercle) " + << "\n between two concentric cercles (rep entre_cercles) " + << "\n addition of an already existing reference (rep in_ref) " + << "\n outside to an already existing reference (rep out_ref) " + << "\n sort N and Gauss points / projection on a line (rep ord_droite ) "; + // << "\n pres d'un rectangle (rep pres_rec) " + // << "\n a l'interieur d'un rectangle (rep in_rec) " + // << "\n a l'exterieur d'un rectangle (rep ex_rec) " + // << "\n entre deux rectangles (rep entre_rec) "; + break; + } + case 1: + if (fr) + { cout << "\n pres d'un point (rep pres_point) " + << "\n d'un cote d'un point (rep cote_point) " + << "\n entre deux points (rep entre_points) " + << "\n entre point +- distance (rep entre_points_dist) " + << "\n addition d'une ref deja existante (rep in_ref) " + << "\n hors une ref dejà existante (rep out_ref) " + << "\n ordonner N et ptint / project sur l'axe (rep ord_droite ) "; + break; + } + else + { cout << "\n near a point (rep pres_point) " + << "\n on one side of a point (rep cote_point) " + << "\n between two points (rep entre_points) " + << "\n between point +- distance (rep entre_points_dist) " + << "\n addition of an already existing reference (rep in_ref) " + << "\n outside to an already existing reference (rep out_ref) " + << "\n sort N and Gauss points / projection on the axe (rep ord_droite ) "; + break; + } + }; + + if (fr){cout << "\n effacer la liste des methode (rep ef) " + << "\n fin def methodes (rep f) ";} + else {cout << "\n clear the list of method (rep ef) " + << "\n end def methods (rep f) ";}; + if (list_methode.size()!=0) + {if (fr) { cout << "\n (pour info: list actuellement enreg: ";} + else { cout << "\n (for info: list currently stored: ";}; + for (it=list_methode.begin();it!=list_methode.end();it++) + cout << " " << *it; + cout << " ) "; + }; + + if (fr) {cout << "\n reponses : (il peut y en avoir plusieurs ) "<< endl;} + else {cout << "\n answers : (several if needed ) "<< endl;} + methode= lect_return_defaut(false,"f"); // lecture + if (methode=="ef") + {list_methode.erase(list_methode.begin(),list_methode.end());} + else + {switch (dima) + {case 1 : + if ((methode == "pres_point")||(methode == "cote_point") + ||(methode == "entre_points")||(methode == "entre_points_dist") + ||(methode == "ord_droite") ||(methode == "in_ref")||(methode == "out_ref")) + { list_methode.push_back(methode);} + else if ((methode == "f") || (methode == "fi") || (methode != "fin")) { } // on ne fait rien + else + {if (fr) {cout << "\n mauvais choix lu : " << methode << ", verifiez la syntaxe et recommencez ";} + else {cout << "\n wrong choice read : " << methode << ", take a look on the syntaxes or spelling and do it again ";} + }; + break; + case 2 : + if ((methode == "pres_point")||(methode == "pres_droite")||(methode == "cote_droite") + ||(methode == "entre_droites")||(methode == "entre_droites_dist") + ||(methode == "pres_cercle")||(methode == "in_cercle")||(methode == "ex_cercle")||(methode == "entre_cercles") + ||(methode == "pres_rec")||(methode == "in_rec")||(methode == "ex_rec")||(methode == "entre_rec") + ||(methode == "ord_droite") ||(methode == "in_ref")||(methode == "out_ref")) + { list_methode.push_back(methode);} + else if ((methode == "f") || (methode == "fi") || (methode != "fin")) { } // on ne fait rien + else + {if (fr) {cout << "\n mauvais choix lu : " << methode << ", verifiez la syntaxe et recommencez ";} + else {cout << "\n wrong choice read : " << methode << ", take a look on the syntaxes or spelling and do it again ";} + }; + break; + case 3 : + if ((methode == "pres_plan")||(methode == "cote_plan")||(methode == "entre_plans") + ||(methode == "entre_plans_dist") + ||(methode == "pres_cylindre")||(methode == "in_cylindre")||(methode == "ex_cylindre")||(methode == "entre_cylindres") + ||(methode == "pres_sphere")||(methode == "in_sphere")||(methode == "ex_sphere")||(methode == "entre_spheres") + // ||(methode == "pres_para")||(methode == "in_para")||(methode == "ex_para")||(methode == "entre_para") + ||(methode == "pres_point")||(methode == "pres_droite")||(methode == "pres_cercle") + ||(methode == "ord_droite") ||(methode == "in_ref")||(methode == "out_ref")) + { list_methode.push_back(methode);} + else if ((methode == "f") || (methode == "fi") || (methode != "fin")) { } // on ne fait rien + else + {if (fr) {cout << "\n mauvais choix lu : " << methode << ", verifiez la syntaxe et recommencez ";} + else {cout << "\n wrong choice read : " << methode << ", take a look on the syntaxes or spelling and do it again ";} + }; + break; + }; + }; + }; + // on récupère pour le passe en interne la liste des références existantes + lesRefin = lesRef; // sert pour InitInRef(), ExeInRef (), InitOutRef(), ExeOutRef() + // execution en fonction des réponses + try // on met le calcul sous surveillance au cas d'un fausse manip + {switch (dima) + { case 1: CalculListRef_1D(list_nomReference,lesRef,list_methode,enu_ddl); break; + case 2: CalculListRef_2D(list_nomReference,lesRef,list_methode,enu_ddl); break; + case 3: CalculListRef_3D(list_nomReference,lesRef,list_methode,enu_ddl); break; + }; + } + catch (ErrSortieFinale) + // cas d'une direction voulue vers la sortie + // on relance l'interuption pour le niveau supérieur + { ErrSortieFinale toto; + throw (toto); + } + catch ( ... ) + { if (fr) {cout << "\n erreur dans la constitution des listes, recommencer ou modifer ";} + else {cout << "\n error in the constitution of lists, try again or modify something ";} + }; + }; + + if (fr) {cout << "\n fin def reference ? (rep f) " + << "\n (ou n'importe quoi d'autre si l'on veut continuer ) " << endl; + reponse = lect_return_defaut(false,"f");; + } + else { cout << "\n end def reference ? (rep f) " + << "\n (or anything else if you want to continue ) " << endl; + reponse = lect_return_defaut(false,"f");; + } + }; + }; + +// calcul des listes de références en fonction de la demande: +// list_nomReference: contient les types de refs que l'on veut +// list_methode: contient la ou les méthodes que l'on veut utiliser +// cas 1D +void Maillage::CalculListRef_1D(list& list_nomReference,LesReferences* lesRef + ,list& list_methode,const Enum_ddl & enu_ddl) + { // def des listes de noeuds et d'éléments à considérer: ces listes diminuent à mesure que l'on + // appliques des contraintes + // au début on part avec tous les noeuds et éléments + list list_noeud_restant; + int nbnoeud = tab_noeud.Taille(); + for (int ne = 1; ne <= nbnoeud; ne++) + list_noeud_restant.push_back(tab_noeud(ne)); + list list_element_restant; + int nbelement = tab_element.Taille(); + for (int nel = 1; nel <= nbelement; nel++) + list_element_restant.push_back(tab_element(nel)); + // def des listes de faces, arêtes, pt integ, là on démarre avec des listes vides et + // on rempli la liste avec la première contrainte, puis avec les autres contraintes on diminue la liste + // les booleen sont utiliser pour savoir si c'est la première contrainte ou pas + list list_elemFace_restant; bool premLpti = true; + list list_elemArrete_restant; bool premLface = true; + list list_elemPtin_restant; bool premLarrete = true; + bool fr = ParaGlob::Francais(); // pour simplifier + + // on balaie la liste des méthodes + list::iterator il,ilfin=list_methode.end(); + for (il = list_methode.begin();il!=ilfin;il++) + { string methode = *il; + if (methode == "pres_point" ) + { initConditionPresDe = & Maillage::InitPresPoint; + ExeConditionPresDe = & Maillage::ExePresPoint; + // appel de la fonction générique + PresDe(list_nomReference,list_noeud_restant,list_element_restant,enu_ddl + ,list_elemPtin_restant,premLpti,list_elemFace_restant,premLface + ,list_elemArrete_restant,premLarrete); + } + else if ( (methode == "cote_point")||(methode == "entre_points") + || (methode == "entre_point_dist") + ||(methode == "in_ref")||(methode == "out_ref") + ) + // sinon c'est du type Toutdedans + { if (methode == "cote_point") + { initConditionToutDedans = & Maillage::InitCotePoint; + ExeConditionToutDedans = & Maillage::ExeCotePoint; + } + else if (methode == "entre_point") + { initConditionToutDedans = & Maillage::InitEntrePoint; + ExeConditionToutDedans = & Maillage::ExeEntrePoint; + } + else if (methode == "entre_point_dist") + { initConditionToutDedans = & Maillage::InitEntrePoint_avec_distance; + ExeConditionToutDedans = & Maillage::ExeEntrePoint_avec_distance; + } + else if (methode == "in_ref") + { initConditionToutDedans = & Maillage::InitInRef; + ExeConditionToutDedans = & Maillage::Exe_In_out_avecRefExistantes; + } + else if (methode == "out_ref") + { initConditionToutDedans = & Maillage::InitOutRef; + ExeConditionToutDedans = & Maillage::Exe_In_out_avecRefExistantes; + } + // appel de la fonction générique + ToutDedans(list_nomReference,list_noeud_restant,list_element_restant,enu_ddl + ,list_elemPtin_restant,premLpti,list_elemFace_restant,premLface + ,list_elemArrete_restant,premLarrete); + } + else if (methode == "ord_droite") {} // on ne fait rien ici, ce sera au deuxième balayage + else + { if (fr) {cout << "\n desole, la condition " << methode << " n'est pas encore implantee " + << " il faut se plaindre !! ";} + else {cout << "\n sorry, the method " << methode << " is not yet implemented " + << " you must complain !! ";} + }; + }; //-- fin du balayage 1) des méthodes + + // on balaie une seconde fois la liste des méthodes, pour voir si éventuellement il faut ordonner + // une liste de noeuds ou de points d'intégration + for (il = list_methode.begin();il!=ilfin;il++) + { string methode = *il; + if (methode == "ord_droite") + { // on regarde s'il faut ordonner des noeuds et des pt d'integ, ou un des deux, ou aucun + list::const_iterator ie,iefin=list_nomReference.end(); + bool ordo_noeud = false; bool ordo_ptinteg = false; + for (ie=list_nomReference.begin();ie!=iefin;ie++) + { if ((*ie)[0] == 'N') ordo_noeud = true; + if ((*ie)[0] == 'G') ordo_ptinteg = true; + }; + if (ordo_noeud || ordo_ptinteg) + InitOrdonneLigne(); // on initialise que s'il y a quelque chose à faire + if (ordo_noeud && ordo_ptinteg) + { OrdonneLigne(list_noeud_restant,list_elemPtin_restant,enu_ddl);} + else if (ordo_noeud) + { list toto; // une liste vide qui ne sera pas ordonnée + OrdonneLigne(list_noeud_restant,toto,enu_ddl); + } + else if (ordo_ptinteg) + { list titi; // une liste vide qui ne sera pas ordonnée + OrdonneLigne(titi,list_elemPtin_restant,enu_ddl); + }; + } + }; + // constitution des références + EnregRef(list_nomReference,list_noeud_restant,list_elemPtin_restant,list_element_restant + ,list_elemFace_restant,list_elemArrete_restant,lesRef); + }; + +// calcul des listes de références en fonction de la demande: +// list_nomReference: contient les types de refs que l'on veut +// list_methode: contient la ou les méthodes que l'on veut utiliser +// cas 2D +void Maillage::CalculListRef_2D(list& list_nomReference,LesReferences* lesRef + ,list& list_methode,const Enum_ddl & enu_ddl) + { // def des listes de noeuds et d'éléments à considérer: ces listes diminuent à mesure que l'on + // appliques des contraintes + // au début on part avec tous les noeuds et éléments + list list_noeud_restant; + int nbnoeud = tab_noeud.Taille(); + for (int ne = 1; ne <= nbnoeud; ne++) + list_noeud_restant.push_back(tab_noeud(ne)); + list list_element_restant; + int nbelement = tab_element.Taille(); + for (int nel = 1; nel <= nbelement; nel++) + list_element_restant.push_back(tab_element(nel)); + // def des listes de faces, arêtes, pt integ, là on démarre avec des listes vides et + // on rempli la liste avec la première contrainte, puis avec les autres contraintes on diminue la liste + // les booleen sont utiliser pour savoir si c'est la première contrainte ou pas + list list_elemFace_restant; bool premLpti = true; + list list_elemArrete_restant; bool premLface = true; + list list_elemPtin_restant; bool premLarrete = true; + bool fr = ParaGlob::Francais(); // pour simplifier + + // on balaie une première fois la liste des méthodes + list::iterator il,ilfin=list_methode.end(); + for (il = list_methode.begin();il!=ilfin;il++) + { string methode = *il; + if ((methode == "pres_point")||(methode == "pres_droite")||(methode == "pres_cercle") + ||(methode == "pres_rec")) + { if (methode == "pres_point" ) + { initConditionPresDe = & Maillage::InitPresPoint; + ExeConditionPresDe = & Maillage::ExePresPoint; + } + else if (methode == "pres_droite") + { initConditionPresDe = & Maillage::InitPresLigne; + ExeConditionPresDe = & Maillage::ExePresLigne; + } + else if (methode == "pres_cercle") + { initConditionPresDe = & Maillage::InitPresCercle; + ExeConditionPresDe = & Maillage::ExePresCercle; + } + // appel de la fonction générique + PresDe(list_nomReference,list_noeud_restant,list_element_restant,enu_ddl + ,list_elemPtin_restant,premLpti,list_elemFace_restant,premLface + ,list_elemArrete_restant,premLarrete); + } + else if ( (methode == "cote_droite")||(methode == "entre_droites") + ||(methode == "entre_droites_dist") + ||(methode == "in_cercle")||(methode == "ex_cercle")||(methode == "entre_cercles") + ||(methode == "in_ref")||(methode == "out_ref") + ) + // sinon c'est du type Toutdedans + { if (methode == "cote_droite") + { initConditionToutDedans = & Maillage::InitCoteDroite; + ExeConditionToutDedans = & Maillage::ExeCoteDroite; + } + else if (methode == "entre_droites") + { initConditionToutDedans = & Maillage::InitEntreDroite; + ExeConditionToutDedans = & Maillage::ExeEntreDroite; + } + else if (methode == "entre_droites_dist") + { initConditionToutDedans = & Maillage::InitEntreDroite_avec_distance; + ExeConditionToutDedans = & Maillage::ExeEntreDroite_avec_distance; + } + else if (methode == "in_cercle") + { initConditionToutDedans = & Maillage::InitDansCercle; + ExeConditionToutDedans = & Maillage::ExeDansCercle; + } + else if (methode == "ex_cercle") + { initConditionToutDedans = & Maillage::InitDansCercle; + ExeConditionToutDedans = & Maillage::ExeOutCercle; + } + else if (methode == "entre_cercles") + { initConditionToutDedans = & Maillage::InitEntreCercles; + ExeConditionToutDedans = & Maillage::ExeEntreCercles; + } + else if (methode == "in_ref") + { initConditionToutDedans = & Maillage::InitInRef; + ExeConditionToutDedans = & Maillage::Exe_In_out_avecRefExistantes; + } + else if (methode == "out_ref") + { initConditionToutDedans = & Maillage::InitOutRef; + ExeConditionToutDedans = & Maillage::Exe_In_out_avecRefExistantes; + } + // appel de la fonction générique + ToutDedans(list_nomReference,list_noeud_restant,list_element_restant,enu_ddl + ,list_elemPtin_restant,premLpti,list_elemFace_restant,premLface + ,list_elemArrete_restant,premLarrete); + } + else if (methode == "ord_droite") {} // on ne fait rien ici, ce sera au deuxième balayage + else + { if (fr) {cout << "\n desole, la condition " << methode << " n'est pas encore implantee " + << " il faut se plaindre !! ";} + else {cout << "\n sorry, the method " << methode << " is not yet implemented " + << " you must complain !! ";} + }; + }; //-- fin du balayage des méthodes + + // on balaie une seconde fois la liste des méthodes, pour voir si éventuellement il faut ordonner + // une liste de noeuds ou de points d'intégration + for (il = list_methode.begin();il!=ilfin;il++) + { string methode = *il; + if (methode == "ord_droite") + { // on regarde s'il faut ordonner des noeuds et des pt d'integ, ou un des deux, ou aucun + list::const_iterator ie,iefin=list_nomReference.end(); + bool ordo_noeud = false; bool ordo_ptinteg = false; + for (ie=list_nomReference.begin();ie!=iefin;ie++) + { if ((*ie)[0] == 'N') ordo_noeud = true; + if ((*ie)[0] == 'G') ordo_ptinteg = true; + }; + if (ordo_noeud || ordo_ptinteg) + InitOrdonneLigne(); // on initialise que s'il y a quelque chose à faire + if (ordo_noeud && ordo_ptinteg) + { OrdonneLigne(list_noeud_restant,list_elemPtin_restant,enu_ddl);} + else if (ordo_noeud) + { list toto; // une liste vide qui ne sera pas ordonnée + OrdonneLigne(list_noeud_restant,toto,enu_ddl); + } + else if (ordo_ptinteg) + { list titi; // une liste vide qui ne sera pas ordonnée + OrdonneLigne(titi,list_elemPtin_restant,enu_ddl); + }; + } + }; + // constitution des références + EnregRef(list_nomReference,list_noeud_restant,list_elemPtin_restant,list_element_restant + ,list_elemFace_restant,list_elemArrete_restant,lesRef); + }; + +// calcul des listes de références en fonction de la demande: +// list_nomReference: contient les types de refs que l'on veut +// list_methode: contient la ou les méthodes que l'on veut utiliser +// cas 3D +void Maillage::CalculListRef_3D(list& list_nomReference,LesReferences* lesRef + ,list& list_methode,const Enum_ddl & enu_ddl) + { // def des listes de noeuds et d'éléments à considérer: ces listes diminuent à mesure que l'on + // appliques des contraintes + // au début on part avec tous les noeuds et éléments + list list_noeud_restant; + int nbnoeud = tab_noeud.Taille(); + for (int ne = 1; ne <= nbnoeud; ne++) + list_noeud_restant.push_back(tab_noeud(ne)); + list list_element_restant; + int nbelement = tab_element.Taille(); + for (int nel = 1; nel <= nbelement; nel++) + list_element_restant.push_back(tab_element(nel)); + // def des listes de faces, arêtes, pt integ, là on démarre avec des listes vides et + // on rempli la liste avec la première contrainte, puis avec les autres contraintes on diminue la liste + // les booleen sont utiliser pour savoir si c'est la première contrainte ou pas + list list_elemFace_restant; bool premLpti = true; + list list_elemArrete_restant; bool premLface = true; + list list_elemPtin_restant; bool premLarrete = true; + bool fr = ParaGlob::Francais(); // pour simplifier + + // on balaie une première fois la liste des méthodes + list::iterator il,ilfin=list_methode.end(); + for (il = list_methode.begin();il!=ilfin;il++) + { string methode = *il; + if ((methode == "pres_plan")||(methode == "pres_cylindre")||(methode == "pres_sphere") +// ||(methode == "pres_para") + ||(methode == "pres_point")||(methode == "pres_cercle")||(methode == "pres_droite")) + { if (methode == "pres_point" ) + { initConditionPresDe = & Maillage::InitPresPoint; + ExeConditionPresDe = & Maillage::ExePresPoint; + } + else if (methode == "pres_droite") + { initConditionPresDe = & Maillage::InitPresLigne; + ExeConditionPresDe = & Maillage::ExePresLigne; + } + else if (methode == "pres_cercle") + { initConditionPresDe = & Maillage::InitPresCercle; + ExeConditionPresDe = & Maillage::ExePresCercle; + } + else if (methode == "pres_plan") + { initConditionPresDe = & Maillage::InitPresPlan; + ExeConditionPresDe = & Maillage::ExePresPlan; + } + else if (methode == "pres_cylindre") + { initConditionPresDe = & Maillage::InitPresCylindre; + ExeConditionPresDe = & Maillage::ExePresCylindre; + } + else if (methode == "pres_sphere") + { initConditionPresDe = & Maillage::InitPresSphere; + ExeConditionPresDe = & Maillage::ExePresSphere; + } +// else if (methode == "pres_para") +// { cout << "\n methode " << methode << " non encore implante, il faut se plaindre !! "; +// } + // appel de la fonction générique + PresDe(list_nomReference,list_noeud_restant,list_element_restant,enu_ddl + ,list_elemPtin_restant,premLpti,list_elemFace_restant,premLface + ,list_elemArrete_restant,premLarrete); + } + else if ((methode == "cote_plan")||(methode == "entre_plans")||(methode == "entre_plans_dist") + ||(methode == "in_cylindre")||(methode == "ex_cylindre")||(methode == "entre_cylindres") + ||(methode == "in_sphere")||(methode == "ex_sphere")||(methode == "entre_spheres") + ||(methode == "in_ref")||(methode == "out_ref") +// ||(methode == "in_para")||(methode == "ex_para")||(methode == "entre_para") + ) + // sinon c'est du type Toutdedans + { if (methode == "cote_plan") + { initConditionToutDedans = & Maillage::InitCotePlan; + ExeConditionToutDedans = & Maillage::ExeCotePlan; + } + else if (methode == "entre_plans") + { initConditionToutDedans = & Maillage::InitEntrePlan; + ExeConditionToutDedans = & Maillage::ExeEntrePlan; + } + else if (methode == "entre_plans_dist") + { initConditionToutDedans = & Maillage::InitEntrePlan_avec_distance; + ExeConditionToutDedans = & Maillage::ExeEntrePlan_avec_distance; + } + else if (methode == "in_cylindre") + { initConditionToutDedans = & Maillage::InitDansCylindre; + ExeConditionToutDedans = & Maillage::ExeDansCylindre; + } + else if (methode == "ex_cylindre") + { initConditionToutDedans = & Maillage::InitDansCylindre; + ExeConditionToutDedans = & Maillage::ExeOutCylindre; + } + else if (methode == "entre_cylindres") + { initConditionToutDedans = & Maillage::InitEntreCylindre; + ExeConditionToutDedans = & Maillage::ExeEntreCylindre; + } + else if (methode == "in_sphere") + { initConditionToutDedans = & Maillage::InitDansSphere; + ExeConditionToutDedans = & Maillage::ExeDansSphere; + } + else if (methode == "ex_sphere") + { initConditionToutDedans = & Maillage::InitDansSphere; + ExeConditionToutDedans = & Maillage::ExeOutSpheres; + } + else if (methode == "entre_spheres") + { initConditionToutDedans = & Maillage::InitEntreSpheres; + ExeConditionToutDedans = & Maillage::ExeEntreSpheres; + } + else if (methode == "in_ref") + { initConditionToutDedans = & Maillage::InitInRef; + ExeConditionToutDedans = & Maillage::Exe_In_out_avecRefExistantes; + } + else if (methode == "out_ref") + { initConditionToutDedans = & Maillage::InitOutRef; + ExeConditionToutDedans = & Maillage::Exe_In_out_avecRefExistantes; + } +// else if (methode == "in_para") +// { cout << "\n methode " << methode << " non encore implante, il faut se plaindre !! "; +// } +// else if (methode == "ex_para") +// { cout << "\n methode " << methode << " non encore implante, il faut se plaindre !! "; +// } +// else if (methode == "entre_paras") +// { cout << "\n methode " << methode << " non encore implante, il faut se plaindre !! "; +// } + // appel de la fonction générique + ToutDedans(list_nomReference,list_noeud_restant,list_element_restant,enu_ddl + ,list_elemPtin_restant,premLpti,list_elemFace_restant,premLface + ,list_elemArrete_restant,premLarrete); + } + else if (methode == "ord_droite") {} // on ne fait rien ici, ce sera au deuxième balayage + else + { if (fr) {cout << "\n desole, la condition " << methode << " n'est pas encore implantee " + << " il faut se plaindre !! ";} + else {cout << "\n sorry, the method " << methode << " is not yet implemented " + << " you must complain !! ";} + }; + }; //-- fin du balayage des méthodes + + // on balaie une seconde fois la liste des méthodes, pour voir si éventuellement il faut ordonner + // une liste de noeuds ou de points d'intégration + for (il = list_methode.begin();il!=ilfin;il++) + { string methode = *il; + if (methode == "ord_droite") + { // on regarde s'il faut ordonner des noeuds et des pt d'integ, ou un des deux, ou aucun + list::const_iterator ie,iefin=list_nomReference.end(); + bool ordo_noeud = false; bool ordo_ptinteg = false; + for (ie=list_nomReference.begin();ie!=iefin;ie++) + { if ((*ie)[0] == 'N') ordo_noeud = true; + if ((*ie)[0] == 'G') ordo_ptinteg = true; + }; + if (ordo_noeud || ordo_ptinteg) + InitOrdonneLigne(); // on initialise que s'il y a quelque chose à faire + if (ordo_noeud && ordo_ptinteg) + { OrdonneLigne(list_noeud_restant,list_elemPtin_restant,enu_ddl);} + else if (ordo_noeud) + { list toto; // une liste vide qui ne sera pas ordonnée + OrdonneLigne(list_noeud_restant,toto,enu_ddl); + } + else if (ordo_ptinteg) + { list titi; // une liste vide qui ne sera pas ordonnée + OrdonneLigne(titi,list_elemPtin_restant,enu_ddl); + }; + } + }; + // constitution des références + EnregRef(list_nomReference,list_noeud_restant,list_elemPtin_restant,list_element_restant + ,list_elemFace_restant,list_elemArrete_restant,lesRef); + }; + + +// fonction générique pour des condition PresDe +void Maillage::PresDe(const list& list_nomReference, list & list_noeud_restant + ,list & list_element_restant,const Enum_ddl & enu_ddl + ,list & list_elemPtin_restant,bool& premLpti + ,list & list_elemFace_restant,bool& premLface + ,list & list_elemArrete_restant,bool& premLarrete) + { // a) on commence par initialiser la condition + bool fr = ParaGlob::Francais(); // pour simplifier + double dist = 0.; + // puis on appelle la fonction d'initialisation + (this->*initConditionPresDe)(dist); + + // b) deuxième temps, on exécute la condition associée (il doit y en avoir qu'une + // car avant chaque condition il faut appeler init !!) + // par contre la condition peut-être appliquée plusieurs fois + + // on balaie la liste des nom de ref pour savoir quel type de ref on cherche + list::const_iterator al,alfin = list_nomReference.end(); + + for (al=list_nomReference.begin();al!=alfin;al++) + if ((*al)[0] == 'N') + {// cas d'une liste de noeuds: on balaie la liste et on cherche + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_noeud_restant.begin(); nits = nit; // init + while (nits != list_noeud_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant + // on supprime si la condition n'est pas remplie + Coordonnee M=(*nit)->Coord0(); + bool condi = (this->*ExeConditionPresDe)(dist,M); + if (!condi) + list_noeud_restant.erase(nit); + }; + } + else if ((*al)[0] == 'E') + {// cas d'une liste d'éléments: on balaie la liste et on cherche + // il faut que un des noeuds de l'élément remplit la condition + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_element_restant.begin(); nits = nit; // init + while (nits != list_element_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant + // recup du tableau de noeuds de l'élément + const Tableau& t_N = (*nit)->Tab_noeud(); + int nbne = t_N.Taille(); + bool condition = false; // par défaut + for (int ie=1;ie<=nbne;ie++) + { Coordonnee M=t_N(ie)->Coord0(); + condition = (this->*ExeConditionPresDe)(dist,M); + }; + // on supprime si la condition n'est pas remplie + if (!condition) + list_element_restant.erase(nit); + }; + } + else if ((*al)[0] == 'G') + {// cas d'une liste de point d'intégration d'éléments: on balaie la liste des éléments + // et dedans la liste des points d'intégration et on cherche + if (premLpti) // cas d'une première contrainte + {// on va balayer tous les éléments existant + int nbne = tab_element.Taille(); + for (int ine=1;ine<=nbne;ine++) + { Element& el = *(tab_element(ine)); + // recup du nombre de point d'intégration de l'élément + int nbpti = el.NbPtInteg(enu_ddl); + // on boucle sur les pt d'integ + for (int ipt = 1;ipt<=nbpti;ipt++) + { bool erreur =false; + Coordonnee Mpti0 = el.CoordPtInteg(TEMPS_0,enu_ddl,ipt,erreur); + if (erreur) + { if (fr) {cout << "\n erreur bizarre, on ne peut pas trouver les coordoonees t0 du pt d'integ " + << ipt << "de l'element " << el.Num_elt() << " du maillage " + << el.Num_maillage() << " on ne le test donc pas pour la liste des pt d'integ ! "; + } + else {cout << "\n strange error, we cannot find the coordinates at t0 of the gauss point " + << ipt << "of the element " << el.Num_elt() << " of the mesh " + << el.Num_maillage() << " so, we do not test it, for the list of integ points ! "; + }; + } + else + { // cas ok + bool condition = (this->*ExeConditionPresDe)(dist,Mpti0); + NBelemEtptInteg nu; nu.nbElem=el.Num_elt(); nu.nbPtInteg = ipt; + if (condition) + { list_elemPtin_restant.push_back(nu);}; // première fois on ajoute + }; + }; //-- fin de la boucle des pt d'integ + }; //-- fin de la boucle sur tous les éléments + // on signale pour la suite qu'une contrainte a déjà été appliqué + premLpti = false; + } + else // cas d'une contrainte qui n'est pas la première + {// on boucle sur les éléments déjà enregistrée + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_elemPtin_restant.begin(); nits = nit; // init + while (nits != list_elemPtin_restant.end()) + {nit = nits; nits++; // nits pointeur sur le suivant +// for (nit=list_elemPtin_restant.begin();nit!=list_elemPtin_restant.end();nit++) + Element& el = *(tab_element((*nit).nbElem)); // récup élément + int ipt = (*nit).nbPtInteg; // récup le pt d'integ + bool erreur =false; + Coordonnee Mpti0 = el.CoordPtInteg(TEMPS_0,enu_ddl,ipt,erreur); + if (erreur) + { if (fr) {cout << "\n erreur bizarre, on ne peut pas trouver les coordoonees t0 du pt d'integ " + << ipt << "de l'element " << el.Num_elt() << " du maillage " + << el.Num_maillage() << " on ne le test donc pas pour la liste des pt d'integ ! "; + } + else {cout << "\n strange error, we cannot find the coordinates at t0 of the gauss point " + << ipt << "of the element " << el.Num_elt() << " of the mesh " + << el.Num_maillage() << " so, we do not test it, for the list of integ points ! "; + }; + } + else + { // cas ok pour la gestion d'erreur + bool condition = (this->*ExeConditionPresDe)(dist,Mpti0); + NBelemEtptInteg nu; nu.nbElem=el.Num_elt(); nu.nbPtInteg = ipt; + if (!condition) + // il ne satisfait pas la contrainte, on le supprime + {list_elemPtin_restant.erase(nit);}; + }; + }; + }; //-- fin du test sur première contrainte ou pas + } + else if ((*al)[0] == 'F') + {// cas d'une liste de face d'éléments: on balaie la liste des éléments + // et dedans la liste des faces et on cherche + if (premLface) // cas d'une première contrainte + {// on va balayer tous les éléments existant + int nbne = tab_element.Taille(); + for (int ine=1;ine<=nbne;ine++) + { Element& el = *(tab_element(ine)); + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nonf = elgeom.Nonf(); // récup de la connection des faces + int nbptface = nonf.Taille(); + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + // on boucle sur les faces + for (int iface = 1;iface<=nbptface;iface++) + { // on regarde si un des noeuds de la face remplit la condition + int nbnoeudface = nonf(iface).Taille(); + for (int ino = 1; ino<= nbnoeudface; ino++) + { Coordonnee M = (t_N(nonf(iface)(ino)))->Coord0(); + bool condition = (this->*ExeConditionPresDe)(dist,M); + if (condition) + { NBelemEtFace nu; nu.nbElem = el.Num_elt(); nu.nbFace = iface; + list_elemFace_restant.push_back(nu); + break; // pour éviter d'enregistrer n fois la même face + }; + }; + }; + }; //-- fin de la boucle sur tous les éléments +////--- debug +// cout << "\n Maillage::PresDe(.."; +// cout << "\n list finale de face après traitement : nb face ="<< list_elemFace_restant.size() << endl; +////--- fin debug + // on signale pour la suite qu'une contrainte a déjà été appliqué + premLface = false; + } + else // cas d'une contrainte qui n'est pas la première + {// on boucle sur les éléments déjà enregistrée + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_elemFace_restant.begin(); nits = nit; // init + while (nits != list_elemFace_restant.end()) + {nit = nits; nits++; // nits pointeur sur le suivant +// for (nit=list_elemFace_restant.begin();nit!=list_elemFace_restant.end();nit++) + Element& el = *(tab_element((*nit).nbElem)); // récup élément + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nonf = elgeom.Nonf(); // récup de la connection des faces + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + bool condition = false; // a priori + int iface = (*nit).nbFace; + // on regarde si un des noeuds de la face rempli la condition + int nbnoeudface = nonf(iface).Taille(); + for (int ino = 1; ino<= nbnoeudface; ino++) + { Coordonnee M = (t_N(nonf(iface)(ino)))->Coord0(); + condition = (this->*ExeConditionPresDe)(dist,M); + if (condition) + break; + }; + if (!condition) + // cas où la condition n'est pas satisfaite on supprime l'élément + {list_elemFace_restant.erase(nit);}; + }; + }; //-- fin du test sur première contrainte ou pas + } + else if ((*al)[0] == 'A') + {// cas d'une liste de d'arêtes d'éléments: on balaie la liste des éléments + // et dedans la liste des arêtes et on cherche + if (premLarrete) // cas d'une première contrainte + {// on va balayer tous les éléments existant + int nbne = tab_element.Taille(); + for (int ine=1;ine<=nbne;ine++) + { Element& el = *(tab_element(ine)); + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nons = elgeom.NonS(); // récup de la connection des arêtes + int nbptarr = nons.Taille(); + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + // on boucle sur les arêtes + for (int iarr = 1;iarr <=nbptarr;iarr++) + { // on regarde si un des noeuds de l'arête remplit la condition + int nbnoeudarr = nons(iarr).Taille(); + for (int ino = 1; ino<= nbnoeudarr; ino++) + { Coordonnee M = (t_N(nons(iarr)(ino)))->Coord0(); + bool condition = (this->*ExeConditionPresDe)(dist,M); + if (condition) + { NBelemEtArete nu; nu.nbElem = el.Num_elt(); nu.nbArete = iarr; + list_elemArrete_restant.push_back(nu); + break; // pour éviter d'enregistrer n fois la même arête + }; + }; + }; + }; //-- fin de la boucle sur tous les éléments + // on signale pour la suite qu'une contrainte a déjà été appliqué + premLarrete = false; + } + else // cas d'une contrainte qui n'est pas la première + {// on boucle sur les éléments déjà enregistrée + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_elemArrete_restant.begin(); nits = nit; // init + while (nits != list_elemArrete_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant +// for (nit=list_elemArrete_restant.begin();nit!=list_elemArrete_restant.end();nit++) + Element& el = *(tab_element((*nit).nbElem)); // récup élément + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nons = elgeom.NonS(); // récup de la connection des arêtes + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + bool condition = false; // a priori + int iarr = (*nit).nbArete; + // on regarde si un des noeuds de l'arête remplit la condition + int nbnoeudarr = nons(iarr).Taille(); + for (int ino = 1; ino<= nbnoeudarr; ino++) + { Coordonnee M = (t_N(nons(iarr)(ino)))->Coord0(); + condition = (this->*ExeConditionPresDe)(dist,M); + if (condition) + break; + }; + if (!condition) + // cas où la condition n'est pas satisfaite on supprime l'élément + {list_elemArrete_restant.erase(nit);}; + }; + }; //-- fin du test sur première contrainte ou pas + } + + }; + +// fonction générique pour des condition "tout dedans" +void Maillage::ToutDedans(const list& list_nomReference, list & list_noeud_restant + ,list & list_element_restant,const Enum_ddl & enu_ddl + ,list & list_elemPtin_restant,bool& premLpti + ,list & list_elemFace_restant,bool& premLface + ,list & list_elemArrete_restant,bool& premLarrete) + { // a) on commence par initialiser la condition + bool fr = ParaGlob::Francais(); // pour simplifier + // puis on appelle la fonction d'initialisation + (this->*initConditionToutDedans)(); + + // b) deuxième temps, on exécute la condition associée (il doit y en avoir qu'une + // car avant chaque condition il faut appeler init !!) + // par contre la condition peut-être appliquée plusieurs fois + + // on balaie la liste des nom de ref pour savoir quel type de ref on cherche + list::const_iterator al,alfin = list_nomReference.end(); + + for (al=list_nomReference.begin();al!=alfin;al++) + if ((*al)[0] == 'N') + {// cas d'une liste de noeuds: on balaie la liste et on cherche + list ::iterator nit,nits; + Tableau t_coor(1); // tableau de travail + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_noeud_restant.begin(); nits = nit; // init + while (nits != list_noeud_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant + // on supprime si la condition n'est pas remplie + t_coor(1)=(*nit)->Coord0(); + bool condi = (this->*ExeConditionToutDedans)(t_coor); + if (!condi) + list_noeud_restant.erase(nit); + }; + } + else if ((*al)[0] == 'E') + {// cas d'une liste d'éléments: on balaie la liste et on cherche + // il faut que tous les noeuds de l'élément remplisse la condition + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_element_restant.begin(); nits = nit; // init + while (nits != list_element_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant + // recup du tableau de noeuds de l'élément + const Tableau& t_N = (*nit)->Tab_noeud(); + int nbne = t_N.Taille(); + bool condition = false; // par défaut + // on définit le tableau de coordonnées de tous les noeuds + Tableau t_coor(nbne); + for (int ie=1;ie<=nbne;ie++) + { t_coor(ie)=t_N(ie)->Coord0();}; + // on vérifie la condition + condition = (this->*ExeConditionToutDedans)(t_coor); + // on supprime si la condition n'est pas remplie + if (!condition) + list_element_restant.erase(nit); + }; + } + else if ((*al)[0] == 'G') + {// cas d'une liste de point d'intégration d'éléments: on balaie la liste des éléments + // et dedans la liste des points d'intégration et on cherche + Tableau t_coor(1); // tableau de travail + if (premLpti) // cas d'une première contrainte + {// on va balayer tous les éléments existant + int nbne = tab_element.Taille(); + for (int ine=1;ine<=nbne;ine++) + { Element& el = *(tab_element(ine)); + // recup du nombre de point d'intégration de l'élément + int nbpti = el.NbPtInteg(enu_ddl); + // on boucle sur les pt d'integ + for (int ipt = 1;ipt<=nbpti;ipt++) + { bool erreur =false; + t_coor(1) = el.CoordPtInteg(TEMPS_0,enu_ddl,ipt,erreur); + if (erreur) + { if (fr) {cout << "\n erreur bizarre, on ne peut pas trouver les coordoonees t0 du pt d'integ " + << ipt << "de l'element " << el.Num_elt() << " du maillage " + << el.Num_maillage() << " on ne le test donc pas pour la liste des pt d'integ ! "; + } + else {cout << "\n strange error, we cannot find the coordinates at t0 of the gauss point " + << ipt << "of the element " << el.Num_elt() << " of the mesh " + << el.Num_maillage() << " so, we do not test it, for the list of integ points ! "; + }; + } + else + { // cas ok + bool condition = (this->*ExeConditionToutDedans)(t_coor); + NBelemEtptInteg nu; nu.nbElem=el.Num_elt(); nu.nbPtInteg = ipt; + if (condition) + { list_elemPtin_restant.push_back(nu);}; // première fois on ajoute + }; + }; //-- fin de la boucle des pt d'integ + }; //-- fin de la boucle sur tous les éléments + // on signale pour la suite qu'une contrainte a déjà été appliqué + premLpti = false; + } + else // cas d'une contrainte qui n'est pas la première + {// on boucle sur les éléments déjà enregistrée + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_elemPtin_restant.begin(); nits = nit; // init + while (nits != list_elemPtin_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant +// for (nit=list_elemPtin_restant.begin();nit!=list_elemPtin_restant.end();nit++) + Element& el = *(tab_element((*nit).nbElem)); // récup élément + int ipt = (*nit).nbPtInteg; // récup le pt d'integ + bool erreur =false; + t_coor(1) = el.CoordPtInteg(TEMPS_0,enu_ddl,ipt,erreur); + if (erreur) + { if (fr) {cout << "\n erreur bizarre, on ne peut pas trouver les coordoonees t0 du pt d'integ " + << ipt << "de l'element " << el.Num_elt() << " du maillage " + << el.Num_maillage() << " on ne le test donc pas pour la liste des pt d'integ ! "; + } + else {cout << "\n strange error, we cannot find the coordinates at t0 of the gauss point " + << ipt << "of the element " << el.Num_elt() << " of the mesh " + << el.Num_maillage() << " so, we do not test it, for the list of integ points ! "; + }; + } + else + { // cas ok pour la gestion d'erreur + bool condition = (this->*ExeConditionToutDedans)(t_coor); + NBelemEtptInteg nu; nu.nbElem=el.Num_elt(); nu.nbPtInteg = ipt; + if (!condition) + // il ne satisfait pas la contrainte, on le supprime + {list_elemPtin_restant.erase(nit);}; + }; + }; + }; //-- fin du test sur première contrainte ou pas + } + else if ((*al)[0] == 'F') + {// cas d'une liste de face d'éléments: on balaie la liste des éléments + // et dedans la liste des faces et on cherche + if (premLface) // cas d'une première contrainte + {// on va balayer tous les éléments existant + int nbne = tab_element.Taille(); + for (int ine=1;ine<=nbne;ine++) + { Element& el = *(tab_element(ine)); + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nonf = elgeom.Nonf(); // récup de la connection des faces + int nbptface = nonf.Taille(); + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + // on boucle sur les faces + for (int iface = 1;iface<=nbptface;iface++) + { // on regarde si tous les noeuds de la face remplissent la condition + int nbnoeudface = nonf(iface).Taille(); + Tableau t_coor(nbnoeudface); // tableau intermédiaire + bool condition = true; // condition vraie par défaut + for (int ino = 1; ino<= nbnoeudface; ino++) + t_coor(ino) = (t_N(nonf(iface)(ino)))->Coord0(); + // on update la condition + condition = (this->*ExeConditionToutDedans)(t_coor); + if (condition) + {NBelemEtFace nu; nu.nbElem = el.Num_elt(); nu.nbFace = iface; + list_elemFace_restant.push_back(nu); + }; + }; + }; //-- fin de la boucle sur tous les éléments + // on signale pour la suite qu'une contrainte a déjà été appliqué + premLface = false; +////--- debug +// cout << "\n Maillage::ToutDedans(.."; +// cout << "\n PREMIER PASSAGE: list finale de face après traitement : nb face ="<< list_elemFace_restant.size() << endl; +////--- fin debug + } + else // cas d'une contrainte qui n'est pas la première + {// on boucle sur les éléments déjà enregistrée + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_elemFace_restant.begin(); nits = nit; // init + while (nits != list_elemFace_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant +// for (nit=list_elemFace_restant.begin();nit!=list_elemFace_restant.end();nit++) + Element& el = *(tab_element((*nit).nbElem)); // récup élément + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nonf = elgeom.Nonf(); // récup de la connection des faces + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + bool condition = true; // a priori + int iface = (*nit).nbFace; + // on regarde si tous les noeuds de la face remplissent la condition + int nbnoeudface = nonf(iface).Taille(); + Tableau t_coor(nbnoeudface); // tableau intermédiaire + for (int ino = 1; ino<= nbnoeudface; ino++) + t_coor(ino) = (t_N(nonf(iface)(ino)))->Coord0(); + // on update la condition + condition = (this->*ExeConditionToutDedans)(t_coor); + if (!condition) + // cas où la condition n'est pas satisfaite on supprime l'élément + {list_elemFace_restant.erase(nit);}; + }; +////--- debug +// cout << "\n Maillage::ToutDedans(.."; +// cout << "\n PASSAGE SECONDAIRE: list finale de face après traitement : nb face ="<< list_elemFace_restant.size() << endl; +////--- fin debug + }; //-- fin du test sur première contrainte ou pas + } + else if ((*al)[0] == 'A') + {// cas d'une liste d'arêtes d'éléments: on balaie la liste des éléments + // et dedans la liste des arêtes et on cherche + if (premLarrete) // cas d'une première contrainte + {// on va balayer tous les éléments existant + int nbne = tab_element.Taille(); + for (int ine=1;ine<=nbne;ine++) + { Element& el = *(tab_element(ine)); + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nons = elgeom.NonS(); // récup de la connection des arêtes + int nbptarr = nons.Taille(); + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + // on boucle sur les arêtes + for (int iarr = 1;iarr <=nbptarr;iarr++) + { // on regarde si un des noeuds de l'arête est près du point + int nbnoeudarr = nons(iarr).Taille(); + Tableau t_coor(nbnoeudarr); // tableau intermédiaire + for (int ino = 1; ino<= nbnoeudarr; ino++) + t_coor(ino) = (t_N(nons(iarr)(ino)))->Coord0(); + bool condition = (this->*ExeConditionToutDedans)(t_coor); + if (condition) + {NBelemEtArete nu; nu.nbElem = el.Num_elt(); nu.nbArete = iarr; + list_elemArrete_restant.push_back(nu); + }; + }; + }; //-- fin de la boucle sur tous les éléments + // on signale pour la suite qu'une contrainte a déjà été appliqué + premLarrete = false; + } + else // cas d'une contrainte qui n'est pas la première + {// on boucle sur les éléments déjà enregistrée + list ::iterator nit,nits; + // on calcul à chaque fois la borne finale car elle peut changer dans la boucle + nit = list_elemArrete_restant.begin(); nits = nit; // init + while (nits != list_elemArrete_restant.end()) + { nit = nits; nits++; // nits pointeur sur le suivant +// for (nit=list_elemArrete_restant.begin();nit!=list_elemArrete_restant.end();nit++) + Element& el = *(tab_element((*nit).nbElem)); // récup élément + ElemGeomC0& elgeom = el.ElementGeometrique(); // récup de l'élément géométrique + const Tableau > nons = elgeom.NonS(); // récup de la connection des arêtes + const Tableau& t_N = el.Tab_noeud(); // récup du tableau de noeud de l'élément + bool condition = false; // a priori + int iarr = (*nit).nbArete; + // on regarde si un des noeuds de l'arête est près du point + int nbnoeudarr = nons(iarr).Taille(); + Tableau t_coor(nbnoeudarr); // tableau intermédiaire + for (int ino = 1; ino<= nbnoeudarr; ino++) + t_coor(ino) = (t_N(nons(iarr)(ino)))->Coord0(); + condition = (this->*ExeConditionToutDedans)(t_coor); + if (!condition) + // cas où la condition n'est pas satisfaite on supprime l'élément + {list_elemArrete_restant.erase(nit);}; + }; + }; //-- fin du test sur première contrainte ou pas + } + + }; + +// constitution des références +void Maillage::EnregRef(const list& list_nomReference,list & list_noeud_restant + ,list & list_elemPtin_restant,list & list_element_restant + ,list & list_elemFace_restant,list & list_elemArrete_restant + ,LesReferences* lesRef) + { + bool fr = ParaGlob::Francais(); // pour simplifier + // on balaie la liste des nom de ref + list::const_iterator ag,agfin = list_nomReference.end(); + for (ag=list_nomReference.begin();ag!=agfin;ag++) + if ((*ag)[0] == 'N') + { // cas d'une liste de noeuds + // mise en place de la condition d'appartenance ou d'exclusion à des références existantes + Exe_In_out_avecRefExistantes_N(list_noeud_restant); + // on crée la nouvelle référence que s'il reste des noeuds + if (list_noeud_restant.size() != 0) + { // mise en place de la condition d'appartenance ou d'exclusion à des références existantes + Exe_In_out_avecRefExistantes_N(list_noeud_restant); + // on ordonne et supprime les noeuds redondants + //list_noeud_restant.sort();list_noeud_restant.unique(); + // création d'un tableau de numéros de noeuds + Tableau tab(list_noeud_restant.size()); + list ::iterator itn,itnfin=list_noeud_restant.end(); + int i=1; + for (itn=list_noeud_restant.begin();itn!=itnfin;itn++,i++) + tab(i)=(*itn)->Num_noeud(); + ReferenceNE* refN = new ReferenceNE(tab,idmail,1,(*ag));// construction de la référence + lesRef->Ajout_reference( refN); + if (fr) {cout << "\n enregistrement ref noeuds " << (*ag) << " de " << tab.Taille() << " item " << endl;} + else {cout << "\n storage of nodes reference " << (*ag) << " of " << tab.Taille() << " item " << endl;}; + }; + } + else if ((*ag)[0] == 'E') + { // cas d'une liste d'éléments + // mise en place de la condition d'appartenance ou d'exclusion à des références existantes + Exe_In_out_avecRefExistantes_E(list_element_restant); + // on crée la nouvelle référence que s'il reste des éléments + if (list_element_restant.size() != 0) + {// on ordonne et supprime les noeuds redondants + //list_element_restant.sort();list_element_restant.unique(); + // création d'un tableau de numéros d'éléments + Tableau tab(list_element_restant.size()); + list ::iterator itn,itnfin=list_element_restant.end(); + int i=1; + for (itn=list_element_restant.begin();itn!=itnfin;itn++,i++) + tab(i)=(*itn)->Num_elt(); + ReferenceNE* refN = new ReferenceNE(tab,idmail,2,(*ag));// création de la référence + lesRef->Ajout_reference( refN); + if (fr) {cout << "\n enregistrement ref elements " << (*ag) << " de " << tab.Taille() << " item " << endl;} + else {cout << "\n storage of elements reference " << (*ag) << " of " << tab.Taille() << " item " << endl;}; + }; + } + else if ((*ag)[0] == 'G') + { // cas d'une liste de points d'intégration d'éléments + // mise en place de la condition d'appartenance ou d'exclusion à des références existantes + Exe_In_out_avecRefExistantes_G(list_elemPtin_restant); + // on crée la nouvelle référence que s'il reste des pti + if (list_elemPtin_restant.size() != 0) + {// on supprime les refs redondantes, mais comme on gère deux listes, on fait le travail à la main + //list_elemPtin_restant.sort();list_elemPtin_restant.unique(); + // création d'un tableau de numéros d'éléments + Tableau tabelem(list_elemPtin_restant.size()); + Tableau tabpti(list_elemPtin_restant.size()); // idem pour les pti + list ::iterator itn,itnfin=list_elemPtin_restant.end(); + int i=1; + for (itn=list_elemPtin_restant.begin();itn!=itnfin;itn++,i++) + {tabelem(i)=(*itn).nbElem;tabpti(i) = (*itn).nbPtInteg;}; + ReferenceAF* refAF = new ReferenceAF(tabelem,tabpti,idmail,6,(*ag));// création de la référence + lesRef->Ajout_reference( refAF); + if (fr) {cout << "\n enregistrement ref pt integ " << (*ag) << " de " << tabelem.Taille() << " item " << endl;} + else {cout << "\n storage of integ points reference " << (*ag) << " of " << tabelem.Taille() << " item " << endl;}; + }; + } + else if ((*ag)[0] == 'F') + { // cas d'une liste de face d'éléments + // mise en place de la condition d'appartenance ou d'exclusion à des références existantes + Exe_In_out_avecRefExistantes_F(list_elemFace_restant); + // on crée la nouvelle ref que s'il reste des faces + if (list_elemFace_restant.size() != 0) + { // on ordonne et supprime les noeuds redondants + //list_elemFace_restant.sort();list_elemFace_restant.unique(); + // création d'un tableau de numéros d'éléments + Tableau tabelem(list_elemFace_restant.size()); + Tableau tabface(list_elemFace_restant.size()); // idem pour les face + list ::iterator itn,itnfin=list_elemFace_restant.end(); + int i=1; + for (itn=list_elemFace_restant.begin();itn!=itnfin;itn++,i++) + {tabelem(i)=(*itn).nbElem;tabface(i) = (*itn).nbFace;}; + ReferenceAF* refAF = new ReferenceAF(tabelem,tabface,idmail,3,(*ag));// création de la référence + lesRef->Ajout_reference( refAF); + if (fr) {cout << "\n enregistrement ref faces " << (*ag) << " de " << tabelem.Taille() << " item " << endl;} + else {cout << "\n storage of facets reference " << (*ag) << " of " << tabelem.Taille() << " item " << endl;}; + if (ParaGlob::NiveauImpression()> 7) + { for (int i=1; i<= tabelem.Taille(); i++) + {int Ne = refAF->NumeroElem(i); + int Nf = refAF->NumeroFA(i); + Element * el = tab_element(Ne); + ElFrontiere* fron = el->Frontiere_surfacique(Nf,true); + fron->Affiche(TEMPS_0); + }; + }; + }; + } + else if ((*ag)[0] == 'A') + { // cas d'une liste d'arêtes d'éléments + // mise en place de la condition d'appartenance ou d'exclusion à des références existantes + Exe_In_out_avecRefExistantes_A(list_elemArrete_restant); + // on crée la nouvelle référence que s'il reste des arêtes d'éléments + if (list_elemArrete_restant.size() != 0) + {// on ordonne et supprime les noeuds redondants + //list_elemArrete_restant.sort();list_elemArrete_restant.unique(); + // création d'un tableau de numéros d'éléments + Tableau tabelem(list_elemArrete_restant.size()); + Tableau tabarr(list_elemArrete_restant.size()); // idem pour les arêtes + list ::iterator itn,itnfin=list_elemArrete_restant.end(); + int i=1; + for (itn=list_elemArrete_restant.begin();itn!=itnfin;itn++,i++) + {tabelem(i)=(*itn).nbElem;tabarr(i) = (*itn).nbArete;}; + ReferenceAF* refAF = new ReferenceAF(tabelem,tabarr,idmail,4,(*ag));// création de la référence + lesRef->Ajout_reference( refAF); + if (fr) {cout << "\n enregistrement ref aretes " << (*ag) << " de " << tabelem.Taille() << " item " << endl;} + else {cout << "\n storage of edges reference " << (*ag) << " of " << tabelem.Taille() << " item " << endl;}; + }; + } + + }; + +// recherche près d'un point +// def interactive du point et de la distance +void Maillage::InitPresPoint(double& dist) + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin(dima); + if (fr) {cout << "\n -- condition : près d'un point ---- "<< endl; + } + else {cout << "\n -- condition : near a point ---- "<< endl; + }; + + // acquisition d'un point + poin = Acquisition_interactive_point(); + if (fr) {cout << "\n distance au point (on retient la partie positive) " << endl;} + else {cout << "\n distance to the point (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + t_poi.Change_taille(1); + t_poi(1) = poin; + }; + +// exécution de la condition : ramène true si ok, false sinon +bool Maillage::ExePresPoint(const double& dist,const Coordonnee& M) const + { return ((M - t_poi(1)).Norme() < dist); + }; + +// recherche d'un coté d'un point (en 1D) +void Maillage::InitCotePoint() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin1(dima),poin2(dima); + if (fr) {cout << "\n -- condition : d'un cote d'un point (en 1D) ---- "<< endl; + } + else {cout << "\n -- condition : on one side of a point (in 1D) ---- " << endl; + }; + // acquisition d'un point + poin1 = Acquisition_interactive_point(); + + if (fr) {cout << "\n donner un second point qui positionne le cote que l'on veut garder " << endl; + } + else {cout << "\n give a second point which locate the side " << endl; + }; + // acquisition d'un point + poin2 = Acquisition_interactive_point(); + + t_poi.Change_taille(2); + t_poi(1) = poin1; + t_poi(2) = poin2; + }; +// ramène true si tous les points sont du même coté que t_poi(2) +bool Maillage::ExeCotePoint(const Tableau & t_M) const + { int tMtaille = t_M.Taille(); + // on regarde si c'est ok pour tous les points + for (int i=1;i<=tMtaille;i++) + if ((t_M(i) - t_poi(1)) * (t_poi(2)-t_poi(1)) < 0) + return false; + // sinon c'est ok + return true; + }; + +// recherche entre deux points (1D) +void Maillage::InitEntrePoint() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin1(dima),poin2(dima); + if (fr) {cout << "\n -- condition : entre deux points (en 1D) ---- "; + cout << "\n premier point " << endl; + } + else {cout << "\n -- condition : between two points (in 1D) ---- "; + cout << "\n first point " << endl; + }; + // acquisition d'un point + poin1 = Acquisition_interactive_point(); + + if (fr) {cout << "\n second point " << endl;} + else {cout << "\n second point " << endl;} + // acquisition d'un point + poin2 = Acquisition_interactive_point(); + + t_poi.Change_taille(2); + t_poi(1) = poin1; + t_poi(2) = poin2; + }; +// ramène true si tous les points sont entre t_poi(1) et t_poi(2) +bool Maillage::ExeEntrePoint(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si c'est ok pour tous les points + for (int i=1;i<=tMtaille;i++) + if ((t_M(i) - t_poi(1)) * (t_poi(2)-t_M(i)) > 0) + return false; + // sinon c'est ok + return true; + }; + +// recherche entre deux points (1D) _avec_distance +void Maillage::InitEntrePoint_avec_distance() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin1(dima),poin2(dima); + if (fr) {cout << "\n -- condition : entre point (en 1D) +- une distance ---- "; + cout << "\n point median: " << endl; + } + else {cout << "\n -- condition : between point (in 1D) +- a distance ---- "; + cout << "\n median point " << endl; + }; + // acquisition d'un point + Coordonnee A = Acquisition_interactive_point(); + double dist=0.; + if (fr) {cout << "\n distance au point median (on retient la partie positive) " << endl;} + else {cout << "\n distance to the median point (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + // on va déplacer le plan via sa normale + poin1(1) = A(1) - dist; + poin2(1) = A(1) + dist; + t_poi.Change_taille(2); + t_poi(1) = poin1; + t_poi(2) = poin2; + }; +// ramène true si tous les points sont entre t_poi(1) et t_poi(2) _avec_distance +bool Maillage::ExeEntrePoint_avec_distance(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si c'est ok pour tous les points + for (int i=1;i<=tMtaille;i++) + if ((t_M(i) - t_poi(1)) * (t_poi(2)-t_M(i)) > 0) + return false; + // sinon c'est ok + return true; + }; + +// recherche près d'une ligne +void Maillage::InitPresLigne(double& dist) + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin1(dima),poin2(dima); + if (fr) {cout << "\n -- condition : pres d'une ligne ---- "; + cout << "\n la ligne est defini par deux points "<< endl; + } + else {cout << "\n -- condition : near a line ---- "; + cout << "\n the line is defined by two points " << endl; + }; + // acquisition d'un point + poin1 = Acquisition_interactive_point(); + if (fr) {cout << "\n second point " << endl;} + else {cout << "\n second point " << endl;} + // acquisition d'un point + poin2 = Acquisition_interactive_point(); + dist=0.; + if (fr) {cout << "\n distance à la ligne (on retient la partie positive) " << endl;} + else {cout << "\n distance to the line (only the absolute value will be kept) " << endl;} + dist=lect_double(); cout << " distance lue: "<< dist << flush; + dist = Dabs(dist); + t_droit.Change_taille(1); + t_droit(1).change_donnees(poin1,(poin2-poin1)); + }; +bool Maillage::ExePresLigne(const double& dist,const Coordonnee& M) const + { return (t_droit(1).Distance_a_la_droite(M) < dist); + }; + +// recherche près d'un cercle +void Maillage::InitPresCercle(double& dist) + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee centre(dima); + if (fr) {cout << "\n -- condition : pres d'un cercle ---- "; + cout << "\n centre du cercle " << endl; + } + else {cout << "\n -- condition : near a cercle ---- "; + cout << "\n cercle center " << endl; + }; + // acquisition d'un point + centre = Acquisition_interactive_point(); + double rayon=0.; + if (fr) {cout << "\n rayon (on retient la partie positive) " << endl;} + else {cout << "\n radius (only the absolute value will be kept) " << endl;} + rayon=lect_double(); + rayon = Dabs(rayon); + t_cercle.Change_taille(1,Cercle(dima)); + t_cercle(1).change_donnees(centre,rayon,NULL); + dist=0.; + if (fr) {cout << "\n distance au cercle (on retient la partie positive) " << endl;} + else {cout << "\n distance to the cercle (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + }; + +bool Maillage::ExePresCercle(const double& dist,const Coordonnee& M) const + { return (t_cercle(1).Distance_au_Cercle(M) < dist); + }; + +// recherche près d'un plan +void Maillage::InitPresPlan( double& dist) + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin(dima); + if (fr) {cout << "\n -- condition : pres d'un plan ---- " << endl; + } + else {cout << "\n -- condition : near a plane ---- " << endl; + }; + + // acquisition d'un plan + Plan pl = Acquisition_interactive_plan(); + t_plan.Change_taille(1); + t_plan(1)=pl; //.change_donnees(poin,normal); + dist=0.; + if (fr) {cout << "\n distance au plan (on retient la partie positive) " << endl;} + else {cout << "\n distance to the plane (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + }; + +bool Maillage::ExePresPlan(const double& dist,const Coordonnee& M) const + { return (t_plan(1).Distance_au_plan(M) < dist); + }; + +// recherche près d'un cylindre +void Maillage::InitPresCylindre(double& dist) + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee centre(dima); + if (fr) {cout << "\n -- condition : pres d'un cylindre ---- "; + cout << "\n un point de l'axe du cylindre " << endl; + } + else {cout << "\n -- condition : near a cylinder ---- "; + cout << "\n a point belonging to the axis of the cylinder " << endl; + }; + // acquisition d'un point + centre = Acquisition_interactive_point(); + double rayon=0.; + cout << "\n rayon du cylindre (on retient la partie positive) " << endl; + rayon=lect_double(); + rayon = Dabs(rayon); cout << " rayon retenu: "<< rayon << endl; + + Coordonnee axe(dima); + if (fr) {cout << "\n coordonnee du vecteur definissant l'axe du cylindre ("<< dima << " reels) " << endl;} + else {cout << "\n coordinate of the vector of the axis of the cylinder ("<< dima << " reals) " << endl;}; + // acquisition d'un vecteur=direction + axe = Acquisition_interactive_vecteur(); + Cercle cer(centre,rayon,&axe); + + t_cylindre.Change_taille(1); + t_cylindre(1).change_donnees(cer); + dist=0.; + if (fr) {cout << "\n distance au cylindre (on retient la partie positive) " << endl;} + else {cout << "\n distance to the cylinder (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + }; + +bool Maillage::ExePresCylindre(const double& dist,const Coordonnee& M) const + { return (t_cylindre(1).Distance_au_Cylindre(M) < dist); + }; + +// recherche près d'un cylindre +void Maillage::InitPresSphere(double& dist) + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee centre(dima); + if (fr) {cout << "\n -- condition : pres d'une sphere ---- "; + cout << "\n centre de la sphere " << endl; + } + else {cout << "\n -- condition : near a sphere ---- "; + cout << "\n the sphere center " << endl; + }; + // acquisition d'un point + centre = Acquisition_interactive_point(); + double rayon=0.; + if (fr) {cout << "\n rayon de la sphere (on retient la partie positive) " << endl;} + else {cout << "\n radius of the sphere (only the absolute value will be kept) " << endl;}; + rayon=lect_double(); + rayon = Dabs(rayon); + + t_sphere.Change_taille(1); + t_sphere(1).change_donnees(centre,rayon); + dist=0.; + if (fr) {cout << "\n distance a la sphere (on retient la partie positive) " << endl;} + else {cout << "\n distance to the sphere (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + }; + +bool Maillage::ExePresSphere(const double& dist,const Coordonnee& M) const + { return (t_sphere(1).Distance_a_sphere(M) < dist); + }; + +// recherche d'un coté d'un plan + void Maillage::InitCotePlan() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin(dima); + if (fr) {cout << "\n -- condition : d'un cote d'un plan ---- " + << "\n le plan: " << endl; + } + else {cout << "\n -- condition : on one side of a plane ---- "; + cout << "\n the plane: " << endl; + } + + // acquisition d'un plan + Plan pl = Acquisition_interactive_plan(); + t_plan.Change_taille(1); + t_plan(1)=pl; //.change_donnees(poin,normal); + + t_poi.Change_taille(1); + if (fr) {cout << "\n un point d'un cote du plan " << endl;} + else {cout << "\n a point on one side of the plane " << endl;} + poin = Acquisition_interactive_point(); + t_poi(1)=poin; + }; +// ramène true si tous les points sont du même coté que t_poi(1) du plan + bool Maillage::ExeCotePlan(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if (!(t_plan(1).DuMemeCote(t_poi(1),t_M(i)))) + return false; + // sinon c'est ok + return true; + }; + +// condition entre plans + void Maillage::InitEntrePlan() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : entre deux plans // ---- "; + cout << "\n premier plan " << endl; + } + else {cout << "\n -- condition : between two planes // ---- "; + cout << "\n first plane " << endl; + } + // acquisition d'un plan + Plan pl = Acquisition_interactive_plan(); + t_plan.Change_taille(1); + t_plan(1) = pl; //.change_donnees(poin,normal); + t_poi.Change_taille(1); + if (fr) {cout << "\n un point du second plan "<< endl;} + else {cout << "\n a point of the second plane "<< endl;} + // acquisition d'un point + Coordonnee poin(Acquisition_interactive_point()); + t_poi(1)=poin; + }; + // ramène true si tous les points sont entre les deux plans + bool Maillage::ExeEntrePlan(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si d'une part les points sont du même coté que t_poi(1) et + // d'autre part si la distance du points au premier plan est <= à celle de t_poi(1) + double dist = t_plan(1).Distance_au_plan(t_poi(1)); + for (int i=1;i<=tMtaille;i++) + if (!(t_plan(1).DuMemeCote(t_poi(1),t_M(i)) && (t_plan(1).Distance_au_plan(t_M(i)) < dist ))) + return false; + // sinon c'est ok + return true; + }; + +// condition entre plans _avec_distance + void Maillage::InitEntrePlan_avec_distance() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : entre un plan +- une distance ---- "; + cout << "\n le plan median: " << endl; + } + else {cout << "\n -- condition : between a plane +- a distance ---- "; + cout << "\n the median plane " << endl; + } + // acquisition d'un plan + Plan pl = Acquisition_interactive_plan(); + double dist=0.; + if (fr) {cout << "\n distance au plan (on retient la partie positive) " << endl;} + else {cout << "\n distance to the plane (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + // on va déplacer le plan via sa normale + const Coordonnee& A = pl.PointPlan(); + const Coordonnee& N = pl.Vecplan(); + Coordonnee Ap = A - dist*N; + pl.Change_ptref(Ap); // nouveau pt de ref du plan + // maintenant le point idem entre plan originale + Coordonnee poin = A + 2.*dist*N; + // on enregistre + t_plan.Change_taille(1); + t_plan(1) = pl; + t_poi.Change_taille(1); + t_poi(1)=poin; + }; + // ramène true si tous les points sont entre les deux plans _avec_distance + bool Maillage::ExeEntrePlan_avec_distance(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si d'une part les points sont du même coté que t_poi(1) et + // d'autre part si la distance du points au premier plan est <= à celle de t_poi(1) +////-- debug +//cout << "\n debug Maillage::ExeEntrePlan_avec_distance( \n" +// << t_plan(1) << "\n point " << t_poi(1); +// +////--- fin debug + double dist = t_plan(1).Distance_au_plan(t_poi(1)); + for (int i=1;i<=tMtaille;i++) + if (!(t_plan(1).DuMemeCote(t_poi(1),t_M(i)) && (t_plan(1).Distance_au_plan(t_M(i)) < dist ))) + return false; + // sinon c'est ok + return true; + }; + +// condition dans ou dehors un cylindre + void Maillage::InitDansCylindre() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : dans ou a l'exterieur d'un cylindre ---- "; + cout << "\n un point de l'axe du cylindre " << endl; + } + else {cout << "\n -- condition : inside or outside a cylinder ---- "; + cout << "\n a point belonging to the axis of the cylinder " << endl; + }; + // acquisition d'un point + Coordonnee centre(Acquisition_interactive_point()); + double rayon=0.; + if (fr) {cout << "\n rayon du cylindre (on retient la partie positive) " << endl;} + else {cout << "\n radius of the cylinder (only the absolute value will be kept) " << endl;}; + rayon=lect_double(); + rayon = Dabs(rayon); cout << " rayon retenu: "<< rayon << endl; + + if (fr) {cout << "\n le vecteur definissant l'axe des cylindres " << endl;} + else {cout << "\n the vector of the axis of the cylinders " << endl;}; + // acquisition d'un vecteur=direction + Coordonnee axe(Acquisition_interactive_vecteur()); + Cercle cer(centre,rayon,&axe); + + t_cylindre.Change_taille(1); + t_cylindre(1).change_donnees(cer); + }; + // ramène true si tous les points sont dans le cylindre + bool Maillage::ExeDansCylindre(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if (!(t_cylindre(1).Dedans(t_M(i)))) + return false; + // sinon c'est ok + return true; + }; +// ramène true si tous les points sont à l'extérieur du cylindre +bool Maillage::ExeOutCylindre(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if ((t_cylindre(1).Dedans(t_M(i)))) + return false; + // sinon c'est ok + return true; + }; + +// condition entre deux cylindre +void Maillage::InitEntreCylindre() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : entre deux cylindres ---- "; + cout << "\n un point de l'axe des deux cylindres " << endl; + } + else {cout << "\n -- condition : between two cylinders ---- "; + cout << "\n a point belonging to the axis of the cylinders " << endl; + }; + // acquisition d'un point + Coordonnee centre(Acquisition_interactive_point()); + double rayon1=0.; + if (fr) {cout << "\n rayon du premier cylindre (on retient la partie positive) " << endl;} + else {cout << "\n radius of the first cylinder (only the absolute value will be kept) " << endl;}; + rayon1=lect_double(); + rayon1 = Dabs(rayon1); + double rayon2=0.; + if (fr) {cout << "\n rayon du second cylindre (on retient la partie positive) " << endl;} + else {cout << "\n radius of the second cylinder (only the absolute value will be kept) " << endl;}; + rayon2=lect_double(); + rayon2 = Dabs(rayon2); + if (fr) {cout << "\n vecteur definissant l'axe des cylindres " << endl;} + else {cout << "\n vector of the axis of the cylinders " << endl;}; + // acquisition d'un vecteur=direction + Coordonnee axe(Acquisition_interactive_vecteur()); + Cercle cer1(centre,MaX(rayon1,rayon2),&axe); + Cercle cer2(centre,MiN(rayon1,rayon2),&axe); + + t_cylindre.Change_taille(2); + t_cylindre(1).change_donnees(cer1); + t_cylindre(2).change_donnees(cer2); + }; +// ramène true si tous les points sont entre les deux cylindres +bool Maillage::ExeEntreCylindre(const Tableau & t_M) const + { int tMtaille = t_M.Taille(); + // on regarde si d'une part les points sont à l'intérieur du cylindre (le plus grand) et + // a l'extérieur du plus petit + for (int i=1;i<=tMtaille;i++) + if ( (!(t_cylindre(1).Dedans(t_M(i)))) + || ((t_cylindre(2).Dedans(t_M(i)))) ) + return false; + // sinon c'est ok + return true; + }; + +// condition dans ou dehors d'une sphére +void Maillage::InitDansSphere() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : dans ou a l'exterieur d'une sphere ---- "; + cout << "\n le centre de la sphere " << endl; + } + else {cout << "\n -- condition : inside or outside of a sphere ---- "; + cout << "\n the sphere center " << endl; + }; + // acquisition d'un point + Coordonnee centre(Acquisition_interactive_point()); + double rayon=0.; + if (fr) {cout << "\n rayon de la sphere (on retient la partie positive) " << endl;} + else {cout << "\n radius of the sphere (only the absolute value will be kept) " << endl;}; + rayon=lect_double(); + rayon = Dabs(rayon); + + t_sphere.Change_taille(1); + t_sphere(1).change_donnees(centre,rayon); + }; + +// ramène true si tous les points sont dans la sphère +bool Maillage::ExeDansSphere(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if (!(t_sphere(1).Dedans(t_M(i)))) + return false; + // sinon c'est ok + return true; + }; +// ramène true si tous les points sont à l'extérieur de la sphère +bool Maillage::ExeOutSpheres(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if ((t_sphere(1).Dedans(t_M(i)))) + return false; + // sinon c'est ok + return true; + }; + +// condition entre deux sphères concentriques +void Maillage::InitEntreSpheres() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : entre deux spheres ---- "; + cout << "\n le centre des spheres " << endl; + } + else {cout << "\n -- condition :between two spheres ---- "; + cout << "\n the center of the spheres " << endl; + }; + // acquisition d'un point + Coordonnee centre(Acquisition_interactive_point()); + double rayon1=0.; + if (fr) {cout << "\n rayon de la premiere sphere (on retient la partie positive) " << endl;} + else {cout << "\n radius of the first sphere (only the absolute value will be kept) " << endl;}; + rayon1=lect_double(); + rayon1 = Dabs(rayon1); + double rayon2=0.; + if (fr) {cout << "\n rayon de la seconde sphere (on retient la partie positive) " << endl;} + else {cout << "\n radius of the second sphere (only the absolute value will be kept) " << endl;}; + rayon2=lect_double(); + rayon2 = Dabs(rayon2); + + t_sphere.Change_taille(2); + t_sphere(1).change_donnees(centre,MaX(rayon1,rayon2)); + t_sphere(2).change_donnees(centre,MiN(rayon1,rayon2)); + }; +// ramène true si tous les points sont entre les deux sphères +bool Maillage::ExeEntreSpheres(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si d'une part les points sont à l'intérieur de la sphère 1 (la plus grande) et + // a l'extérieur de la plus petite + for (int i=1;i<=tMtaille;i++) + if ( (!(t_sphere(1).Dedans(t_M(i)))) + || ((t_sphere(2).Dedans(t_M(i)))) ) + return false; + // sinon c'est ok + return true; + }; + +// condition du même coté d'une droite +void Maillage::InitCoteDroite() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + //Coordonnee poin1(dima),poin2(dima); + if (fr) {cout << "\n -- condition : d'un meme cote d'une droite (2D) ---- "; + cout << "\n def de la ligne: " << endl; + } + else {cout << "\n -- condition : on one side of a line (2D) ---- "; + cout << "\n the line : " << endl; + }; + // acquisition d'une droite + Droite dr(Acquisition_interactive_droite()); + t_droit.Change_taille(1); + t_droit(1)=dr; //change_donnees(poin1,(poin2-poin1)); + t_poi.Change_taille(1); + if (fr) {cout << "\n un point d'un cote de la droite " << endl;} + else {cout << "\n a point on one side of the line " << endl;}; + // acquisition d'un point + Coordonnee poin(Acquisition_interactive_point()); + t_poi(1)=poin; + }; + +// ramène true si tous les points sont du même coté que t_poi(1) de la droite (en 2D uniquement) +bool Maillage::ExeCoteDroite(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if (!(t_droit(1).DuMemeCote(t_poi(1),t_M(i)))) + return false; + // sinon c'est ok + return true; + }; + +// condition entre 2 droites (en 2D seulement) +void Maillage::InitEntreDroite() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : entre deux droite (2D) ---- "; + cout << "\n la premiere ligne: " << endl; + } + else {cout << "\n -- condition : between two lines (2D) ---- "; + cout << "\n the first line: " << endl; + } + // acquisition d'une droite + Droite dr(Acquisition_interactive_droite()); + t_droit.Change_taille(1); + t_droit(1)=dr; // + t_poi.Change_taille(1); + if (fr) {cout << "\n un point de la seconde droite (//) " << endl;} + else {cout << "\n a point belonging to the second line (//) " << endl;}; + // acquisition d'un point + Coordonnee poin(Acquisition_interactive_point()); + t_poi(1)=poin; + }; + +// ramène true si tous les points sont entre les 2 droites (en 2D uniquement) +bool Maillage::ExeEntreDroite(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si d'une part les points sont du même coté que t_poi(1) et + // d'autre part si la distance du points à la première droite est <= à celle de t_poi(1) + double dist = t_droit(1).Distance_a_la_droite(t_poi(1)); + for (int i=1;i<=tMtaille;i++) + if (!(t_droit(1).DuMemeCote(t_poi(1),t_M(i)) && (t_droit(1).Distance_a_la_droite(t_M(i)) < dist ))) + return false; + // sinon c'est ok + return true; + }; + +// condition entre 2 droites (en 2D seulement) _avec_distance +void Maillage::InitEntreDroite_avec_distance() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : entre droite (2D) +- une distance ---- "; + cout << "\n la ligne mediane : " << endl; + } + else {cout << "\n -- condition : between line (2D) +- a distance---- "; + cout << "\n the mediane line: " << endl; + } + // acquisition d'une droite + Droite dr(Acquisition_interactive_droite()); + const Coordonnee& A = dr.PointDroite(); + // retourne le vecteur directeur de la droite (de norme = 1 ) + const Coordonnee& U = dr.VecDroite(); + double dist=0.; + if (fr) {cout << "\n distance a la droite (on retient la partie positive) " << endl;} + else {cout << "\n distance to the line (only the absolute value will be kept) " << endl;} + dist=lect_double(); + dist = Dabs(dist); + Coordonnee Ap = A - dist * U; + dr.Change_ptref(Ap); + Coordonnee poin = A + 2.*dist * U; + // enreg + t_droit.Change_taille(1); + t_droit(1)=dr; // + t_poi.Change_taille(1); + t_poi(1)=poin; + }; + +// ramène true si tous les points sont entre les 2 droites (en 2D uniquement) _avec_distance +bool Maillage::ExeEntreDroite_avec_distance(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si d'une part les points sont du même coté que t_poi(1) et + // d'autre part si la distance du points à la première droite est <= à celle de t_poi(1) + double dist = t_droit(1).Distance_a_la_droite(t_poi(1)); + for (int i=1;i<=tMtaille;i++) + if (!(t_droit(1).DuMemeCote(t_poi(1),t_M(i)) && (t_droit(1).Distance_a_la_droite(t_M(i)) < dist ))) + return false; + // sinon c'est ok + return true; + }; + +// condition dans ou dehors un cercle (en 2D seulement) +void Maillage::InitDansCercle() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : dans ou a l'exterieur d'un cercle (2D) ---- "; + cout << "\n le centre du cercle : " << endl; + } + else {cout << "\n -- condition : inside or outside a cercle (2D) ---- "; + cout << "\n the cercle center: " << endl; + } + // acquisition d'un point + Coordonnee centre(Acquisition_interactive_point()); + double rayon=0.; + if (fr) {cout << "\n rayon du cercle (on retient la partie positive) "<< endl; } + else {cout << "\n radius of the cercle (only the absolute value will be kept) "<< endl; }; + rayon=lect_double(); + rayon = Dabs(rayon); + + t_cercle.Change_taille(1,Cercle(dima)); + t_cercle(1).change_donnees(centre,rayon,NULL); + }; + +// ramène true si tous les points sont dans le cercle (en 2D seulement) +bool Maillage::ExeDansCercle(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if (!(t_cercle(1).Dedans(t_M(i)))) + return false; + // sinon c'est ok + return true; + }; +// ramène true si tous les points sont à l'extérieur du cercle (en 2D seulement) +bool Maillage::ExeOutCercle(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + for (int i=1;i<=tMtaille;i++) + if ((t_cercle(1).Dedans(t_M(i)))) + return false; + // sinon c'est ok + return true; + }; + +// condition entre cercles concentriques (en 2D seulement) +void Maillage::InitEntreCercles() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + if (fr) {cout << "\n -- condition : entre deux cercles concentriques ---- "; + cout << "\n centre des cercle: " << endl; + } + else {cout << "\n -- condition : between two concentric cercles ---- "; + cout << "\n the center of the cercles: " << endl; + }; + // acquisition d'un point + Coordonnee centre(Acquisition_interactive_point()); + double rayon1=0.; + if (fr) {cout << "\n rayon du premier cercle (on retient la partie positive) "<< endl; } + else {cout << "\n radius of the first cercle (only the absolute value will be kept) "<< endl; }; + rayon1=lect_double(); + rayon1 = Dabs(rayon1); + double rayon2=0.; + if (fr) {cout << "\n rayon du second cercle (on retient la partie positive) " << endl;} + else {cout << "\n radius of the second cercle (only the absolute value will be kept) "<< endl; }; + rayon2=lect_double(); + rayon2 = Dabs(rayon2); + + t_cercle.Change_taille(2,Cercle(dima)); + t_cercle(1).change_donnees(centre,MaX(rayon1,rayon2),NULL); + t_cercle(2).change_donnees(centre,MiN(rayon1,rayon2),NULL); + }; +// ramène true si tous les points sont entre les deux cercles concentriques +bool Maillage::ExeEntreCercles(const Tableau & t_M)const + { int tMtaille = t_M.Taille(); + // on regarde si d'une part les points sont à l'intérieur du cercle 1 (le plus grand) et + // a l'extérieur du plus petit + for (int i=1;i<=tMtaille;i++) + if ( (!(t_cercle(1).Dedans(t_M(i)))) + || ((t_cercle(2).Dedans(t_M(i)))) ) + return false; + // sinon c'est ok + return true; + }; + +// acquisition d'un plan +Plan Maillage::Acquisition_interactive_plan() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin(dima); + Coordonnee normal(dima); + if (fr) {cout << "\n coordonnee d'un point du premier plan ("<< dima << " reels) " + << "\n ou un noeud -> rep: noeud= " + << "\n ou 3 noeuds pour tout le plan " + << "\n -> noeudi= " + << endl; + } + else {cout << "\n coordinates of a point of the first plane ("<< dima << " reals) " + << "\n or one node -> answer: noeud= " + << "\n or 3 nodes for the whole plane " + << "\n -> noeudi= " + << endl; + } + int c=getchar(); + string inter("");// une chaîne vide + string rep; + std::getline (std::cin,rep); + if (isalnum(c)|| (c=='-')) // si jamais on a lu quelque chose de viable dans c on le rajoute + {inter.push_back(c); + rep = inter + rep; + }; + // si la taille de rep == 0 cela veut dire que c'est un retour chariot +// if (rep.size()==0) + char * chh = (char*)rep.c_str(); + #ifndef ENLINUX_STREAM + istringstream flux (chh); + #else + istrstream flux (chh); + #endif + if(strstr(chh,"oeud=")!=0) + {int numn; string toto; + flux >> toto >> numn; + cout << "\n numero de noeud lu "<< numn; + poin = tab_noeud(numn)->Coord0(); + cout << "\n --> coordonnees lues: "; poin.Affiche_1(cout) ; + if (fr) {cout << "\n coordonnees de la normale du plan ("<< dima << " reels) " << endl;} + else {cout << "\n coordinates of the plane normal ("<< dima << " reals) " << endl;} + for (int i = 1; i<= dima; i++) cin >> normal(i); + cout << "\n --> normale lue: "; normal.Affiche_1(cout) ; + std::cin.ignore( std::numeric_limits::max(), '\n' );// purge de cin + } + else if(strstr(chh,"oeudi=")!=0) + { int n1,n2,n3; string toto; + flux >> toto >> n1 >> n2 >> n3; + cout << "\n numeros de noeud lu "<< n1 <<", "<Coord0(); + // on fait le produit vectoriel pour la normale + Coordonnee v1( tab_noeud(n2)->Coord0() - poin); + Coordonnee v2( tab_noeud(n3)->Coord0() - poin); + normal = Util::ProdVec_coor(v1,v2); + } + else + { for (int i = 1; i<= dima; i++) flux >> poin(i); + cout << "\n --> coordonnees lues: "; poin.Affiche_1(cout) ; + if (fr) {cout << "\n coordonnees de la normale du plan ("<< dima << " reels) " << endl;} + else {cout << "\n coordinates of the plane normal ("<< dima << " reals) " << endl;} + for (int i = 1; i<= dima; i++) cin >> normal(i); + cout << "\n --> normale lue: "; normal.Affiche_1(cout) ; + std::cin.ignore( std::numeric_limits::max(), '\n' );// purge de cin + + }; + + Plan pl(poin,normal); + return pl; + }; + +// acquisition d'un point +Coordonnee Maillage::Acquisition_interactive_point() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin(dima); + if (fr) {cout << "\n coordonnee d'un point ("<< dima << " reels) " + << "\n ou un noeud -> rep: noeud= " + << flush; + } + else {cout << "\n coordinates of a point ("<< dima << " reals) " + << "\n or one node -> answer: noeud= " + << flush; + } + using namespace std; + // on passe un caractère, *** je ne sais pas pourquoi *** pour que getline fonctionne !! (pas d'indication au niveau de rdstate +// cout << "\n cin.iostat good(): "<< cin.good() << " eof: "<< cin.eof() +// << " fail: "<< cin.fail() << " bad: "<< cin.bad() +// << "\n rdstate(): " << cin.rdstate() << endl; + int c=getchar(); + string inter("");// une chaîne vide + string rep; + std::getline (std::cin,rep); + if (isalnum(c) || (c=='-')) // si jamais on a lu quelque chose de viable dans c on le rajoute + {inter.push_back(c); +// cout << "\n** valeur de c "<< c << flush; + rep = inter + rep; + }; + // si la taille de rep == 0 cela veut dire que c'est un retour chariot +// if (rep.size()==0) + char * chh = (char*)rep.c_str(); + #ifndef ENLINUX_STREAM + istringstream flux (chh); + #else + istrstream flux (chh); + #endif + if(strstr(chh,"oeud=")!=0) + {int numn; string toto; + flux >> toto >> numn; + cout << "\n numero de noeud lu "<< numn; + poin = tab_noeud(numn)->Coord0(); + } + else + { for (int i = 1; i<= dima; i++) flux >> poin(i); + cout << "\n --> coordonnees lues: "; poin.Affiche_1(cout) ; + }; + return poin; + }; + +// acquisition d'une droite +Droite Maillage::Acquisition_interactive_droite() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee poin1(dima); + // --- le premier point ---- + if (fr) {cout << "\n coordonnee d'un point de la droite ("<< dima << " reels) " + << "\n ou un noeud -> rep: noeud= " + << endl; + } + else {cout << "\n coordinates of a point of the line ("<< dima << " reals) " + << "\n or one node -> answer: noeud= " + << endl; + } + using namespace std; + {// on passe un caractère, *** je ne sais pas pourquoi *** pour que getline fonctionne !! (pas d'indication au niveau de rdstate +// cout << "\n cin.iostat good(): "<< cin.good() << " eof: "<< cin.eof() +// << " fail: "<< cin.fail() << " bad: "<< cin.bad() +// << "\n rdstate(): " << cin.rdstate() << endl; + int c=getchar(); + string inter("");// une chaîne vide + string rep; + std::getline (std::cin,rep); + if (isalnum(c)) // si jamais on a lu quelque chose de viable dans c on le rajoute + {inter.push_back(c); + rep = inter + rep; + }; + // si la taille de rep == 0 cela veut dire que c'est un retour chariot +// if (rep.size()==0) + char * chh = (char*)rep.c_str(); + #ifndef ENLINUX_STREAM + istringstream flux (chh); + #else + istrstream flux (chh); + #endif + if(strstr(chh,"oeud=")!=0) + {int numn; string toto; + flux >> toto >> numn; + cout << "\n numero de noeud lu "<< numn; + poin1 = tab_noeud(numn)->Coord0(); + } + else + { for (int i = 1; i<= dima; i++) flux >> poin1(i); + cout << "\n --> coordonnees lues: "; poin1.Affiche_1(cout) ; + }; + }; + // --- le second point ---- + Coordonnee poin2(dima); + if (fr) {cout << "\n coordonnee du second point de la droite ("<< dima << " reels) " + << "\n ou un noeud -> rep: noeud= " + << endl; + } + else {cout << "\n coordinates of the second point of the line ("<< dima << " reals) " + << "\n or one node -> answer: noeud= " + << endl; + } + {// on passe un caractère, *** je ne sais pas pourquoi *** pour que getline fonctionne !! (pas d'indication au niveau de rdstate +// cout << "\n cin.iostat good(): "<< cin.good() << " eof: "<< cin.eof() +// << " fail: "<< cin.fail() << " bad: "<< cin.bad() +// << "\n rdstate(): " << cin.rdstate() << endl; + int c=getchar(); + string inter("");// une chaîne vide + string rep; + std::getline (std::cin,rep); + if (isalnum(c)|| (c=='-')) // si jamais on a lu quelque chose de viable dans c on le rajoute + {inter.push_back(c); + rep = inter + rep; + }; + // si la taille de rep == 0 cela veut dire que c'est un retour chariot +// if (rep.size()==0) + char * chh = (char*)rep.c_str(); + #ifndef ENLINUX_STREAM + istringstream flux (chh); + #else + istrstream flux (chh); + #endif + if(strstr(chh,"oeud=")!=0) + {int numn; string toto; + flux >> toto >> numn; + cout << "\n numero de noeud lu "<< numn; + poin2 = tab_noeud(numn)->Coord0(); + } + else + { for (int i = 1; i<= dima; i++) flux >> poin2(i); + cout << "\n --> coordonnees lues: "; poin2.Affiche_1(cout) ; + }; + }; + Coordonnee V(poin2-poin1); + Droite dl(poin1,V); + return dl; + }; + +// acquisition d'un vecteur=direction +Coordonnee Maillage::Acquisition_interactive_vecteur() + { int dima = ParaGlob::Dimension(); + bool fr = ParaGlob::Francais(); // pour simplifier + Coordonnee V(dima); + if (fr) {cout << "\n coordonnee du vecteur ("<< dima << " reels) " + << "\n ou 2 noeuds pour tout le plan " + << "\n -> noeudi= " + << endl; + } + else {cout << "\n coordinates of a the vector ("<< dima << " reals) " + << "\n or 2 nodes for the whole plane " + << "\n -> noeudi= " + << endl; + } + int c=getchar(); + string inter("");// une chaîne vide + string rep; + std::getline (std::cin,rep); + if (isalnum(c) || (c=='-')) // si jamais on a lu quelque chose de viable dans c on le rajoute + {inter.push_back(c); + rep = inter + rep; + }; + // si la taille de rep == 0 cela veut dire que c'est un retour chariot +// if (rep.size()==0) + char * chh = (char*)rep.c_str(); + #ifndef ENLINUX_STREAM + istringstream flux (chh); + #else + istrstream flux (chh); + #endif + if(strstr(chh,"noeudi=")!=0) + { + Coordonnee poin1(dima); + Coordonnee poin2(dima); + int n1,n2; string toto; + flux >> toto >> n1 >> n2 ; + cout << "\n numeros de noeud lu "<< n1 <<", "<Coord0(); + poin2 = tab_noeud(n2)->Coord0(); + V = poin2-poin1; + } + else + { for (int i = 1; i<= dima; i++) flux >> V(i); + cout << "\n --> coordonnees lues: "; V.Affiche_1(cout) ; + }; + + return V; + }; + + +// condition d'appartenance à une référence existante +void Maillage::InitInRef() + { bool fr = ParaGlob::Francais(); // pour simplifier + string nom_ref; const Reference * refIn = NULL; + bool demande_fin = false; + while (!demande_fin) + {if (fr) {cout << "\n -- condition : appartenance a une reference ---- "; + cout << "\n nom de la reference existante ? (seules les ref de " + << "\n meme type seront comparees) " << endl; + } + else {cout << "\n -- condition : belonging to an already existing reference ---- "; + cout << "\n name of the reference ? (only a reference of a " + << "\n same type can be used) " << endl; + }; + nom_ref=lect_return_defaut(true,"f"); + if (nom_ref == "f" ) {demande_fin = true;} + // sinon on essaie de récupérer la référence + else if (!(lesRefin->Existe(nom_ref,idmail))) + {if (fr) {cout << "\n le nom lue " << nom_ref << " ne correspond pas a une reference existante " + << " donnez un autre nom ou taper f pour finir "; + } + else {cout << "\n the input name " << nom_ref << " does not belong to an existing reference " + << " give another name, or f for leaving "; + }; + } + else + { // on récupère la référence + refIn = &(lesRefin->Trouve(nom_ref,idmail)); + list_refIn.push_back(refIn); + demande_fin=true; // seul cas où tout est ok + } + }; + }; +// ramène true si tous les points appartiennent à la ref +//bool Maillage::ExeInRef (const Tableau & t_M)const +// { //const ReferenceNE & refi = *((ReferenceNE *) refIn); + // on récupère tous les noeuds de la référence + + +// }; +// condition d'exclusion à une référence existante +void Maillage::InitOutRef() + { bool fr = ParaGlob::Francais(); // pour simplifier + string nom_ref; const Reference * refOut = NULL; + bool demande_fin = false; + while (!demande_fin) + {if (fr) {cout << "\n -- condition : hors d'une reference ---- "; + cout << "\n nom de la reference existante ? (seules les ref de " + << "\n meme type seront comparees) " << endl; + } + else {cout << "\n -- condition : out of to an already existing reference ---- "; + cout << "\n name of the reference ? (only a reference of a " + << "\n same type can be used) " << endl; + }; + nom_ref=lect_return_defaut(true,"f"); + if (nom_ref == "f" ) {demande_fin = true;} + // sinon on essaie de récupérer la référence + else if (!(lesRefin->Existe(nom_ref,idmail))) + {if (fr) {cout << "\n le nom lue " << nom_ref << " ne correspond pas a une reference existante " + << " donnez un autre nom ou taper f pour finir "; + } + else {cout << "\n the input name " << nom_ref << " does not belong to an existing reference " + << " give another name, or f for leaving "; + } + } + else + { // on récupère la référence + refOut = &(lesRefin->Trouve(nom_ref,idmail)); + list_refOut.push_back(refOut); + demande_fin=true; // seul cas où tout est ok + } + }; + }; + +// 1) une fonction qui ne fait rien, mais est là pour que le tout fonctionne normalement +bool Maillage::Exe_In_out_avecRefExistantes(const Tableau & t_M)const + {return true;}; // ne fait rien + +// 2) fonctions qui réellement font quelque chose: utilisées dans la méthode EnregRef +// a - cas des ref de noeuds +void Maillage::Exe_In_out_avecRefExistantes_N(list & list_noeud_restant) +{ + // ---- cas des ref in + list liste_finale_in; + { // on commence par concaténer l'ensemble des noeuds des refs In + list ::iterator lref,lref_fin= list_refIn.end(); + for (lref=list_refIn.begin();lref != lref_fin; lref++) + {// on ne continue que si c'est une ref de noeud, du même maillage + if (((*lref)->Indic() == 1) && ((*lref)->Nbmaille() == idmail)) + { ReferenceNE * refi = ((ReferenceNE *) (*lref)); + const Tableau& tab_num = refi->Tab_num(); + int tailmax = tab_num.Taille(); + for (int i=1;i<=tailmax;i++) + {liste_finale_in.push_back(tab_noeud(tab_num(i)));}; + }; + }; + // on trie et on supprime les doublons + liste_finale_in.sort(); + liste_finale_in.unique(); + }; + list ::iterator lf_in_deb=liste_finale_in.begin(); + list ::iterator lf_in_end=liste_finale_in.end(); + // ---- cas des ref out + list liste_finale_out; + { // on commence par concaténer l'ensemble des noeuds des refs out + list ::iterator lref,lref_fin= list_refOut.end(); + for (lref=list_refOut.begin();lref != lref_fin; lref++) + { // on ne continue que si c'est une ref de noeud, du même maillage + if (((*lref)->Indic() == 1) && ((*lref)->Nbmaille() == idmail)) + { ReferenceNE * refi = ((ReferenceNE *) (*lref)); + const Tableau& tab_num = refi->Tab_num(); + int tailmax = tab_num.Taille(); + for (int i=1;i<=tailmax;i++) + {liste_finale_out.push_back(tab_noeud(tab_num(i)));}; + }; + }; + // on trie et on supprime les doublons + liste_finale_out.sort(); + liste_finale_out.unique(); + }; + list ::iterator lf_out_deb=liste_finale_out.begin(); + list ::iterator lf_out_end=liste_finale_out.end(); + +////--- debug +// cout << "\n Maillage::Exe_In_out_avecRefExistantes_N(.."; +// cout << "\n list in "; +// list < Noeud*>::iterator lnn; +// for (lnn=lf_in_deb;lnn != lf_in_end; lnn++) +// cout << (*lnn)->Num_noeud() << " "; +// cout << "\n list out "; +// for (lnn=lf_out_deb;lnn != lf_out_end; lnn++) +// cout << (*lnn)->Num_noeud() << " "; +// cout << "\n list finale avant traitement "; +// for (lnn=list_noeud_restant.begin();lnn != list_noeud_restant.end(); lnn++) +// cout << (*lnn)->Num_noeud() << " "; +////--- fin debug + + + // ---- application + // on passe en revue les noeuds et on regarde s'ils font partie d'une des listes In + // et s'ils sont en dehors des out + bool liste_finale_in_a_considerer = liste_finale_in.size(); + bool liste_finale_out_a_considerer = liste_finale_out.size(); +////--- debug +// cout << "liste_finale_in_a_considerer" << liste_finale_in_a_considerer +// << "liste_finale_out_a_considerer" << liste_finale_out_a_considerer << endl; +////--- fin debug + list ::iterator li; + list liinter(list_noeud_restant); + int nb_trouve_in=0; int nb_trouve_out=0; + // comme on supprime en cours de route des ref de noeuds on recalcul la borne sup à chaque passage + for (li=list_noeud_restant.begin();li != list_noeud_restant.end();li++) + { bool deja_supprime = false; // pour indiquer si un element a déjà ete supprimer, ce qui evite une double +////--- fin debug +// cout << "(*li)->Num_noeud()=" << (*li)->Num_noeud() << endl; +// cout << "\n taper un lettre "; string unelettre ; cin >> unelettre; +////--- fin debug + if (liste_finale_in_a_considerer) // prise en compte que si la liste est non vide + {if (find(lf_in_deb, lf_in_end, *li) == lf_in_end) + // on n'a pas trouvé de noeud appartenant à la liste, on supprime le noeud + {//list ::iterator toto = li; + liinter.remove(*li);// +// list_noeud_restant.remove(*li); + nb_trouve_in++;deja_supprime=true; + } + }; + if ((liste_finale_out_a_considerer)&&(!deja_supprime)) // prise en compte que si la liste est non vide + {if (find(lf_out_deb, lf_out_end, *li) != lf_out_end) + // on a trouvé un noeud appartenant à la liste, on supprime le noeud + {//list_noeud_restant.erase(li); + liinter.remove(*li);// + nb_trouve_out++; + }; + }; + }; + + list_noeud_restant = liinter; + + if (ParaGlob::NiveauImpression() > 4) + { if (liste_finale_in_a_considerer) + cout << "\n "<& list_element_restant) +{ + // ---- cas des ref in + list liste_finale_in; + { // on commence par concaténer l'ensemble des Elements des refs In + list ::iterator lref,lref_fin= list_refIn.end(); + for (lref=list_refIn.begin();lref != lref_fin; lref++) + {// on ne continue que si c'est une ref de Element, du même maillage + if (((*lref)->Indic() == 2) && ((*lref)->Nbmaille() == idmail)) + { ReferenceNE * refi = ((ReferenceNE *) (*lref)); + const Tableau& tab_num = refi->Tab_num(); + int tailmax = tab_num.Taille(); + for (int i=1;i<=tailmax;i++) + {liste_finale_in.push_back(tab_element(tab_num(i)));}; + }; + }; + // on trie et on supprime les doublons + liste_finale_in.sort(); + liste_finale_in.unique(); + }; + list ::iterator lf_in_deb=liste_finale_in.begin(); + list ::iterator lf_in_end=liste_finale_in.end(); + // ---- cas des ref out + list liste_finale_out; + { // on commence par concaténer l'ensemble des Elements des refs out + list ::iterator lref,lref_fin= list_refOut.end(); + for (lref=list_refOut.begin();lref != lref_fin; lref++) + { // on ne continue que si c'est une ref de Element, du même maillage + if (((*lref)->Indic() == 2) && ((*lref)->Nbmaille() == idmail)) + { ReferenceNE * refi = ((ReferenceNE *) (*lref)); + const Tableau& tab_num = refi->Tab_num(); + int tailmax = tab_num.Taille(); + for (int i=1;i<=tailmax;i++) + {liste_finale_out.push_back(tab_element(tab_num(i)));}; + }; + }; + // on trie et on supprime les doublons + liste_finale_out.sort(); + liste_finale_out.unique(); + }; + list ::iterator lf_out_deb=liste_finale_out.begin(); + list ::iterator lf_out_end=liste_finale_out.end(); + +////--- debug +// cout << "\n Maillage::Exe_In_out_avecRefExistantes_N(.."; +// cout << "\n list in "; +// list < Element*>::iterator lnn; +// for (lnn=lf_in_deb;lnn != lf_in_end; lnn++) +// cout << (*lnn)->Num_Element() << " "; +// cout << "\n list out "; +// for (lnn=lf_out_deb;lnn != lf_out_end; lnn++) +// cout << (*lnn)->Num_Element() << " "; +// cout << "\n list finale avant traitement "; +// for (lnn=list_element_restant.begin();lnn != list_element_restant.end(); lnn++) +// cout << (*lnn)->Num_Element() << " "; +////--- fin debug + + + // ---- application + // on passe en revue les Elements et on regarde s'ils font partie d'une des listes In + // et s'ils sont en dehors des out + bool liste_finale_in_a_considerer = liste_finale_in.size(); + bool liste_finale_out_a_considerer = liste_finale_out.size(); + list ::iterator li; + int nb_trouve_in=0; int nb_trouve_out=0; + // comme on supprime en cours de route des ref de Elements on recalcul la borne sup à chaque passage + for (li=list_element_restant.begin();li != list_element_restant.end();li++) + { bool deja_supprime = false; // pour indiquer si un element a déjà ete supprimer, ce qui evite une double + if (liste_finale_in_a_considerer) // prise en compte que si la liste est non vide + if (find(lf_in_deb, lf_in_end, *li) == lf_in_end) + // on n'a pas trouvé de Element appartenant à la liste, on supprime le Element + {list_element_restant.erase(li);nb_trouve_in++;deja_supprime=true;} + if ((liste_finale_out_a_considerer)&&(!deja_supprime)) // prise en compte que si la liste est non vide + if (find(lf_out_deb, lf_out_end, *li) != lf_out_end) + // on a trouvé un Element appartenant à la liste, on supprime le Element + {list_element_restant.erase(li);nb_trouve_out++;} + }; + + if (ParaGlob::NiveauImpression() > 4) + { if (liste_finale_in_a_considerer) + cout << "\n "<& list_elemPtin_restant) +{ + // ---- cas des ref in pour les pti + list liste_finale_in; + { // on commence par concaténer l'ensemble des pti des refs In + list ::iterator lref,lref_fin= list_refIn.end(); + for (lref=list_refIn.begin();lref != lref_fin; lref++) + {// on ne continue que si c'est une ref de pti, du même maillage + if (((*lref)->Indic() == 6) && ((*lref)->Nbmaille() == idmail)) + { ReferenceAF * refi = ((ReferenceAF *) (*lref)); + const Tableau& tab_elem = refi->Tab_Elem(); + const Tableau& tab_fa = refi->Tab_FA(); + int tailmax = tab_elem.Taille(); + for (int i=1;i<=tailmax;i++) + { NBelemEtptInteg nu; nu.nbElem = tab_elem(i); nu.nbPtInteg = tab_fa(i); + liste_finale_in.push_back(nu); + }; + }; + }; + // on trie et on supprime les doublons + liste_finale_in.sort(); + liste_finale_in.unique(); + }; + list ::iterator lf_in_deb=liste_finale_in.begin(); + list ::iterator lf_in_end=liste_finale_in.end(); + // ---- cas des ref out + list liste_finale_out; + { // on commence par concaténer l'ensemble des pti des refs out + list ::iterator lref,lref_fin= list_refOut.end(); + for (lref=list_refOut.begin();lref != lref_fin; lref++) + { // on ne continue que si c'est une ref de pti, du même maillage + if (((*lref)->Indic() == 6) && ((*lref)->Nbmaille() == idmail)) + { ReferenceAF * refi = ((ReferenceAF *) (*lref)); + const Tableau& tab_elem = refi->Tab_Elem(); + const Tableau& tab_fa = refi->Tab_FA(); + int tailmax = tab_elem.Taille(); + for (int i=1;i<=tailmax;i++) + { NBelemEtptInteg nu; nu.nbElem = tab_elem(i); nu.nbPtInteg = tab_fa(i); + liste_finale_out.push_back(nu); + }; + }; + }; + // on trie et on supprime les doublons + liste_finale_out.sort(); + liste_finale_out.unique(); + }; + list ::iterator lf_out_deb=liste_finale_out.begin(); + list ::iterator lf_out_end=liste_finale_out.end(); + +////--- debug +// +////--- debug +// cout << "\n Maillage::Exe_In_out_avecRefExistantes_F(.."; +// cout << "\n list in "; +// list < NBelemEtptInteg>::iterator lnn; +// for (lnn=lf_in_deb;lnn != lf_in_end; lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbPtInteg << " "; +// cout << "\n list out "; +// for (lnn=lf_out_deb;lnn != lf_out_end; lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbPtInteg << " "; +// cout << "\n list finale avant traitement "; +// for (lnn=list_elemPtin_restant.begin();lnn != list_elemPtin_restant.end(); lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbPtInteg << " "; +////--- fin debug + + + // ---- application + // on passe en revue les pti et on regarde s'ils font partie d'une des listes In + // et s'ils sont en dehors des out + bool liste_finale_in_a_considerer = liste_finale_in.size(); + bool liste_finale_out_a_considerer = liste_finale_out.size(); + list ::iterator li; + int nb_trouve_in=0; int nb_trouve_out=0; + // comme on supprime en cours de route des ref de face on recalcul la borne sup à chaque passage + for (li=list_elemPtin_restant.begin();li != list_elemPtin_restant.end();li++) + { bool deja_supprime = false; // pour indiquer si un element a déjà ete supprimer, ce qui evite une double + if (liste_finale_in_a_considerer) // prise en compte que si la liste est non vide + if (find(lf_in_deb, lf_in_end, *li) == lf_in_end) + // on n'a pas trouvé de face appartenant à la liste, on supprime le pti + {list_elemPtin_restant.erase(li);nb_trouve_in++;deja_supprime=true;} + if ((liste_finale_out_a_considerer)&&(!deja_supprime)) // prise en compte que si la liste est non vide + if (find(lf_out_deb, lf_out_end, *li) != lf_out_end) + // on a trouvé une face appartenant à la liste, on supprime le pti + {list_elemPtin_restant.erase(li);nb_trouve_out++;} + }; + + if (ParaGlob::NiveauImpression() > 4) + { if (liste_finale_in_a_considerer) + cout << "\n "<& list_elemFace_restant) +{ + // ---- cas des ref in pour les faces + list liste_finale_in; + { // on commence par concaténer l'ensemble des faces des refs In + list ::iterator lref,lref_fin= list_refIn.end(); + for (lref=list_refIn.begin();lref != lref_fin; lref++) + {// on ne continue que si c'est une ref de face, du même maillage + if (((*lref)->Indic() == 3) && ((*lref)->Nbmaille() == idmail)) + { ReferenceAF * refi = ((ReferenceAF *) (*lref)); + const Tableau& tab_elem = refi->Tab_Elem(); + const Tableau& tab_fa = refi->Tab_FA(); + int tailmax = tab_elem.Taille(); + for (int i=1;i<=tailmax;i++) + { NBelemEtFace nu; nu.nbElem = tab_elem(i); nu.nbFace = tab_fa(i); + liste_finale_in.push_back(nu); + }; + }; + }; + // on trie et on supprime les doublons + liste_finale_in.sort(); + liste_finale_in.unique(); + }; + list ::iterator lf_in_deb=liste_finale_in.begin(); + list ::iterator lf_in_end=liste_finale_in.end(); + // ---- cas des ref out + list liste_finale_out; + { // on commence par concaténer l'ensemble des faces des refs out + list ::iterator lref,lref_fin= list_refOut.end(); + for (lref=list_refOut.begin();lref != lref_fin; lref++) + { // on ne continue que si c'est une ref de face, du même maillage + if (((*lref)->Indic() == 3) && ((*lref)->Nbmaille() == idmail)) + { ReferenceAF * refi = ((ReferenceAF *) (*lref)); + const Tableau& tab_elem = refi->Tab_Elem(); + const Tableau& tab_fa = refi->Tab_FA(); + int tailmax = tab_elem.Taille(); + for (int i=1;i<=tailmax;i++) + { NBelemEtFace nu; nu.nbElem = tab_elem(i); nu.nbFace = tab_fa(i); + liste_finale_out.push_back(nu); + }; + }; + }; + // on trie et on supprime les doublons + liste_finale_out.sort(); + liste_finale_out.unique(); + }; + list ::iterator lf_out_deb=liste_finale_out.begin(); + list ::iterator lf_out_end=liste_finale_out.end(); + +////--- debug +// +////--- debug +// cout << "\n Maillage::Exe_In_out_avecRefExistantes_F(.."; +// cout << "\n list in "; +// list < NBelemEtFace>::iterator lnn; +// for (lnn=lf_in_deb;lnn != lf_in_end; lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbFace << " "; +// cout << "\n list out "; +// for (lnn=lf_out_deb;lnn != lf_out_end; lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbFace << " "; +// cout << "\n list finale avant traitement "; +// for (lnn=list_elemFace_restant.begin();lnn != list_elemFace_restant.end(); lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbFace << " "; +////--- fin debug + + + // ---- application + // on passe en revue les faces et on regarde s'ils font partie d'une des listes In + // et s'ils sont en dehors des out + bool liste_finale_in_a_considerer = liste_finale_in.size(); + bool liste_finale_out_a_considerer = liste_finale_out.size(); + list ::iterator li; + int nb_trouve_in=0; int nb_trouve_out=0; + // comme on supprime en cours de route des ref de face on recalcul la borne sup à chaque passage + for (li=list_elemFace_restant.begin();li != list_elemFace_restant.end();li++) + { bool deja_supprime = false; // pour indiquer si un element a déjà ete supprimer, ce qui evite une double + if (liste_finale_in_a_considerer) // prise en compte que si la liste est non vide + if (find(lf_in_deb, lf_in_end, *li) == lf_in_end) + // on n'a pas trouvé de face appartenant à la liste, on supprime le face + {list_elemFace_restant.erase(li);nb_trouve_in++;deja_supprime=true;} + if ((liste_finale_out_a_considerer)&&(!deja_supprime)) // prise en compte que si la liste est non vide + if (find(lf_out_deb, lf_out_end, *li) != lf_out_end) + // on a trouvé une face appartenant à la liste, on supprime le face + {list_elemFace_restant.erase(li);nb_trouve_out++;} + }; + if (ParaGlob::NiveauImpression() > 4) + { if (liste_finale_in_a_considerer) + cout << "\n "<& list_elemArrete_restant) +{ + // ---- cas des ref in pour les arêtes + list liste_finale_in; + { // on commence par concaténer l'ensemble des arêtes des refs In + list ::iterator lref,lref_fin= list_refIn.end(); + for (lref=list_refIn.begin();lref != lref_fin; lref++) + {// on ne continue que si c'est une ref de arêtes, du même maillage + if (((*lref)->Indic() == 4) && ((*lref)->Nbmaille() == idmail)) + { ReferenceAF * refi = ((ReferenceAF *) (*lref)); + const Tableau& tab_elem = refi->Tab_Elem(); + const Tableau& tab_fa = refi->Tab_FA(); + int tailmax = tab_elem.Taille(); + for (int i=1;i<=tailmax;i++) + { NBelemEtArete nu; nu.nbElem = tab_elem(i); nu.nbArete = tab_fa(i); + liste_finale_in.push_back(nu); + }; + }; + }; + // on trie et on supprime les doublons + liste_finale_in.sort(); + liste_finale_in.unique(); + }; + list ::iterator lf_in_deb=liste_finale_in.begin(); + list ::iterator lf_in_end=liste_finale_in.end(); + // ---- cas des ref out + list liste_finale_out; + { // on commence par concaténer l'ensemble des arêtes des refs out + list ::iterator lref,lref_fin= list_refOut.end(); + for (lref=list_refOut.begin();lref != lref_fin; lref++) + { // on ne continue que si c'est une ref de arête, du même maillage + if (((*lref)->Indic() == 4) && ((*lref)->Nbmaille() == idmail)) + { ReferenceAF * refi = ((ReferenceAF *) (*lref)); + const Tableau& tab_elem = refi->Tab_Elem(); + const Tableau& tab_fa = refi->Tab_FA(); + int tailmax = tab_elem.Taille(); + for (int i=1;i<=tailmax;i++) + { NBelemEtArete nu; nu.nbElem = tab_elem(i); nu.nbArete = tab_fa(i); + liste_finale_out.push_back(nu); + }; + }; + }; + // on trie et on supprime les doublons + liste_finale_out.sort(); + liste_finale_out.unique(); + }; + list ::iterator lf_out_deb=liste_finale_out.begin(); + list ::iterator lf_out_end=liste_finale_out.end(); + +////--- debug +// +////--- debug +// cout << "\n Maillage::Exe_In_out_avecRefExistantes_F(.."; +// cout << "\n list in "; +// list < NBelemEtArete>::iterator lnn; +// for (lnn=lf_in_deb;lnn != lf_in_end; lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbArete << " "; +// cout << "\n list out "; +// for (lnn=lf_out_deb;lnn != lf_out_end; lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbArete << " "; +// cout << "\n list finale avant traitement "; +// for (lnn=list_elemArrete_restant.begin();lnn != list_elemArrete_restant.end(); lnn++) +// cout << (*lnn).nbElem << " "<< (*lnn).nbArete << " "; +////--- fin debug + + + // ---- application + // on passe en revue les arêtes et on regarde s'ils font partie d'une des listes In + // et s'ils sont en dehors des out + bool liste_finale_in_a_considerer = liste_finale_in.size(); + bool liste_finale_out_a_considerer = liste_finale_out.size(); + int nb_trouve_in=0; int nb_trouve_out=0; + list ::iterator li; + // comme on supprime en cours de route des ref de arête on recalcul la borne sup à chaque passage + for (li=list_elemArrete_restant.begin();li != list_elemArrete_restant.end();li++) + { bool deja_supprime = false; // pour indiquer si un element a déjà ete supprimer, ce qui evite une double + if (liste_finale_in_a_considerer) // prise en compte que si la liste est non vide + if (find(lf_in_deb, lf_in_end, *li) == lf_in_end) + // on n'a pas trouvé de arête appartenant à la liste, on supprime le arête + {list_elemArrete_restant.erase(li);nb_trouve_in++;deja_supprime=true;} + if ((liste_finale_out_a_considerer)&&(!deja_supprime)) // prise en compte que si la liste est non vide + if (find(lf_out_deb, lf_out_end, *li) != lf_out_end) + // on a trouvé une arête appartenant à la liste, on supprime le arête + {list_elemArrete_restant.erase(li);nb_trouve_out++;} + }; + + if (ParaGlob::NiveauImpression() > 4) + { if (liste_finale_in_a_considerer) + cout << "\n "<& list_noeud_restant,list & list_elemPtin_restant + ,const Enum_ddl & enu_ddl) +{ // --- cas des noeuds --- + bool fr = ParaGlob::Francais(); // pour simplifier + // on crée un tableau des noeuds restants + if (list_noeud_restant.size() != 0) + {int nbtn = list_noeud_restant.size(); + Tableau tab_n(nbtn); + list ::iterator il,ilfin=list_noeud_restant.end(); + int i=1; + for (il = list_noeud_restant.begin();il != ilfin;il++,i++) + tab_n(i) = *il; + // maintenant on crée une liste de Entier_et_Double qui contient le numéro dans le tableau et la coordonnée + // curviligne de la projection + list list_curvi; + // on rempli la liste + Droite & dr = t_droit(1); // pour simplifier + for (int i=1;i<=nbtn;i++) + { Coordonnee M = tab_n(i)->Coord0(); + Coordonnee Mp = dr.Projete(M); + double xcurv = (Mp-dr.PointDroite()) * dr.VecDroite(); + list_curvi.push_front(Entier_et_Double(i,xcurv)); + }; + // on ordonne la liste + list_curvi.sort(); + // on reconstruit la liste de noeud restant + list_noeud_restant.clear(); + list ::iterator ia,iafin= list_curvi.end(); + for (ia=list_curvi.begin();ia!=iafin;ia++) + list_noeud_restant.push_front(tab_n((*ia).n)); + }; // encapsulation + + // --- cas des points d'intégrations --- + if (list_elemPtin_restant.size() != 0) + {list list_curvi; + // on crée un tableau des ptint + int nbptint = list_elemPtin_restant.size(); + Tableau tab_ptint(nbptint); + + list ::iterator jl,jlfin=list_elemPtin_restant.end(); + int j=1; + for (jl = list_elemPtin_restant.begin();jl != jlfin;jl++,j++) + tab_ptint(j) = *jl; + // maintenant on crée une liste de Entier_et_Double qui contient le numéro dans le tableau et la coordonnée + // curviligne de la projection: + list_curvi.clear(); // en fait on utilise la précédente liste + // on rempli la liste + Droite & dr = t_droit(1); // pour simplifier + for (int i=1;i<=nbptint;i++) + { Element& el = *(tab_element(tab_ptint(i).nbElem)); + bool erreur =false; + Coordonnee M = el.CoordPtInteg(TEMPS_0,enu_ddl,tab_ptint(i).nbPtInteg,erreur); + if (erreur) + { int num = tab_ptint(i).nbPtInteg; + if (fr) {cout << "\n erreur bizarre, on ne peut pas trouver les coordoonees t0 du pt d'integ " + << num << "de l'element " << el.Num_elt() << " du maillage " + << el.Num_maillage() << " on arrete d'ordonner les pt d'integ ! ! "; + } + else {cout << "\n strange error, we cannot find the coordinates at t0 of the gauss point " + << num << "of the element " << el.Num_elt() << " of the mesh " + << el.Num_maillage() << " we stop the process of sorting the integ pt ! ! "; + } + return; + } + Coordonnee Mp = dr.Projete(M); + double xcurv = (Mp-dr.PointDroite()) * dr.VecDroite(); + list_curvi.push_front(Entier_et_Double(i,xcurv)); + }; + // on ordonne la liste + list_curvi.sort(); + // on reconstruit la liste des ptinteg restants + list_elemPtin_restant.clear(); + list ::iterator ja,jafin= list_curvi.end(); + for (ja=list_curvi.begin();ja!=jafin;ja++) + list_elemPtin_restant.push_front(tab_ptint((*ja).n)); + }; // encapsulation + }; + + +//- il faut faire la doc en ligne d'herehz++ +//- il faut mettre un ordre pour sauvegarder le nouveau maillage +//- mettre un sous-ordre dans l'algo, qui a pour objet de rien faire au niveau algo mettre de faire +// l'exécution des choses prévu dans les classes utilisées: ici les maillages + + + + + + + + diff --git a/Maillage/Noeud.cc b/Maillage/Noeud.cc new file mode 100644 index 0000000..4a19e86 --- /dev/null +++ b/Maillage/Noeud.cc @@ -0,0 +1,1864 @@ +// FICHIER : Noeud.cp +// CLASSE : Noeud + + +// 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 "Noeud.h" +#include "Util.h" +#include +#include "TypeQuelconqueParticulier.h" + +// variable globale à la classe +short int Noeud::posi_type_quel = 1; +short int Noeud::posi_ddletendu = 1; +list > Noeud::list_tab_enum; +List_io > Noeud::list_tab_posi_actif; +List_io > Noeud::list_tab_typeQuelconque; // au début il n'y a rien dans la liste +List_io > Noeud::list_tab_ddletendu; // au début il n'y a rien dans la liste + +// ------ méthode concernant laclass Posi_ddl_noeud ---------------- +// surcharge de l'operateur de lecture +istream & operator >> ( istream & ent, Posi_ddl_noeud & a) + { // lecture du type et vérification + string nomtype; ent >> nomtype; + if (nomtype != "Posi_ddl_noeud") + { Sortie(1); + return ent; + } + // lecture des data + ent >> a.nb_maillage >> a.nb_noeud >> a.enu ; + return ent; + }; + +// surcharge de l'operateur d'ecriture +ostream & operator << ( ostream & sort,const Posi_ddl_noeud & a) + { // écriture du type + sort << " Posi_ddl_noeud " ; + // les data + sort << a.nb_maillage << " "<< a.nb_noeud << " "<< a.enu << " "; + return sort; + }; + +// Affiche les donnees liees au noeud +void Posi_ddl_noeud::Affiche (ofstream& sort) const +{ // les data + sort << " Posi_ddl_noeud " ; + sort << nb_maillage << " "<< nb_noeud << " "<< enu << " "; +}; + + +// ------ fin des méthodes concernant la sous_class Posi_ddl_noeud ---------------- + +//========================================================================= + +// Fait appel au constructeur par defaut de Coordonnee et de Tableau +// Constructeur se servant eventuellement d'un numero d'identification +Noeud::Noeud (int num_id,int num_M): + tab_0(),tab_ddl(),tab_tdt(),coord1() + ,tab_var_actives(),tab_actif(),pos_enum(list_tab_enum.end()) + ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) + ,t_enum_s(),tab_type_quel(),update_type_quel(),nbTypeQ_update(0) + ,tab_nb_Elem(),pos_Quelconque(list_tab_typeQuelconque.end()) + ,pos_ddletendu(list_tab_ddletendu.end()) + ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) + ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) + { num_noeud=num_id; + coord0 = NULL; + coord2 = NULL; + num_Mail = num_M; + posi_type_quel = 1; + MiseAjourEnum(); // mise en place de l'adressage directe + MiseAjourDdl_etendu(); // cas des ddl étendue + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + }; + +// Constructeur utile quand seuls le numero d'identification et la +// dimension de l'espace sont connus +Noeud::Noeud (int num_id,int dimension,int num_M): + tab_0(),tab_ddl(),tab_tdt(),coord1(),tab_var_actives(),tab_actif() + ,pos_enum(list_tab_enum.end()) + ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) + ,t_enum_s(),tab_type_quel() + ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() + ,pos_Quelconque(list_tab_typeQuelconque.end()) + ,pos_ddletendu(list_tab_ddletendu.end()) + ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) + ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) + { num_noeud=num_id; + coord0 = new Coordonnee(dimension); + coord2 = NULL; + num_Mail = num_M; + posi_type_quel = 1; + MiseAjourEnum(); // mise en place de l'adressage directe + MiseAjourDdl_etendu(); // cas des ddl étendue + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + }; + +// Constructeur pour un noeud dont le numero et les coordonnees initiales +// sont connus +Noeud::Noeud (int num_id,const Coordonnee& c0,int num_M): + tab_0(),tab_ddl(),tab_tdt(),coord1(),tab_var_actives(),tab_actif() + ,pos_enum(list_tab_enum.end()) + ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) + ,t_enum_s(),tab_type_quel() + ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() + ,pos_Quelconque(list_tab_typeQuelconque.end()) + ,pos_ddletendu(list_tab_ddletendu.end()) + ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) + ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) + { num_noeud=num_id; + coord0 = new Coordonnee(c0); + coord2 = NULL; + num_Mail = num_M; + posi_type_quel = 1; + MiseAjourEnum(); // mise en place de l'adressage directe + MiseAjourDdl_etendu(); // cas des ddl étendue + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + }; + +// Constructeur fonction d'un numero d'identification, des coordonnees +// initiales et du tableau des degres de liberte +// les ddl t=0 sont initialises avec les valeurs du tableaux +// sauf coord0 qui est initialise avec c0 +// par defaut les tableaux de ddl a 0 et t sont initialises mais pas +// a t+dt +Noeud::Noeud (int num_id,const Coordonnee& c0,const Tableau& tab,int num_M): + tab_ddl(tab),tab_0(tab_ddl.Taille()),tab_tdt(),coord1() + ,tab_var_actives(),tab_actif() + ,pos_enum(list_tab_enum.end()) + ,baseB(NULL),baseB_t(NULL),baseB_0(NULL) + ,posiAssemb(),t_enum_s(),tab_type_quel() + ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() + ,pos_Quelconque(list_tab_typeQuelconque.end()) + ,pos_ddletendu(list_tab_ddletendu.end()) + ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) + ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) + { num_noeud=num_id; + coord0 = NULL; + coord2 = NULL; + num_Mail = num_M; + // init de tab_0 + for (int i=1;i<=tab_0.Taille();i++) + tab_0(i) = tab_ddl(i).Valeur(); + // cas ou l'on est en coordonnees entrainees + if ( Existe(X1) != 0) + { Liaison_t(Existe(X1)); + *coord0 = c0; + } + // cas ou les ddl sont separes des coordonnees + else + { coord0 = new Coordonnee(c0); + }; + posi_type_quel = 1; + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); + MiseAjourEnum(); // mise en place de l'adressage directe + MiseAjourDdl_etendu(); // cas des ddl étendue + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + }; + +// Constructeur fonction d'un numero d'identification, des coordonnees +// initiales, a un instant t, et du tableau des degres de liberte +// les ddl t=0 sont initialises avec les valeurs du tableaux +// par defaut les tableaux de ddl a 0 et t sont initialises mais pas +// a t+dt +// les ddl corespondant a Xi sont ajoute s'ils n'existaient pas +// et il y a automatiquement liaison entre ddl et coordonnées +Noeud::Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Tableau& tab,int num_M): + tab_ddl(tab),tab_0(tab_ddl.Taille()),tab_tdt(),coord1(c1.Dimension()) + ,tab_var_actives(),tab_actif() + ,pos_enum(list_tab_enum.end()) + ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) + ,t_enum_s(),tab_type_quel() + ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() + ,pos_Quelconque(list_tab_typeQuelconque.end()) + ,pos_ddletendu(list_tab_ddletendu.end()) + ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) + ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) + { num_noeud=num_id; + coord0 = NULL; + coord2 = NULL; + num_Mail = num_M; + // init de tab_0 + #ifdef MISE_AU_POINT // vérification de la dimension de tab_ddl + if (tab.Taille() < c1.Dimension()) + { cout << "\nErreur : dans le constructeur de noeud : "; + cout << " Noeud (int num_id,Coordonnee& c0,Coordonnee& c1," + << "const Tableau& tab,int num_M)\n"; + Sortie(1); + }; + #endif + for (int i=1;i<=tab_0.Taille();i++) + tab_0(i) = tab_ddl(i).Valeur(); + // cas ou l'on est en coordonnees entrainees + int posi_X1=0; // init + if ( Existe(X1) == 0) + { // le ddl X1 n'existe pas on le rajoute + int an = tab_ddl.Taille(); + tab_ddl.Change_taille(an+Dimension()); + tab_0.Change_taille(an+Dimension()); + for (int jj=1;jj<=Dimension();jj++) + tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); + posi_X1 = an+1; // c'est la position du ddl X1 + } + else // sinon il existe on récupère sa position + posi_X1 = Existe(X1) ; + // on effectue la liaison ddl/ deplacement + Liaison_t(posi_X1); // (Existe(X1)); + *coord0 = c0; + for (int j=1;j<= Dimension();j++) + *(coord1(j)) = c1(j); + posi_type_quel = 1; + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); + MiseAjourEnum(); // mise en place de l'adressage directe + MiseAjourDdl_etendu(); // cas des ddl étendue + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + }; + +// Constructeur pour un noeud dont le numero, les coordonnees initiales, aux +// instant t et t+dt ainsi que le tableau des degres de liberte sont connus +// comme les coordonnées à t+dt sont données cela signifie qu'ils sont des +// degrés de liberté +// les ddl corespondant a Xi sont ajoute s'ils n'existaient pas +// et il y a automatiquement liaison entre ddl et coordonnées +Noeud::Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Coordonnee& c2, + const Tableau& tab,int num_M): + tab_ddl(tab),tab_0(tab.Taille()),tab_tdt(tab.Taille()),coord1(c1.Dimension()) + ,tab_var_actives(),tab_actif() + ,pos_enum(list_tab_enum.end()) + ,posiAssemb(),baseB(NULL),baseB_t(NULL),baseB_0(NULL) + ,t_enum_s(),tab_type_quel() + ,update_type_quel(),nbTypeQ_update(0),tab_nb_Elem() + ,pos_Quelconque(list_tab_typeQuelconque.end()) + ,pos_ddletendu(list_tab_ddletendu.end()) + ,nbddletendu_update(0),tab_ddletendu(0),update_ddletendu(0) + ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) + { num_noeud=num_id; + coord0 = NULL; + coord2 = NULL; + num_Mail = num_M; + // init de tab_0 + #ifdef MISE_AU_POINT // vérification de la dimension de tab_ddl + if (tab.Taille() < c1.Dimension()) + { cout << "\nErreur : dans le constructeur de noeud : "; + cout << " Noeud (int num_id,Coordonnee& c0,Coordonnee& c1,Coordonnee& c2," + << "const Tableau& tab,int num_M)\n"; + Sortie(1); + }; + #endif + int tab0Taille = tab_0.Taille(); + for (int i=1;i<=tab0Taille;i++) + tab_0(i) = tab_ddl(i).Valeur(); + // on est en coordonnees entrainees, on vérifie que les ddl XI + // sont présent sinon on rajoute + int posi_X1=0; // init + if ( Existe(X1) == 0) + { // le ddl X1 n'existe pas on rajoute les XI + int an = tab_ddl.Taille(); + tab_ddl.Change_taille(an+Dimension()); + tab_0.Change_taille(an+Dimension()); + tab_tdt.Change_taille(an+Dimension()); + for (int jj=1;jj<=Dimension();jj++) + tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); + posi_X1 = an+1; // c'est la position du ddl X1 + } + else // sinon il existe on récupère sa position + posi_X1 = Existe(X1) ; + // on effectue la liaison ddl/ deplacement, donc la mémoire + // des coordonnées est positionnée dans le tableau de ddl + Liaison_tdt(posi_X1); // (Existe(X1)); +// Liaison_tdt(Existe(X1)); + *coord0 = c0; // recopie des valeurs + *coord2 = c2; // """" + for (int j=1;j<= Dimension();j++) + *(coord1(j)) = c1(j); + posi_type_quel = 1; + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); + MiseAjourEnum(); // mise en place de l'adressage directe + MiseAjourDdl_etendu(); // cas des ddl étendue + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + }; + + +// Constructeur de copie +Noeud::Noeud (const Noeud& nd): + tab_0(nd.tab_0),tab_ddl(nd.tab_ddl),tab_tdt(nd.tab_tdt),coord1() + ,tab_var_actives(nd.tab_var_actives),tab_actif(nd.tab_actif) + ,pos_enum(nd.pos_enum) + ,posiAssemb(nd.posiAssemb),baseB(NULL),baseB_t(NULL) // on définit ensuite la base + ,baseB_0(NULL) + ,t_enum_s(nd.t_enum_s) + ,tab_type_quel(nd.tab_type_quel),update_type_quel(nd.update_type_quel) + ,nbTypeQ_update(0),tab_nb_Elem(nd.tab_nb_Elem) + ,pos_Quelconque(list_tab_typeQuelconque.end()) // idem ddl étendues + ,pos_ddletendu(list_tab_ddletendu.end()) // c'est dans la méthode MiseAjourDdl_etendu, que le pointeur sera mis à jour + ,nbddletendu_update(nd.nbddletendu_update) + ,tab_ddletendu(nd.tab_ddletendu),update_ddletendu(nd.update_ddletendu) + // pour les liaisons cinématiques: pas de recopie, il s'agit d'un stockage uniquement: + // l'utilisation et la manipulation est à la charge des classes appelantes + ,tab_enu_liaison(NULL),tab_ddl_lier(NULL) + { num_noeud=nd.num_noeud; + coord2 = NULL; // initialisation + num_Mail = nd.num_Mail; + if ( Existe(X1) != 0) + { coord0 = NULL; + // traitement des liaisons et avec du cas de coord1 + if ( tab_tdt.Taille() != 0) + // cas avec les coordonnees a t+dt + //on effectue la liaison ddl/ deplacement + Liaison_tdt(Existe(X1)); + else // sinon uniquement à t + Liaison_t(Existe(X1)); + } + else + {if (nd.coord0 != NULL) + {coord0 = new Coordonnee(*(nd.coord0)); + } + else + {coord0 = NULL; + }; + }; + // cas d'une base locale éventuelle + if (nd.baseB != NULL) + {baseB = new BaseB(*nd.baseB);}; + if (nd.baseB_t != NULL) + {baseB_t = new BaseB(*nd.baseB_t);}; + if (nd.baseB_0 != NULL) + {baseB_0 = new BaseB(*nd.baseB_0);}; + + + posi_type_quel = nd.posi_type_quel; + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); + // pour les grandeurs quelconques, a priori on les met "non a jour" + // la mise à jour nécessite l'appel explicite à l'ordre de mise à jour + if (update_type_quel.Taille() != 0) + { int t_typTaille = update_type_quel.Taille(); + for (int titq=1;titq<= t_typTaille;titq++) update_type_quel(titq)=0; + }; + MiseAjourDdl_etendu(); // cas des ddl étendue + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + }; + +Noeud::~Noeud() + // Destructeur de Noeud utilisant les destructeurs + // de Coordonnee et de Tableau + { delete coord0; // le choix de la destruction ou pas de la zone + //mémoire est fait dans coord0 + if (coord2 != NULL) delete coord2; + + // on n'efface pas le tableau coord2 car s'il existe (c-a-d différent de null) il représente aussi + // des degrés de liberté, donc il se situe au même endroit que les éléments de tab_tdt + // qui lui sera de toute façon détruit par le destructeur automatique + // pour les enum étendus, on utilise la méthode MiseAjourDdl_etendu(), pour que tout soit cohérent + // on commence par supprimer les tableaux ad hoc et ensuite on met à jour + tab_ddletendu.Libere();update_ddletendu.Libere();nbddletendu_update=0; + MiseAjourDdl_etendu(); + // idem pour les grandeurs quelconques + tab_type_quel.Libere(); update_type_quel.Libere(); nbTypeQ_update=0; + MiseAjourTypeQuelconque(); // cas des grandeurs quelconques + // dans le cas ou il existe des liaisons cinématiques on supprime les conteneurs + Suppression_tous_liaisons_noeuds(); + // cas où il existe une base locale + if (baseB_0 != NULL) delete baseB_0; + if (baseB_t != NULL) delete baseB_t; + if (baseB != NULL) delete baseB; + }; + +// surcharge de l'operator de lecture, avec typage +istream & operator >> (istream & ent, Noeud & noe) + { // lecture du type et vérification + string nomType,nom; + ent >> nomType; + if (nomType != "Noeud") + { Sortie(1); + return ent; + }; + // puis le numéro de noeud et le numéro de maillage + ent >> noe.num_noeud >> noe.num_Mail ; + + // les liaisons éventuelles + bool test; + ent >> nom >> test; // tab_enu_liaison + if (test) + { int nb;int toto; + ent >> nb; + if (noe.tab_enu_liaison != NULL) + {noe.tab_enu_liaison->Change_taille(nb);} + else + {noe.tab_enu_liaison = new Tableau (nb);}; + for (int i=1;i<= nb;i++) + { ent >> nom >> toto >> nom; + (*noe.tab_enu_liaison)(i) = Id_nom_liaison_noeud(nom); + }; + } + else + {if (noe.tab_enu_liaison != NULL) + { delete noe.tab_enu_liaison; noe.tab_enu_liaison = NULL;} + }; + + ent >> nom >> test; // tab_ddl_lier + if (test) + { int nb;int toto; + ent >> nb; + if (noe.tab_ddl_lier != NULL) + {noe.tab_ddl_lier->Change_taille(nb);} + else + {noe.tab_ddl_lier = new Tableau >(nb);}; + for (int i=1;i<= nb;i++) + ent >> nom >> toto >> (*noe.tab_ddl_lier)(i); + } + else + {if (noe.tab_ddl_lier != NULL) + { delete noe.tab_ddl_lier; noe.tab_ddl_lier = NULL;} + }; + + // le tableau des degrés de liberté + ent >> noe.tab_ddl; + // coordonnee initiale on les récupère par défaut + // ensuite on fera la mise à jour + ent >> *(noe.coord0); + ent >> nom >> noe.tab_0; // valeurs a l'instant 0 des ddl + ent >> nom >> noe.tab_tdt; // valeurs a l'instant t+dt des ddl + // les coordonnees a un instant t et tdt sont reconstruit avec + // la mise à jour si nécessaire + noe.MiseAjour(); + // vérif si les coordonnees a un instant t+dt existent + // si oui liaison + ent >> nom; + if (nom == "coord2Existe") + noe.Liaison_tdt(noe.Existe(X1)); + // ent >> nom >> noe.tab_var_actives; // les numéros des ddl actifs + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + noe.MiseAjourActif(); + noe.MiseAjourEnum(); // mise en place de l'adressage directe + // %% cas des types quelconques éventuelles %% + noe.Lecture_grandeurs_quelconque(ent); + // idem pour les ddl_etendu + noe.Lecture_Ddl_etendu(ent); + + // cas d'une base locale éventuelle + {int existe_base; + ent >> existe_base; + if (existe_base == 1) + {if (noe.baseB_0 == NULL) {noe.baseB_0=new BaseB();}; + ent >> nom >> (*noe.baseB_0); + }; + ent >> existe_base; + if (existe_base == 1) + {if (noe.baseB_t == NULL) {noe.baseB_t=new BaseB();}; + ent >> nom >> (*noe.baseB_t); + }; + ent >> existe_base; + if (existe_base == 1) + {if (noe.baseB == NULL) {noe.baseB=new BaseB();}; + ent >> nom >> (*noe.baseB); + }; + }; + + return ent; + }; + +// surcharge de l'operator d'ecriture avec typage +ostream & operator << (ostream & sort , const Noeud & noe) + { // le type, le numéro de noeud et le numéro de maillage + sort << "Noeud " << noe.num_noeud << " " << noe.num_Mail ; + // les liaisons éventuelles + if (noe.tab_enu_liaison != NULL) + { sort << "\n tab_enu_liaison " << 1 << " "; // on signale la présence du tableau + int nb = (noe.tab_enu_liaison)->Taille(); + sort << nb << " "; + for (int i=1;i<= nb;i++) + sort << " ass: "<< i << Nom_liaison_noeud((*noe.tab_enu_liaison)(i)) << " "; + } + else + sort << "\n tab_enu_liaison " << 0 << " "; // on signale l'absence du tableau ; + + if (noe.tab_ddl_lier != NULL) + { sort << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau + int nb = (noe.tab_ddl_lier)->Taille(); + sort << nb << " "; + for (int i=1;i<= nb;i++) + sort << "\n ass: "<< i << " "<< (*noe.tab_ddl_lier)(i); + } + else + sort << "\n tab_ddl_lier " << 0 << " "; // on signale l'absence du tableau ; + + // le tableau des degrés de liberté + sort << noe.tab_ddl; + // coordonnee initiale on les sauvegarde par défaut + // ensuite on fera la mise à jour + sort << *(noe.coord0); + sort << " ddl_a_0 " << noe.tab_0; // valeurs a l'instant 0 des ddl + sort << " ddl_a_tdt " << noe.tab_tdt; // valeurs a l'instant t+dt des ddl + // les coordonnees a un instant t ne sont pas sauvegardées elles seront + // reconstruites si besoin avec la mise à jour + // coordonnee a un instant t+dt on signale son existence + if (noe.coord2 != NULL) + sort << "coord2Existe \n"; + else + sort << "pascoord2 \n"; + // sort << "ddl_actif " << noe.tab_var_actives; // les numéros des ddl actifs + // %% cas des types quelconques éventuelles %% + noe.Ecriture_grandeurs_quelconque(sort); + // idem pour les ddl_etendu + noe.Ecriture_Ddl_etendu(sort); + + // cas d'une base locale éventuelle + if (noe.baseB_0 != NULL) + {sort << "\n 1 base_locale_0: " << (*noe.baseB_0);} + else {sort << "\n 0 base_locale_0: "; }; + if (noe.baseB_t != NULL) + {sort << "\n 1 base_locale_t: " << (*noe.baseB_t);} + else {sort << "\n 0 base_locale_t: "; }; + if (noe.baseB != NULL) + {sort << "\n 1 base_locale: " << (*noe.baseB);} + else {sort << "\n 0 base_locale: "; }; + + return sort; + }; + +// lecture du noeud en mémoire +void Noeud::Lecture(UtilLecture *entreePrinc) + { int numero; + Coordonnee co(Dimension()); // def d'un tableau de coordonnées + *(entreePrinc->entree) >> numero ; + // lecture brut des coordonnées sans la dimension + co.Lecture(*entreePrinc); + Change_coord0(co); // transmission a noeud + if (numero != num_noeud) + { cout << " ***ATTENTION dans la lecture du noeud "; + cout << " le numero d identification du noeud attribue par " + << " le constructeur (" << num_noeud << ") est different de celui lu !!! " + << " (" << numero << ") " + << " Noeud::Lecture((UtilLecture *entreePrinc) " << endl ; + }; + }; + +// affichage et definition interactive des commandes +// coor: des coordonnees fixée pour un affichage different pour chaque noeud +void Noeud::Info_commande_Noeud(UtilLecture * entreePrinc,Coordonnee& co,int numero) + { ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier + int dima = ParaGlob::Dimension(); + sort << "\n" << setw (6) << numero <<" "; + double sero = 0.; + #ifndef ENLINUX_STREAM + sort.setf(ios_base::scientific); + #else + sort.setf(ios::scientific); + #endif + // sort.setf(ios_base::scientific); + for (int j=1;j<=3;j++) + if (j<=dima) + sort << setw (18) << setprecision(ParaGlob::NbdigdoCA()) < 0) + {// les liaisons éventuelles + if (tab_enu_liaison != NULL) + { cout << "\n tab_enu_liaison " << 1 << " "; // on signale la présence du tableau + int nb = (tab_enu_liaison)->Taille(); + cout << nb << " "; + for (int i=1;i<= nb;i++) + cout << " ass: "<< i << Nom_liaison_noeud((*tab_enu_liaison)(i)) << " "; + } + else + cout << "\n tab_enu_liaison " << 0 << " "; // on signale l'absence du tableau ; + + if (tab_ddl_lier != NULL) + { cout << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau + int nb = (tab_ddl_lier)->Taille(); + cout << nb << " "; + for (int i=1;i<= nb;i++) + cout << "\n ass: "<< i << " "<< (*tab_ddl_lier)(i); + } + else + cout << "\n tab_ddl_lier " << 0 << " "; // on signale l'absence du tableau ; + }; + + cout << "Coordonnee(s) initiale(s) du noeud : \n"; + coord0->Affiche(); + if (coord1.Taille() != 0) + { cout << "Coordonnee(s) a l'instant t : \n"; + Coord1().Affiche(); + } + if (coord2 != NULL) + { cout << "Coordonnee(s) a l'instant t+dt : \n"; + coord2->Affiche(); + } + cout << "Degre(s) de liberte lie(s) au noeud : \n"; + cout << "Taille du tableau : " << tab_ddl.Taille() << " , a 0, a t ( et t+dt ?)\n"; + for (int i=1;i<=tab_ddl.Taille();i++) + { if (tab_0.Taille() != 0) cout << tab_0(i) << " "; + tab_ddl(i).Affiche(); + if (tab_tdt.Taille() != 0) cout << tab_tdt(i) << " "; + }; + // affichage éventuelle des grandeurs enum étendue stockées au noeud + int tail_tab_ddletendu = tab_ddletendu.Taille(); + if (tail_tab_ddletendu != 0) + {cout << "\nddl_etendu: "; + for (int itq=1;itq<=tail_tab_ddletendu;itq++) + {Ddl_etendu& ddlenum = tab_ddletendu(itq); + if (ddlenum.DdlEnumEtendu().Nom_vide()) + { cout << Nom_ddl(ddlenum.DdlEnumEtendu().Enum()) ;} + else + { cout << ddlenum.DdlEnumEtendu().Nom() ;}; + cout << " " << ddlenum.ConstValeur()<< " "; + }; + }; + + // affichage éventuelle des grandeurs quelconques stockées au noeud + int tail_tab_type_quel = tab_type_quel.Taille(); + if (tail_tab_type_quel != 0) + {cout << "\nddl_quelconque: "; + for (int itq=1;itq<=tail_tab_type_quel;itq++) + {cout << tab_type_quel(itq).EnuTypeQuelconque().NomPlein() << " " + << *(tab_type_quel(itq).Grandeur_pointee()) << " \n"; + }; + }; + + // cas d'une base locale éventuelle + if (baseB_0 != NULL) + {cout << "\n base_locale_0: " << (*baseB_0);} + if (baseB_t != NULL) + {cout << "\n base_locale_t: " << (*baseB_t);} + if (baseB != NULL) + {cout << "\n base_locale: " << (*baseB);} + + // dans le cas ou la variable niveau est plus grande que 0 on affiche plus d'information + if (niveau > 0) + { cout << "\n le tableau d'adressage directe " << (* pos_enum) << endl; + }; + cout << "-- fin noeud --\n"; + }; + + // Affiche les donnees liees au noeud + void Noeud::Affiche (ofstream& sort) const + { // l'entete + sort << " Numero : [ " << num_noeud + << " ]****/////, du maillage: < "<< num_Mail + << " > "; + // les liaisons éventuelles + if (tab_enu_liaison != NULL) + { int nb = (tab_enu_liaison)->Taille(); + sort << nb << " liaison(s) (ass,type): "; + for (int i=1;i<= nb;i++) + sort << i << " " << Nom_liaison_noeud((*tab_enu_liaison)(i)) << " "; + }; + + if (tab_ddl_lier != NULL) + { cout << "\n tab_ddl_lier " << 1 << " "; // on signale la présence du tableau + int nb = (tab_ddl_lier)->Taille(); + sort << nb << " , ddl_lie(s) (ass,maill,noe,enu): "; + for (int i=1;i<= nb;i++) + sort << i << " "<< (*tab_ddl_lier)(i); + }; + + sort << " =======================\n"; + // les coordonnees + sort << "Coord t=0 : "; coord0->Affiche(sort,16); sort << ", " ; + if (coord1.Taille() != 0) + { sort << "\nCoord a t : "; Coord1().Affiche(sort,16); sort << ", " ;}; + if (coord2 != NULL) + {sort << "\nCoord a t+dt: " ; coord2->Affiche(sort,16); sort << ", " ;}; + // les ddl et variations + sort << '\n' << tab_ddl.Taille() << " Ddl a "; + if (tab_0.Taille() != 0) sort << " <<0>> "; + sort << " <> ( et variation) "; + if (tab_tdt.Taille() != 0) sort << " <> (et variation) : \n"; + + for (int i=1;i<=tab_ddl.Taille();i++) + { sort << tab_ddl(i).Nom() << " = "; // le nom + if (tab_0.Taille() != 0) sort << setw (16) << tab_0(i) << ", "; // val a t=0 + sort << setw (16) << tab_ddl(i).Valeur() << " "; // val a t + if (tab_0.Taille() != 0) + sort << "( " << setw (16) << (tab_ddl(i).Valeur() - tab_0(i)) << "), "; // delta 0 t + if (tab_tdt.Taille() != 0) sort << setw (16) << tab_tdt(i) << " "; // val a tdt + if ((tab_0.Taille() != 0)&&(tab_tdt.Taille() != 0)) + sort << "(" << setw (16) << (tab_tdt(i) - tab_0(i)) << " );"; // deltat 0 tdt + + // decalage pour la ligne suivante + sort << "\n"; + }; + // affichage éventuelle des grandeurs quelconques stockées au noeud + int tail_tab_type_quel = tab_type_quel.Taille(); + for (int itq=1;itq<=tail_tab_type_quel;itq++) + {sort << (tab_type_quel(itq).EnuTypeQuelconque()).NomPlein() << " " + << *(tab_type_quel(itq).Grandeur_pointee()) << " \n"; + }; + + // cas d'une base locale éventuelle + if (baseB_0 != NULL) + {sort << "\n base_locale_0: " << (*baseB_0);} + if (baseB_t != NULL) + {sort << "\n base_locale_t: " << (*baseB_t);} + if (baseB != NULL) + {sort << "\n base_locale: " << (*baseB);} + + sort << "\n"; + }; + +// insert des coordonnees coord1 si elles n'existent pas encore +// permet de définir des coordonnées à t, dans ce cas des ddl XI sont inclus +// et sont mis inactif par défaut +void Noeud::Insert_coord1(const Coordonnee& nouveau_coord1) + { // si les coordonnées n'existe pas encore il faut les créer + if ( Existe(X1) == 0) + { // le ddl X1 n'existe pas on le rajoute + int an = tab_ddl.Taille(); + tab_ddl.Change_taille(an+Dimension()); + tab_0.Change_taille(an+Dimension()); + int dim = Dimension(); + for (int jj=1;jj<=dim;jj++) + tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); + // on effectue la liaison ddl/ deplacement + Liaison_t(Existe(X1)); + // on met les XI hors service + for (int i = 1; i<=dim; i++) + tab_ddl(an+i).Met_hors_service(); + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); + MiseAjourEnum(); // mise en place de l'adressage directe + }; + // copie des ddl + for (int i=1;i<=coord1.Taille();i++) + *(coord1(i)) = nouveau_coord1(i); + }; + +// idem mais sans paramètre indique que l'on initialise aux coordonnées à t=0 +// s'ils n'existent pas, sinon on ne fait rien +void Noeud::Insert_coord1() + { // si les coordonnées n'existe pas encore il faut les créer + if ( Existe(X1) == 0) + { // le ddl X1 n'existe pas on le rajoute + int an = tab_ddl.Taille(); + tab_ddl.Change_taille(an+Dimension()); + tab_0.Change_taille(an+Dimension()); + int dim = Dimension(); + for (int jj=1;jj<=dim;jj++) + tab_ddl(an+jj).Change_nom(Enum_ddl(jj)); + // on effectue la liaison ddl/ deplacement + // donc le ddl X1 se situe maintenant à la place an+1 dans le tableau + // des ddl + Liaison_t(an+1); //(Existe(X1)); + // on met les XI hors service + for (int i = 1; i<=dim; i++) + tab_ddl(an+i).Met_hors_service(); + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); + MiseAjourEnum(); // mise en place de l'adressage directe + // copie des ddl + for (int i=1;i<=coord1.Taille();i++) + *(coord1(i)) = (*coord0)(i); + }; + }; + + +// Modifie les valeurs des coordonnees coord1 +void Noeud::Change_coord1(const Coordonnee& nouveau_coord1) + { // si les coordonnées n'existe pas encore il faudrait les créer avant de les utiliser + #ifdef MISE_AU_POINT // vérif + if ((nouveau_coord1.Dimension() != Dimension()) || + (coord1.Taille() == 0) || ((coord1(1)) == NULL)) + { cout << "\nErreur : dans l'affectation de coordonnées à t, elles ne sont pas définies !\n"; + cout << " Noeud::Change_coord1(Coordonnee& nouveau_coord1)\n"; + Sortie(1); + } + #endif + + for (int i=1;i<=coord1.Taille();i++) + *(coord1(i)) = nouveau_coord1(i); + }; + + +// Retourne les coordonnees coord1 du noeud +// uniquement pour la lecture +//Coordonnee Noeud::Coord1 () +// { int nbcoo = coord1.Taille(); +// Coordonnee coo(nbcoo); +// for (int i=1;i<=nbcoo;i++) +// coo(i) = *(coord1(i)); +// return coo; +// }; + +// Retourne le nombre de degres de liberte du noeud +// qui sont actuellement actifs +//int Noeud::Nombre_var_ddl_actives () +// { int total = 0; +// int imax = tab_ddl.Taille(); +// for (int i=1;i<=imax;i++) +// if (tab_ddl(i).Service()) total ++; +// return total; +// }; + + +// retourne la liste de tous les types de ddl actuellement utilisé +// par le noeud (actif ou non) +List_io Noeud::Les_type_de_ddl(bool) + { int tail = tab_ddl.Taille(); + List_io tab_enum; + for (int i= 1;i<= tail;i++) + tab_enum.push_back(tab_ddl(i).Id_nom()); + return tab_enum; + }; + +// retourne la liste de tous les Ddl_enum_etendu disponible +List_io Noeud::Les_type_de_ddl_etendu(bool) + { int tail = tab_ddletendu.Taille(); + List_io tab_enum_etendu; + for (int i= 1;i<= tail;i++) + tab_enum_etendu.push_back(tab_ddletendu(i).Const_DdlEnumEtendu()); + return tab_enum_etendu; + }; + +// retourne la liste de tous les TypeQuelconque disponibles +List_io Noeud::Les_TypeQuelconque(bool ) + { int tail = tab_type_quel.Taille(); + List_io tab_TypeQuelconque; + for (int i= 1;i<= tail;i++) + tab_TypeQuelconque.push_back(tab_type_quel(i)); + return tab_TypeQuelconque; + }; + +// récupération d'une liste d'info +// le tableau de retour à la taille de li_enu_scal et contient +// les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud +// en fait ici on cumule les ddl pur "et" les ddl_étendue, +// li_quelc : est modifié par les valeurs contenues au noeud +Tableau Noeud::Valeur_multi_et_Tensorielle + (const List_io & li_enu_scal,List_io & li_quelc) const + {int nb_ddl_enum_etendu = li_enu_scal.size(); // la taille du tableau de retour + Tableau tab_ret(nb_ddl_enum_etendu); // le tableau de retour + // on balaie les ddl_enum_etendu pour les alimenter + {List_io ::const_iterator il,il_fin = li_enu_scal.end(); + int i_tab=1; // init + for (il= li_enu_scal.begin(); il != il_fin; il++,i_tab++) + { // on regarde s'il s'agit d'un ddl pur + const Ddl_enum_etendu& ddl = (*il); // pour simplifier + if (ddl.Nom_vide()) + // cas d'un ddl pur + { if (Existe_ici(ddl.Enum())) + {tab_ret(i_tab)= Valeur_tdt(ddl.Enum());} + else + {cout << "\n *** erreur d'acces, le ddl "<< Nom_ddl(ddl.Enum()) + << " n'est pas disponible au temps tdt " + << "\n Noeud::Valeur_multi_et_Tensorielle(..."; + Noeud::Affiche(0); + Sortie(1); + }; + } + else // cas d'un ddl étendu + { if (Existe_ici_ddlEtendu(ddl)) + {tab_ret(i_tab)= DdlEtendue(ddl).ConstValeur();} + else + {cout << "\n *** erreur d'acces, le ddl etendue "<< ddl.Nom_plein() + << " n'est pas disponible au temps tdt " + << "\n Noeud::Valeur_multi_et_Tensorielle(..."; + Noeud::Affiche(0); + Sortie(1); + }; + }; + }; + }; + //on balaie les types quelconques + {List_io ::iterator il,il_fin = li_quelc.end(); + int i_tab=1; // init + for (il= li_quelc.begin(); il != il_fin; il++,i_tab++) + { TypeQuelconque& etq = (*il); // pour simplifier + // on regarde s'il existe + TypeQuelconque_enum_etendu en = etq.EnuTypeQuelconque(); // pour simplifier + if (Existe_ici(en)) + { etq = Grandeur_quelconque(en);} + else + {// on test s'il s'agit d'un type correspondant à une grandeur + // stockée naturellement au noeud + bool trouver = false; // init + if(en.Nom_vide()) // on ne prend en compte que les types initiaux + {switch (en.EnumTQ()) + { case NUM_NOEUD: + { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) (etq.Grandeur_pointee())); + *(gr.ConteneurEntier()) = this->Num_noeud(); + trouver = true; + break; + } + case NUM_MAIL_NOEUD: + { Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) (etq.Grandeur_pointee())); + *(gr.ConteneurEntier()) = this->Num_Mail(); + trouver = true; + break; + } + case POSITION_GEOMETRIQUE: + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee())); + (*gr.ConteneurCoordonnee())= this->Coord2(); + trouver = true; + break; + } + case POSITION_GEOMETRIQUE_t: + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee())); + (*gr.ConteneurCoordonnee())= this->Coord1(); + trouver = true; + break; + } + case POSITION_GEOMETRIQUE_t0: + {Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (etq.Grandeur_pointee())); + (*gr.ConteneurCoordonnee())= this->Coord0(); + trouver = true; + break; + } + + //*** fin + + + default: + trouver = false; + break; + }; + }; + if (!trouver) + {cout << "\n *** erreur d'acces, le ddl "<< en.NomPlein() + << " n'est pas disponible " + << "\n Noeud::Valeur_multi_et_Tensorielle(..."; + Noeud::Affiche(0); + Sortie(1); + }; + }; + }; + }; + + // retour + return tab_ret; + }; + +// ramene le nombre de variables ddl actives pour un type de ddl donné, +// c'est-à-dire 1 ou la dimension, suivant que le type dépend +// ou pas de la dimension +int Noeud::Nombre_var_ddl_actives (Enum_ddl en) const + { int retour = 0; + if ((Existe(en) != 0) && (En_service(en)) && (UneVariable(en))) + { switch (TypeGrandeur(en)) + { case SCALAIRE : + retour=1; + break; + case VECTEUR : case COORDONNEE : // là il y a un mélange pas sain ! + // dans le cas où le calcul est axisymétrique + // on ne prend pas en compte le 3 ième ddl + if (ParaGlob::AxiSymetrie()) + {retour = 2; }// on est forcément en 3D + else + {retour=ParaGlob::Dimension();}; + break; + case TENSEUR : + retour = ParaGlob::NbCompTens(); + break; + case RIEN_TYPEGRANDEUR : + retour = 0; + break; + default : + cout << "\nErreur : valeur incorrecte du type Enum_ddl !\n"; + cout << "Nombre_var_ddl_actives (Enum_ddl en) \n"; + Sortie(1); + }; + }; + return retour; + }; + +// surcharge de l'affectation entre deux noeuds +Noeud& Noeud::operator= (const Noeud& nd) + { // recopie des tableaux + tab_0 = nd.tab_0; + tab_ddl = nd.tab_ddl; + tab_tdt = nd.tab_tdt; + num_Mail = nd.num_Mail; +// // liaison éventuelle +// enu_liaison = nd.enu_liaison; +// noeud_lier = nd.noeud_lier; + // puis les variables + num_noeud=nd.num_noeud; + posiAssemb = nd.posiAssemb; + // cas d'une base locale éventuelle + if (nd.baseB != NULL) + {if (baseB != NULL) + { (*baseB) = (*(nd.baseB));} + else + {baseB = new BaseB(*nd.baseB);}; + } + else // cas où nulle + { if (baseB != NULL) delete baseB;} + + if (nd.baseB_t != NULL) + {if (baseB_t != NULL) + { (*baseB_t) = (*(nd.baseB_t));} + else + {baseB_t = new BaseB(*nd.baseB_t);}; + } + else // cas où nulle + { if (baseB_t != NULL) delete baseB_t;} + + if (nd.baseB_0 != NULL) + {if (baseB_0 != NULL) + { (*baseB_0) = (*(nd.baseB_0));} + else + {baseB_0 = new BaseB(*nd.baseB_0);}; + } + else // cas où nulle + { if (baseB_0 != NULL) delete baseB_0;} + + coord2 = NULL; // initialisation + if ( Existe(X1) != 0) + { // on met à null coord0 pour éviter de prendre ses valeurs + coord0 = NULL; + if ( tab_tdt.Taille() != 0) + // cas avec les coordonnees a t+dt + //on effectue la liaison ddl/ deplacement + Liaison_tdt(Existe(X1)); + else + Liaison_t(Existe(X1)); + } + else // cas où il n'y a pas de liaison + {coord0 = new Coordonnee(*(nd.coord0)); + // la taille de coord1 est initialisé à 0 par défaut + }; + tab_var_actives = nd.tab_var_actives;tab_actif = nd.tab_actif; + pos_enum = nd.pos_enum; // mise en place de l'adressage directe + t_enum_s = nd.t_enum_s; // mise en place + // dans le cas où il y a des ddl_etendu + // on recopie les différents tableaux et on met à jour + tab_ddletendu=nd.tab_ddletendu; + update_ddletendu=nd.update_ddletendu; + nbddletendu_update=nd.nbddletendu_update; + // on ne recopie pas le pointeur pos_ddletendu, car se sera dans la méthode MiseAjourDdl_etendu + // qu'il sera mis à jour + MiseAjourDdl_etendu(); + // dans le cas où il y a des grandeurs quelconques (mêmes remarques que dans le cas des enum étendus) + tab_type_quel = nd.tab_type_quel; + update_type_quel = nd.update_type_quel; + nbTypeQ_update = nd.nbTypeQ_update; + MiseAjourTypeQuelconque(); + return (*this); + }; + +// initialisation d'un ou de plusieurs nouveaux cas d'assemblage +void Noeud::InitNouveauCasAssemb(int nb_cas) + { // récup de la taille actuelle + int taille_actuelle = posiAssemb.Taille(); + // nouvelle taille + int nouvelle_taille = taille_actuelle + nb_cas; + // changement de taille, normalement les anciennes valeurs sont gardée + // en début de tableau + posiAssemb.Change_taille(nouvelle_taille); + t_enum_s.Change_taille(nouvelle_taille); + // on initialise les nouveaux éléments -> pour l'instant pointe sur rien + // car c'est la fin de la liste + for (int i= taille_actuelle+1;i<= nouvelle_taille;i++) + t_enum_s(i)=list_tab_posi_actif.end(); + }; + +// enregistrement de l'ordre des variables ddl actives, ceci pour un cas d'assemblage +// donné, cette fonction permet ensuite d'utiliser la fonction +// Position_ddl qui donne la position d'un ddl pour un cas d'assemblage +// donné +void Noeud::Enreg_ordre_variable_ddl_actives(int nb_assemb) + { // l'objectif est de déterminer ou de construire s'il n'existe pas, un tableau + // indexé par les types énumérés des ddl actifs + // le programme est construit sur le même modèle que MiseAjourEnum() + // mais ici on ne s'intéresse qu'au ddl actif + List_io >::iterator& pos_enum_s = t_enum_s(nb_assemb); // pour simplifier + // tout d'abord on regarde si le dernier tableau construit dans la liste + // list_tab_posi_actif, convient, car ce sera le cas pour le cas courant + // le dernier tableau est positionné en début de liste. + List_io >::iterator ideb; + ideb = list_tab_posi_actif.begin(); + List_io >::iterator iancien = pos_enum_s; + int taille = tab_var_actives.Taille(); + // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position + int ttail = (*ideb).Taille(); + bool okk = true; + // le test n'est effectué que si la liste n'est pas vide + if (list_tab_posi_actif.size() != 0) + { // d'abort la taille, on compte le nombre d'élément non nul dans + int ttaile = (*ideb)(ttail); + if (taille != ttaile) + okk = false; + else + // maintenant le contenu + for (int i = 1; i<= taille;i++) + if( (*ideb)(tab_ddl(tab_var_actives(i)).Id_nom()) != i) + { okk = false; break;} + } + else + okk = false; + // si le tableau convient on met à jour le pointeur et c'est fini + // sinon on passe en revu toute la liste + if (okk) + pos_enum_s = ideb; + else // ---- cas où on passe en revue la liste ----- + // ici la procédure est plus longue, mais normalement elle ne sera + // utilisé que peut souvent + { + // on reconstruit un tableau d'adressage indirect des ddl + // la taille du tableau d'adressage est celui du nombre maxi + // de type de ddl différent (donc certain ne serviron pas) + // les données du tableau sont initialisées à 0, ainsi si l'on + // cherche à utiliser un ddl indice 0, l'erreur sera détecté au + // niveau de Tableau_T + // l'avant dernier élément du tableau sert à stocker le nombre de noeud + // qui utilise le tableau + // le dernier élément indique le nombre d'élément non nul + Tableau tab_indi_enum(NbEnum_ddl()+2,0); + for (int i=1;i<=taille;i++) + tab_indi_enum(tab_ddl(tab_var_actives(i)).Id_nom())=i; + // on enregistre la taille + tab_indi_enum(NbEnum_ddl()+2) = taille; + // maintenant on va regarder si ce tableau existe dans la liste + List_io >::iterator ifin = list_tab_posi_actif.end(); + List_io >::iterator iter; + bool trouver = false; + for (iter = ideb;ideb!= ifin;ideb++) + if ((*iter) == tab_indi_enum) + { trouver = true; break;} + // si pas trouver on ajoute sinon on utilise la position déjà existante + if (!trouver) + // cas où on n'a pas trouvé de tableau + { list_tab_posi_actif.push_front(tab_indi_enum); // allocation + // on attribue le nouveau pointage + pos_enum_s = list_tab_posi_actif.begin(); // sauvegarde de la position + } + else // cas où on a trouvé un tableau dans la liste + pos_enum_s = iter; + }; + + // on regarde si pos_enum_s était déjà attribué + if (iancien != list_tab_posi_actif.end()) + // cas où ce n'est pas la première initialisation + {if ((*iancien)(NbEnum_ddl()+1) == 1) + // cas où c'est le dernier noeud qui pointe sur ce tableau + // on supprime le tableau + list_tab_posi_actif.erase(iancien); + else + // sinon on décrémente le compteur + ((*iancien)(NbEnum_ddl()+1))--; + // maintenant on s'occupe du nouveau pointage + ((*pos_enum_s)(NbEnum_ddl()+1))++; + } + else + // c'est la première initialisation + // on incrémente le compteur du tableau + ((*pos_enum_s)(NbEnum_ddl()+1))++; + }; + + +// test si le noeud est complet +// = 1 tout est ok, =0 element incomplet +int Noeud::TestComplet() const + { bool ret=true; + if ((num_noeud == -3) || (num_Mail == -3)) + { if (num_noeud == -3) cout << "\n le numero du noeud n'est pas defini"; + if (num_Mail == -3) cout << "\n le numero de maillage n'est pas defini"; + if (ParaGlob::NiveauImpression() >= 6) this->Affiche(); + ret = false; + } + if (tab_ddl.Taille() == 0) + { cout << "\n ***** warning : il n'y a pas de ddl rattache au noeud " << num_noeud + << ", du maillage " << num_Mail; +// ret = false; + // maintenant normalement ce n'est plus un pb + } + else + { int nbdd = tab_ddl.Taille(); + for (int i=1;i<= nbdd ;i++) + if (tab_ddl(i).TestComplet() == 0) + { cout << "\n probleme avec le ddl " << i << "du noeud " << num_noeud + << ", du maillage " << num_Mail; + ret = false; + }; +// if (posiAssemb.Taille() == 0) return 0; + }; + return ret; + }; + + +// ajout de ddl +// 1) s'il n'y a pas de ddl il y a initialisation +// 2) si les ddl existent deja, on égalise au ddl passé en paramètre +// 3) lorsque le ddl appartient à une famille, tous les ddl de la famille sont +// ajoutées, les ddl supplémentaires ont une valeurs par défaut nulle + +void Noeud::PlusDdl(Ddl& a) + { // on regarde si le tableau des ddl existant est vide + int taille = tab_ddl.Taille(); + if (taille == 0) + { tab_ddl.Change_taille(1); + tab_ddl(1) = a; + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour + MiseAjourEnum(); // mise en place de l'adressage directe + // mise a jour des tableaux et des liaisons ddl/deplacement + MiseAjour(); + } + else + { // on regarde si le Ddl existe + for (int i=1;i<= taille; i++) + // on test uniquement sur l'identificateur du ddl, ces caractéristiques + // pouvant être différents suite à un précédent calcul + if ((tab_ddl(i)).Id_nom() == a.Id_nom()) + { tab_ddl(i) = a; + MiseAjourActif(); + return; + }; + // dans le cas où la dimension est supérieur à 1 et que le ddl appartient + // à une famille dépendant de la dimension, on ajoute tous les ddl de la famille + Enum_ddl enu = a.Id_nom(); + if ((ParaGlob::Dimension()>1)&&FoncDim(enu)) + {// on récupère tous les ddl de la famille + Tableau t_enu =TableauTypeDdl(enu); + // fabrication d'un tableau de ddl associé + int ttaille = t_enu.Taille(); + Tableau t_ddl(ttaille,a);// tous les nouveaux ddl on le même statut que a + for (int il=1;il<=ttaille;il++) + {t_ddl(il).Change_nom(t_enu(il)); + if (t_ddl(il).Id_nom() != enu) + t_ddl(il).Valeur() = 0.; // mise à 0 pour les valeurs des ddl supplémentaires + } + // appel de la méthode gérant un tableau de ddl + PlusTabDdl(t_ddl); + return; + }; + // dans le cas ou la dimension est supérieur à 1 et que les ddl est un XI + // erreur +// if ( (PremierDdlFamille(a.Id_nom())==X1) && (ParaGlob::Dimension() != 1)) +// { cout <<"\n Erreur, la dimension etant superieur a 1 il n'est pas " +// << " possible d'ajouter qu'un seul ddl de position \n"; +// cout << "void Noeud::PlusDdl(Ddl& a)" << endl; +// Sortie (1); +// } + // on regarde s'il y a une incompatibilite Xi Ui + if ((Existe_ici(X1) && (PremierDdlFamille(a.Id_nom())==UX)) || + (Existe_ici(UX) && (PremierDdlFamille(a.Id_nom())==X1)) || + (Existe_ici(UY) && (PremierDdlFamille(a.Id_nom())==X1)) || + (Existe_ici(UZ) && (PremierDdlFamille(a.Id_nom())==X1)) ) + { cout <<"\n Erreur, on ne peut pas avoir de coordonnees entrainees" + << " avec des ddl Ui \n"; + cout << "void Noeud::PlusDdl(Ddl& a)" << endl; + Sortie (1); + }; + // sauvegarde éventuelle des coordonnées + if (coord0 != NULL) // il existe déjà des coordonnées 0 + // si les coordonnees existent deja on les sauvegarde dans une + //instance réelle et non éventuellement pointé + // sera ensuite modifié avec MiseAjour() éventuellement + { Coordonnee truc(*coord0); + delete coord0; + coord0 = new Coordonnee(truc); + }; + int coord1Taille = coord1.Taille(); + Vecteur* toto = NULL; + if (coord1Taille != 0) + // signifie qu'il y a une liaison entre les ddl à t et coord1 + if (coord1(1) != NULL) + // tableau existant et affecte, on cré un tableau + //intermédiaire, qui est supprimé à la fin de la routine + toto = new Vecteur(coord1Taille); + // réécriture dans toto, place qui sera utilisée dans mise à jour + // puis après MiseAjour() suppression de toto + for (int ii=1;ii<=coord1Taille;ii++) + { (*toto)(ii) = *(coord1(ii)); + coord1(ii) = &(*toto)(ii); + }; + if (coord2 != NULL) // il existe déjà des coordonnées finales + // si les coordonnees existent deja on les sauvegarde dans + // une instance réelle et non éventuellement pointé + { Coordonnee truc(*coord2); + delete coord2; + coord2 = new Coordonnee(truc); + }; + // maintenant on peut changer le tableau de ddl + // on augmente la taille du tableau + tab_ddl.Change_taille(taille+1); + tab_ddl(taille+1) = a; + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour + MiseAjourEnum(); // mise en place de l'adressage directe + // mise a jour des tableaux et des liaisons ddl/deplacement + MiseAjour(); + if (toto != NULL) delete toto; + }; + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); + // MiseAjourEnum(); // mise en place de l'adressage directe + }; + +// ajout d'un tableau de ddl +// 1) s'il n'y a pas de ddl il y a initialisation +// 2) si les ddl existent deja, on égalise avec les ddl passés en par +// 3) lorsque un nouveau ddl appartient à une famille, et que tous les ddl de la famille +// ne sont pas présents dans les ddl passés en paramètre, tous les ddl manquant de la famille sont +// ajoutées, avec une valeurs par défaut nulle +void Noeud::PlusTabDdl(Tableau& ta) + { // on commence par ordonner le tableau ta + OrdonnerTableauDdl(ta); + // maintenant tous les ddl de ta sont dans le bonne ordre et à suivre + + // on regarde si le tableau est vide + int taille = tab_ddl.Taille(); + if (taille == 0) + { tab_ddl = ta; + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour + MiseAjourEnum(); // mise en place de l'adressage directe + // mise a jour des tableaux et des liaisons ddl/deplacement + MiseAjour(); + } + else + {// on regarde combien de Ddl existe deja + // et on crée une liste des ddl à ajouter + // les ddl qui existent déjà sont éventuellement updaté + list liDdl; + bool change_donn_var=false; + ListeDdlAajouter(liDdl,ta,change_donn_var); + // on augmente la taille du tableau en consequence + // mais auparavant dans le cas où les coordonnées sont connues + // que sous la forme de valeurs pointées il faut les sauvegarder + if (liDdl.size() == 0) + { // dans le cas où on a aucun ddl a ajouter + // on regarde cependant si il y a eu un changement de type + if (change_donn_var) MiseAjourActif(); + return; + } + else + { // sauvegarde éventuelle des coordonnées + if (coord0 != NULL) // il existe déjà des coordonnées 0 + // si les coordonnees existent deja on les sauvegarde + // dans une instance réelle et non éventuellement pointé + { Coordonnee truc(*coord0); + delete coord0; + coord0 = new Coordonnee(truc); + }; + int coord1Taille = coord1.Taille(); + Vecteur* toto = NULL; + if (coord1Taille != 0) + if (coord1(1) != NULL) + {// tableau existant et affecte, on crée un tableau intermédiaire, + // qui est supprimé à la fin de la routine + toto = new Vecteur(coord1Taille); + // réécriture dans toto, place qui sera utilisée dans mise à jour + // puis après MiseAjour() suppression de toto + for (int ii=1;ii<=coord1Taille;ii++) + { (*toto)(ii) = *(coord1(ii)); + coord1(ii) = &(*toto)(ii); + }; + }; + if (coord2 != NULL) // il existe déjà des coordonnées finales + // si les coordonnees existent deja on les sauvegarde dans + // une instance réelle et non éventuellement pointé + { Coordonnee truc(*coord2); + delete coord2; + coord2 = new Coordonnee(truc); + }; + // maintenant on peut changer le tableau de ddl + int nbddl_a_ajouter=liDdl.size(); + tab_ddl.Change_taille(taille+nbddl_a_ajouter); + // on rempli le tableau + list ::iterator il=liDdl.begin(); + for (int j1=1;j1<= nbddl_a_ajouter;j1++,il++) + { tab_ddl(taille+j1)=(*il);}; + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour par exemple + MiseAjourEnum(); // mise en place de l'adressage directe + // on regarde s'il y a une incompatibilite Xi Ui + int tab_ddlTaille = tab_ddl.Taille(); + if (Existe_ici(X1)) + for (int i=1;i<= tab_ddlTaille;i++) + if (Meme_famille(tab_ddl(i).Id_nom(),UX)) + { cout <<"\n Erreur, on ne peut pas avoir de coordonnees entrainees" + << " avec des ddl Ui \n"; + cout << "void Noeud::PlusTabDdl(Tableau& ta)" << endl; + Sortie (1); + }; + // mise a jour des tableaux et des liaisons ddl/deplacement + MiseAjour(); + if (toto != NULL) delete toto; + }; + }; + // mise a jour des ddl actifs et de l'adressage via l'énumération des ddl + MiseAjourActif(); +// MiseAjourEnum(); // mise en place de l'adressage directe + }; + + +// ajout du tableau de ddl d'un autre noeud +void Noeud::PlusTabDdl(const Noeud & noe) + { // on récupère le tableau de ddl géné par noe + Tableau ta = noe.tab_ddl; + if (ta.Taille() != 0) + Noeud::PlusTabDdl(ta); + }; + +// modification du statut d'un ddl +// si en est inconnu, aucune action +void Noeud::Met_hors_service(Enum_ddl en) + { tab_ddl(Existe(en)).Met_hors_service(); + MiseAjourActif(); + }; + +void Noeud::Met_en_service(Enum_ddl en) + { tab_ddl(Existe(en)).Met_en_service(); + MiseAjourActif(); + }; + +// modification du statut d'un tableau de ddl +// si un des elements du tableau est inconnu, aucune action +void Noeud::Met_hors_service(const Tableau& taben) + { int tabenTaille = taben.Taille(); + for (int i = 1; i<=tabenTaille; i++) + tab_ddl(Existe(taben(i))).Met_hors_service(); + MiseAjourActif(); + }; + +void Noeud::Met_en_service(const Tableau& taben) + { int tabenTaille = taben.Taille(); + for (int i = 1; i<=tabenTaille; i++) + tab_ddl(Existe(taben(i))).Met_en_service(); + MiseAjourActif(); + }; + +// modification du statut de tous les ddl actuellements présent +// y compris les données +// si un des elements du tableau est inconnu, aucune action +void Noeud::Met_hors_service() + { int tab_ddlTaille = tab_ddl.Taille(); + for (int i = 1; i<=tab_ddlTaille; i++) + tab_ddl(i).Met_hors_service(); + MiseAjourActif(); + }; + +void Noeud::Met_en_service() +// y compris les données + { int tab_ddlTaille = tab_ddl.Taille(); + for (int i = 1; i<=tab_ddlTaille; i++) + tab_ddl(i).Met_en_service(); + MiseAjourActif(); + }; +// modification du statut de tous les ddl actuellements présent +// sauf les données qui ne sont pas modifiées +// si un des elements du tableau est inconnu, aucune action +void Noeud::Met_hors_service_ddl() + { int tab_ddlTaille = tab_ddl.Taille(); + for (int i = 1; i<=tab_ddlTaille; i++) + tab_ddl(i).Met_hors_service_ddl(); + MiseAjourActif(); + }; + +void Noeud::Met_en_service_ddl() +// y compris les données + { int tab_ddlTaille = tab_ddl.Taille(); + for (int i = 1; i<=tab_ddlTaille; i++) + tab_ddl(i).Met_en_service_ddl(); + MiseAjourActif(); + }; + +// changement du statut de variable à donnée pour un tableau d'enum de ddl +void Noeud::ChangeVariable_a_Donnee(const Tableau& taben) + { int tabenTaille = taben.Taille(); + for (int i = 1; i<=tabenTaille; i++) + tab_ddl(Existe(taben(i))).ChangeVariable_a_Donnee(); + MiseAjourActif(); + }; + +// changement du statut de donnée à variable pour un tableau d'enum de ddl +void Noeud::ChangeDonnee_a_Variable(const Tableau& taben) + { int tabenTaille = taben.Taille(); + for (int i = 1; i<=tabenTaille; i++) + tab_ddl(Existe(taben(i))).ChangeVariable_a_Donnee(); + MiseAjourActif(); + }; + +// changement de toutes les conditions données (service, variable, fixage ..) +// selon le tableau de ddl passé en paramètre +// par contre la valeur n'est pas utilisé donc la valeur actuelle reste inchangé +void Noeud::ChangeToutesLesConditions(const Tableau& ta) + { int taTaille = ta.Taille(); + for (int i = 1; i<=taTaille; i++) + { tab_ddl(Existe(ta(i).Id_nom())).CopieToutesLesConditions(ta(i).Retour_Fixe());}; + MiseAjourActif(); + }; + +// changement de statu des ddl d'une combinaison, (cf. Enum_ddl) +// les ddl de la combinaison, prennent le même statut que celui +// actuellement stocké, correspondant à enuta +// cas est la combinaison, +void Noeud::ChangeStatut(int cas,Enum_ddl enuta) + { // on récupère tous les membres de la combinaison + Tableau tenu= Combinaison(cas); + int tenuTaille = tenu.Taille(); + Enum_boolddl enubold=tab_ddl(Existe(enuta)).Retour_Fixe(); + for (int i = 1; i<=tenuTaille; i++) + { tab_ddl(Existe(tenu(i))).CopieToutesLesConditions(enubold);}; + MiseAjourActif(); + }; + +// changement de statu des ddl d'une combinaison, (cf. Enum_ddl) +// les ddl de la combinaison, prennent le même statut que celui de enubold +// cas est la combinaison, +void Noeud::ChangeStatut(int cas,Enum_boolddl enubold) + { // on récupère tous les membres de la combinaison + Tableau tenu= Combinaison(cas); + int tenuTaille = tenu.Taille(); + for (int i = 1; i<=tenuTaille; i++) + { tab_ddl(Existe(tenu(i))).CopieToutesLesConditions(enubold);}; + MiseAjourActif(); + }; + +/*// retourne le numero du ddl recherche identifie par en, +// s'il existe sinon 0 +int Noeud::Existe(const Enum_ddl en) + { int tab_ddl_Taille = tab_ddl.Taille(); + // on commence par tester a partir de la derniere position sauvegardee + for (short int i=(short)(posiddl);i<= tab_ddl_Taille;i++) + if (en == tab_ddl(i).Id_nom()) + { posiddl=i; return i; } + // on continue la recherche a partir du debut + for (short int i=1;i< posiddl;i++) + if (en == tab_ddl(i).Id_nom()) + { posiddl=i; return i; } + // sinon retour 0 + return 0; + }; */ + +// indique que l'on va utiliser les ddl en 0, t et tdt +// les grandeurs en tdt sont cree s'ils n'existent pas +// et initialisees par defaut +void Noeud::Travail_tdt() + { if (tab_tdt.Taille() == 0) + tab_tdt.Change_taille(tab_ddl.Taille()); + // les grandeurs à tdt peuvent changer des coordonnées vers + // autre chose, pour cela on commence par les supprimer, ensuite + // dans la procédure MiseAjour() elles sont recréées si besoin est + // a partir du tableau de tab_tdt + if (coord2 != NULL) delete coord2; + coord2 = NULL; + MiseAjour(); + }; + +// indique que l'on va utiliser les ddl en 0, t +// si les grandeurs en tdt existaient, elles sont supprimées +void Noeud::Travail_t() + { if (tab_tdt.Taille() != 0) + { tab_tdt.Libere(); + if (coord2 != NULL) delete coord2; + coord2 = NULL; + } + MiseAjour(); + }; + +// mise a zero de tous les variables ddl actives +// sauf dans le cas de coordonnees entrainees. dans ce dernier +// cas les coordonnees correspondants a Xi pour t et t+dt +// sont mis a la valeur de celles de t=0 +// a moins que le paramètre booléen est mis à false, +// dans ce cas les coordonnées à t sont inchangées +void Noeud::ZeroVariablesDdl(bool cas) + { int nbactif = tab_var_actives.Taille(); + for (int j=1; j<= nbactif; j++) + {int i = tab_var_actives(j); + if (((tab_ddl(i)).Nom())[0] != 'X') + { tab_ddl(i).Valeur() = 0.; + tab_0(i) = 0.; + } + else // cas de coordonnees entrainees + if (cas) + tab_ddl(i).Valeur() = tab_0(i); + }; + if (tab_tdt.Taille() != 0) + // cas de l'utilisation du tableau a tdt + for (int j1=1; j1<= nbactif; j1++) + {int ii = tab_var_actives(j1); + if (((tab_ddl(ii)).Nom())[0] != 'X') + tab_tdt(ii) = 0.; + else + tab_tdt(ii) = tab_0(ii); + }; + }; + +// actualisation des ddl actifs (variable et donnee) de t+dt vers t +void Noeud::TdtversT() + { int nbactif = tab_actif.Taille(); + for (int j=1; j<= nbactif; j++) + {int i = tab_actif(j); + tab_ddl(i).Valeur() = tab_tdt(i); + }; + // cas d'une base locale + if (baseB != NULL) + {(*baseB_t) = (*baseB);} + + }; + +// actualisation des ddl actifs (variables et donnees) de t vers t+dt +void Noeud::TversTdt() + { int nbactif = tab_actif.Taille(); + for (int j=1; j<= nbactif; j++) + {int i = tab_actif(j); + tab_tdt(i)= tab_ddl(i).Valeur(); + }; + // cas d'une base locale + if (baseB != NULL) + {(*baseB) = (*baseB_t);} + + }; + + +// retourne dans le vecteur d'entrée les réels représentant les contraintes +// si les degrés de liberté contrainte existent +// sinon retourne false, en ne modifiant pas l'entrée +bool Noeud::Contrainte(Vecteur& Sig) + { int position = Existe(SIG11); + int l_sigma; // dimension des contraintes + // test pour l'existence des ddl de sigma + if ( position != 0) + { l_sigma = 1 ; // c'est au moins un tenseur d'ordre 1 + if (Existe(SIG22) != 0) + { l_sigma = 3 ; // c'est au moins un tenseur d'ordre 2 + // donc trois coordonnées + if (Existe(SIG33) != 0) + l_sigma = 6 ; // c'est un tenseur d'ordre 3 + // donc 6 coordonnées + }; + if (Sig.Taille() != l_sigma) Sig.Change_taille(l_sigma); + int fin = position + l_sigma-1; int j = 1; + for (int i=position;i<= fin; i++,j++) + Sig(j) = tab_ddl(i).Valeur(); + return true; + } + else + return false; // pas de contrainte + + }; + +// retourne dans le tenseur d'entrée les réels représentant les contraintes +// si les degrés de liberté contrainte existent +// sinon retourne l'entrée sans modification +// le tenseur est choisit mixte pour représenter tous les cas +// !!! important : le tenseur Sig doit avoir la bonne dimension +// en entrée, car il n'est pas redimensionné dans la méthode +TenseurHB& Noeud::Contrainte(TenseurHB& Sig) + { int position = Existe(SIG11); + if (position == 0) return Sig; // cas où il n'y a pas de contrainte + // ----- sinon on remplit les composantes du tenseur ------ + int l_sigma = Sig.Dimension(); // dimension des contraintes + #ifdef MISE_AU_POINT // vérif des dimensions pour le debug + // comme position n'est pas nulle la dimension dans les ddl est au moins 1 + int dimm = 1; + if (Existe(SIG22) != 0) + { dimm = 2 ; // c'est au moins un tenseur d'ordre 2 + if (Existe(SIG33) != 0) + dimm = 3 ; // c'est un tenseur d'ordre 3 + }; + if (l_sigma != dimm) + { cout << "\nErreur : dimensions du tenseur d'entrée incorrecte Sig = " << dimm << " !\n"; + cout << " Noeud::Contrainte(TenseurHB& Sig)\n"; + Sortie(1); + }; + #endif + switch (l_sigma) + { case 1 : // cas à une dimension + Sig.Coor(1,1) = tab_ddl(position).Valeur(); + break; + case 2 : // cas à 2 dimension + Sig.Coor(1,1) = tab_ddl(position).Valeur(); + Sig.Coor(2,2) = tab_ddl(position+1).Valeur(); + Sig.Coor(1,2) = tab_ddl(position+2).Valeur(); + Sig.Coor(2,1) = tab_ddl(position+2).Valeur(); + break; + case 3 : // cas à 3 dimension + Sig.Coor(1,1) = tab_ddl(position).Valeur(); + Sig.Coor(2,2) = tab_ddl(position+1).Valeur(); + Sig.Coor(3,3) = tab_ddl(position+2).Valeur(); + Sig.Coor(1,2) = tab_ddl(position+3).Valeur();Sig.Coor(2,1) = Sig(1,2); + Sig.Coor(2,3) = tab_ddl(position+4).Valeur();Sig.Coor(3,2) = Sig(2,3); + Sig.Coor(1,3) = tab_ddl(position+5).Valeur();Sig.Coor(3,1) = Sig(1,3); + break; + default : + { cout <<"\n Erreur, la dimension du tenseur Sig n'est pas correcte "; + cout << "Noeud::Contrainte(TenseurHB& Sig)" << endl; + Sortie (1); + } + }; + return Sig; + }; + +// lecture sur le flot d'entée de déplacement +// et mise à jour des positions à t et t+dt correspondantes +void Noeud::LectureDeplacements(UtilLecture *entreePrinc) + { // récup de la dimension + // définition du déplacement + Coordonnee dep = *coord0; + // lecture brut des coordonnées du déplacement sans la dimension + dep.Lecture(*entreePrinc); + // on ajoute aux coordonnées initiales pour avoir celles à t + dep += (*coord0); + // on insert les coordonnées à t qui sont créées si elles n'existent pas + // elles ont le statut inactif par défaut + Insert_coord1(dep); + }; + +//----- lecture écriture dans base info ----- +// cas donne le niveau de la récupération +// = 1 : on récupère tout +// = 2 : on récupère uniquement les données variables (supposées comme telles) +// ( ici on ne redimentionne pas, +// cela signifie que le nombre de ddl augmente mais ne diminue pas !!) + + +void Noeud::Lecture_base_info(ifstream& ent,int cas) + { // traitement en fonction du cas + switch (cas) + { case 1 : // ------- on récupère tout ------------------------- + { ent >> (*this) ; + break; + } + case 2 : // ----------- récup uniquement de se qui varie -------------------- + { // ici se sont les degrés de liberté + string toto;int nb; + ent >> toto >> nb; + #ifdef MISE_AU_POINT // vérification du numéro + if (nb != num_noeud ) + { cout << "\nErreur : numero de noeud lu : " << nb + << " au lieu de " << num_noeud << " \n";; + cout << " Noeud::Lecture_base_info"; + Sortie(1); + }; + #endif + /* // ici on ne redimentionne pas, + /// // cela signifie que le nombre de ddl augmente mais ne diminue pas ! + /// Tableau * pt_tableau = tab_ddl.New_en_lecture_si_taille_superieur_a_lire(ent); + /// // on regarde si le tableau a été redimensionné + /// if (pt_tableau != NULL) + /// // cas d'une redimension on ajoute les ddl + /// PlusTabDdl(*pt_tableau); */ + + // le code précédent pose des pb lorsque les ddl à lire sont différents de ceux existants + // donc systématiquement, on en crée des nouveaux et on met à jour + Tableau tableau; + tableau.Entree(ent); + // on ajoute les ddl + PlusTabDdl(tableau); + + // on recopie les valeurs à t + int taille_tabddl=tab_ddl.Taille(); + + // en fait ce n'est pas la peine, ça a été fait dans PlusTabDdl !! + + // cas de valeur à tdt + if (tab_tdt.Taille() != 0) + {for (int i=1;i<=taille_tabddl;i++) + tab_tdt(i) = tab_ddl(i).Valeur(); + }; + + // cas d'une base locale éventuelle + {int existe_base; + ent >> existe_base >> toto; + if (existe_base == 1) + {if (baseB == NULL) {baseB=new BaseB();}; + ent >> toto >> (*baseB); + // dans le cas où la grandeur à t n'existe pas + // on l'a crée et on lui donne la valeur de tdt + // sinon on fait une affectation, pour redémarrer avec quelque chose de correcte à t + if (baseB_t == NULL) + {baseB_t=new BaseB(*baseB);} + else // sinon on affecte + {(*baseB_t) = (*baseB);}; + // cas à 0 + if (baseB_0 == NULL) + {baseB_0=new BaseB(*baseB);}; + // sinon on ne fait rien car la base est sensée avoir été correctement + // définit au départ + }; + + }; + + break; + } + default : + { cout << "\nErreur : valeur incorrecte du type d'écriture !\n"; + cout << "Noeud::Ecriture_base_info(ofstream& sort,int cas)" + << " cas= " << cas << endl; + Sortie(1); + } + } + }; + +// cas donne le niveau de sauvegarde +// = 1 : on sauvegarde tout +// = 2 : on sauvegarde uniquement les données variables (supposées comme telles) +void Noeud::Ecriture_base_info(ofstream& sort,int cas) + { // traitement en fonction du cas + switch (cas) + { case 1 : // ------- on sauvegarde tout ------------------------- + { sort << (*this) << "\n"; + break; + } + case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- + { // ici se sont les degrés de liberté + sort << "Noeud " << num_noeud << " "; + sort << tab_ddl ; + if (baseB != NULL) + {sort << " 1 baseLoc: " << (*baseB);} + else {sort << " 0 baseLoc: "; }; + + sort << "\n"; + + break; + } + default : + { cout << "\nErreur : valeur incorrecte du type d'écriture !\n"; + cout << "Noeud::Ecriture_base_info(ofstream& sort,int cas)" + << " cas= " << cas << endl; + Sortie(1); + } + }; + // pour l'instant on ne sauvegarde pas les ddl_étendu et les type_quelconque car on considère + // que ce sont des résultats et non pas des données indispensables. + // idem pour enu_liaison et noeud_lier, qui sont liées aux conditions limites + // A priori, c'est infos sont reconstruites + // à chaque démarrage + +}; + diff --git a/Maillage/Noeud.h b/Maillage/Noeud.h new file mode 100644 index 0000000..62a3f17 --- /dev/null +++ b/Maillage/Noeud.h @@ -0,0 +1,860 @@ +// FICHIER : Noeud.h +// CLASSE : Noeud + +// 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: . + +/************************************************************************ +* DATE: 23/01/97 * +* $ * +* AUTEUR: G RIO (mailto:gerardrio56@free.fr) * +* $ * +* PROJET: Herezh++ * +* $ * +************************************************************************ +* Une instance de la classe Noeud est definie a partir d'un numero d'identification +* et du tableau de connexite des degres de liberte lies au noeud. Trois instances +* de la classe Coordonnee sont aussi associes a la classe Noeud (coordonnees initiales, +* aux instants t et t+dt). +* $ * +* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * +* VERIFICATION: * +* * +* ! date ! auteur ! but ! * +* ------------------------------------------------------------ * +* ! ! ! ! * +* $ * +* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * +* MODIFICATIONS: * +* ! date ! auteur ! but ! * +* ------------------------------------------------------------ * +* $ * +************************************************************************/ + +// Une instance de la classe Noeud est definie a partir d'un numero d'identification +// et du tableau de connexite des degres de liberte lies au noeud. Trois instances +// de la classe Coordonnee sont aussi associes a la classe Noeud (coordonnees initiales, +// aux instants t et t+dt). + + +#ifndef NOEUD_H +#define NOEUD_H + + +#include + + +#include "Coordonnee.h" +#include "Ddl.h" +#include "Tableau_T.h" +#include "ParaGlob.h" +#include "Vecteur.h" +#include "Tenseur.h" +#include "List_io.h" +#include "EnumTypeGrandeur.h" +#include "MathUtil.h" +#include "TypeQuelconque.h" +#include "Ddl_etendu.h" +#include "Enum_liaison_noeud.h" + + +/// @addtogroup Les_Maillages +/// @{ +/// + +//------------------------------------------------------------------ +//! Posi_ddl_noeud: un conteneur qui associe numéro de noeud, de maillage, et enu ddl +//------------------------------------------------------------------ +/// \author Gérard Rio +/// \version 1.0 +/// \date 23/01/97 + + + // --------- class de stockage ----- + class Posi_ddl_noeud + { // surcharge lecture écriture + friend istream & operator >> (istream &, Posi_ddl_noeud &); + friend ostream & operator << (ostream &, const Posi_ddl_noeud &); + public : + // constructeurs + Posi_ddl_noeud () : nb_maillage(-1),nb_noeud(-1),enu(NU_DDL) {}; + Posi_ddl_noeud (int aa, Enum_ddl enuu,int bb) : + nb_maillage(aa),nb_noeud(bb),enu(enuu) {}; + Posi_ddl_noeud (const Posi_ddl_noeud & a): + nb_maillage(a.nb_maillage),nb_noeud(a.nb_noeud),enu(a.enu) {}; + // opérateur + Posi_ddl_noeud& operator = ( const Posi_ddl_noeud & a) + {nb_maillage=a.nb_maillage;nb_noeud=a.nb_noeud;enu=a.enu; return *this;}; + bool operator == ( const Posi_ddl_noeud & a) + { if((nb_maillage==a.nb_maillage) && (nb_noeud==a.nb_noeud) + && (enu==a.enu)) return true; else return false; }; + bool operator != ( const Posi_ddl_noeud & a) + { if((*this) == a) return false; else return true; }; + // Affiche les donnees liees au noeud + void Affiche (ofstream& sort) const; + // récup des données en lecture écriture + int& Nb_maillage() {return nb_maillage;}; + int& Nb_noeud() {return nb_noeud;}; + Enum_ddl& Enu() {return enu;}; + // récup des données en lecture uniquement + const int& Const_Nb_maillage() const {return nb_maillage;}; + const int& Const_Nb_noeud() const {return nb_noeud;}; + const Enum_ddl& Const_Enu() const {return enu;}; + + protected: + // données + int nb_maillage; // le numéro du maillage + int nb_noeud; // le numéro du noeud + Enum_ddl enu; // l'identifieur du ddl + }; +/// @} // end of group + + +/// @addtogroup Les_Maillages +/// @{ +/// + +//------------------------------------------------------------------ +//! Noeud: un noeud +//------------------------------------------------------------------ +/// \author Gérard Rio +/// \version 1.0 +/// \date 23/01/97 + + +class Noeud +{ + // surcharge de l'operator de lecture, avec typage + friend istream & operator >> (istream &, Noeud &); + // surcharge de l'operator d'ecriture avec typage + friend ostream & operator << (ostream &, const Noeud &); + + public : + + + // CONSTRUCTEURS : + + // IMPORTANT!!! : l'ordre de succession des ddl doit etre conforme + // aux infos de l'enumeration (cf enum_ddl) + + // Constructeur par defaut + Noeud (int num_id=-3,int num_maill=0); + + // Constructeur fonction d'un numero d'identification et de la + // dimension de l'espace du probleme et du nb de maillage + Noeud (int num_id,int dimension,int num_maill); + + // Constructeur fonction d'un numero d'identification et des coordonnees + // initiales et du nb de maillage + Noeud (int num_id,const Coordonnee& c0,int num_Mail); + + // Constructeur fonction d'un numero d'identification, des coordonnees + // initiales et du tableau des degres de liberte, et du nb de maillage + // les ddl t=0 et t sont initialises avec les valeurs du tableaux + // par defaut les tableaux de ddl a 0 et t sont initialises mais pas + // a t+dt, + Noeud (int num_id,const Coordonnee& c0,const Tableau& tab,int num_Mail); + + // Constructeur fonction d'un numero d'identification, des coordonnees + // initiales, a un instant t, et du tableau des degres de liberte, et du nb de maillage + // les ddl t=0 sont initialises avec les valeurs du tableaux + // par defaut les tableaux de ddl a 0 et t sont initialises mais pas + // a t+dt + // les ddl corespondant a Xi sont ajoute s'ils n'existaient pas + Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Tableau& tab,int num_Mail); + + // Constructeur fonction d'un numero d'identification, de trois instances + // de Coordonnee et du tableau des degres de liberte, et du nb de maillage + Noeud (int num_id,const Coordonnee& c0,const Coordonnee& c1,const Coordonnee& c2, + const Tableau& tab,int num_Mail); + + // Constructeur de copie + Noeud (const Noeud& nd); + + + // DESTRUCTEUR : + ~Noeud (); + + + // METHODES : + + // Affiche à l'ecran les donnees liees au noeud + // le niveau différent de 0 permet d'accèder à plus d'info + void Affiche(int niveau=0) const; + // Affiche dans sort les donnees liees au noeud + void Affiche(ofstream& sort) const; + + inline void Change_num_noeud(int nouveau_num) + // Modifie le numero d'identification du noeud + // ATTENTION : Les modifications liees au changement de numero du noeud + // sont a la charge de l'utilisateur. + { num_noeud=nouveau_num; }; + + inline void Change_num_Mail(int nouveau_num) + // Modifie le numero de maillage du noeud + { num_Mail=nouveau_num; }; + + // récup du type de liaison entre noeud éventuel + // pour le cas d'assemblage nb_assemb + inline Enum_liaison_noeud Enu_liaison(int nb_assemb) const + {if (tab_enu_liaison != NULL) return (*tab_enu_liaison)(nb_assemb); + else return PAS_LIER;}; + + // récup d'un pointeur de tableau des ddl affectés par une liaison entre noeud + // pour le cas d'assemblage nb_assemb, NULL s'il n'y en a pas + inline const Tableau * Ddl_Noeud_lier(int nb_assemb) const + {if (tab_ddl_lier != NULL) return &((*tab_ddl_lier)(nb_assemb)); + else return NULL; }; + // modification du type de laison entre noeud éventuel avec init des tableaux de liaison + // pour le cas d'assemblage nb_assemb + void Change_Enu_liason(int nb_assemb, Enum_liaison_noeud enu_liai + ,const Tableau & tab__lier); + // suppression de tous les liaisons noeuds + void Suppression_tous_liaisons_noeuds(); + + // Modifie les valeurs des coordonnees coord0 + inline void Change_coord0(const Coordonnee& nouveau_coord0) + { *coord0=nouveau_coord0;}; + + // insert des coordonnees coord1 si elles n'existent pas encore + // permet de définir des coordonnées à t, dans ce cas des ddl XI sont inclus + // et sont mis inactif par défaut + void Insert_coord1(const Coordonnee& nouveau_coord1); + // idem mais sans paramètre indique que l'on initialise aux coordonnées à t=0 + // s'ils n'existent pas sinon on ne fait rien + void Insert_coord1(); + + // Modifie les valeurs des coordonnees coord1 + void Change_coord1(const Coordonnee& nouveau_coord1); + + + // Modifie les valeurs des coordonnees coord2 + inline void Change_coord2(const Coordonnee& nouveau_coord2) + { *coord2=nouveau_coord2; }; + + + // Modifie les valeurs des coordonnees coord2 par l'ajout d'un delta + inline void Ajout_coord2(const Coordonnee& delta_coord2) + { *coord2=*coord2+delta_coord2; }; + + + inline const Coordonnee& Coord0() const + // Retourne les coordonnees initiales du noeud + { return *coord0; }; + + // test si les coordonnées à t=0 existent + inline bool ExisteCoord0() const + { if (coord0 == NULL) return false; else return true;}; + + // Retourne les coordonnees coord1 du noeud + // uniquement pour la lecture + inline Coordonnee Coord1() const + { int nbcoo = coord1.Taille(); + Coordonnee coo(nbcoo); + for (int i=1;i<=nbcoo;i++) + coo(i) = *(coord1(i)); + return coo; + }; + + // test si les coordonnées à t existent + inline bool ExisteCoord1() const + { if (coord1.Taille() == 0) return false; else return true;}; + + // Retourne les coordonnees coord2 du noeud + inline const Coordonnee& Coord2() const + { return *coord2; }; + + // retourne la valeur absolu du maximum de variation de coordonnée entre t et tdt + inline double Max_var_coor_t_a_tdt() const + { double ret=0.; + if (ExisteCoord2() && ExisteCoord1()) + {int nbcoo=coord2->Dimension(); + for (int i=1;i<=nbcoo;i++) ret = MaX(Dabs((*coord2)(i) - *(coord1(i))),ret); + }; + // sinon cela veut dire que le maillage n'a pas bougé (cas d'un solide fixe) + return ret; + }; + + // test si les coordonnées à tdt existent + inline bool ExisteCoord2() const + { if (coord2 == NULL) return false; else return true;}; + + // Retourne le nombre de tous les degres de liberte du noeud + // qu'ils soient actifs ou non, fixes ou non + inline int Nombre_ddl() const + { return tab_ddl.Taille(); }; + + // Retourne le nombre de variables degres de liberte du noeud + // qui sont actuellement actives + inline int Nombre_var_ddl_actives() const + { return tab_var_actives.Taille();}; + + // Retourne le nombre de variables degres de liberte du noeud + // qui sont actives pour un cas d'assemblage donné. + // (ces ddl peuvent ne pas être actuellement actif !!) + inline int NB_ddl_actif_casAssemb (int nb_assemb) const + { Tableau & tib = (*t_enum_s(nb_assemb)); + return (tib(tib.Taille()));}; + + // ramene le nombre de variables ddl actives pour un type de ddl donné, + // c'est-à-dire 1 ou la dimension, suivant que le type dépend + // ou pas de la dimension + int Nombre_var_ddl_actives (Enum_ddl en) const ; + + // retourne la liste de tous les types de ddl actuellement utilisé + // par le noeud (actif ou non) + // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière + List_io Les_type_de_ddl(bool absolue); + // retourne la liste de tous les Ddl_enum_etendu disponibles + List_io Les_type_de_ddl_etendu(bool absolue); + // retourne la liste de tous les TypeQuelconque disponibles + List_io Les_TypeQuelconque(bool absolue); + + // récupération d'une liste d'info + // le tableau de retour à la taille de li_enu_scal et contient + // les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud + // en fait ici on cumule les ddl pur "et" les ddl_étendue, + // li_quelc : est modifié par les valeurs contenues au noeud + Tableau Valeur_multi_et_Tensorielle + (const List_io & li_enu_scal,List_io & li_quelc) const; + + // Retourne le numero d'identification du noeud + inline int Num_noeud() const + { return num_noeud; }; + + // Retourne le numero de maillage auquel appartiend le noeud + inline int Num_Mail() const + { return num_Mail; }; + + // Retourne la dimension des coordonnées + inline int Dimension() const + { return coord0->Dimension(); }; + + // surcharge de l'affectation entre deux noeuds + // attention, le pointeur d'assemblage de this est identique a celui de n + // il faut donc l'updater pour pouvoir l'utiliser!! + Noeud& operator= (const Noeud& n); + + // acces en lecture au pointeur de position pour l'assemblage + // i : donne le numéro du cas d'assemblage associé + inline int PosiAssemb(int i ) const + { return posiAssemb(i);}; + + // initialisation d'un ou de plusieurs nouveau cas d'assemblage + void InitNouveauCasAssemb(int nb_cas); + + // enregistrement de l'ordre des variables ddl actives, ceci pour un cas d'assemblage + // donné, cette fonction permet ensuite d'utiliser la fonction + // Position_ddl qui donne la position d'un ddl pour un cas d'assemblage + // donné + void Enreg_ordre_variable_ddl_actives(int nb_assemb); + + // position d'un ddl par rapport à un cas d'assemblage donné (de 1 à ..) + // il n'y a pas de vérification que le ddl en question est actif ou pas + // cette fonction ne peut être utilisé, que après l'utilisation + // de la fonction Enreg_ordre_variable_ddl_actives + // si l'énuméré n'existe pas dans la liste des ddl actif du cas d'assemblage + // on retourne -1 + inline int Position_ddl(Enum_ddl enu, int nb_assemb) const + { int pointe = (*(t_enum_s(nb_assemb)))(enu); + if (pointe == 0) return -1; else return pointe; } + + // modification du pointeur de position du noeud pour l'assemblage + // i : donne le numéro du cas d'assemblage associé + inline void ChangePosiAssemb(int a,int i ) + { posiAssemb(i) = a;}; + + // ramène le pointeur d'assemblage pour un ddl donné, et un cas d'assemblage + // le résultat correspond à la position globale d'assemblage du noeud + + // la position du ddl dans la liste des ddl actifs du cas d'assemblage + // si l'énuméré ne correspond pas à un ddl actif du cas d'assemblage + // on retourne -1, dans le cas ok, c'est un nombre de 1 à ... + inline int Pointeur_assemblage(Enum_ddl enu, int nb_assemb) const + { int pointe = (*(t_enum_s(nb_assemb)))(enu); + if (pointe == 0) return -1; + return pointe + posiAssemb(nb_assemb); }; + + // le noeud peut contenir éventuellement une base rattachée + // récupération de la base, si le pointeur en retour est null + // cela signifie que la base n'existe pas + // a) en constant, la base actuelle + const BaseB* Const_BaseB_Noeud() const {return baseB;}; + // b) en constant, la base à t + const BaseB* Const_BaseB_Noeud_t() const {return baseB_t;}; + // c) en constant, la base initiale + const BaseB* Const_BaseB_Noeud_0() const {return baseB_0;}; + + // d) en lecture écriture, la base actuelle + BaseB* BaseB_Noeud() const {return baseB;}; + // e) en lecture écriture, la base à t + BaseB* BaseB_Noeud_t() const {return baseB_t;}; + // f) en lecture écriture, la base à 0 + BaseB* BaseB_Noeud_0() const {return baseB_0;}; + + // test si le noeud est complet + // = 1 tout est ok, =0 element incomplet + int TestComplet() const; + + // ajout de ddl + // 1) s'il n'y a pas de ddl il y a initialisation + // 2) si les ddl existent deja, on l'égalise au ddl passé en para + // 3) lorsque le ddl appartient à une famille, tous les ddl de la famille sont + // ajoutées, les ddl supplémentaires ont une valeurs par défaut nulle + void PlusDdl(Ddl& a); + + // ajout d'un tableau de ddl + // 1) s'il n'y a pas de ddl il y a initialisation + // 2) si les ddl existent deja, on égalise avec les ddl passés en par + // 3) lorsque un nouveau ddl appartient à une famille, et que tous les ddl de la famille + // ne sont pas présents dans les ddl passés en paramètre, tous les ddl manquant de la famille sont + // ajoutées, avec une valeurs par défaut nulle + void PlusTabDdl(Tableau& ta); + + // ajout du tableau de ddl d'un autre noeud + void PlusTabDdl(const Noeud & noe); + + // modification du blocage ou non d'un ddl + inline void Change_fixe(Enum_ddl en,bool val) + { tab_ddl((*pos_enum)(en)).Change_fixe(val); }; + inline void Change_fixe(int nb,bool val) + { tab_ddl(nb).Change_fixe(val); }; + // test pour savoir si le ddl est fixé ou pas + inline bool Ddl_fixe(Enum_ddl en) const + { return tab_ddl((*pos_enum)(en)).Fixe();}; + // test pour savoir si le ddl est SURFIXE ou SOUSLIBRE + // (c-a-d plusieurs fois fixé ou libre à la suite) + inline bool Ddl_sous_ou_sur_fixe(Enum_ddl en) const + { return tab_ddl((*pos_enum)(en)).SousSurFixe();}; + // remise à normal si le ddl est en souslibre ou surfixe + // s'il est en souslibre il passe en libre et s'il est en surfixe il passe en fixe + inline void Retour_a_la_normal_sur_ou_sous_fixe(Enum_ddl en) + { tab_ddl((*pos_enum)(en)).Retour_normal_sur_ou_sous_fixe();}; + + // modification du statut d'un ddl + // si est inconnu, aucune action + void Met_hors_service(Enum_ddl en); + void Met_en_service(Enum_ddl en); + // modification du statut d'un tableau de ddl + // si un des elements du tableau est inconnu, aucune action + void Met_hors_service(const Tableau& taben); + void Met_en_service(const Tableau& taben); + // modification du statut de tous les ddl actuellements présent + // y compris les données + // si un des elements du tableau est inconnu, aucune action + void Met_hors_service(); + void Met_en_service(); + // idem mais restreint uniquement aux ddl (pas les données) + void Met_hors_service_ddl(); + void Met_en_service_ddl(); + + // test si un ddl est en service ou pas + bool En_service (Enum_ddl en) const { return tab_ddl((*pos_enum)(en)).Service();}; + // test si un ddl est une variable ou pas + bool UneVariable(Enum_ddl en) const { return tab_ddl((*pos_enum)(en)).UneVariable();}; + // changement du statut de variable à donnée d'un ddl + void ChangeVariable_a_Donnee(Enum_ddl en) + { tab_ddl((*pos_enum)(en)).ChangeVariable_a_Donnee();MiseAjourActif();}; + // changement du statut de donnée à variable d'un ddl + void ChangeDonnee_a_Variable(Enum_ddl en) + { tab_ddl((*pos_enum)(en)).ChangeDonnee_a_Variable();MiseAjourActif();}; + // changement du statut de variable à donnée pour un tableau d'enum de ddl + void ChangeVariable_a_Donnee(const Tableau& taben); + // changement du statut de donnée à variable pour un tableau d'enum de ddl + void ChangeDonnee_a_Variable(const Tableau& taben); + // changement de toutes les conditions données (service, variable, fixage ..) + // selon le tableau de ddl passé en paramètre + // par contre la valeur n'est pas utilisé donc la valeur actuelle reste inchangé + void ChangeToutesLesConditions(const Tableau& ta); + // changement de statu des ddl d'une combinaison, (cf. Enum_ddl) + // les ddl de la combinaison, prennent le même statut que celui + // actuellement stocké, correspondant à enuta + // cas est la combinaison, + void ChangeStatut(int cas,Enum_ddl enuta); + // changement de statu des ddl d'une combinaison, (cf. Enum_ddl) + // les ddl de la combinaison, prennent le même statut que celui de enuta + // cas est la combinaison, + void ChangeStatut(int cas,Enum_boolddl enubold); + +// -------- manipulation de ddl identifié par un énuméré ------ +// *****!!!!!***** attention il n'y a pas vérification de l'existence +// de ce type énuméré dans des ddl du noeud + + // change la valeur du ddl identifie par en , + inline void Change_val_0(Enum_ddl en,double val) // t=0 + { tab_0((*pos_enum)(en)) = val; }; + inline void Change_val_t(Enum_ddl en,double val) // t=t + { tab_ddl((*pos_enum)(en)).Valeur() = val;}; + inline void Change_val_tdt(Enum_ddl en,double val) // t=tdt + { tab_tdt((*pos_enum)(en)) = val;}; + // incremente la valeur du ddl identifie par en , + inline void Ajout_val_0(Enum_ddl en,double val) // t=0 + { tab_0((*pos_enum)(en)) += val; }; + inline void Ajout_val_t(Enum_ddl en,double val) // t=t + { tab_ddl((*pos_enum)(en)).Valeur() += val;}; + inline void Ajout_val_tdt(Enum_ddl en,double val) // t=tdt + { tab_tdt((*pos_enum)(en)) += val;}; + // retourne la valeur du ddl identifie par en + inline double Valeur_0(Enum_ddl en) const // t=0 + { return tab_0((*pos_enum)(en)); }; + inline double Valeur_t(Enum_ddl en) const // t=t + { return tab_ddl((*pos_enum)(en)).Valeur();}; + inline double Valeur_tdt(Enum_ddl en) const // t=tdt + { return tab_tdt((*pos_enum)(en));}; + // Retourne le ddl à t=0 identifie par enu, en lecture + inline Ddl Ddl_noeud_0(Enum_ddl enu) const + {return Ddl(enu,tab_0((*pos_enum)(enu)),tab_ddl((*pos_enum)(enu)).Retour_Fixe());}; + // Retourne le ddl à t=t identifie par en, en lecture + inline Ddl Ddl_noeud_t(Enum_ddl enu) const + {return Ddl(enu,tab_ddl((*pos_enum)(enu)).Valeur(),tab_ddl((*pos_enum)(enu)).Retour_Fixe());}; + // Retourne le ddl à t=tdt identifie par en, en lecture + inline Ddl Ddl_noeud_tdt(Enum_ddl enu) const + {return Ddl(enu,tab_tdt((*pos_enum)(enu)),tab_ddl((*pos_enum)(enu)).Retour_Fixe());}; + + // indique que l'on va utiliser les ddl en 0, t et tdt + // les grandeurs en tdt sont cree et initialisees par defaut + void Travail_tdt(); + + // indique que l'on va utiliser les ddl en 0, t + // si les grandeurs en tdt existaient, elles sont supprimées + void Travail_t(); + + // teste si un ddl existe + inline bool Existe_ici(const Enum_ddl en) const + { if (Existe(en) == 0) + return false; + else + return true; + }; + + // mise a zero de tous les variables ddl actives + // sauf dans le cas de coordonnees entrainees. dans ce dernier + // cas les coordonnees correspondants a Xi pour t et t+dt + // sont mis a la valeur de celles de t=0 + // a moins que le paramètre booléen est mis à false, + // dans ce cas les coordonnées à t sont inchangées + void ZeroVariablesDdl(bool cas); + + // actualisation des ddl actifs (variables et donnees) de t+dt vers t + // seuls sont actualisée, les ddl actifs + void TdtversT(); + // actualisation des ddl actifs (variables et donnees) de t vers t+dt + // seuls sont actualisée, les ddl actifs + void TversTdt(); + + // retourne true si le tableau a t+dt existe , false sinon + inline bool Tdt() + {if (tab_tdt.Taille() != 0) return true; else return false; }; + + // retourne dans le vecteur d'entrée les réels représentant les contraintes + // si les degrés de liberté contrainte existent + // sinon retourne false, en ne modifiant pas l'entrée + bool Contrainte(Vecteur& Sig); + + // retourne dans le tenseur d'entrée les réels représentant les contraintes + // si les degrés de liberté contrainte existent + // sinon retourne l'entrée sans modification + // le tenseur est choisit mixte pour représenter tous les cas + // !!! important : le tenseur Sig doit avoir la bonne dimension + // en entrée, car il n'est pas redimensionné dans la méthode + TenseurHB& Contrainte(TenseurHB& Sig); + + // lecture du noeud dans la mémoire + void Lecture (UtilLecture *entreePrinc); + // sortie du schemaXML: en fonction de enu + static void SchemaXML_Noeud(ofstream& sort,const Enum_IO_XML enu); + + // affichage et definition interactive des commandes + // coor: des coordonnees fixée pour un affichage different pour chaque noeud + void Info_commande_Noeud(UtilLecture * entreePrinc,Coordonnee& coor,int nb_du_noeud); + + // lecture sur le flot d'entée de déplacement + // et mise à jour des positions à t et t+dt correspondantes + void LectureDeplacements(UtilLecture *entreePrinc); + + //----- lecture écriture dans base info ----- + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) + // ( ici on ne redimentionne pas, + // cela signifie que le nombre de ddl augmente mais ne diminue pas !!) + void Lecture_base_info(ifstream& ent,int cas); + // cas donne le niveau de sauvegarde + // = 1 : on sauvegarde tout + // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) + void Ecriture_base_info(ofstream& sort,int cas); + +// -------- manipulation de types quelconques stockées aux noeuds ------ +// les opérations dans les types quelconques ne sont pas faites par le noeud +// le noeud gère les grandeurs, mais ne les modifies pas directement + + // ajout d'un type quelconque au noeud (il s'agit ici de définir le conteneur) + // dans le cas où les types existent déjà, on ne fait rien + // cas d'un tableau + void AjoutTabTypeQuelconque(const Tableau & tab_t_quel); + // cas d'une seule grandeur quelconque + void AjoutUnTypeQuelconque(const TypeQuelconque & t_quel); + // supprime une grandeur quelconque (si elle est présente) + // opération aussi longue que l'ajout !! + void SupprimeUnTypeQuelconque(const TypeQuelconque & t_quel); + // supprime un tableau de grandeurs quelconques (si elles sont présentes) + // opération aussi longue que l'ajout !! + void SupprimeTabTypeQuelconque(const Tableau & tab_t_quel); + // ramène un booléen indiquant si la grandeur quelconque existe ou pas + inline bool Existe_ici(TypeQuelconque_enum_etendu en) const + { if (Existe(en) == 0) return false; else return true;}; + // récupération d'une grandeur quelconque pour modification + // après l'appel de cette méthode, la grandeur quelconque est réputée updaté + TypeQuelconque& ModifGrandeur_quelconque(TypeQuelconque_enum_etendu a); + // récupération d'une grandeur quelconque pour lecture uniquement + inline const TypeQuelconque& Grandeur_quelconque(TypeQuelconque_enum_etendu enu) const + { return (tab_type_quel((*pos_Quelconque)(enu.Position())));}; + // ramène le nombre de fois où la grandeur quelconque a été updaté + inline int Grandeur_quelconque_update(TypeQuelconque_enum_etendu enu) const + { return (update_type_quel((*pos_Quelconque)(enu.Position())));}; + // signale que toutes les grandeurs quelconques sont non-updatées + // en particulier les grandeurs en question ne seront pas sauvegarder dans base_info + void Mise_non_update_grandeurs_quelconques(); + // signale qu'une grandeur quelconque est non-updatées + // en particulier la grandeur en question ne sera pas sauvegarder dans base_info + void Mise_non_update_grandeurs_quelconques(TypeQuelconque_enum_etendu enu); + +// -------- manipulation de types Ddl_etendu stockées aux noeuds ------ +// les opérations dans les types Ddl_enum_etendu ne sont pas faites par le noeud +// le noeud gère les grandeurs, mais ne les modifies pas directement + + // ajout d'un type Ddl_enum_etendu au noeud (il s'agit ici de définir le conteneur) + // dans le cas où les types existent déjà, on ne fait rien + // cas d'un tableau + void AjoutTabDdl_etendu(const Tableau & tab_ddletendu); + // cas d'un seul Ddl_enum_etendu + void AjoutUnDdl_etendu(const Ddl_enum_etendu & ddletendu); + // supprime un Ddl_enum_etendu (si elle est présente) + // opération aussi longue que l'ajout !! + void SupprimeUnDdl_etendu(const Ddl_enum_etendu & ddletendu); + // supprime un tableau de Ddl_enum_etendu (si ils sont présents) + // opération aussi longue que l'ajout !! + void SupprimeTabDdl_etendu(const Tableau & tab_ddletendu); + // ramène un booléen indiquant si le Ddl_enum_etendu existe ou pas + inline bool Existe_ici_ddlEtendu(const Ddl_enum_etendu& ddletendu) const + { if (Existe_ddlEtendu(ddletendu) == 0) return false; else return true;}; + // récupération d'un Ddl_etendu pour modification + // après l'appel de cette méthode, le Ddl_enum_etendu est réputée updaté + Ddl_etendu& ModifDdl_etendu(const Ddl_enum_etendu& addletendu); + // récupération d'un Ddl_etendu pour lecture uniquement + inline const Ddl_etendu& DdlEtendue(const Ddl_enum_etendu& ddlenumetendu) const + { return (tab_ddletendu((*pos_ddletendu)(ddlenumetendu.Position())));}; + // ramène le nombre de fois que le ddl a été updaté + inline int DdlEtendue_update(const Ddl_enum_etendu& ddlenumetendu) + { return (update_ddletendu((*pos_ddletendu)(ddlenumetendu.Position())));}; + // signale que tous les Ddl_etendu sont non-updatées ( mise à zéro du nombre d'update) + // en particulier les grandeurs en question ne seront pas sauvegarder dans base_info + void Mise_non_update_Ddl_etendu(); + // signale qu'un Ddl_etendu est non-updatées + // en particulier le Ddl_etendu en question ne sera pas sauvegarder dans base_info + void Mise_non_update_Ddl_etendu(Ddl_enum_etendu ddlenumetendu); + +//===================================================================================== + protected : +//===================================================================================== + + // donnees de base + + int num_noeud; // numero d'identification dans le maillage + int num_Mail; // numero de maillage auquel appartiend le noeud + Tableau tab_ddl; // tableau des degres de liberte + // les valeurs sont celles a l'instant t + Coordonnee* coord0; // coordonnee initiale + + // liaison entre noeuds : il s'agit d'un stockage uniquement: l'utilisation et la manipulation + // est à la charge des classes appelantes + Tableau * tab_enu_liaison; // tab_enu_liaison(i) définit un type éventuel + // de liaison pour le cas d'assemblage i + Tableau < Tableau >* tab_ddl_lier; // tab_ddl_lier(i) donne la liste des ddl liés + // avec les noeuds associés + + // donnees evoluant avec le calcul + // les differents tableaux si-desous peuvent ne pas etre affecte + // cela depend du pb, certaines valeurs ont plusiurs meme nom + // comme coord0 cood1 et cood2, mais un seul endroit de stockage + Tableau tab_0; // valeurs a l'instant 0 des ddl + Tableau tab_tdt; // valeurs a l'instant t+dt des ddl + Tableau coord1; // coordonnee a un instant t + // pour l'exterieur le tableau est transforme en coordonnees mais + // en interne comme les infos peuvent etre en double avec le tableau de ddl + // et non contigues, on utilise un adressage indirecte + // Sa taille est différente de 0 si les coordonnées à t varie ou + // sont succeptibles de varier. + // a priori si coord1 est affecté c'est uniquement en pointant sur tab_ddl + // donc il ne crée pas avec new + Coordonnee* coord2; // coordonnee a un instant t+dt + // tableau pour une gestion rapide des ddl en service + // et que l'on appelle par leur identification + Tableau tab_var_actives; // les numéros des variables ddl actives + Tableau tab_actif; // les numéros des donnees et variables ddl actives + + Tableau posiAssemb; // tableau de pointeurs de position pour l'assemblage + // defini l'endroit ou est mis le premier ddl ds les seconds + //membres et raideurs globaux + + // le noeud peut contenir éventuellement une base rattachée + BaseB* baseB_0; // actuelle + BaseB* baseB_t; // et à t + BaseB* baseB; // actuelle + + Tableau tab_nb_Elem; // tableau éventuel des numéros d'éléments qui contiennent le noeud + // --- cas des types quelconques + Tableau tab_type_quel; // grandeur quelconques stockées aux noeuds + Tableau update_type_quel; // indique si la grandeur quelconque est update ou pas + static short int posi_type_quel; // utilisée par la méthode Existe_quelconque(.. + // pour memoriser la dernière position accèdée + int nbTypeQ_update; // indique le nombre de type quelconque updaté actuel (pour optimiser vitesse) + + // --- cas des ddl étendus + Tableau tab_ddletendu; // ddl étendu stockées aux noeuds + Tableau update_ddletendu; // indique si le ddl étendu est update ou pas + static short int posi_ddletendu; // utilisée par la méthode Existe_ddletendu(.. + // pour memoriser la dernière position accèdée + int nbddletendu_update; // indique le nombre de ddl étendu updaté actuel (pour optimiser vitesse) + + // --- pour un acces rapide à un ddl donné repéré par un type énuméré on met en place --- + // une liste de type de succession d'enum ddl + // en ce servant de l'équivalence enum int + // il y a une liste pour tous les noeuds + static list > list_tab_enum; + // et un type de tableau pour chaque noeud + list >::iterator pos_enum ; + // (* posi_enum)(enum) = l'indice du ddl dans les + // tableau de ddl : tab_ddl, tab_0 etc.. + // la liste n'est jamais diminuée, par contre comme les noeuds + // sont construit d'une manière automatique et systématique on + // suppose qu'il y aura en fait très peu d'élément dans la liste + + // --- pour déterminer rapidement la position dans la liste + // des ddl actifs, d'un ddl donné repéré par un type énuméré + // même principe que pour list_tab_enum + static List_io > list_tab_posi_actif; + // et un tableau de pointeur d'élément de la liste, + // chaque tableau étant relatif à untype de combinaison de ddl actif + Tableau < List_io >::iterator > t_enum_s ; + + // ---- idem pour les types quelconques repéré par un type énuméré + // même principe que pour list_tab_enum + static List_io > list_tab_typeQuelconque; + // et un type de tableau pour chaque noeud + list >::iterator pos_Quelconque ; + + // ---- idem pour les types Ddl_etendu repéré par un type énuméré + // même principe que pour list_tab_enum + static List_io > list_tab_ddletendu; + // et un type de tableau pour chaque noeud + list >::iterator pos_ddletendu ; + + // fonctions internes + + // liaison des ddl et des deplacement a t et 0 + // nb = le nb du début des deplacement dans les ddl + void Liaison_t(int nb); + + // liaison des ddl et des deplacement a t,tdt et 0 + // nb = le nb du début des deplacement dans les ddl + void Liaison_tdt(int nb); + + // liaison des ddl et des deplacement a tdt seulement + // nb = le nb du début des deplacement dans les ddl + void LiaiSeuletdt(int nb); + + // mise a jour des liaisons ddl/deplacement + void MiseAjour(); + + // mise a jour de l'adressage via l'identificateur d'énumération + // c'est-à-dire la gestion via list_tab_enum et pos_enum + // ne doit être appelé que si l'on a introduit un nouveau ddl !! + // ou changé l'ordre etc.. + void MiseAjourEnum(); + + // mise a jour du tableau de ddl des variables actives + void MiseAjourActif(); + + // retourne le numero du ddl recherche identifie par en, + // s'il existe sinon 0 + int Existe(const Enum_ddl en) const { return (*pos_enum)(en);}; + // --- cas des grandeurs quelconques ---- + // lecture des grandeurs quelconques sur flot + void Lecture_grandeurs_quelconque(istream & ent); + // écriture des grandeurs quelconques sur flot + void Ecriture_grandeurs_quelconque(ostream & sort) const; + // récupe de l'indice d'une grandeur quelconque + // si la grandeur n'existe pas -> ramène 0 + int Indice_grandeur_quelconque(TypeQuelconque_enum_etendu a); + // mise a jour de l'adressage via l'identificateur d'énumération + // c'est-à-dire la gestion via list_tab_typeQuelconque et pos_Quelconque + // ne doit être appelé que si l'on a introduit un nouveau type quelconque !! + // ou changé l'ordre etc.. + void MiseAjourTypeQuelconque(); + // retourne le numero du type quelconque recherche identifie par en, + // s'il existe sinon 0 + int Existe(TypeQuelconque_enum_etendu en) + const { return ( (pos_Quelconque == list_tab_typeQuelconque.end()) ? 0 : (*pos_Quelconque)(en.Position()));}; + // --- cas des Ddl_etendu ---- + // lecture des Ddl_etendu sur flot + void Lecture_Ddl_etendu(istream & ent); + // écriture des Ddl_etendu sur flot + void Ecriture_Ddl_etendu(ostream & sort) const; + // récupe de l'indice d'un Ddl_etendu + // si la grandeur n'existe pas -> ramène 0 + int Indice_Ddl_etendu(const Ddl_enum_etendu& a); + // mise a jour de l'adressage via l'identificateur d'énumération + // c'est-à-dire la gestion via list_tab_ddletendu et pos_ddletendu + // ne doit être appelé que si l'on a introduit un nouveau Ddl_etendu !! + // ou changé l'ordre etc.. + void MiseAjourDdl_etendu(); + // retourne le numero du Ddl_enum_etendu recherche identifie par en, + // s'il existe sinon 0 + int Existe_ddlEtendu(const Ddl_enum_etendu& en) + const { return ( (pos_ddletendu == list_tab_ddletendu.end()) ? 0 : (*pos_ddletendu)(en.Position()));}; + +// // ordonne et on met a suivre les ddl d'une même famille suivant un ordre croissant +// // ceci pour des ddl que l'on vient d'ajouter, QUE L'ON CONSIDÈRE ÊTRE À LA FIN DE TAB_DDL ! +// // en paramètre le ou les ddl +// void OrdonneDdlMemeFamille(const Ddl& a); +// void OrdonneDdlMemeFamille(const Tableau& ta); +// // permutation de deux ddl (sert pour OrdonneDdlMemeFamille) +// void Permutation_2ddl(const int& ipo1,cont int& ipo2); + // ordonner un tableau de ddl suivant un ordre croissant et avec des ddl à suivre + void OrdonnerTableauDdl(Tableau& ta); + // liste des ddl (en famille) à ajouter + // recopie des ddl existant déjà + // change_donn_var indique si les ddl existant on été modifiée + void ListeDdlAajouter(list& liDdl,Tableau& ta,bool& change_donn_var); + +}; +/// @} // end of group + + +#endif + diff --git a/Maillage/Noeud2.cc b/Maillage/Noeud2.cc new file mode 100644 index 0000000..c95421c --- /dev/null +++ b/Maillage/Noeud2.cc @@ -0,0 +1,1174 @@ +// FICHIER : Noeud2.cp +// CLASSE : Noeud + + +// 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 "Noeud.h" +#include "Util.h" +#include +#include "TypeQuelconqueParticulier.h" + +// ajout d'un type quelconque au noeud (il s'agit ici de définir le conteneur) +// dans le cas où les types existent déjà, on ne fait rien +// cas d'un tableau +void Noeud::AjoutTabTypeQuelconque(const Tableau & tab_t_quel) + {// on passe en revue le tableau transmis + int tailt = tab_t_quel.Taille(); + int tailtab = tab_type_quel.Taille(); + // pour ne faire qu'une passe on crée un tableau d'existence + Tableau tab_ex(tailt); + int a_ajouter=0; // le nombre de grandeur à ajouter + for (int i=1;i<=tailt;i++) + { bool trouver = false; + for (int j=1;j<=tailtab;j++) + if (tab_type_quel(j).EnuTypeQuelconque()==tab_t_quel(i).EnuTypeQuelconque()) + {trouver = true;break;}; + if (!trouver) + {a_ajouter++; tab_ex(i)=1;}; + }; + // dans le cas où il n'y a rien n'a ajouter on retourne + if (a_ajouter == 0) return; + // maintenant on ajoute vraiment + tab_type_quel.Change_taille(tailtab+a_ajouter); + update_type_quel.Change_taille(tailtab+a_ajouter); // =0 par défaut + int compteur=1; + for (int ii=1;ii<=tailt;ii++) + {if (tab_ex(ii)==1) {tab_type_quel(tailtab+compteur).ChangeGrandeur(tab_t_quel(ii));compteur++;} }; + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour + MiseAjourTypeQuelconque(); // mise en place de l'adressage directe + }; + +// cas d'une seule grandeur quelconque +void Noeud::AjoutUnTypeQuelconque(const TypeQuelconque & t_quel) + {int tailtab = tab_type_quel.Taille(); + // on n'ajoute que si la grandeur n'existe pas déjà + bool existe=false; + for (int j=1;j<=tailtab;j++) + if (tab_type_quel(j).EnuTypeQuelconque()==t_quel.EnuTypeQuelconque()) + {existe = true;break;}; + if (!existe) + { tab_type_quel.Change_taille(tailtab+1); + update_type_quel.Change_taille(tailtab+1,0); // =0 par défaut + tab_type_quel(tailtab+1).ChangeGrandeur(t_quel); + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour + MiseAjourTypeQuelconque(); // mise en place de l'adressage directe + }; + }; + +// supprime une grandeur quelconque (si elle est présente) +void Noeud::SupprimeUnTypeQuelconque(const TypeQuelconque & t_quel) + { // récup du type + TypeQuelconque_enum_etendu en = t_quel.EnuTypeQuelconque(); + int nb=Existe(en); + if ( nb != 0) + {// dans le cas où la grandeur existe on la supprime + int tai=tab_type_quel.Taille(); + if ( update_type_quel(nb) != 0) nbTypeQ_update--; + for (int i= nb;i & tab_t_quel) + {// on passe en revue le tableau transmis + int tailt = tab_t_quel.Taille(); + int tailtab = tab_type_quel.Taille(); + // pour ne faire qu'une passe on crée un tableau d'existence + Tableau tab_in(tailtab); + bool on_supprime=false; + for (int i=1;i<=tailt;i++) + { // on passe en revue le tableau fourni + int num = Existe(tab_t_quel(i).EnuTypeQuelconque()); + if (num != 0) + {tab_in(num)=1; + if ( update_type_quel(num) != 0) nbTypeQ_update--; + on_supprime=true;}; + }; + // retour s'il n'y a rien à supprimer + if (!on_supprime) return; + // maintenant on supprime vraiment + int i=1; // pointeur des grandeurs restantes + for (int j=1;i<=tailtab;i++,j++) + { // on passe en revue + if (tab_in(j)!=1) + { // grandeur à garder + tab_type_quel(i).ChangeGrandeur(tab_type_quel(j)); + update_type_quel(i)=update_type_quel(j); + i++; + }; + }; + // la valeur de i-1 = la taille à conserver + tab_type_quel.Change_taille(i-1); + // on met à jour le tableau de gestion d'indiçage indirecte + MiseAjourTypeQuelconque(); + }; + +// récupération d'une grandeur quelconque pour modification +// après l'appel de cette méthode, la grandeur quelconque est réputée updaté +TypeQuelconque& Noeud::ModifGrandeur_quelconque(TypeQuelconque_enum_etendu enu) + { // récup de l'indice de la grandeur + int indice = (*pos_Quelconque)(enu.Position()); + // si le type n'était pas updaté on met à jour les 2 indicateurs + if (update_type_quel(indice) == 0) {update_type_quel(indice)=1; nbTypeQ_update++;} + else {update_type_quel(indice)++; }; + return (tab_type_quel(indice)); + }; + +// signale que toutes les grandeurs quelconques sont non-updatées +void Noeud::Mise_non_update_grandeurs_quelconques() + { int tailupdate = update_type_quel.Taille(); + for (int i=1;i<=tailupdate;i++) update_type_quel(i)=0; + nbTypeQ_update=0; // reset du nombre total + }; + +// signale qu'une grandeur quelconque est non-updatées +// en particulier la grandeur en question ne sera pas sauvegarder dans base_info +void Noeud::Mise_non_update_grandeurs_quelconques(TypeQuelconque_enum_etendu enu) + { // récup de l'indice + int nb=Existe(enu); + update_type_quel(nb)=0; + nbTypeQ_update--; // met à jour du nombre total + }; + +// ajout d'un ddl étendu (il s'agit ici de définir le conteneur) +// dans le cas où les types existent déjà, on ne fait rien +// cas d'un tableau +void Noeud::AjoutTabDdl_etendu(const Tableau & t_ddletendu) + {// on passe en revue le tableau transmis + int tailt = t_ddletendu.Taille(); + int tailtab = tab_ddletendu.Taille(); + // pour ne faire qu'une passe on crée un tableau d'existence + Tableau tab_ex(tailt,0); + int a_ajouter=0; // le nombre de grandeur à ajouter + int ttaill = tab_ddletendu.Taille(); + for (int i=1;i<=tailt;i++) + { bool trouver = false; + // on passe en revue le tableau actuel + for (int j=1;j<=tailtab;j++) + if (tab_ddletendu(j).DdlEnumEtendu()==t_ddletendu(i)) + {trouver = true;break;}; + if (!trouver) + {a_ajouter++; tab_ex(i)=1;}; + }; + // dans le cas où il n'y a rien n'a ajouter on retourne + if (a_ajouter == 0) return; + // maintenant on ajoute vraiment + tab_ddletendu.Change_taille(tailtab+a_ajouter); + update_ddletendu.Change_taille(tailtab+a_ajouter,0); // =0 par défaut + int compteur=1; + for (int ii=1;ii<=tailt;ii++) + {if (tab_ex(ii)==1) + {tab_ddletendu(tailtab+compteur)=t_ddletendu(ii); compteur++;}; + }; + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour + MiseAjourDdl_etendu(); // mise en place de l'adressage directe + }; + +// cas d'un seul ddl étendu +void Noeud::AjoutUnDdl_etendu(const Ddl_enum_etendu & ddlenumetendu) + {int tailtab = tab_ddletendu.Taille(); + // on n'ajoute que si la grandeur n'existe pas déjà + bool existe=false; + for (int j=1;j<=tailtab;j++) + if (tab_ddletendu(j).DdlEnumEtendu()==ddlenumetendu) + {existe = true;break;}; + if (!existe) + { tab_ddletendu.Change_taille(tailtab+1); + update_ddletendu.Change_taille(tailtab+1,0); // =0 par défaut + tab_ddletendu(tailtab+1)=Ddl_etendu(ddlenumetendu); + // on peut maintenant mettre en place l'adressage directe + // ce qui permettra d'utiliser Existe(..) dans MiseAjour + MiseAjourDdl_etendu(); // mise en place de l'adressage directe + }; + }; + +// supprime un ddl étendu (si il est présent) +void Noeud::SupprimeUnDdl_etendu(const Ddl_enum_etendu & ddletendu) + { // récup du type + int nb=Existe_ddlEtendu(ddletendu); + if ( nb != 0) + {// dans le cas où la grandeur existe on la supprime + int tai=tab_ddletendu.Taille(); + if ( update_ddletendu(nb) != 0) nbddletendu_update--; + for (int i= nb;i & t_ddletendu) + {// on passe en revue le tableau transmis + int tailt = t_ddletendu.Taille(); + int tailtab = tab_ddletendu.Taille(); + // pour ne faire qu'une passe on crée un tableau d'existence + Tableau tab_in(tailtab); + bool on_supprime=false; + for (int i=1;i<=tailt;i++) + { // on passe en revue le tableau fourni + int num = Existe_ddlEtendu(t_ddletendu(i)); + if (num != 0) + {tab_in(num)=1; + if ( update_type_quel(num) == 1) nbTypeQ_update--; + on_supprime=true;}; + }; + // retour s'il n'y a rien à supprimer + if (!on_supprime) return; + // maintenant on supprime vraiment + int i=1; // pointeur des grandeurs restantes + for (int j=1;i<=tailtab;i++,j++) + { // on passe en revue + if (tab_in(j)!=1) + { // grandeur à garder + tab_ddletendu(i)=tab_ddletendu(j); + update_ddletendu(i)=update_ddletendu(j); + i++; + }; + }; + // la taille à conserver + update_ddletendu.Change_taille(i-1); + tab_ddletendu.Change_taille(i-1); + // on met à jour le tableau de gestion d'indiçage indirecte + MiseAjourDdl_etendu(); + }; + +// récupération d'un ddl étendu pour modification +// après l'appel de cette méthode, le ddl étendu est réputée updaté +Ddl_etendu& Noeud::ModifDdl_etendu(const Ddl_enum_etendu& ddletendu) + { // récup de l'indice de la grandeur + int indice = Existe_ddlEtendu(ddletendu); + // si le type n'était pas updaté on met à jour les 2 indicateurs + if (update_ddletendu(indice) == 0) {update_ddletendu(indice)=1; nbddletendu_update++;} + else {update_ddletendu(indice)++;}; + return (tab_ddletendu(indice)); + }; + +// signale que toutes les ddl étendus sont non-updatées +void Noeud::Mise_non_update_Ddl_etendu() + { int tailupdate = update_ddletendu.Taille(); + for (int i=1;i<=tailupdate;i++) update_ddletendu(i)=0; + nbddletendu_update=0; // reset du nombre total + }; + +// signale qu'un Ddl_etendu est non-updatées +// en particulier le Ddl_etendu en question ne sera pas sauvegarder dans base_info +void Noeud::Mise_non_update_Ddl_etendu(Ddl_enum_etendu ddlenumetendu) + { // récup de l'indice de la grandeur + int indice = Existe_ddlEtendu(ddlenumetendu); + update_ddletendu(indice)=0; + nbddletendu_update--; // met à jour du nombre total + }; + +// ------------------------ procedures protegees ------------------------ + + +// liaison des ddl et des deplacement a t et 0 +// nb = le numero correspondant aux début des coordonnees dans les tableaux +// de ddl +void Noeud::Liaison_t(int nb) + { // cas ou l'on est en coordonnees entrainees + // 1) cas des coord0 + // positionnement a l'adresse des coordonnees + double * pt = &(tab_0(nb)); + if (coord0 != NULL) + // si les coordonnees existent deja on les sauvegarde + // et on remplace les valeurs des ddl par les coor + { Coordonnee truc(*coord0); + delete coord0; + // on passe un pointeur donc il n'y a pas de creation de memoire + // dans le new + coord0 = new Coordonnee(ParaGlob::Dimension(),pt); + *coord0 = truc; + } + else + // sinon on cree coord0 a la meme place que les ddl a t = 0 + {coord0 = new Coordonnee(ParaGlob::Dimension(),pt); + } + // 2) cas des coord1 + int dim = ParaGlob::Dimension(); + if (coord1.Taille() == 0) + { // il faut construire le tableau + coord1.Change_taille(dim); + for (int ii=1;ii<=dim;ii++) + coord1(ii) = &(tab_ddl(nb+ii-1).Valeur()); + } + else if (coord1(1) == NULL) + // tableau existant mais non affecte + for (int ii=1;ii<=dim;ii++) + coord1(ii) = &(tab_ddl(nb+ii-1).Valeur()); + else + // tableau existant et affecte, donc ici pas de pb a priori car lorsque les coordonnées à t + // sont affectées elles le sont obligatoirement sur le tableau de ddl + //les valeurs du tableau + // de coordonnées vont etre misent a la place des valeurs de ddl + for (int ii=1;ii<=dim;ii++) + { double sa = *(coord1(ii)); + // on ne supprime pas la valeur pointée car il n'y a jamais eu de new avec + // l'allocation de coord1 + // on réaffecte + coord1(ii) = &(tab_ddl(nb+ii-1).Valeur()); + // récup de la valeur + *(coord1(ii)) = sa; + } + }; + +// liaison des ddl et des deplacement a tdt seulement +// nb = le nb du début des deplacement dans les ddl +void Noeud::LiaiSeuletdt(int nb) + { + // positionnement a l'adresse des coordonnees + double * pt = &(tab_tdt(nb)); + if (coord2 != NULL) + // si les coordonnees existent deja on les sauvegarde + // et on remplace les valeurs des ddl par les coor + { Coordonnee truc(*coord2); + delete coord2; + coord2 = new Coordonnee(ParaGlob::Dimension(),pt); + *coord2 = truc; + } + else + // sinon on cree coord2 a la meme place que les ddl a tdt + {coord2 = new Coordonnee(ParaGlob::Dimension(),pt); + } + + }; + +// liaison des ddl et des deplacement a t,tdt et 0 +// nb = le nb du début des deplacement dans les ddl +void Noeud::Liaison_tdt(int nb) + { // cas ou l'on est en coordonnees entrainees + // 1) cas des coord0 et des coord1 + Liaison_t(nb); + // 2) cas des coord2 + LiaiSeuletdt(nb); + }; + +// mise a jour des tableaux et des liaisons +void Noeud::MiseAjour() + { // tout d'abord on regarde si tab_0 est correctement dimensionne + int t1 = tab_0.Taille(); + int t2 = tab_ddl.Taille(); + if (t1 != t2) + // cas ou le tableau de ddl a ete agrandi + // on change la taille des tableaux. + // on sauvegarde les coordonnées à 0 si elles sont liées + if (Existe(X1)) + { Coordonnee truc(*coord0); + delete coord0; + coord0 = new Coordonnee(truc); + }; + // maintenant on peut changer les tableaux + { tab_0.Change_taille(t2); + for (int i=t1+1;i<=t2;i++) + tab_0(i) = tab_ddl(i).Valeur(); + if ( tab_tdt.Taille() != 0) + // cas ou le tableau tdt est en service + tab_tdt.Change_taille(t2); + } + // on regarde ensuite s'il y a des liaisons entre ddl et deplacements + int nb = Existe(X1); + if (nb != 0) // cas ou il y a une liaison ddl coordonnées + {double * pt0 = &((*coord0)(1)); + if (pt0 != &(tab_0(nb))) + // cas d'une mauvaise liaison, on remet à jour + if (tab_tdt.Taille() == 0) // choix t ou t et tdt + Liaison_t(nb); + else + Liaison_tdt(nb); + else if (tab_tdt.Taille() != 0) + // cas d'une bonne liaison pour t=0, reste le cas à tdt + { if (coord2 != NULL) + // cas ou les coord2 sont deja affectees + { double * pt2 = &((*coord2)(1)); + if (pt2 != &(tab_tdt(nb))) + LiaiSeuletdt(nb); // cas pas affectees au bonne endroit + } + else // cas où il n'y avait pas encore de liaison + LiaiSeuletdt(nb); // on affecte les coordonnees + } + } + }; + +// mise a jour de l'adressage via l'identificateur d'énumération +// c'est-à-dire la gestion via list_tab_enum et pos_enum +// ne doit être appelé que si l'on a introduit un nouveau ddl !! +// ou changé l'ordre etc.. +void Noeud::MiseAjourEnum() + { // tout d'abord on regarde si le dernier tableau construit dans la liste + // convient, car ce sera le cas pour le cas courant + // le dernier tableau est positionné en début de liste. + list >::iterator ideb = list_tab_enum.begin(); + list >::iterator iancien = pos_enum; + int taille = tab_ddl.Taille(); + // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position + int ttail = (*ideb).Taille(); + bool okk = true; + // le test n'est effectué que si la liste n'est pas vide + if (list_tab_enum.size() != 0) + { // d'abort la taille, on compte le nombre d'élément non nul dans + int ttaile = (*ideb)(ttail); + if (taille != ttaile) + okk = false; + else + // maintenant le contenu + for (int i = 1; i<= taille;i++) + if( (*ideb)(tab_ddl(i).Id_nom()) != i) + { okk = false; break;} + } + else + okk = false; + // si le tableau convient on met à jour le pointeur et c'est fini + // sinon on passe en revu toute la liste + if (okk) + pos_enum = ideb; + else // ---- cas où on passe en revue la liste ----- + // ici la procédure est plus longue, mais normalement elle ne sera + // utilisé que peut souvent + { + // on reconstruit un tableau d'adressage indirect des ddl + // la taille du tableau d'adressage est celui du nombre maxi + // de type de ddl différent (donc certain ne serviron pas) + // les données du tableau sont initialisées à 0, ainsi si l'on + // cherche à utiliser un ddl indice 0, l'erreur sera détecté au + // niveau de Tableau_T + // l'avant dernier élément du tableau sert à stocker le nombre de noeud + // qui utilise le tableau + // le dernier élément indique le nombre d'élément non nul + Tableau tab_indi_enum(NbEnum_ddl()+2,0); + for (int i=1;i<=taille;i++) + tab_indi_enum(tab_ddl(i).Id_nom())=i; + // on enregistre la taille + tab_indi_enum(NbEnum_ddl()+2) = taille; + // maintenant on va regarder si ce tableau existe dans la liste + list >::iterator ifin = list_tab_enum.end(); + list >::iterator iter; + bool trouver = false; + for (iter = ideb;ideb!= ifin;ideb++) + if ((*iter) == tab_indi_enum) + { trouver = true; break;} + // si pas trouver on ajoute sinon on utilise la position déjà existante + if (!trouver) + // cas où on n'a pas trouvé de tableau + { list_tab_enum.push_front(tab_indi_enum); // allocation + // on attribue le nouveau pointage + pos_enum = list_tab_enum.begin(); // sauvegarde de la position + } + else // cas où on a trouvé un tableau dans la liste + pos_enum = iter; + } + // --- gestions des tableaux ---- + // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau + // (permet de supprimer les tableaux qui ne servent plus) + // on regarde si pos_enum était déjà attribué + if (iancien != list_tab_enum.end()) + // cas où ce n'est pas la première initialisation + {if ((*iancien)(NbEnum_ddl()+1) == 1) + // cas où c'est le dernier noeud qui pointe sur ce tableau + // on supprime le tableau + list_tab_enum.erase(iancien); + else + // sinon on décrémente le compteur + ((*iancien)(NbEnum_ddl()+1))--; + // maintenant on s'occupe du nouveau pointage + ((*pos_enum)(NbEnum_ddl()+1))++; + } + else + // c'est la première initialisation + // on incrémente le compteur du tableau + ((*pos_enum)(NbEnum_ddl()+1))++; + }; + +// mise a jour du tableau des ddl de variable actives +// et du tableau de ddl actives (variables et données) +void Noeud::MiseAjourActif() + { // ------- cas des variables uniquement -------- + // tout d'abord on regarde le nombre de ddl actif + int nbddlactif = 0; + int tab_ddlTaille = tab_ddl.Taille(); + for (int i = 1; i<=tab_ddlTaille; i++) + if ((tab_ddl(i).Service())&&(tab_ddl(i).UneVariable())) nbddlactif++; + // dimensionnement du tableau de pointeur + if (tab_var_actives.Taille() != nbddlactif) tab_var_actives.Change_taille(nbddlactif); + // remplissage du tableau + int indice = 1; + for (short int i = 1; i<=tab_ddlTaille; i++) + if ((tab_ddl(i).Service())&&(tab_ddl(i).UneVariable())) + {tab_var_actives(indice) = i; indice++; } + // -------- cas des données et des variables ---------- + nbddlactif = 0; + for (int i = 1; i<=tab_ddlTaille; i++) + if (tab_ddl(i).Service()) nbddlactif++; + // dimensionnement du tableau de pointeur + if (tab_actif.Taille() != nbddlactif) tab_actif.Change_taille(nbddlactif); + // remplissage du tableau + indice = 1; + for (short int i = 1; i<=tab_ddlTaille; i++) + if (tab_ddl(i).Service()) + {tab_actif(indice) = i; indice++; } + + }; + +// lecture des grandeurs quelconques sur flot +void Noeud::Lecture_grandeurs_quelconque(istream & ent) + { // la lecture est longue, ne sert que pour la visualisation en faite + string nom; + ent >> nom >> nbTypeQ_update; + if (nbTypeQ_update != 0) // lecture que s'il y a des types updatées enregistrées + { // tout d'abord on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes + TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE); + // lecture de l'entête et récup d'enu + EnuTypeQuelParticulier enu = pour_lire.Lecture_un(ent); + // on regarde si ce type quelconque existe déjà + int indice = Indice_grandeur_quelconque(pour_lire.EnuTypeQuelconque()); + if (indice == 0) + { // cas d'une grandeur qui n'existe pas déjà, on la crée + int tailtab = tab_type_quel.Taille();tailtab++; + tab_type_quel.Change_taille(tailtab); + update_type_quel.Change_taille(tailtab); // =0 par défaut + // création d'une grandeur associée et lecture des information sur le flot + TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent); + // création d'un type quelconque + TypeQuelconque tq(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur); + delete grandeur; // car il ne sert plus à rien + // affectation + tab_type_quel(tailtab)=tq;update_type_quel(tailtab)=1; //normalement update + } + else + { // cas d'une grandeur qui existe déjà + ent >> tab_type_quel(indice);update_type_quel(indice)=1; //normalement update + }; + }; + }; + +// écriture des grandeurs quelconques sur flot +void Noeud::Ecriture_grandeurs_quelconque(ostream & sort) const + { // on ne sauvegarde que les grandeurs updatées et qui sont prévu pour une sauvegarde + sort << " G_quel " << nbTypeQ_update << " "; // en tête et nombre de grandeurs updatées + int tailupdate = update_type_quel.Taille(); + for (int i=1;i<=tailupdate;i++) + { if (update_type_quel(i) != 0) sort << tab_type_quel(i) << " ";}; + }; + +// récupe de l'indice d'une grandeur quelconque +// si la grandeur n'existe pas -> ramène 0 +int Noeud::Indice_grandeur_quelconque(TypeQuelconque_enum_etendu a) + { int tailtab = tab_type_quel.Taille(); + for (int i=posi_type_quel;i<=tailtab;i++) + { if ( tab_type_quel(i).EnuTypeQuelconque() == a) + { posi_type_quel=i; return i;} + }; + // cas on la grandeur a chercher est peut-être au début du tableau + for (int j=1;j< posi_type_quel;j++) + { if ( tab_type_quel(j).EnuTypeQuelconque() == a) + { posi_type_quel=j; return j;} + }; + // cas où l'on n'a pas trouvé la grandeur + return 0; + }; + +// mise a jour de l'adressage via l'identificateur d'énumération +// c'est-à-dire la gestion via list_tab_typeQuelconque et popos_Quelconque +// ne doit être appelé que si l'on a introduit un nouveau type quelconque !! +// ou changé l'ordre etc.. +void Noeud::MiseAjourTypeQuelconque() + { // la méthode sert à mettre à jour les différents indicateurs d'adressage rapides + // 1-- s'il n'y a pas de type quelconque, on regarde si le pointeur de tableau a changé + // utilisé par exemple par le destructeur, ou les constructeurs + + // on récupère le nombre maxi de type de grandeurs quelconques existantes actuellement + // (ce nombre n'est pas forcément fixe pendant le calcul, on peut avoir de nouvelle grandeur qui + // sont définit pendant le calcul : typiquement associée à de nouvelles grandeurs globales créées par + // l'utilisateur: ex: le calcul d'une intégrale) + int nbmaxTypeQ = TypeQuelconque_enum_etendu::NBmax_TypeQuelconque_enum_etendue(); + if (tab_type_quel.Taille() == 0) // -> pas de type quelconque stocké + { if (pos_Quelconque == list_tab_typeQuelconque.end()) + // cela signifie qu'il n'y a jamais eu de type quelconque pour tous les noeuds + // et qu'il n'y a rien à faire, retour directe + {return;} + else // sinon c'est le cas d'une destruction de types quelconques + // on met à jour les indicateurs ad hoc + { // l'avant dernier élément du tableau contient le nombre de noeud qui utilise ce type + int taille_pos_quelconque = (*pos_Quelconque).Taille(); +// on n'utilise pas nbmaxTypeQ car il peut varier pendant le calcul if ((*pos_Quelconque)(nbmaxTypeQ+1) == 1) + if ((*pos_Quelconque)(taille_pos_quelconque-1) == 1) + // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau + list_tab_typeQuelconque.erase(pos_Quelconque); + else + // sinon on décrémente le compteur + ((*pos_Quelconque)(taille_pos_quelconque-1))--; + // puis on met à jour le pointeur + pos_Quelconque = list_tab_typeQuelconque.end(); // -> veut dire pas de tableau associé + // et retour + return; + }; + }; + + // 2-- la suite concerne le cas où des types quelconque existent + // tout d'abord on regarde si le dernier tableau construit dans la liste + // convient, car ce sera le cas pour le cas courant + // le dernier tableau est positionné en début de liste. + list >::iterator ideb = list_tab_typeQuelconque.begin(); + list >::iterator iancien = pos_Quelconque; + int taille = tab_type_quel.Taille(); // nombre d'éléments quelconques actuellement stocké + // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position + bool okk = true; + // le test n'est effectué que si la liste n'est pas vide + if (list_tab_typeQuelconque.size() != 0) + { // d'abort la taille, on compte le nombre d'élément non nul + int ttail = (*ideb).Taille();// les deux dernières valeurs = le nombre de noeuds associés, le nombre de quelconque à considérer + int ttaile = (*ideb)(ttail); // == le nombre de quelconque qui sont considérer + if (taille != ttaile) // -> là c'est sûr que cela ne convient pas car déjà le nombre est différent + okk = false; + else // sinon on test les contenues + // maintenant le contenu + for (int i = 1; i<= taille;i++) + if( (*ideb)(tab_type_quel(i).EnuTypeQuelconque().Position()) != i) + { okk = false; break;} + } + else // si n'existe pas encore, il faut le créer + {okk = false;}; + // si le tableau convient on met à jour le pointeur et c'est fini + // sinon on passe en revu toute la liste + if (okk) + {pos_Quelconque = ideb;} // cas ou on n'a pas à faire de création + else // ---- cas où on passe en revue la liste : cas d'une création ----- + // ici la procédure est plus longue, mais normalement elle ne sera + // utilisé que peut souvent + { + // on reconstruit un tableau d'adressage indirect des types quelconques + // la taille du tableau d'adressage est celui du nombre maxi + // de type quelconques différent (donc certain ne serviront pas) + // les données du tableau sont initialisées à 0, ainsi si l'on + // cherche à utiliser un type quelconque indice 0, l'erreur sera détecté au + // niveau de Tableau_T + // l'avant dernier élément du tableau sert à stocker le nombre de noeud + // qui utilise le tableau + // le dernier élément indique le nombre d'élément non nul + Tableau tab_indi_TypeQ(nbmaxTypeQ+2,0); + for (int i=1;i<=taille;i++) + tab_indi_TypeQ(tab_type_quel(i).EnuTypeQuelconque().Position())=i; + // on enregistre la taille + tab_indi_TypeQ(nbmaxTypeQ+2) = taille; + // maintenant on va regarder si ce tableau existe dans la liste + list >::iterator ifin = list_tab_typeQuelconque.end(); + list >::iterator iter; + bool trouver = false; + for (iter = ideb;ideb!= ifin;ideb++) + if ((*iter) == tab_indi_TypeQ) + { trouver = true; break;} + // si pas trouver on ajoute sinon on utilise la position déjà existante + if (!trouver) + // cas où on n'a pas trouvé de tableau + { list_tab_typeQuelconque.push_front(tab_indi_TypeQ); // allocation + // on attribue le nouveau pointage + pos_Quelconque = list_tab_typeQuelconque.begin(); // sauvegarde de la position + } + else // cas où on a trouvé un tableau dans la liste + pos_Quelconque = iter; + }; + // --- gestions des tableaux ---- + // l'idée est ici la suivante: si le pointeur de tableau: pos_Quelconque a changé par rapport à iancien + // et que iancien était associé à un seul noeud, alors il faut le supprimer car il n'est plus associé à aucun noeud + // évidemment ceci n'est a considérer que si iancien pointait sur quelque chose de valide + + int taille_pos_quelconque = (*pos_Quelconque).Taille(); // récup de la taille actuelle + // on regarde si pos_Quelconque était déjà attribué + // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau + // (permet de supprimer les tableaux qui ne servent plus) + if (iancien != pos_Quelconque) + { // cas où on a changé de pointeur de tableau + if (iancien != list_tab_typeQuelconque.end()) + // cas où ce n'est pas la première initialisation + {int taille_pos_ancien = (*iancien).Taille(); + if ((*iancien)(taille_pos_ancien-1) == 1) + // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau + list_tab_typeQuelconque.erase(iancien); + else + // sinon on décrémente le compteur + ((*iancien)(taille_pos_ancien-1))--; + // maintenant on s'occupe du nouveau pointage + ((*pos_Quelconque)(taille_pos_quelconque-1))++; + } + else + // c'est la première initialisation + // on incrémente le compteur du tableau: -> on ajoute 1 noeud + ((*pos_Quelconque)(taille_pos_quelconque-1))++; + }; + // si iancien == pos_Quelconque, il n'y a pas eu de nouveau noeud ajouté, donc rien à faire + }; + +// --- cas des Ddl_enum_etendu ---- + +// lecture des Ddl_enum_etendu sur flot +void Noeud::Lecture_Ddl_etendu(istream & ent) + { string nom; + ent >> nom >> nbddletendu_update; + tab_ddletendu.Change_taille(nbddletendu_update); + ent >> nom >> update_ddletendu; + int tailupdate = update_ddletendu.Taille(); + for (int i=1;i<=tailupdate;i++) + { if (update_ddletendu(i) != 0) ent >> tab_ddletendu(i) ;}; + }; + +// écriture des Ddl_enum_etendu sur flot +void Noeud::Ecriture_Ddl_etendu(ostream & sort) const + { // on ne sauvegarde que les grandeurs updatées et qui sont prévu pour une sauvegarde + sort << "\n G_ddletendu " << nbddletendu_update << " "; // en tête et nombre de grandeurs updatées + // écriture du tableau d'update + sort << "\n update_ddletendu: "<< update_ddletendu << " "; + // sortie conditionnelle de tab_ddletendu + int tailupdate = update_ddletendu.Taille(); + for (int i=1;i<=tailupdate;i++) + { if (update_ddletendu(i) != 0) sort << tab_ddletendu(i) << " ";}; + }; + +// récupe de l'indice d'un Ddl_enum_etendu +// si la grandeur n'existe pas -> ramène 0 +int Noeud::Indice_Ddl_etendu(const Ddl_enum_etendu& a) + { int tailtab = tab_ddletendu.Taille(); + for (int i=posi_ddletendu;i<=tailtab;i++) + { if ( tab_ddletendu(i).Const_DdlEnumEtendu() == a) + { posi_ddletendu=i; return i;} + }; + // cas ou la grandeur a chercher est peut-être au début du tableau + for (int j=1;j< posi_ddletendu;j++) + { if ( tab_ddletendu(j).Const_DdlEnumEtendu() == a) + { posi_ddletendu=j; return j;} + }; + // cas où l'on n'a pas trouvé la grandeur + return 0; + }; + +// mise a jour de l'adressage via l'identificateur d'énumération +// c'est-à-dire la gestion via list_tab_ddletendu et pos_ddletendu +// ne doit être appelé que si l'on a introduit un nouveau Ddl_enum_etendu !! +// ou changé l'ordre etc.. +void Noeud::MiseAjourDdl_etendu() + { // la méthode sert à mettre à jour les différents indicateurs d'adressage rapides + // 1-- s'il n'y a pas de ddl étendue, on regarde si le pointeur de tableau a changé + // utilisé par exemple par le destructeur, ou les constructeurs + int nbmaxddleten = Ddl_enum_etendu::NBmax_ddl_enum_etendue(); + if (tab_ddletendu.Taille() == 0) + { if (pos_ddletendu == list_tab_ddletendu.end()) + // cela signifie qu'il n'y a jamais eu de ddl étendue et qu'il n'y a rien à faire, retour directe + {return;} + else // sinon c'est le cas d'une destruction des ddl étendue + // on met à jour les indicateurs ad hoc + { if ((*pos_ddletendu)(nbmaxddleten+1) == 1) + // cas où c'est le dernier noeud qui pointe sur ce tableau on supprime le tableau + list_tab_ddletendu.erase(pos_ddletendu); + else + // sinon on décrémente le compteur + ((*pos_ddletendu)(nbmaxddleten+1))--; + // puis on met à jour le pointeur + pos_ddletendu = list_tab_ddletendu.end(); // -> veut dire pas de tableau associé + // et retour + return; + }; + }; + + // 2-- la suite concerne le cas où il y a des ddl étendue + // tout d'abord on regarde si le dernier tableau construit dans la liste + // convient, car ce sera le cas courant + // le dernier tableau est positionné en début de liste. + list >::iterator ideb = list_tab_ddletendu.begin(); + list >::iterator iancien = pos_ddletendu; + int taille = tab_ddletendu.Taille(); + // le dernier élément stocké contiend le nombre d'élément non nul, on récupère sa position + bool okk = true; // init + // le test n'est effectué que si la liste n'est pas vide + if (list_tab_ddletendu.size() != 0) + { // d'abort la taille, on compte le nombre d'élément non nul + int ttail = (*ideb).Taille(); // les deux dernières valeurs = le nombre de noeuds associés, le nombre de ddl enum étendu à considérer + int ttaile = (*ideb)(ttail); + if (taille != ttaile) + okk = false; + else + // maintenant le contenu + for (int i = 1; i<= taille;i++) + if( (*ideb)(tab_ddletendu(i).Const_DdlEnumEtendu().Position()) != i) + { okk = false; break;} + } + else + {okk = false;}; + // si le tableau convient on met à jour le pointeur et c'est fini + // sinon on passe en revu toute la liste + if (okk) + pos_ddletendu = ideb; + else // ---- cas où on passe en revue la liste ----- + // ici la procédure est plus longue, mais normalement elle ne sera + // utilisé que peu souvent + { + // on reconstruit un tableau d'adressage indirect des ddl étendu + // la taille du tableau d'adressage est celui du nombre maxi + // de ddl étendu différents (donc certain ne serviron pas) + // les données du tableau sont initialisées à 0, ainsi si l'on + // cherche à utiliser un ddl étendu indice 0, l'erreur sera détecté au + // niveau de Tableau_T + // l'avant dernier élément du tableau sert à stocker le nombre de noeud + // qui utilise le tableau + // le dernier élément indique le nombre d'élément non nul + Tableau tab_indi_ddletendu(nbmaxddleten+2,0); + for (int i=1;i<=taille;i++) + tab_indi_ddletendu(tab_ddletendu(i).Const_DdlEnumEtendu().Position())=i; + // on enregistre la taille + tab_indi_ddletendu(nbmaxddleten+2) = taille; + // maintenant on va regarder si ce tableau existe dans la liste + list >::iterator ifin = list_tab_ddletendu.end(); + list >::iterator iter; + bool trouver = false; + for (iter = ideb;ideb!= ifin;ideb++) + if ((*iter) == tab_indi_ddletendu) + { trouver = true; break;} + // si pas trouver on ajoute sinon on utilise la position déjà existante + if (!trouver) + // cas où on n'a pas trouvé de tableau + { list_tab_ddletendu.push_front(tab_indi_ddletendu); // allocation + // on attribue le nouveau pointage + pos_ddletendu = list_tab_ddletendu.begin(); // sauvegarde de la position + } + else // cas où on a trouvé un tableau dans la liste + pos_ddletendu = iter; + }; + // --- gestions des tableaux ---- + // l'idée est ici la suivante: si le pointeur de tableau: pos_ddletendu a changé par rapport à iancien + // et que iancien était associé à un seul noeud, alors il faut le supprimer car il n'est plus associé à aucun noeud + // évidemment ceci n'est a considérer que si iancien pointait sur quelque chose de valide + + // on regarde si pos_ddletendu était déjà attribué + // l'avant dernier élément stocké contiend le nombre de noeud qui utilise le tableau + // (permet de supprimer les tableaux qui ne servent plus) + if (iancien != pos_ddletendu) + { // cas où on a changé de pointeur de tableau + if (iancien != list_tab_ddletendu.end()) + // cas où ce n'est pas la première initialisation + {if ((*iancien)(nbmaxddleten+1) == 1) + // cas où c'est le dernier noeud qui pointe sur ce tableau + // on supprime le tableau + list_tab_ddletendu.erase(iancien); + else + // sinon on décrémente le compteur + ((*iancien)(nbmaxddleten+1))--; + // maintenant on s'occupe du nouveau pointage + ((*pos_ddletendu)(nbmaxddleten+1))++; + } + else + // c'est la première initialisation + // on incrémente le compteur du tableau + ((*pos_ddletendu)(nbmaxddleten+1))++; + }; + // si iancien == pos_ddletendu, il n'y a pas eu de nouveau noeud ajouté, donc rien à faire + }; + +// ordonne et on met a suivre les ddl d'une même famille suivant un ordre croissant +// ceci pour des ddl que l'on vient d'ajouter, QUE L'ON CONSIDÈRE ÊTRE À LA FIN DE TAB_DDL ! +// en paramètre le ou les ddl +/*void Noeud::OrdonneDdlMemeFamille(const Ddl& a) +{ // on ne traite que si la dimension est supérieur à 1 ou que le ddl fait partie d'une famille + if ((ParaGlob::Dimension()>1)&&FoncDim(a.Id_nom())) + {Enum_ddl enu=a.Id_nom(); int dim = ParaGlob::Dimension();// pour simplifier + // On parcourt le tableau pour trouver les autres ddl de la même famille + // et on en profite pour ordonner les ddl + Tableau ptin(dim); int irecup=0; + int taille=tab_ddl.Taille(); + for (int i=0; i<= taille-1;i++) + if (Meme_famille(tab_ddl(i).Id_nom(),enu)) + {if (tab_ddl(i).Id_nom() > enu) + Permutation_2ddl(i,taille); + irecup++; ptin(irecup)=i; + }; + // -- maintenant les ddl de la même famille sont dans un ordre croissant, il reste + // -- à les mettre à suivre + // on continu que si effectivement il y a des autre ddl de la même famille + if (irecup == 0) return; // retour car aucun ddl de la meme famille + // on traite en fonction de irecup + if (irecup == 1) + {// cas sympathique ou l'on a simplement à permutter deux positions du tableau + Enum_ddl enu1=tab_ddl(ptin(irecup)).Id_nom(); + if (ptin(irecup)==taille-1) + {return;}// cas déjà à suivre + else // sinon on permutte le suivant de enu1 et enu + {Permutation_2ddl(ptin(irecup)+1,taille);} + } + else // cas + +}; + +void Noeud::OrdonneDdlMemeFamille(const Tableau& ta) + { + + }; + +// permutation de deux ddl (sert pour OrdonneDdlMemeFamille) +void Noeud::Permutation_2ddl(const int& ipo1,cont int& ipo2) + { // tout d'abord le ddl + Ddl intir=tab_ddl(ipo1); + tab_ddl(ipo1)=tab_ddl(ipo2); tab_ddl(ipo2)=intir; + // maintenant les valeurs à 0 + double xnia0=tab_0(ipo1); + tab_0(ipo1)=tab_0(ipo2); tab_0(ipo2)=xnia0; + // éventuellement les valeurs à tdt + if (tab_tdt.Taille()!=0) + { double xniatdt=tab_tdt(ipo1); + tab_tdt(ipo1)=tab_tdt(ipo2); tab_tdt(ipo2)=xniatdt; + }; + }; */ + +// ordonner un tableau de ddl suivant un ordre croissant et avec des ddl à suivre +void Noeud::OrdonnerTableauDdl(Tableau& ta) + { int tataille = ta.Taille(); + for (int i1=1;i1<=tataille;i1++) + {for (int j1=i1+1;j1<=tataille;j1++) + if (ta(i1).Id_nom() > ta(j1).Id_nom()) + {// il ne sont pas dans le bonne ordre on permutte + Ddl intir = ta(i1); + ta(i1)=ta(j1); + ta(j1)=intir; + } + } + }; + +// liste des ddl (en famille) à ajouter +// (la liste est initialisée au début) +// recopie des ddl existant déjà +// change_donn_var indique si les ddl existant on été modifiée +void Noeud::ListeDdlAajouter(list& liDdl,Tableau& ta,bool& change_donn_var) +{ // dans la liste existante tous les ddl des familles existantes, sont présents + // et ordonné dans chaque famille mais par forcément globalement, + // par contre dans ta on peut avoir que certains représentants de famille + // mais ta est également ordonnée + // on regarde combien de Ddl existe deja + list ::iterator il; + liDdl.clear(); // init au début + list li_travail; // une liste de travaille + int j=1; + int taille=tab_ddl.Taille(); + int tataille=ta.Taille(); + if (j>tataille) return; // cas d'un tableau vide + do + { bool rel = false;Enum_ddl enu=ta(j).Id_nom(); + // on cherche si le ddl existe déjà + for (int i=1;i<= taille; i++) + {if (tab_ddl(i).Id_nom() == enu) + { rel = true; + tab_ddl(i) = ta(j); + change_donn_var=true; + j++; // on passe au suivant + break; + }; + }; + + // cas où il n'y a pas de ddl existant + if (!rel) + {// dans le cas d'une famille: + // on regarde si tous les ddl de la famille font partie de la liste + if (FoncDim(enu) && (ParaGlob::Dimension()!=1)) + {// on récupère tous les ddl de la famille + Tableau t_enu =TableauTypeDdl(enu); + int ttlle = t_enu.Taille(); + // on regarde tout d'abord si les premiers ddl sont présents + // sachant que enu est le plus petit de la famille ! (car ta est ordonné) + int iy=0; + for (iy=1;iy<=ttlle;iy++) + {if (t_enu(iy)!=enu) + { // on regarde également s'il est déjà dans la liste, si oui, on passe + if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) + {li_travail.push_back(t_enu(iy)); + // on ajoute le ddl pour l'instant hors service et a priori libre + Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE); + liDdl.push_back(addl); + }; + } + else + { // on regarde également s'il est déjà dans la liste, si oui, on passe + if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) + {li_travail.push_back(t_enu(iy)); + // il n'existe pas , on ajoute le bon ddl + liDdl.push_back(ta(j)); + } + else // il exite, on met la bonne valeur + { list ::iterator ith,ithfin=liDdl.end(); + for (ith = liDdl.begin();ith!=ithfin;ith++) + { if ((*ith).Id_nom() == t_enu(iy)) + {(*ith)=ta(j);break;} + }; + }; + break; + }; + }; + + iy++; // on passe à l'enu suivant des ddl de la famille + // maintenant on balaie les enu restants si nécessaire + j++; //on incrémente car on regarde l'élément suivant du tableau + for (;iy<=ttlle;iy++) + { if(j <= tataille) // donc j est valide + { if ((t_enu(iy)!=ta(j).Id_nom())) + { // on regarde également s'il est déjà dans la liste, si oui, on passe + if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) + {li_travail.push_back(t_enu(iy)); + // on ajoute le ddl pour l'instant hors service et a priori libre + Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE); + liDdl.push_back(addl); + }; + } + else + { // on regarde également s'il est déjà dans la liste, si oui, on passe + if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) + {li_travail.push_back(t_enu(iy)); + // il n'existe pas , on ajoute le bon ddl + liDdl.push_back(ta(j)); + } + else // il exite, on met la bonne valeur + { list ::iterator ith,ithfin=liDdl.end(); + for (ith = liDdl.begin();ith!=ithfin;ith++) + { if ((*ith).Id_nom() == t_enu(iy)) + {(*ith)=ta(j);break;} + }; + }; + break; + }; + } + else // cas ou le j n'est plus valide on rajoute les ddl manquants + { // on regarde également s'il est déjà dans la liste, si oui, on passe + if (find(li_travail.begin(),li_travail.end(),t_enu(iy)) == li_travail.end()) + {li_travail.push_back(t_enu(iy)); + // on ajoute le ddl pour l'instant hors service et a priori libre + Ddl addl(t_enu(iy),0.0,HS_LISIBLE_LIBRE); + liDdl.push_back(addl); + }; + }; + }; + } + else // cas d'un ddl qui n'appartient pas à une famille + // on l'ajoute tout simplement + { liDdl.push_back(ta(j)); + j++; + }; + }//-- fin du cas on on ajoute des ddl à la liste + } while (j<=tataille) ; + +}; + +// modification du type de laison entre noeud éventuel avec init des tableaux de liaison +// pour le cas d'assemblage nb_assemb +void Noeud::Change_Enu_liason(int nb_assemb, Enum_liaison_noeud enu_liai + ,const Tableau & tab_N_lier) + { + // on fait tout d'abord une petite vérification + if (enu_liai && ((tab_N_lier.Taille() == 0))) + { cout << "\n inchoerence !! on veut une liaison entre noeud mais le tableau de liaison est vide ! " + << "\n nb_assemb= "<< nb_assemb << " Enum_liaison_noeud= "<< Nom_liaison_noeud(enu_liai) + << " taille de tab_N_lier= " << tab_N_lier.Taille() + << "\n Noeud::Change_Enu_liason(... "<; + tab_ddl_lier = new Tableau < Tableau > ; + }; + // cas où il faut augmenter les tailles + if (nb_assemb > tab_enu_liaison->Taille()) + {tab_enu_liaison->Change_taille(nb_assemb); + tab_ddl_lier->Change_taille(nb_assemb); + }; + // maintenant on renseigne les valeurs + (*tab_enu_liaison)(nb_assemb) = enu_liai; + (*tab_ddl_lier)(nb_assemb) = tab_N_lier; + }; + +// suppression de tous les liaisons noeuds +void Noeud::Suppression_tous_liaisons_noeuds() + { if (tab_enu_liaison != NULL) + delete tab_enu_liaison; + if (tab_ddl_lier != NULL) + delete tab_ddl_lier; + }; + +// sortie du schemaXML: en fonction de enu +void Noeud::SchemaXML_Noeud(ofstream& sort,const Enum_IO_XML enu) + { switch (enu) + {case XML_TYPE_GLOBAUX: + {// on définit des types pour un maillage + sort << "\n " + << "\n" + << "\n " + << "\n un numero et 3 coordonnees " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n " + << "\n"; + break; + } + case XML_IO_POINT_INFO: + { // définition d'une liste de noeuds + // sort << "\n "; + break; + } + }; + }; + + + + + + diff --git a/Maillage/VariablesExporter.cc b/Maillage/VariablesExporter.cc new file mode 100755 index 0000000..3feeb94 --- /dev/null +++ b/Maillage/VariablesExporter.cc @@ -0,0 +1,3580 @@ +// FICHIER : VariablesExporter.cc +// CLASSE : VariablesExporter + +// 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 "VariablesExporter.h" +# include +using namespace std; //introduces namespace std +#include +#include "Sortie.h" +#include +#include +#include "List_io.h" +#include "CharUtil.h" +#include "TypeQuelconqueParticulier.h" +#include "Banniere.h" +#include "ReferenceNE.h" +#include "ReferenceAF.h" + + +// ------------ classes conteneur ---------------- +// ======== A_un_NE ============ + +// classe conteneur de base pour noeud et élément + +ostream & operator << ( ostream & sort,const VariablesExporter::A_un_NE & a) +{ sort << a.nom_var; + if (a.nom_mail != "") + {sort << " nom_mail= "<< a.nom_mail;}; + sort << " ref_ " << a.ref ; + + return sort; +}; + +// lecture +istream & operator >> ( istream & ent, VariablesExporter::A_un_NE & a) +{ string toto; + ent >> a.nom_var >> toto; + // lecture éventuelle d'un nom de maillage + if (toto == "nom_mail=") + {ent >> a.nom_mail >> toto;} + else if (toto == "ref_") + {a.nom_mail ="";} + else + {cout << "\n *** erreur de syntaxe en lecture d'une variable utilisateur," + << " on attendait soit la chaine de characteres: nom_mail= ou soit ref_ " + << " et on a lu: "<< toto << " !!" + << endl; + Sortie(1); + } ; + // fin de la lecture + ent >> a.ref ; + // vérif il faut que les 3 premiers caractères de a.nom_var soit un V__ + if (!((a.nom_var[0]== 'V')&&(a.nom_var[1]== '_')&&(a.nom_var[2]== '_'))) + { cout << "\n *** erreur de syntaxe en lecture d'une variable utilisateur," + << " les 3 premieres lettres " + << " devraientt etre un 'V__' et on a lu: "< (const A_un_NE& a) const + {if (nom_mail != a.nom_mail) + { return (nom_mail > a.nom_mail);} + else // cas nom_mail = a.nom_mail + { if (ref != a.ref) + {return (ref > a.ref);} + else //cas nom_mail = a.nom_mail et ref = a.ref + {if (nom_var != a.nom_var) + {return (nom_var > a.nom_var);} + else // cas où tout est égal on n'est pas supérieur + {return false;}; + }; + }; + }; + + +bool VariablesExporter::A_un_NE::operator>= (const A_un_NE& a) const + {if (nom_mail != a.nom_mail) + { return (nom_mail >= a.nom_mail);} + else // cas nom_mail = a.nom_mail + { if (ref != a.ref) + {return (ref >= a.ref);} + else //cas nom_mail = a.nom_mail et ref = a.ref + {if (nom_var != a.nom_var) + {return (nom_var >= a.nom_var);} + else // cas où tout est égal + {return true;}; + }; + }; + }; + +// affichage +void VariablesExporter::A_un_NE::Affiche() + { cout << "\n Variable utilisateur: " << nom_var + << " au_noeud_ref: " << ref + << " maillage: " << nom_mail; + }; + +// ======== Ddl_a_un_noeud ============ + +// classe conteneur pour un ddl à un noeud +ostream & operator << ( ostream & sort,const VariablesExporter::Ddl_a_un_noeud & a) +{ sort << "\n Ddl_noeud_ " << a.nom_var; + if (a.nom_mail != "") + {sort << " nom_mail= "<< a.nom_mail;}; + + sort << " ref_ " << a.ref_num_NE << " ddl_ " << a.enu + << " temps_ " << a.temps; + + + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::Ddl_a_un_noeud & a) +{// lecture du type et vérification + string nomtype; ent >> nomtype; + if (nomtype != "Ddl_noeud_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Ddl_noeud_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::Ddl_a_un_noeud(..."; + Sortie(1); + return ent; + }; + // lecture + string toto; + ent >> a.nom_var >> toto; + // lecture éventuelle d'un nom de maillage + if (toto == "nom_mail=") + {ent >> a.nom_mail >> toto;} + else if (toto == "ref_") + {a.nom_mail ="";} + else + {cout << "\n *** erreur de syntaxe en lecture d'une variable utilisateur de type ddl," + << " on attendait soit la chaine de characteres: nom_mail= ou soit ref_ " + << " et on a lu: "<< toto << " !!" + << endl; + Sortie(1); + } ; + // fin de la lecture + ent >> a.ref_num_NE >> toto >> a.enu >> toto >> a.temps; + + // vérif il faut que les 3 premiers caractères de a.nom_var soit un V__ + if (!((a.nom_var[0]== 'V')&&(a.nom_var[1]== '_')&&(a.nom_var[2]== '_'))) + { cout << "\n *** erreur de syntaxe en lecture d'une variable utilisateur de type ddl," + << " les 3 premieres lettres " + << " devraientt etre un 'V__' et on a lu: "< (const Ddl_a_un_noeud& a) const +{if (enu != a.enu) + { return (enu > a.enu);} + else // cas enu = a.enu + {if (nom_mail != a.nom_mail) + { return (nom_mail > a.nom_mail);} + else // cas enu = a.enu et nom_mail = a.nom_mail + { if (ref_num_NE != a.ref_num_NE) + {return (ref_num_NE > a.ref_num_NE);} + else //cas enu = a.enu et nom_mail = a.nom_mail et ref_num_NE = a.ref_num_NE + {if (nom_var != a.nom_var) + {return (nom_var > a.nom_var);} + else //cas enu = a.enu et nom_mail = a.nom_mail et ref_num_NE = a.ref_num_NE + // et nom_var == a.nom_var + {if (temps != a.temps) + {return (temps <= a.temps);} + else // cas où tout est égal on n'est pas supérieur + {return false;}; + }; + }; + }; + }; +}; + + +bool VariablesExporter::Ddl_a_un_noeud::operator>= (const Ddl_a_un_noeud& a) const +{if (enu != a.enu) + { return (enu >= a.enu);} + else // cas enu = a.enu + {if (nom_mail != a.nom_mail) + { return (nom_mail >= a.nom_mail);} + else // cas enu = a.enu et nom_mail = a.nom_mail + { if (ref_num_NE != a.ref_num_NE) + {return (ref_num_NE >= a.ref_num_NE);} + else //cas enu = a.enu et nom_mail = a.nom_mail et ref_num_NE = a.ref_num_NE + {if (nom_var != a.nom_var) + {return (nom_var >= a.nom_var);} + else //cas enu = a.enu et nom_mail = a.nom_mail et ref_num_NE = a.ref_num_NE + // et nom_var == a.nom_var + {if (temps != a.temps) + {return (temps <= a.temps);} + else // cas où tout est égal + {return true;}; + }; + }; + }; + }; +}; + +// affichage +void VariablesExporter::Ddl_a_un_noeud::Affiche() + { cout << "\n Variable utilisateur: " << nom_var + << "ddl " << enu.Nom_plein() + << " au_noeud_ref: " << ref_num_NE + << " maillage: " << nom_mail + << " temps= " << temps; + }; + +// ======== Ddl_etendu_a_un_noeud ============ + +// classe conteneur pour un ddl étendu à un noeud +ostream & operator << ( ostream & sort,const VariablesExporter::Ddl_etendu_a_un_noeud & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::A_un_NE* aA = a.PointeurClass_const(); + // sortie + sort << "\n Ddl_etendu_a_un_noeud_ "; + sort << *aA; // la classe mère + sort << " ddl_etendu_ "<< a.Enu_const() << " "; + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::Ddl_etendu_a_un_noeud & a) +{ // récup du pointeur de la classe mère + VariablesExporter::A_un_NE* aA = a.PointeurClass(); + // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Ddl_etendu_a_un_noeud_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Ddl_etendu_a_un_noeud_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::Ddl_etendu_a_un_noeud(..."; + Sortie(1); + return ent; + }; + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref de noeud + if (aA->Ref_NE()[0] != 'N') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference de noeud ," + << " la premiere lettre " + << " devraientt etre N et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + // lecture du ddl étendu + ent >> toto >> a.enu ; + + return ent; +}; + +VariablesExporter::Ddl_etendu_a_un_noeud::Ddl_etendu_a_un_noeud () : // constructeur par défaut + A_un_NE(),enu() {}; +// constructeur fonction de toutes les grandeurs +VariablesExporter::Ddl_etendu_a_un_noeud::Ddl_etendu_a_un_noeud + (Ddl_enum_etendu e,string ref_noeud,string nom_mail_,string nom_var_) : + A_un_NE(ref_noeud,nom_mail_,nom_var_) + ,enu(e) + {}; +// constructeur de copie +VariablesExporter::Ddl_etendu_a_un_noeud::Ddl_etendu_a_un_noeud (const Ddl_etendu_a_un_noeud& a) : + A_un_NE(a) + ,enu(a.enu) + {}; +// destructeur +VariablesExporter::Ddl_etendu_a_un_noeud::~Ddl_etendu_a_un_noeud() + {}; + +// opérateurs +VariablesExporter::Ddl_etendu_a_un_noeud& VariablesExporter::Ddl_etendu_a_un_noeud::operator= + (const VariablesExporter::Ddl_etendu_a_un_noeud& a) + {enu = a.enu; + *(this->PointeurClass()) = *(a.PointeurClass_const()); + return (*this); + }; + +bool VariablesExporter::Ddl_etendu_a_un_noeud::operator== (const Ddl_etendu_a_un_noeud& a) const + {if ((enu ==a.enu) + && (*(this->PointeurClass_const()) == *(a.PointeurClass_const()))) + return true; + else + return false; + }; + +bool VariablesExporter::Ddl_etendu_a_un_noeud::operator< (const Ddl_etendu_a_un_noeud& a) const +{if (enu != a.enu) + { return (enu < a.enu);} + else // cas enu = a.enu + {return (*(this->PointeurClass_const()) < *(a.PointeurClass_const()));} +}; + +bool VariablesExporter::Ddl_etendu_a_un_noeud::operator<= (const Ddl_etendu_a_un_noeud& a) const +{if (enu != a.enu) + { return (enu <= a.enu);} + else // cas enu = a.enu + {return (*(this->PointeurClass_const()) <= *(a.PointeurClass_const()));} +}; + +bool VariablesExporter::Ddl_etendu_a_un_noeud::operator> (const Ddl_etendu_a_un_noeud& a) const +{if (enu != a.enu) + { return (enu > a.enu);} + else // cas enu = a.enu + {return (*(this->PointeurClass_const()) > *(a.PointeurClass_const()));} +}; + + +bool VariablesExporter::Ddl_etendu_a_un_noeud::operator>= (const Ddl_etendu_a_un_noeud& a) const +{if (enu != a.enu) + { return (enu >= a.enu);} + else // cas enu = a.enu + {return (*(this->PointeurClass_const()) >= *(a.PointeurClass_const()));} +}; + +// affichage +void VariablesExporter::Ddl_etendu_a_un_noeud::Affiche() + { A_un_NE::Affiche(); + cout << " Ddl_etendu_a_un_noeud_ " << Enu() ; + }; + +// ======== Quelconque_a_un_noeud ============ + +// classe conteneur pour une grandeur quelconque à un noeud +ostream & operator << ( ostream & sort,const VariablesExporter::Quelconque_a_un_noeud & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::A_un_NE* aA = a.PointeurClass_const(); + // récup de l'énuméré du type quelconque + const TypeQuelconque_enum_etendu& quelc = a.Quelc_const(); + // sortie + sort << "\n Quelconque_a_un_noeud_ " ; + sort << *aA; // la classe mère + sort << " grandeur_quelconque_ " << quelc.NomPlein() << " composante: " << a.num_ordre << " "; + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::Quelconque_a_un_noeud & a) +{ // récup du pointeur de la classe mère + VariablesExporter::A_un_NE* aA = a.PointeurClass(); + // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Quelconque_a_un_noeud_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Quelconque_a_un_noeud_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::Quelconque_a_un_noeud(..."; + Sortie(1); + return ent; + }; + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref de noeud + if (aA->Ref_NE()[0] != 'N') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference de noeud ," + << " la premiere lettre " + << " devraientt etre N et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + // lecture de la grandeur quelconque + string nom_quelc; + ent >> toto >> nom_quelc; + a.quelc = TypeQuelconque_enum_etendu(nom_quelc); + + ent >> toto >> a.num_ordre; + return ent; +}; + +VariablesExporter::Quelconque_a_un_noeud::Quelconque_a_un_noeud () : // constructeur par défaut + A_un_NE(),quelc() {}; +// constructeur fonction de toutes les grandeurs +VariablesExporter::Quelconque_a_un_noeud::Quelconque_a_un_noeud + (TypeQuelconque_enum_etendu e,string ref_noeud,string nom_mail_,string nom_var_,int num_ord) : + A_un_NE(ref_noeud,nom_mail_,nom_var_) + ,quelc(e),num_ordre(num_ord) + {}; +// constructeur de copie +VariablesExporter::Quelconque_a_un_noeud::Quelconque_a_un_noeud (const Quelconque_a_un_noeud& a) : + A_un_NE(a) + ,quelc(a.quelc),num_ordre(a.num_ordre) + {}; +// destructeur +VariablesExporter::Quelconque_a_un_noeud::~Quelconque_a_un_noeud() + {}; + +// opérateurs +VariablesExporter::Quelconque_a_un_noeud& VariablesExporter::Quelconque_a_un_noeud::operator= + (const VariablesExporter::Quelconque_a_un_noeud& a) + {quelc = a.quelc;num_ordre = a.num_ordre; + *(this->PointeurClass()) = *(a.PointeurClass_const()); + return (*this); + }; + +bool VariablesExporter::Quelconque_a_un_noeud::operator== (const Quelconque_a_un_noeud& a) const + {if ((quelc==a.quelc) && (num_ordre == a.num_ordre) + && (*(this->PointeurClass_const()) == *(a.PointeurClass_const()))) + return true; + else + return false; + }; + +bool VariablesExporter::Quelconque_a_un_noeud::operator< (const Quelconque_a_un_noeud& a) const +{if (quelc != a.quelc) + { return (quelc < a.quelc);} + else // cas quelc = a.quelc + {if (num_ordre != a.num_ordre) + {return (num_ordre < a.num_ordre); } + else + {return (*(this->PointeurClass_const()) < *(a.PointeurClass_const()));} + }; +}; + +bool VariablesExporter::Quelconque_a_un_noeud::operator<= (const Quelconque_a_un_noeud& a) const +{if (quelc != a.quelc) + { return (quelc <= a.quelc);} + else // cas quelc = a.quelc + {if (num_ordre != a.num_ordre) + {return (num_ordre <= a.num_ordre); } + else + {return (*(this->PointeurClass_const()) <= *(a.PointeurClass_const()));} + }; +}; + +bool VariablesExporter::Quelconque_a_un_noeud::operator> (const Quelconque_a_un_noeud& a) const +{if (quelc != a.quelc) + { return (quelc > a.quelc);} + else // cas quelc = a.quelc + {if (num_ordre != a.num_ordre) + {return (num_ordre > a.num_ordre); } + else + {return (*(this->PointeurClass_const()) > *(a.PointeurClass_const()));} + }; +}; + + +bool VariablesExporter::Quelconque_a_un_noeud::operator>= (const Quelconque_a_un_noeud& a) const +{if (quelc != a.quelc) + { return (quelc >= a.quelc);} + else // cas quelc = a.quelc + {if (num_ordre != a.num_ordre) + {return (num_ordre >= a.num_ordre); } + else + {return (*(this->PointeurClass_const()) >= *(a.PointeurClass_const()));} + }; +}; + +// affichage +void VariablesExporter::Quelconque_a_un_noeud::Affiche() + { A_un_NE::Affiche(); + cout << " quelconque_a_un_noeud_ " << quelc.NomPlein() + << " composante: " << num_ordre ; + }; + +// ======== A_un_E ============ + +// classe conteneur pour un élément +ostream & operator << ( ostream & sort,const VariablesExporter::A_un_E & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::A_un_NE* aA = a.PointeurClass_const(); + // sortie + sort << *aA; // la classe mère + sort << " absolu_ " << a.absolu + << " num_pti_ " << a.num_pti + << " "; + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::A_un_E & a) +{ // récup du pointeur de la classe mère + VariablesExporter::A_un_NE* aA = a.PointeurClass(); + // lecture du type et vérification + // lecture de la partie mère + ent >> *aA ; + // on vérifie également qu'il s'agit bien d'une ref d'élément + if (aA->Ref_NE()[0] != 'E') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference d'element ," + << " la premiere lettre " + << " devraientt etre E et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + string toto; + ent >> toto; + // lecture éventuelle du paramètre absolu + if (toto == "absolu_") + {ent >> a.absolu >> toto;} + else if (toto == "num_pti_") + {a.absolu = 1;} + else + {cout << "\n *** erreur de syntaxe en lecture d'une variable utilisateur," + << " on attendait soit la chaine de characteres: absolu_ ou soit num_pti_ " + << " et on a lu: "<< toto << " !!" + << endl; + Sortie(1); + } ; + // fin de la lecture + ent >> a.num_pti ; + + return ent; +}; + +VariablesExporter::A_un_E::A_un_E () : // constructeur par défaut + A_un_NE(),num_pti(0),absolu(1) {}; +// constructeur fonction de toutes les grandeurs +VariablesExporter::A_un_E::A_un_E + (int absolu_,string ref + ,string nom_mail_,string nom_var_,int nbpti) : + A_un_NE(ref,nom_mail_,nom_var_) + ,num_pti(nbpti),absolu(absolu_) + {}; +// constructeur de copie +VariablesExporter::A_un_E::A_un_E (const A_un_E& a) : + A_un_NE(a) + ,num_pti(a.num_pti),absolu(a.absolu) + {}; +// destructeur +VariablesExporter::A_un_E::~A_un_E() + {}; + +// opérateurs +VariablesExporter::A_un_E& VariablesExporter::A_un_E::operator= + (const VariablesExporter::A_un_E& a) + {num_pti=a.num_pti; + absolu = a.absolu; + *(this->PointeurClass()) = *(a.PointeurClass_const()); + return (*this); + }; + +bool VariablesExporter::A_un_E::operator== (const A_un_E& a) const + {if (((num_pti==a.num_pti)&&(absolu ==a.absolu) + && (*(this->PointeurClass_const()) == *(a.PointeurClass_const()))) + ) + return true; + else + return false; + }; + +bool VariablesExporter::A_un_E::operator< (const A_un_E& a) const +{ if (num_pti != a.num_pti) + {return (num_pti < a.num_pti);} + else // num_pti == a.num_pti + {if (absolu != a.absolu) + {return (absolu < a.absolu);} + else + {return (*(this->PointeurClass_const()) < *(a.PointeurClass_const()));} + } + }; + +bool VariablesExporter::A_un_E::operator<= (const A_un_E& a) const + { if (num_pti != a.num_pti) + {return (num_pti <= a.num_pti);} + else // num_pti == a.num_pti + {if (absolu != a.absolu) + {return (absolu <= a.absolu);} + else + {return (*(this->PointeurClass_const()) <= *(a.PointeurClass_const()));} + } + }; + +bool VariablesExporter::A_un_E::operator> (const A_un_E& a) const + { if (num_pti != a.num_pti) + {return (num_pti > a.num_pti);} + else // num_pti == a.num_pti + {if (absolu != a.absolu) + {return (absolu > a.absolu);} + else + {return (*(this->PointeurClass_const()) > *(a.PointeurClass_const()));} + }; + }; + + +bool VariablesExporter::A_un_E::operator>= (const A_un_E& a) const + { if (num_pti != a.num_pti) + {return (num_pti >= a.num_pti);} + else // temps == a.temps et num_pti == a.num_pti + {if (absolu != a.absolu) + {return (absolu >= a.absolu);} + else + {return (*(this->PointeurClass_const()) >= *(a.PointeurClass_const()));} + } + }; + +// affichage +void VariablesExporter::A_un_E::Affiche() + { A_un_NE::Affiche(); + cout << " absolu= " << absolu + << " num_pti= " << num_pti << " "; + }; + +// ======== Ddl_a_un_element ============ + +// classe conteneur pour un ddl à un élément +ostream & operator << ( ostream & sort,const VariablesExporter::Ddl_a_un_element & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::A_un_E* aA = a.PointeurClass_E_const(); + // sortie + sort << "\n Ddl_a_un_element_ "; + sort << *aA; // la classe mère + sort << " temps_ " << a.temps + << " ddl_ "<< a.enu << " "; + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::Ddl_a_un_element & a) +{ // récup du pointeur de la classe mère + VariablesExporter::A_un_E* aA = a.PointeurClass_E(); + // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Ddl_a_un_element_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Ddl_a_un_element_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::Ddl_a_un_element(..."; + Sortie(1); + return ent; + }; + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref d'élément + if (aA->Ref_NE()[0] != 'E') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference d'element ," + << " la premiere lettre " + << " devraientt etre E et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + // lecture du ddl étendu + ent >> toto >> a.temps >> toto >> a.enu ; + + return ent; +}; + +VariablesExporter::Ddl_a_un_element::Ddl_a_un_element () : // constructeur par défaut + A_un_E(),enu(),temps() {}; +// constructeur fonction de toutes les grandeurs +VariablesExporter::Ddl_a_un_element::Ddl_a_un_element + (int absolu_,Ddl_enum_etendu e,string ref_NE + ,string nom_mail_,Enum_dure tps,string nom_var_,int nbpti) : + A_un_E(absolu_,ref_NE,nom_mail,nom_var,nbpti) + ,enu(e),temps(tps) + {}; +// constructeur de copie +VariablesExporter::Ddl_a_un_element::Ddl_a_un_element (const Ddl_a_un_element& a) : + A_un_E(a) + ,enu(a.enu),temps(a.temps) + {}; +// destructeur +VariablesExporter::Ddl_a_un_element::~Ddl_a_un_element() + {}; + +// opérateurs +VariablesExporter::Ddl_a_un_element& VariablesExporter::Ddl_a_un_element::operator= + (const VariablesExporter::Ddl_a_un_element& a) + {enu = a.enu;temps=a.temps; + *(this->PointeurClass()) = *(a.PointeurClass_E_const()); + return (*this); + }; + +bool VariablesExporter::Ddl_a_un_element::operator== (const Ddl_a_un_element& a) const + {if ((enu ==a.enu) && (temps == a.temps) + && (*(this->PointeurClass_E_const()) == *(a.PointeurClass_E_const()))) + return true; + else + return false; + }; + +bool VariablesExporter::Ddl_a_un_element::operator< (const Ddl_a_un_element& a) const +{if (enu != a.enu) + { return (enu < a.enu);} + else // cas enu = a.enu + {if (temps != a.temps) + {return (temps < a.temps);} + else + {return (*(this->PointeurClass_E_const()) < *(a.PointeurClass_E_const()));} + }; +}; + +bool VariablesExporter::Ddl_a_un_element::operator<= (const Ddl_a_un_element& a) const +{if (enu != a.enu) + { return (enu <= a.enu);} + else // cas enu = a.enu + {if (temps != a.temps) + {return (temps <= a.temps);} + else + {return (*(this->PointeurClass_E_const()) <= *(a.PointeurClass_E_const()));} + }; +}; + +bool VariablesExporter::Ddl_a_un_element::operator> (const Ddl_a_un_element& a) const +{if (enu != a.enu) + { return (enu > a.enu);} + else // cas enu = a.enu + {if (temps != a.temps) + {return (temps > a.temps);} + else + {return (*(this->PointeurClass_E_const()) > *(a.PointeurClass_E_const()));} + }; +}; + + +bool VariablesExporter::Ddl_a_un_element::operator>= (const Ddl_a_un_element& a) const +{if (enu != a.enu) + { return (enu >= a.enu);} + else // cas enu = a.enu + {if (temps != a.temps) + {return (temps >= a.temps);} + else + {return (*(this->PointeurClass_E_const()) >= *(a.PointeurClass_E_const()));} + }; +}; + +// affichage +void VariablesExporter::Ddl_a_un_element::Affiche() + { A_un_E::Affiche(); + cout << " Ddl_a_un_element_ " << Enu() << " temps_ " << temps ; + }; + +// ======== TypeQuelconque_a_un_element ============ +// classe conteneur pour les grandeurs particulières à un élément +ostream & operator << ( ostream & sort,const VariablesExporter::TypeQuelconque_a_un_element & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::A_un_E* aA = a.PointeurClass_Quelc_const(); + // récup de l'énuméré du type quelconque + const TypeQuelconque_enum_etendu& quelc = a.Quelc_const(); + // sortie + sort << *aA; // la classe mère + sort << " grandeur_quelconque_ " << quelc.NomPlein() << " composante: " << a.num_ordre << " "; + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::TypeQuelconque_a_un_element & a) +{ // récup du pointeur de la classe mère + VariablesExporter::A_un_E* aA = a.PointeurClass_Quelc(); + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref d'élément + if (aA->Ref_NE()[0] != 'E') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference d'element ," + << " la premiere lettre " + << " devraientt etre E et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + // lecture de la grandeur quelconque + string toto,nom_quelc; + ent >> toto >> nom_quelc; + a.quelc = TypeQuelconque_enum_etendu(nom_quelc); + + ent >> toto >> a.num_ordre; + + return ent; +}; + +VariablesExporter::TypeQuelconque_a_un_element::TypeQuelconque_a_un_element () : // constructeur par défaut + A_un_E(),quelc() {}; +// constructeur fonction de toutes les grandeurs +VariablesExporter::TypeQuelconque_a_un_element::TypeQuelconque_a_un_element + (int absolu_,TypeQuelconque_enum_etendu e,string ref_NE + ,string nom_mail_,Enum_dure tps,string nom_var_,int nbpti,int num_ord) : + A_un_E(absolu_,ref_NE,nom_mail,nom_var,nbpti) + ,quelc(e),num_ordre(num_ord) + {}; +// constructeur de copie +VariablesExporter::TypeQuelconque_a_un_element::TypeQuelconque_a_un_element (const TypeQuelconque_a_un_element& a) : + A_un_E(a) + ,quelc(a.quelc),num_ordre(a.num_ordre) + {}; +// destructeur +VariablesExporter::TypeQuelconque_a_un_element::~TypeQuelconque_a_un_element() + {}; + +// opérateurs +VariablesExporter::TypeQuelconque_a_un_element& VariablesExporter::TypeQuelconque_a_un_element::operator= + (const VariablesExporter::TypeQuelconque_a_un_element& a) + {quelc = a.quelc;num_ordre = a.num_ordre; + *(this->PointeurClass()) = *(a.PointeurClass_E_const()); + return (*this); + }; + +bool VariablesExporter::TypeQuelconque_a_un_element::operator== (const TypeQuelconque_a_un_element& a) const + {if ((quelc ==a.quelc)&& (num_ordre == a.num_ordre) + && (*(this->PointeurClass_E_const()) == *(a.PointeurClass_E_const()))) + return true; + else + return false; + }; + +bool VariablesExporter::TypeQuelconque_a_un_element::operator< (const TypeQuelconque_a_un_element& a) const +{if (quelc != a.quelc) + { return (quelc < a.quelc);} + else // cas quelc = a.quelc + {if (num_ordre != a.num_ordre) + {return (num_ordre < a.num_ordre); } + else + {return (*(this->PointeurClass_E_const()) < *(a.PointeurClass_E_const()));} + }; +}; + +bool VariablesExporter::TypeQuelconque_a_un_element::operator<= (const TypeQuelconque_a_un_element& a) const +{if (quelc != a.quelc) + { return (quelc <= a.quelc);} + else // cas quelc = a.quelc + {if (num_ordre != a.num_ordre) + {return (num_ordre <= a.num_ordre); } + else + {return (*(this->PointeurClass_E_const()) <= *(a.PointeurClass_E_const()));} + }; +}; + +bool VariablesExporter::TypeQuelconque_a_un_element::operator> (const TypeQuelconque_a_un_element& a) const +{if (quelc != a.quelc) + { return (quelc > a.quelc);} + else // cas quelc = a.quelc + {if (num_ordre != a.num_ordre) + {return (num_ordre > a.num_ordre); } + else + {return (*(this->PointeurClass_E_const()) > *(a.PointeurClass_E_const()));} + }; +}; + + +bool VariablesExporter::TypeQuelconque_a_un_element::operator>= (const TypeQuelconque_a_un_element& a) const +{if (quelc != a.quelc) + { return (quelc >= a.quelc);} + else // cas enu = a.enu + {if (num_ordre != a.num_ordre) + {return (num_ordre >= a.num_ordre); } + else + {return (*(this->PointeurClass_E_const()) >= *(a.PointeurClass_E_const()));} + }; +}; + +// ======== TypeParticulier_a_un_element ============ + +// classe conteneur pour les grandeurs particulières à un élément +ostream & operator << ( ostream & sort,const VariablesExporter::TypeParticulier_a_un_element & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::TypeQuelconque_a_un_element* aA = a.PointeurClass_Quelc_const(); + // récup de l'énuméré du type quelconque + const TypeQuelconque_enum_etendu& quelc = a.Quelc_const(); + // sortie + sort << "\n Particulier_a_un_element_ "; + sort << *aA; // la classe mère + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::TypeParticulier_a_un_element & a) +{ // récup du pointeur de la classe mère + VariablesExporter::TypeQuelconque_a_un_element* aA = a.PointeurClass_Quelc(); + // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Particulier_a_un_element_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Particulier_a_un_element_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::Particulier_a_un_element_(..."; + Sortie(1); + return ent; + }; + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref d'élément + if (aA->Ref_NE()[0] != 'E') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference d'element ," + << " la premiere lettre " + << " devraientt etre E et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + + return ent; +}; + +// affichage +void VariablesExporter::TypeParticulier_a_un_element::Affiche() + { A_un_E::Affiche(); + cout << " grandeur_particuliere_a_un_element_ " << quelc.NomPlein() + << " composante: " << num_ordre ; + }; +// ======== TypeEvoluee_a_un_element ============ + +// classe conteneur pour les grandeurs évoluées à un élément +ostream & operator << ( ostream & sort,const VariablesExporter::TypeEvoluee_a_un_element & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::TypeQuelconque_a_un_element* aA = a.PointeurClass_Quelc_const(); + // récup de l'énuméré du type quelconque + const TypeQuelconque_enum_etendu& quelc = a.Quelc_const(); + // sortie + sort << "\n Evoluee_a_un_element_ "; + sort << *aA; // la classe mère + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::TypeEvoluee_a_un_element & a) +{ // récup du pointeur de la classe mère + VariablesExporter::TypeQuelconque_a_un_element* aA = a.PointeurClass_Quelc(); + // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Evoluee_a_un_element_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Evoluee_a_un_element_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::TypeEvoluee_a_un_element(..."; + Sortie(1); + return ent; + }; + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref d'élément + if (aA->Ref_NE()[0] != 'E') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference d'element ," + << " la premiere lettre " + << " devraientt etre E et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + + return ent; +}; + +// affichage +void VariablesExporter::TypeEvoluee_a_un_element::Affiche() + { A_un_E::Affiche(); + cout << " grandeur_Evoluee_a_un_element_ " << quelc.NomPlein() + << " composante: " << num_ordre ; + }; + +// ======== TypeQuelconque_a_Face_arete ============ + +// classe conteneur pour un TypeQuelconque à une face ou arête +ostream & operator << ( ostream & sort,const VariablesExporter::TypeQuelconque_a_Face_arete & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::TypeQuelconque_a_un_element* aA = a.PointeurClass_Quelc_const(); + // sortie + sort << *aA; // la classe mère + // num FA + sort << " num_FA_ "<< a.Num_FA_const() << " "; + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::TypeQuelconque_a_Face_arete & a) +{ // récup du pointeur de la classe mère + VariablesExporter::TypeQuelconque_a_un_element* aA = a.PointeurClass_Quelc(); + // lecture de la partie mère + ent >> *aA; + // num FA + string toto; + ent >> toto >> a.Num_FA() ; + + return ent; +}; + + +VariablesExporter::TypeQuelconque_a_Face_arete::TypeQuelconque_a_Face_arete () : // constructeur par défaut + TypeQuelconque_a_un_element(),num_FA() {}; +// constructeur fonction de toutes les grandeurs +VariablesExporter::TypeQuelconque_a_Face_arete::TypeQuelconque_a_Face_arete + (int absolu_,TypeQuelconque_enum_etendu e,string ref_element + ,string nom_mail_,int nbFA, Enum_dure tps,string nom_var_,int nbpti,int num_ord) : + TypeQuelconque_a_un_element(absolu_,e,ref_element,nom_mail,tps,nom_var,nbpti,num_ord) + ,num_FA(nbFA) + {}; +// constructeur de copie +VariablesExporter::TypeQuelconque_a_Face_arete::TypeQuelconque_a_Face_arete (const TypeQuelconque_a_Face_arete& a) : + TypeQuelconque_a_un_element(a) + ,num_FA(a.num_FA) + {}; +// destructeur +VariablesExporter::TypeQuelconque_a_Face_arete::~TypeQuelconque_a_Face_arete() + {}; + +// opérateurs +VariablesExporter::TypeQuelconque_a_Face_arete& VariablesExporter::TypeQuelconque_a_Face_arete::operator= + (const VariablesExporter::TypeQuelconque_a_Face_arete& a) + {num_FA = a.num_FA; + *(this->PointClass_QuelcFA()) = *(a.PointClass_QuelcFA_const()); + return (*this); + }; + +bool VariablesExporter::TypeQuelconque_a_Face_arete::operator== (const TypeQuelconque_a_Face_arete& a) const + {if ((num_FA ==a.num_FA) + && (*(this->PointClass_QuelcFA_const()) == *(a.PointClass_QuelcFA_const()))) + return true; + else + return false; + }; + +bool VariablesExporter::TypeQuelconque_a_Face_arete::operator< (const TypeQuelconque_a_Face_arete& a) const +{if (num_FA != a.num_FA) + { return (num_FA < a.num_FA);} + else // cas num_FA = a.num_FA + {return (*(this->PointClass_QuelcFA_const()) < *(a.PointClass_QuelcFA_const()));} +}; + +bool VariablesExporter::TypeQuelconque_a_Face_arete::operator<= (const TypeQuelconque_a_Face_arete& a) const +{if (num_FA != a.num_FA) + { return (num_FA <= a.num_FA);} + else // cas num_FA = a.num_FA + {return (*(this->PointClass_QuelcFA_const()) <= *(a.PointClass_QuelcFA_const()));} +}; + +bool VariablesExporter::TypeQuelconque_a_Face_arete::operator> (const TypeQuelconque_a_Face_arete& a) const +{if (num_FA != a.num_FA) + { return (num_FA > a.num_FA);} + else // cas num_FA = a.num_FA + {return (*(this->PointClass_QuelcFA_const()) > *(a.PointClass_QuelcFA_const()));} +}; + + +bool VariablesExporter::TypeQuelconque_a_Face_arete::operator>= (const TypeQuelconque_a_Face_arete& a) const +{if (num_FA != a.num_FA) + { return (num_FA >= a.num_FA);} + else // cas num_FA = a.num_FA + {return (*(this->PointClass_QuelcFA_const()) >= *(a.PointClass_QuelcFA_const()));} +}; + +// ======== TypeQuelc_face_a_un_element ============ + +// classe conteneur pour les grandeurs quelconque à une face d'élément +ostream & operator << ( ostream & sort,const VariablesExporter::TypeQuelc_face_a_un_element & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::TypeQuelconque_a_Face_arete* aA = a.PointClass_QuelcFA_const(); + // sortie + sort << "\n Quelconque_face_element_ "; + sort << *aA; // la classe mère + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::TypeQuelc_face_a_un_element & a) +{ // récup du pointeur de la classe mère + VariablesExporter::TypeQuelconque_a_Face_arete* aA = a.PointClass_QuelcFA(); + // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Quelconque_face_element_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Quelconque_face_element_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::TypeQuelc_face_a_un_element(..."; + Sortie(1); + return ent; + }; + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref d'élément + if (aA->Ref_NE()[0] != 'E') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference d'element ," + << " la premiere lettre " + << " devraientt etre E et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + + return ent; +}; + +// affichage +void VariablesExporter::TypeQuelc_face_a_un_element::Affiche() + { cout << (*this) ; + }; + +// ======== TypeQuelc_arete_a_un_element ============ + +// classe conteneur pour les grandeurs quelconque à une arete d'élément +ostream & operator << ( ostream & sort,const VariablesExporter::TypeQuelc_arete_a_un_element & a) +{ // récup du pointeur de la classe mère + const VariablesExporter::TypeQuelconque_a_Face_arete* aA = a.PointClass_QuelcFA_const(); + // sortie + sort << "\n Quelconque_arete_element_ "; + sort << *aA; // la classe mère + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::TypeQuelc_arete_a_un_element & a) +{ // récup du pointeur de la classe mère + VariablesExporter::TypeQuelconque_a_Face_arete* aA = a.PointClass_QuelcFA(); + // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Quelconque_arete_element_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Quelconque_arete_element_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::TypeQuelc_arete_a_un_element(..."; + Sortie(1); + return ent; + }; + // lecture de la partie mère + ent >> *aA; + // on vérifie également qu'il s'agit bien d'une ref d'élément + if (aA->Ref_NE()[0] != 'E') + { cout << "\n *** lecture de la variable utilisateur: " << a.nom_var + << " erreur de syntaxe en lecture d'une reference d'element ," + << " la premiere lettre " + << " devraientt etre E et on a lu: "<Ref_NE() << " !!" + << endl; + Sortie(1); + }; + + return ent; +}; + +// affichage +void VariablesExporter::TypeQuelc_arete_a_un_element::Affiche() + { cout << (*this) ; + }; + +// ======== TypeQuelc_Une_composante_Grandeur_globale ============ + +// classe conteneur pour une composante de grandeur globale +ostream & operator << ( ostream & sort,const VariablesExporter::TypeQuelc_Une_composante_Grandeur_globale & a) +{ // sortie + sort << "\n Une_composante_Grandeur_globale_ "; + sort << a.var.nom1 << " " << a.var.nom2 << " composante: " << a.var.n << " "; + // retour + return sort; +}; + +istream & operator >> ( istream & ent, VariablesExporter::TypeQuelc_Une_composante_Grandeur_globale & a) +{ // lecture du type et vérification + string nomtype,toto; ent >> nomtype ; + if (nomtype != "Une_composante_Grandeur_globale_") + { cout << "\n *** erreur en lecture: on attendait le mot cle Une_composante_Grandeur_globale_ et on a lue " + << nomtype + << "\n operator >> ( istream & ent, VariablesExporter::TypeQuelc_Une_composante_Grandeur_globale(..."; + Sortie(1); + return ent; + }; + // lecture des infos + ent >> a.var.nom1 >> a.var.nom2 >> toto >> a.var.n; + // vérif il faut que les 3 premiers caractères de a.nom_var soit un VR_ + if (!((a.var.nom1[0]== 'V')&&(a.var.nom1[1]== 'R')&&(a.var.nom1[2]== '_'))) + { cout << "\n *** erreur de syntaxe en lecture d'une variable utilisateur," + << " les 3 premieres lettres " + << " devraientt etre un 'VR_' et on a lu: "<> ( istream & ent, VariablesExporter::TypeQuelc_Une_composante_Grandeur_globale(..."; + Sortie(1); + return ent; + }; + + return ent; +}; + +// affichage +void VariablesExporter::TypeQuelc_Une_composante_Grandeur_globale::Affiche() + { cout << (*this) ; + }; + +//--------------------------- VariablesExporter -------------- + +// CONSTRUCTEURS : + +// Constructeur par defaut +VariablesExporter::VariablesExporter (): + li_Q(),li_nom() + // ----- les variables + // -> noeuds + ,list_noeud_type_ddl() + ,list_noeud_type_ddlEtendu() + ,list_noeud_type_quelconque() + + // -> éléments + ,list_element_type_ddl() + ,list_element_type_particulier(),list_quelc_element_type_particulier() + ,list_element_type_evoluee() + ,list_quelc_element_type_evoluee() + + // -> face d'éléments + ,list_face_element_type_quelc() + ,list_quelc_face_element_type_quelc() + + // -> arête d'éléments + ,list_arete_element_type_quelc() + ,list_quelc_arete_element_type_quelc() + + // -> une composante d'une variable globale de type multidimentionnel + ,list_var_glob_sur_grandeur_globale() + + ,initiaConteneurQuelconque(false) + + { + }; + + +// Constructeur de copie, +VariablesExporter::VariablesExporter (const VariablesExporter& a): + li_Q(a.li_Q),li_nom(a.li_nom) + // ----- les variables + // -> noeuds + ,list_noeud_type_ddl(a.list_noeud_type_ddl) + ,list_noeud_type_ddlEtendu(a.list_noeud_type_ddlEtendu) + ,list_noeud_type_quelconque(a.list_noeud_type_quelconque) + + // -> éléments + ,list_element_type_ddl(a.list_element_type_ddl) + ,list_element_type_particulier(a.list_element_type_particulier) + ,list_quelc_element_type_particulier(a.list_quelc_element_type_particulier) + ,list_element_type_evoluee(a.list_element_type_evoluee) + ,list_quelc_element_type_evoluee(a.list_quelc_element_type_evoluee) + + // -> face d'éléments + ,list_face_element_type_quelc(a.list_face_element_type_quelc) + ,list_quelc_face_element_type_quelc(a.list_quelc_face_element_type_quelc) + + // -> arête d'éléments + ,list_arete_element_type_quelc(a.list_arete_element_type_quelc) + ,list_quelc_arete_element_type_quelc(a.list_quelc_arete_element_type_quelc) + + // -> une composante d'une variable globale de type multidimentionnel + ,list_var_glob_sur_grandeur_globale(a.list_var_glob_sur_grandeur_globale) + + ,initiaConteneurQuelconque(a.initiaConteneurQuelconque) + { + }; + + + +VariablesExporter::~VariablesExporter() +// Destructeur +{ + }; + +// lecture +void VariablesExporter::LectureVariablesExporter(UtilLecture * entreePrinc) +{ if (ParaGlob::NiveauImpression() >= 5) cout << " debut de lecture des constantes et variables a exporter globalement " << endl; + // 1) cas des constantes + LecConstantesUtilisateur(*entreePrinc); + LecVariablesUtilisateur(*entreePrinc); + +}; + + + +// affichage et definition interactive des commandes +// cas = 1: interactif complet +// cas = 2: entrée uniquement de noms de fichier +void VariablesExporter::Info_commande_VariablesExporters(UtilLecture * entreePrinc) + { Info_commande_ConstantesUtilisateur(entreePrinc); + Info_commande_VariablesUtilisateur(entreePrinc); + }; + +// insertion des constantes et variables utilisateurs vers globales +void VariablesExporter::InsertConstVarUtilisateur_dans_globale() + {InsertConstUtilisateur_dans_globale(); + Insert_VarUtilisateur_dans_globale(); + }; + + + +// initialisation des conteneurs quelconques +// création des conteneurs aux noeuds s'il s'agit d'une variable +// associée à un vecteur global (au sens des algorithmes globaux) +void VariablesExporter::InitialisationConteneursQuelconques(LesMaillages& lesMail + ,const List_io < TypeQuelconque >& listeVecGlob,const LesReferences& lesRef) + { if (!initiaConteneurQuelconque) + { // on commence par récupérer les conteneurs disponibles + // on se met en absolu par défaut -> le conteneur le + grand + // ---> pourrait poser pb, si ensuite le conteneur diminue !! à surveiller ! + bool absolu = true; + Tableau > tabelement_typeParti + (lesMail.Les_type_de_donnees_particulieres_par_element(absolu)); + // idem mais sous forme de grandeurs évoluées + Tableau > tabelement_evoluee + (lesMail.Les_type_de_donnees_evolues_internes_par_element(absolu)); + + // pour les faces et arêtes + Tableau >tab_F_element_TypeQuelconque + (lesMail.Les_type_de_donnees_evolues_internes_par_face_element(absolu)); + Tableau > tab_A_element_TypeQuelconque + (lesMail.Les_type_de_donnees_evolues_internes_par_arete_element(absolu)); + + // on passe en revue les grandeurs pour définir les conteneurs associés + // --- cas des grandeurs particulières aux pti d'élément + {list_quelc_element_type_particulier.clear(); // init + List_io < TypeParticulier_a_un_element >::iterator + il,ilfin=list_element_type_particulier.end(); + for (il = list_element_type_particulier.begin(); il != ilfin;il++) + {// on vérifie qu'elle appartient à la liste des grandeurs disponibles + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + TypeQuelconque a((*il).Quelc_const()); // création d'un type quelconque sans grandeur + List_io& tpg = (tabelement_typeParti(n_mail)); // pour simplifier + if (find(tpg.begin(),tpg.end(),a) != tpg.end()) + { // il existe -> enregistrement + List_io::iterator it = find(tpg.begin(),tpg.end(),a); // récup du réel type + list_quelc_element_type_particulier.push_back(*it); + } + else + { cout << "\n *** erreur dans l'initialisation de la variable utilisateur " + << (*il).Nom_var() << " la grandeur associee " << (*il).Quelc_const().NomPlein() + << " n'existe pas !! " + << "\n VariablesExporter::InitialisationConteneursQuelconques(..." << flush; + (*il).Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs évoluées aux pti d'élément + {list_quelc_element_type_evoluee.clear(); // init + List_io < TypeEvoluee_a_un_element >::iterator + il,ilfin=list_element_type_evoluee.end(); + for (il = list_element_type_evoluee.begin(); il != ilfin;il++) + {// on vérifie qu'elle appartient à la liste des grandeurs disponibles + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + TypeQuelconque a((*il).Quelc_const()); // création d'un type quelconque sans grandeur + List_io& tpg = (tabelement_typeParti(n_mail)); // pour simplifier + if (find(tpg.begin(),tpg.end(),a) != tpg.end()) + { // il existe -> enregistrement + List_io::iterator it = find(tpg.begin(),tpg.end(),a); // récup du réel type + list_quelc_element_type_evoluee.push_back(*it); + } + else + { cout << "\n *** erreur dans l'initialisation de la variable utilisateur " + << (*il).Nom_var() << " la grandeur associee " << (*il).Quelc_const().NomPlein() + << " n'existe pas !! " + << "\n VariablesExporter::InitialisationConteneursQuelconques(..." << flush; + (*il).Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs quelconques aux pti de faces d'élément + {list_quelc_face_element_type_quelc.clear(); // init + List_io < TypeQuelc_face_a_un_element >::iterator + il,ilfin=list_face_element_type_quelc.end(); + for (il = list_face_element_type_quelc.begin(); il != ilfin;il++) + {// on vérifie qu'elle appartient à la liste des grandeurs disponibles + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + TypeQuelconque a((*il).Quelc_const()); // création d'un type quelconque sans grandeur + List_io& tpg = (tab_F_element_TypeQuelconque(n_mail)); // pour simplifier + if (find(tpg.begin(),tpg.end(),a) != tpg.end()) + { // il existe -> enregistrement + List_io::iterator it = find(tpg.begin(),tpg.end(),a); // récup du réel type + list_quelc_face_element_type_quelc.push_back(*it); + } + else + { cout << "\n *** erreur dans l'initialisation de la variable utilisateur " + << (*il).Nom_var() << " la grandeur associee " << (*il).Quelc_const().NomPlein() + << " n'existe pas !! " + << "\n VariablesExporter::InitialisationConteneursQuelconques(..." << flush; + (*il).Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs quelconques aux pti d'arêtes d'élément + {list_quelc_arete_element_type_quelc.clear(); // init + List_io < TypeQuelc_arete_a_un_element >::iterator + il,ilfin=list_arete_element_type_quelc.end(); + for (il = list_arete_element_type_quelc.begin(); il != ilfin;il++) + {// on vérifie qu'elle appartient à la liste des grandeurs disponibles + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + TypeQuelconque a((*il).Quelc_const()); // création d'un type quelconque sans grandeur + List_io& tpg = (tab_A_element_TypeQuelconque(n_mail)); // pour simplifier + if (find(tpg.begin(),tpg.end(),a) != tpg.end()) + { // il existe -> enregistrement + List_io::iterator it = find(tpg.begin(),tpg.end(),a); // récup du réel type + list_quelc_arete_element_type_quelc.push_back(*it); + } + else + { cout << "\n *** erreur dans l'initialisation de la variable utilisateur " + << (*il).Nom_var() << " la grandeur associee " << (*il).Quelc_const().NomPlein() + << " n'existe pas !! " + << "\n VariablesExporter::InitialisationConteneursQuelconques(..." << flush; + (*il).Affiche(); + Sortie(1); + }; + }; + }; + + // --- traitement particulier pour les noeuds + {// dans le cas où il y a des vecteurs globaux qui ont été retenus, + // il faut définir aux noeuds des conteneurs adéquates + if ((listeVecGlob.size() != 0) && (list_noeud_type_quelconque.size() != 0)) + { // on boucle sur les var de noeud: a priori c'est le nombre le plus petit + List_io ::iterator il,ilfin=list_noeud_type_quelconque.end(); + for(il= list_noeud_type_quelconque.begin();il != ilfin; il++) + {// on boucle sur les vecteurs globaux pour savoir s'il y en a un qui correspond + List_io < TypeQuelconque >::const_iterator it,itfin = listeVecGlob.end(); + for (it=listeVecGlob.begin();it != itfin;it++) + {//cout << "\n (*it) "<<(*it).EnuTypeQuelconque().NomPlein() + // << " *il "<< (*il).Quelc().NomPlein() << flush; + + if ((*it).EnuTypeQuelconque() == (*il).Quelc()) + { // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + int nmail = 1; + if ((*il).Nom_mail() != "") + nmail = lesMail.NumMaillage((*il).Nom_mail()); + Noeud * noo = & lesMail.Noeud_LesMaille(nmail,ne); + noo->AjoutUnTypeQuelconque(*it); + }; + }; + }; + }; + }; + + initiaConteneurQuelconque=true; // pour une initialisation unique + } + + }; + +// insertion et stockage des variables au niveau de ParaGlob +void VariablesExporter::Insert_VarUtilisateur_dans_globale() + +{ + // --- cas des ddl aux noeuds: list_noeud_type_ddl + {List_io < Ddl_a_un_noeud >::iterator il,ilfin=list_noeud_type_ddl.end(); + for (il=list_noeud_type_ddl.begin();il != ilfin;il++) + { Ddl_a_un_noeud& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on crée un conteneur d'un double + double val=0; + Grandeur_scalaire_double grand_courant(val); + switch (dan.Temps()) + {case TEMPS_0 : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_0,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + break; + } + case TEMPS_t : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_T,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + break; + } + case TEMPS_tdt : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_TDT,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + break; + } + default : + cout << "\nErreur : valeur incorrecte du temps pour une variable ddl globale !\n"; + cout << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(... \n"; + Sortie(1); + }; + }; + }; + }; + + // --- cas des ddl étendus aux noeuds: list_noeud_type_ddlEtendu + {List_io < Ddl_etendu_a_un_noeud >::iterator il,ilfin=list_noeud_type_ddlEtendu.end(); + for (il=list_noeud_type_ddlEtendu.begin();il != ilfin;il++) + { Ddl_etendu_a_un_noeud& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on crée un conteneur d'un double + double val=0; + Grandeur_scalaire_double grand_courant(val); + TypeQuelconque typQ1(UN_DDL_ENUM_ETENDUE,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + }; + }; + }; + + // --- cas des grandeurs quelconques aux noeuds: list_noeud_type_quelconque + {List_io < Quelconque_a_un_noeud >::iterator il,ilfin=list_noeud_type_quelconque.end(); + for (il=list_noeud_type_quelconque.begin();il != ilfin;il++) + { Quelconque_a_un_noeud& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on insert un conteneur double associé + VariablesExporter::InsertCompGrandeurQuelc(dan.Nom_var(),dan.Quelc_const()); + }; + }; + }; + + // --- cas des ddl pur à un pti d'élément : list_element_type_ddl + {List_io < Ddl_a_un_element >::iterator il,ilfin=list_element_type_ddl.end(); + for (il=list_element_type_ddl.begin();il != ilfin;il++) + { Ddl_a_un_element& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on crée un conteneur d'un double + double val=0; + Grandeur_scalaire_double grand_courant(val); + switch (dan.Temps()) + {case TEMPS_0 : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_0,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + break; + } + case TEMPS_t : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_T,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + break; + } + case TEMPS_tdt : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_TDT,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + break; + } + default : + cout << "\nErreur : valeur incorrecte du temps pour une variable ddl globale !\n"; + cout << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(... \n"; + Sortie(1); + }; + }; + }; + }; + + // --- cas des grandeurs particulières aux éléments: list_element_type_particulier + {List_io < TypeParticulier_a_un_element >::iterator il,ilfin=list_element_type_particulier.end(); + for (il=list_element_type_particulier.begin();il != ilfin;il++) + { TypeParticulier_a_un_element& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on insert un conteneur double associé + VariablesExporter::InsertCompGrandeurQuelc(dan.Nom_var(),dan.Quelc_const()); + }; + }; + }; + + // --- cas des grandeurs évoluées aux éléments: list_element_type_evoluee + {List_io < TypeEvoluee_a_un_element >::iterator il,ilfin=list_element_type_evoluee.end(); + for (il=list_element_type_evoluee.begin();il != ilfin;il++) + { TypeEvoluee_a_un_element& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on insert un conteneur double associé + VariablesExporter::InsertCompGrandeurQuelc(dan.Nom_var(),dan.Quelc_const()); + }; + }; + }; + + // --- cas des grandeurs quelconques aux pti de faces d'éléments: list_face_element_type_quelc + {List_io < TypeQuelc_face_a_un_element >::iterator il,ilfin=list_face_element_type_quelc.end(); + for (il=list_face_element_type_quelc.begin();il != ilfin;il++) + { TypeQuelc_face_a_un_element& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on insert un conteneur double associé + VariablesExporter::InsertCompGrandeurQuelc(dan.Nom_var(),dan.Quelc_const()); + }; + }; + }; + + // --- cas des grandeurs quelconques aux pti d'arête d'éléments: list_arete_element_type_quelc + {List_io < TypeQuelc_arete_a_un_element >::iterator il,ilfin=list_arete_element_type_quelc.end(); + for (il=list_arete_element_type_quelc.begin();il != ilfin;il++) + { TypeQuelc_arete_a_un_element& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on insert un conteneur double associé + VariablesExporter::InsertCompGrandeurQuelc(dan.Nom_var(),dan.Quelc_const()); + }; + }; + }; + + // --- cas d'une composante d'une variable globale de type multidimentionnel + {List_io ::iterator + il,ilfin=list_var_glob_sur_grandeur_globale.end(); + for (il=list_var_glob_sur_grandeur_globale.begin();il != ilfin;il++) + { TypeQuelc_Une_composante_Grandeur_globale& dan = *il; // pour simplifier + // on regarde si la grandeur existe déjà + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + if (pointe != NULL) + {cout << "\n *** pb dans dans la def de la variable utilisateur globale "<< dan.Nom_var() + << " elle existe deja !! , ce n'est pas normal " + << "\n VariablesExporter::Insert_VarUtilisateur_dans_globale(..." + << endl; + Sortie(1); + } + else // sinon c'est ok, on la défini + {// on insert un conteneur double nommé et indicé associé + double val=0; + Grandeur_Double_Nommer_indicer grand_courant(dan.Nom_grandeur_globale(),val,dan.Indice_const()); + TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_TDT,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,dan.Nom_var()); + }; + }; + }; + + }; + +// Affiche l'ensemble des variables et constantes utilisateur +void VariablesExporter::Affiche () const +{ cout << "\n\t\t*** constantes et Variables exportees globalement ***\n\n"; + // -- cas des Constantes utilisateurs --- + cout << "\n ===constantes_utilisateur==== "; + { List_io < Ddl_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddl.end(); + List_io < string >::const_iterator il = li_nom.begin(); + for (it = list_noeud_type_ddl.begin();it != itfin; it++,il++) + cout << "\n double_ " << (*il) ; + }; + + // -- cas des variables utilisateurs --- + cout << "\n ===variables_utilisateur==== "; + { List_io < Ddl_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddl.end(); + for (it = list_noeud_type_ddl.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas des ddl étendu aux noeuds --- + { List_io < Ddl_etendu_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddlEtendu.end(); + for (it = list_noeud_type_ddlEtendu.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas des grandeurs quelconques aux noeuds --- + { List_io < Quelconque_a_un_noeud >::const_iterator it, itfin = list_noeud_type_quelconque.end(); + for (it = list_noeud_type_quelconque.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas des ddl aux pti d'éléments --- + { List_io < Ddl_a_un_element >::const_iterator it, itfin = list_element_type_ddl.end(); + for (it = list_element_type_ddl.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas des grandeurs particulières aux pti d'éléments --- + { List_io < TypeParticulier_a_un_element >::const_iterator it, itfin = list_element_type_particulier.end(); + for (it = list_element_type_particulier.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas des grandeurs évoluées aux pti d'éléments --- + { List_io < TypeEvoluee_a_un_element >::const_iterator it, itfin = list_element_type_evoluee.end(); + for (it = list_element_type_evoluee.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas des grandeurs quelconques aux pti de faces d'éléments --- + { List_io < TypeQuelc_face_a_un_element >::const_iterator it, itfin = list_face_element_type_quelc.end(); + for (it = list_face_element_type_quelc.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas des grandeurs quelconques aux pti d'arête d'éléments --- + { List_io < TypeQuelc_arete_a_un_element >::const_iterator it, itfin = list_arete_element_type_quelc.end(); + for (it = list_arete_element_type_quelc.begin();it != itfin; it++) + cout << (*it); + }; + // -- cas d'une composante d'une variable globale de type multidimentionnel --- + { List_io < TypeQuelc_Une_composante_Grandeur_globale >::const_iterator it, itfin = list_var_glob_sur_grandeur_globale.end(); + for (it = list_var_glob_sur_grandeur_globale.begin();it != itfin; it++) + cout << (*it); + }; + +}; + + + +// Surcharge de l'operateur = : realise l'egalite entre deux instances +VariablesExporter& +VariablesExporter::operator= (VariablesExporter& a) +{ li_Q=a.li_Q; li_nom=a.li_nom; + // ----- les variables + // -> noeuds + list_noeud_type_ddl = a.list_noeud_type_ddl; + list_noeud_type_ddlEtendu=a.list_noeud_type_ddlEtendu; + list_noeud_type_quelconque = a.list_noeud_type_quelconque; + + // -> éléments + list_element_type_ddl = a.list_element_type_ddl; + list_element_type_particulier = a.list_element_type_particulier; + list_quelc_element_type_particulier = a.list_quelc_element_type_particulier; + list_element_type_evoluee = a.list_element_type_evoluee; + list_quelc_element_type_evoluee = a.list_quelc_element_type_evoluee; + + // -> face d'éléments + list_face_element_type_quelc = a.list_face_element_type_quelc; + list_quelc_face_element_type_quelc = a.list_quelc_face_element_type_quelc; + + // -> arête d'éléments + list_arete_element_type_quelc = a.list_arete_element_type_quelc; + list_quelc_arete_element_type_quelc = a.list_quelc_arete_element_type_quelc; + + // -> une composante d'une variable globale de type multidimentionnel + list_var_glob_sur_grandeur_globale = a.list_var_glob_sur_grandeur_globale; + + return (*this); +}; + +// test si toutes les informations des maillages sont completes +// = true -> complet +// = false -> incomplet +bool VariablesExporter::Complet_VariablesExporter(const LesReferences& lesRef) + { bool res = true; // init + + // ***vérifier que toutes les variables ont des noms différents + // a priori c'est ok vu que la vérif est déjà effectuée à la lecture + + // on va vérifier que toutes les références sont correctes + // --- cas des ddl aux noeuds + {List_io < Ddl_a_un_noeud >::iterator il,ilfin = list_noeud_type_ddl.end(); + for (il = list_noeud_type_ddl.begin();il != ilfin;il++) + {Ddl_a_un_noeud& dan = *il; // pour simplifier + + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_Num_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref de noeud + if (ref.Indic() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference de noeud " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro de noeud + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " noeud(s) alors qu'il ne faut qu'un seul noeud !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des ddl étendus aux noeuds + {List_io < Ddl_etendu_a_un_noeud >::iterator il,ilfin = list_noeud_type_ddlEtendu.end(); + for (il = list_noeud_type_ddlEtendu.begin();il != ilfin;il++) + {Ddl_etendu_a_un_noeud& dan = *il; // pour simplifier + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref de noeud + if (ref.Indic() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference de noeud " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro de noeud + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " noeud(s) alors qu'il ne faut qu'un seul noeud !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs quelconques aux noeuds + {List_io < Quelconque_a_un_noeud >::iterator il,ilfin = list_noeud_type_quelconque.end(); + for (il = list_noeud_type_quelconque.begin();il != ilfin;il++) + {Quelconque_a_un_noeud& dan = *il; // pour simplifier + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref de noeud + if (ref.Indic() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference de noeud " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro de noeud + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " noeud(s) alors qu'il ne faut qu'un seul noeud !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des ddl aux pti d'élément + {List_io < Ddl_a_un_element >::iterator il,ilfin = list_element_type_ddl.end(); + for (il = list_element_type_ddl.begin();il != ilfin;il++) + {Ddl_a_un_element& dan = *il; // pour simplifier + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref d'élément + if (ref.Indic() != 2) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference d'element' " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro d'élément + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " element(s) alors qu'il ne faut qu'un seul element !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs particulières aux pti d'élément + {List_io < TypeParticulier_a_un_element >::iterator il,ilfin + = list_element_type_particulier.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_element_type_particulier.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_element_type_particulier.begin();il != ilfin;il++,it++) + {TypeParticulier_a_un_element& dan = *il; // pour simplifier + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref d'élément + if (ref.Indic() != 2) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference d'element' " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro d'élément + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " element(s) alors qu'il ne faut qu'un seul element !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs évoluées aux pti d'élément + {List_io < TypeEvoluee_a_un_element >::iterator il,ilfin + = list_element_type_evoluee.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_element_type_evoluee.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_element_type_evoluee.begin();il != ilfin;il++,it++) + {TypeEvoluee_a_un_element& dan = *il; // pour simplifier + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref d'élément + if (ref.Indic() != 2) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference d'element' " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro d'élément + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " element(s) alors qu'il ne faut qu'un seul element !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs quelconques aux pti de faces d'élément + {List_io < TypeQuelc_face_a_un_element >::iterator il,ilfin + = list_face_element_type_quelc.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_face_element_type_quelc.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_face_element_type_quelc.begin();il != ilfin;il++,it++) + {TypeQuelc_face_a_un_element& dan = *il; // pour simplifier + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref d'élément + if (ref.Indic() != 2) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference d'element' " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro d'élément + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " element(s) alors qu'il ne faut qu'un seul element !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des grandeurs quelconques aux pti d'arêtes d'élément + {List_io < TypeQuelc_arete_a_un_element >::iterator il,ilfin + = list_arete_element_type_quelc.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_arete_element_type_quelc.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_arete_element_type_quelc.begin();il != ilfin;il++,it++) + {TypeQuelc_arete_a_un_element& dan = *il; // pour simplifier + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + // on vérifie qu'il s'agit d'une ref d'élément + if (ref.Indic() != 2) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " n'est pas associee a une reference d'un element' " + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + // on vérifie qu'il n'y a qu'un seule numéro d'élément + if (ref.Taille() != 1) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " est associee a une reference qui comporte " + << ref.Taille() << " element(s) alors qu'il ne faut qu'un seul element !" + << " revoir la mise en donnees ! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // ----- cas une composante d'une variable globale de type multidimentionnel + // rien à faire, c'est fait à l'appel de la variable globale (cf. ParaGlob) + + + // retour + return res; + }; + + + +// mises à jour de constantes globales définies par l'utilisateur +// permet de changer les valeurs, lors d'une suite .info par exemple +void VariablesExporter::MiseAjourConstantesUtilisateur(UtilLecture& lec) + { if (strstr(lec.tablcar,"Mise_A_jour_Constantes_utilisateurs_")!=NULL) + { lec.NouvelleDonnee(); // on se positionne sur le premier enreg + // on lit tant que l'on ne rencontre pas la ligne contenant + // "fin_Mise_A_jour_Constantes_utilisateurs_" + while (strstr(lec.tablcar,"fin_Mise_A_jour_Constantes_utilisateurs_")==0) + {// lecture d'un mot clé + string nom; + *(lec.entree) >> nom; + + if ((lec.entree)->rdstate() == 0) + {} // lecture normale + #ifdef ENLINUX + else if ((lec.entree)->fail()) + // on a atteind la fin de la ligne et on appelle un nouvel enregistrement + { lec.NouvelleDonnee(); // lecture d'un nouvelle enregistrement + *(lec.entree) >> nom; + } + #else + else if ((lec.entree)->eof()) + // la lecture est bonne mais on a atteind la fin de la ligne + { if(nom != "fin_Mise_A_jour_Constantes_utilisateurs_") + {lec.NouvelleDonnee(); *(lec.entree) >> nom;}; + } + #endif + else // cas d'une erreur de lecture + { cout << "\n erreur de lecture inconnue "; + lec.MessageBuffer("** erreur en lecture pour la mise a jour des constantes utilisateur **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + + // en fonction du type de donnée on modifie + if (nom == "double_") + { string nom_constante; double val; + *(lec.entree) >> nom_constante >> val; + + // on récupère le pointeur correspondant à la grandeur + const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_constante)); + if (pointe != NULL) + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + if ((gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()==TYPE_SIMPLE) + && (gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()==PARTICULIER_SCALAIRE_DOUBLE) + ) + {Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // on met à jour la grandeur + *(gr.ConteneurDouble()) = val; + } + else // sinon pb + { cout << "\n *** pb dans dans la mise a jour de la constante globale "<< nom_constante + << " le conteneur lu " << nom << " n'est pas d'un type correct !! " + << "\n Projet::MiseAjourConstantesUtilisateur(..." + <> nom_constante >> val; +// +// // on récupère le pointeur correspondant à la grandeur +// const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_constante)); +// if (pointe != NULL) +// {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); +// if ((gr_quelc->Grandeur_pointee()->Type_structure_grandeurAssocie()==TYPE_SIMPLE) +// && (gr_quelc->Grandeur_pointee()->Type_enumGrandeurParticuliere()==PARTICULIER_SCALAIRE_ENTIER) +// ) +// {Grandeur_scalaire_entier& gr +// = *((Grandeur_scalaire_entier*) gr_quelc->Grandeur_pointee()); // pour simplifier +// // on met à jour la grandeur +// *(gr.ConteneurEntier()) = val; +// } +// else // sinon pb +// { cout << "\n *** pb dans dans la mise a jour de la constante globale "<< nom_constante +// << " le conteneur lu " << nom << " n'est pas d'un type correct !! " +// << "\n Projet::MiseAjourConstantesUtilisateur(..." +// <3) + cout << "\n Projet::MiseAjourConstantesUtilisateur(... " << endl ; + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + + }; //-- fin du while + lec.NouvelleDonnee(); // on prépare la nouvelle lecture + }; + }; + + // renseigne les variables définies par l'utilisateur + // via les valeurs calculées par Herezh + void VariablesExporter::RenseigneVarUtilisateur(LesMaillages& lesMail,const LesReferences& lesRef) + { + // --- cas des ddl aux noeuds + {List_io < Ddl_a_un_noeud >::iterator il,ilfin = list_noeud_type_ddl.end(); + for (il = list_noeud_type_ddl.begin();il != ilfin;il++) + {Ddl_a_un_noeud& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau des noeuds + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_Num_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Noeud& noe = lesMail.Noeud_LesMaille(n_mail,ne); + if (!noe.Existe_ici((dan.Enu()).Enum())) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " ne peut pas etre renseignee car le ddl " + << dan.Enu().Nom_plein() << " n'est pas disponible !!! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + switch (dan.Temps()) + { case TEMPS_0 : + (*(gr.ConteneurDouble())) = noe.Valeur_0((dan.Enu()).Enum());break; + case TEMPS_t : + (*(gr.ConteneurDouble())) = noe.Valeur_t((dan.Enu()).Enum());break; + case TEMPS_tdt : + (*(gr.ConteneurDouble())) = noe.Valeur_tdt((dan.Enu()).Enum());break; + }; + }; + }; + + // --- cas des ddl étendus aux noeuds + {List_io < Ddl_etendu_a_un_noeud >::iterator il,ilfin = list_noeud_type_ddlEtendu.end(); + for (il = list_noeud_type_ddlEtendu.begin();il != ilfin;il++) + {Ddl_etendu_a_un_noeud& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau des noeuds + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Noeud& noe = lesMail.Noeud_LesMaille(n_mail,ne); +// Noeud& noe = lesMail.Noeud_LesMaille(n_mail,dan.Num_NE()); + if (!noe.Existe_ici_ddlEtendu((dan.Enu()))) + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " ne peut pas etre renseignee car le ddl etendu " + << dan.Enu().Nom_plein() << " n'est pas disponible !!! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + (*(gr.ConteneurDouble())) = noe.DdlEtendue(dan.Enu()).ConstValeur(); + }; + }; + + // --- cas des grandeurs quelconques aux noeuds + {List_io < Quelconque_a_un_noeud >::iterator il,ilfin = list_noeud_type_quelconque.end(); + for (il = list_noeud_type_quelconque.begin();il != ilfin;il++) + {Quelconque_a_un_noeud& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau des noeuds + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Noeud& noe = lesMail.Noeud_LesMaille(n_mail,ne); +// Noeud& noe = lesMail.Noeud_LesMaille(n_mail,dan.Num_NE()); + + // le conteneur au noeud + const TypeQuelconque_enum_etendu& type_quel = dan.Quelc_const(); // la grandeur constante + if( noe.Existe_ici(type_quel)) + {const TypeQuelconque& grand_quelconque_noe = noe.Grandeur_quelconque(dan.Quelc_const()); + // l'affectation + (*(gr.ConteneurDouble())) = grand_quelconque_noe.Const_Grandeur_pointee()->GrandeurNumOrdre(dan.Num_ordre()); + } + else + { cout << "\n *** erreur la variable utilisateur " << dan.Nom_var() + << " ne peut pas etre renseignee car la grandeur " + << type_quel.NomPlein() << " n'est pas disponible !!! "; + if (ParaGlob::NiveauImpression() >= 2) + dan.Affiche(); + Sortie(1); + }; + }; + }; + + // --- cas des ddl aux pti d'élément + {List_io < Ddl_a_un_element >::iterator il,ilfin = list_element_type_ddl.end(); + for (il = list_element_type_ddl.begin();il != ilfin;il++) + {Ddl_a_un_element& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau du pti d'élément + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Element& ele = lesMail.Element_LesMaille(n_mail,ne); + List_io inter; inter.push_back(dan.Enu()); + Tableau tab= ele.Valeur_a_diff_temps(dan.Absolue_const(),dan.Temps_const(),inter,dan.NBpti_const()); + (*(gr.ConteneurDouble())) = tab(1); + }; + }; + + // --- cas des grandeurs particulières aux pti d'élément + {List_io < TypeParticulier_a_un_element >::iterator il,ilfin + = list_element_type_particulier.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_element_type_particulier.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_element_type_particulier.begin();il != ilfin;il++,it++) + {TypeParticulier_a_un_element& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau du pti d'élément + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Element& ele = lesMail.Element_LesMaille(n_mail,ne); + List_io inter; inter.push_back((*it)); // il y a une recopie + ele.Grandeur_particuliere(dan.Absolue_const(),inter,dan.NBpti_const()); + // le résultat est dans inter, pas dans (*it) + // affectation + (*(gr.ConteneurDouble())) = (*inter.begin()).GrandeurNumOrdre(dan.Num_ordre()); + }; + }; + + // --- cas des grandeurs évoluées aux pti d'élément + {List_io < TypeEvoluee_a_un_element >::iterator il,ilfin + = list_element_type_evoluee.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_element_type_evoluee.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_element_type_evoluee.begin();il != ilfin;il++,it++) + {TypeEvoluee_a_un_element& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau du pti d'élément + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Element& ele = lesMail.Element_LesMaille(n_mail,ne); + List_io inter; inter.push_back((*it)); // il y a une recopie + ele.Grandeur_particuliere(dan.Absolue_const(),inter,dan.NBpti_const()); + // le résultat est dans inter, pas dans (*it) + // affectation + (*(gr.ConteneurDouble())) = (*inter.begin()).GrandeurNumOrdre(dan.Num_ordre()); + }; + }; + + // --- cas des grandeurs quelconques aux pti de faces d'élément + {List_io < TypeQuelc_face_a_un_element >::iterator il,ilfin + = list_face_element_type_quelc.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_face_element_type_quelc.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_face_element_type_quelc.begin();il != ilfin;il++,it++) + {TypeQuelc_face_a_un_element& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau du pti d'élément + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Element& ele = lesMail.Element_LesMaille(n_mail,ne); + List_io inter; inter.push_back((*it)); // il y a une recopie + ele.Grandeur_particuliere_face(dan.Absolue_const(),inter,dan.Num_FA_const(),dan.NBpti_const()); + // le résultat est dans inter, pas dans (*it) + // affectation + (*(gr.ConteneurDouble())) = (*inter.begin()).GrandeurNumOrdre(dan.Num_ordre()); + }; + }; + + // --- cas des grandeurs quelconques aux pti d'arêtes d'élément + {List_io < TypeQuelc_arete_a_un_element >::iterator il,ilfin + = list_arete_element_type_quelc.end(); + List_io < TypeQuelconque >::iterator it = list_quelc_arete_element_type_quelc.begin(); + // on balaie la liste avec les conteneurs associés + for (il = list_arete_element_type_quelc.begin();il != ilfin;il++,it++) + {TypeQuelc_arete_a_un_element& dan = *il; // pour simplifier + // récup du conteneur global + const void* pointe = (ParaGlob::param->GrandeurGlobal(dan.Nom_var())); + TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + Grandeur_scalaire_double& gr + = *((Grandeur_scalaire_double*) gr_quelc->Grandeur_pointee()); // pour simplifier + // récup de la valeur demandée au niveau du pti d'élément + int n_mail = 1; // init par défaut + if ((*il).Nom_mail() != "") + n_mail = lesMail.NumMaillage((*il).Nom_mail()); + // récup de la reférence + const string * point_mail = NULL; + if ((*il).Nom_mail_const() != "") + point_mail = &((*il).Nom_mail_const()); + const ReferenceNE & ref = + ((ReferenceNE &) lesRef.Trouve((*il).Ref_NE(),point_mail)); + int ne = ref.Numero(1); // le num du noeud: uniquement le premier + Element& ele = lesMail.Element_LesMaille(n_mail,ne); + List_io inter; inter.push_back((*it)); // il y a une recopie + ele.Grandeur_particuliere_arete(dan.Absolue_const(),inter,dan.Num_FA_const(),dan.NBpti_const()); + // le résultat est dans inter, pas dans (*it) + // affectation + (*(gr.ConteneurDouble())) = (*inter.begin()).GrandeurNumOrdre(dan.Num_ordre()); + }; + }; + + // ----- cas une composante d'une variable globale de type multidimentionnel + // rien à faire, c'est fait à l'appel de la variable globale (cf. ParaGlob) + + }; + + + +//----- lecture écriture de base info ----- +// lecture base info +// = 1 : on récupère tout +// = 2 : on récupère uniquement les données variables (supposées comme telles) +void VariablesExporter::Lecture_base_info(ifstream& entr,const int cas) +{switch (cas) + { case 1 : // ------- on récupère tout ------------------------- + { + break; + } + case 2 : // ----------- lecture uniquement de se qui varie -------------------- + { + break; + } + default : + { cout << "\nErreur : valeur incorrecte du type de lecture !\n"; + cout << "VariablesExporter::Lecture_base_info(ofstream& sort,int cas)" + << " cas= " << cas << endl; + Sortie(1); + }; + }; +}; + +// écriture base info +// = 1 : on sauvegarde tout +// = 2 : on sauvegarde uniquement les données variables (supposées comme telles) +void VariablesExporter::Ecriture_base_info(ofstream& sort,const int cas) +{switch (cas) + { case 1 : // ------- on sauvegarde tout ------------------------- + { + // -- cas des Constantes utilisateurs --- + sort << "\n ===constantes_utilisateur==== "; + { List_io < Ddl_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddl.end(); + List_io < string >::const_iterator il = li_nom.begin(); + for (it = list_noeud_type_ddl.begin();it != itfin; it++,il++) + sort << "\n double_ " << (*il) ; + }; + + // -- cas des variables utilisateurs --- + sort << "\n ===variables_utilisateur==== "; + { List_io < Ddl_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddl.end(); + for (it = list_noeud_type_ddl.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas des ddl étendu aux noeuds --- + { List_io < Ddl_etendu_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddlEtendu.end(); + for (it = list_noeud_type_ddlEtendu.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas des grandeurs quelconques aux noeuds --- + { List_io < Quelconque_a_un_noeud >::const_iterator it, itfin = list_noeud_type_quelconque.end(); + for (it = list_noeud_type_quelconque.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas des ddl aux pti d'éléments --- + { List_io < Ddl_a_un_element >::const_iterator it, itfin = list_element_type_ddl.end(); + for (it = list_element_type_ddl.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas des grandeurs particulières aux pti d'éléments --- + { List_io < TypeParticulier_a_un_element >::const_iterator it, itfin = list_element_type_particulier.end(); + for (it = list_element_type_particulier.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas des grandeurs évoluées aux pti d'éléments --- + { List_io < TypeEvoluee_a_un_element >::const_iterator it, itfin = list_element_type_evoluee.end(); + for (it = list_element_type_evoluee.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas des grandeurs quelconques aux pti de faces d'éléments --- + { List_io < TypeQuelc_face_a_un_element >::const_iterator it, itfin = list_face_element_type_quelc.end(); + for (it = list_face_element_type_quelc.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas des grandeurs quelconques aux pti d'arête d'éléments --- + { List_io < TypeQuelc_arete_a_un_element >::const_iterator it, itfin = list_arete_element_type_quelc.end(); + for (it = list_arete_element_type_quelc.begin();it != itfin; it++) + sort << (*it); + }; + // -- cas d'une composante d'une variable globale de type multidimentionnel --- + { List_io < TypeQuelc_Une_composante_Grandeur_globale >::const_iterator it, itfin = list_var_glob_sur_grandeur_globale.end(); + for (it = list_var_glob_sur_grandeur_globale.begin();it != itfin; it++) + sort << (*it); + }; + + break; + } + case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- + { + + break; + } + default : + { cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n"; + cout << "VariablesExporter::Ecriture_base_info(ofstream& sort,int cas)" + << " cas= " << cas << endl; + Sortie(1); + }; + }; +}; + +// sortie du schemaXML: en fonction de enu +void VariablesExporter::SchemaXML_VariablesExporters(UtilLecture * entreePrinc,const Enum_IO_XML enu) + { +// switch (enu) +// {case XML_TYPE_GLOBAUX: +// { // cas des classes de base +// DeuxEntiers toto; +// toto.SchemaXML_DeuxEntiers(sort,enu); +// break; +// } +// case XML_IO_POINT_INFO: +// {// cas de def de LesMaillages +// sort << "\n " +// << "\n " +// << "\n " +// << "\n une suite de maillages " +// << "\n " +// << "\n " +// << "\n " +// << "\n " +// << "\n " +// << "\n "; +// // def de Maillage +//// SchemaXML_Maillage(sort,niveau); +// break; +// } +// }; + }; + + // -- def de constantes utilisateur pour une sortie sur un fichier de commande + void VariablesExporter::Info_commande_ConstantesUtilisateur(UtilLecture * entreePrinc) + { cout << "\n definition de constante(s) utilisateur (defaut 0 c-a-d non) : 1 (c-a-d oui) ? "; + string rep;bool choix_valide=false; + + while (!choix_valide) + { rep = "_"; + // procédure de lecture avec prise en charge d'un retour chariot + rep = lect_return_defaut(true,"0"); + if (rep.size()==0) + {rep = "0"; + cout << "--> valeur: 0 "; + }; + + if (rep == "1") { choix_valide=true;} + else if (rep == "0") {choix_valide=true;} + else if (rep == "f") {choix_valide=true;} + else if (rep == "fin_prog") Sortie(1); + else { cout << "\n Erreur on attendait 0 ou 1 ou f !!, redonnez une bonne valeur" + << "\n ou taper fin_prog pour arreter le programme "; + choix_valide=false; + } + }; + // écriture + ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier + // affichage de la banniere sur la sortie passée en argument + Banniere::Sortie_banniere( sort); + // puis affichage de la version + ParaGlob::Sortie_Version(sort); sort << "\n \n"; + sort << "\n#######################################################################" + << "\n# fichier de commande #" + << "\n \n \n" + << "# --- commentaire sur l'objet du travail ???" + << "\n \n \n" + << endl; + + // maintenant on regarde s'il faut des constantes utilisateurs + try + {if (rep == "1") + {sort << "\n#------------------------------------------------------------------" + << "\n Constantes_utilisateurs_ "; + while (choix_valide) + { rep = "_";string nom;double val; + cout << "\n nom de la variable ? (ou f ou 0 (defaut)) "; + nom = lect_return_defaut(false,"f"); + if ((nom != "f")&&(nom != "0")) + { cout << "\n valeur ? ";val=lect_double(); + cout << "\n constante lue : "<< "C__"+nom << " "<< val << flush; + choix_valide = true; + sort << "\n double_ " << "C__"+nom << " "<< val << flush; + } + else {choix_valide = false;}; + }; + sort << "\n fin_Constantes_utilisateurs_ \n" << flush; + }; + } + catch (ErrSortieFinale) + // cas d'une direction voulue vers la sortie + // on relance l'interuption pour le niveau supérieur + { ErrSortieFinale toto; + throw (toto); + } + catch (...) + {cout << "\n *** erreur en definition des constantes utilisateurs ! stop " << flush; + Sortie(1); + }; + + }; + +// -- def de variables utilisateur pour une sortie sur un fichier de commande +void VariablesExporter::Info_commande_VariablesUtilisateur(UtilLecture * entreePrinc) +{ cout << "\n definition de variable(s) utilisateur (defaut 0 c-a-d non) : 1 (c-a-d oui) ? "; + string rep;bool choix_valide=false; + + while (!choix_valide) + { rep = "_"; + // procédure de lecture avec prise en charge d'un retour chariot + rep = lect_return_defaut(true,"0"); + if (rep.size()==0) + {rep = "0"; + cout << "--> valeur: 0 "; + }; + + if (rep == "1") { choix_valide=true;} + else if (rep == "0") {choix_valide=true;} + else if (rep == "f") {choix_valide=true;} + else if (rep == "fin_prog") Sortie(1); + else { cout << "\n Erreur on attendait 0 ou 1 ou f !!, redonnez une bonne valeur" + << "\n ou taper fin_prog pour arreter le programme "; + choix_valide=false; + } + }; + // écriture + ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier + + // maintenant on regarde s'il faut des variables utilisateurs + try + {choix_valide=false; + if (rep == "1") + {sort << "\n#------------------------------------------------------------------" + << "\n Variables_utilisateurs_ "; + while (!choix_valide) + { rep = "_";string nom; + cout << "\n ddl aux noeuds -> rep : noe ?" + << "\n ddl etendu aux noeuds -> rep : net ?" + << "\n grandeur particuliere aux noeuds -> rep : nop ?" + << "\n grandeurs generique aux elements -> rep : ele " + << "\n grandeurs particulieres aux elements -> rep : elp " + << "\n grandeurs tensorielles aux elements -> rep : elt " + << "\n grandeurs aux faces d'elements -> rep : elF " + << "\n grandeurs aux aretes d'elements -> rep : elA " + << "\n une composante de grandeur globale -> rep : cgl " + << "\n pour arreter les questions (defaut) -> rep : fin (ou f) "; + + if (ParaGlob::Francais()) + {cout << "\n reponse ? ";}else {cout << "\n answer ? ";} + rep = lect_return_defaut(false,"f"); + cout << " rep lue: "<< rep << " "; + if (rep == "noe") + { // cas d'un ddl à un noeud + Ddl_a_un_noeud dan; + cout << "\n nom du maillage (defaut aucun) ? "; + dan.Nom_mail() = lect_return_defaut(false,"aucun"); + cout << " val lue: "<< dan.Nom_mail(); + if (dan.Nom_mail() == "aucun") + {dan.Nom_mail() = "";} + cout << "\n ddl (defaut X1) ? "; + dan.Enu() = lect_return_defaut(false,"X1"); + cout << " ddl lu: "<< dan.Enu(); + cout << "\n reference du noeud (defaut N_1) ? "; + dan.Ref_Num_NE() = lect_return_defaut(false,"N_1"); + cout << " val lue: "<< dan.Ref_Num_NE(); + dan.Nom_var() = Lect_interactive_nom_var(); + cout << "\n le temps ou est evalue la variable (defaut: TEMPS_0) ? "; + dan.Temps() = Id_nom_dure(lect_return_defaut(false,"TEMPS_0")); + cout << " temps lu "<< Nom_dure(dan.Temps()); + // on a toutes les infos, on peut enregistrer + sort << dan << flush; + list_noeud_type_ddl.push_back(dan); + } + else if (rep == "net") + { // cas d'un ddl étendu à un noeud + Ddl_etendu_a_un_noeud dan; + cout << "\n nom du maillage (defaut aucun) ? "; + dan.Nom_mail() = lect_return_defaut(false,"aucun"); + cout << " val lue: "<< dan.Nom_mail(); + if (dan.Nom_mail() == "aucun") + {dan.Nom_mail() = "";} + cout << "\n ddl etendu (defaut Masse_diago_noeud) ? "; +// string nom_ddl(lect_return_defaut(false,"Masse_diago_noeud")); + dan.Enu() = lect_return_defaut(false,"Masse_diago_noeud"); + cout << " ddl etendu lu: "<< dan.Enu(); + cout << "\n reference du noeud (defaut N_1) ? "; + dan.Ref_NE() = lect_return_defaut(false,"N_1"); + cout << " val lue: "<< dan.Ref_NE(); + dan.Nom_var() = Lect_interactive_nom_var(); + // on a toutes les infos, on peut enregistrer + sort << dan << flush; + list_noeud_type_ddlEtendu.push_back(dan); + } + else if (rep == "nop") + { Quelconque_a_un_noeud dan; + cout << "\n nom du maillage (defaut aucun) ? "; + dan.Nom_mail() = lect_return_defaut(false,"aucun"); + cout << " val lue: "<< dan.Nom_mail(); + if (dan.Nom_mail() == "aucun") + {dan.Nom_mail() = "";} + cout << "\n grandeur (defaut POSITION_GEOMETRIQUE) ? "; + dan.Quelc() = lect_return_defaut(false,"POSITION_GEOMETRIQUE"); + cout << " lu: "<< dan.Quelc().NomPlein(); + cout << "\n reference du noeud (defaut N_1) ? "; + dan.Ref_NE() = lect_return_defaut(false,"N_1"); + cout << " val lue: "<< dan.Ref_NE(); + dan.Nom_var() = Lect_interactive_nom_var(); + cout << "\n le num d'ordre (ex: num de la composante, defaut 1) ?"; + dan.Num_ordre() = ChangeEntier(lect_return_defaut(false,"1")); + cout << " val lue: "<> nom; + + if ((lec.entree)->rdstate() == 0) + {} // lecture normale + #ifdef ENLINUX + else if ((lec.entree)->fail()) + // on a atteind la fin de la ligne et on appelle un nouvel enregistrement + { lec.NouvelleDonnee(); // lecture d'un nouvelle enregistrement + *(lec.entree) >> nom; + } + #else + else if ((lec.entree)->eof()) + // la lecture est bonne mais on a atteind la fin de la ligne + { if(nom != "fin_Constantes_utilisateurs_") + {lec.NouvelleDonnee(); *(lec.entree) >> nom;}; + } + #endif + else // cas d'une erreur de lecture + { cout << "\n erreur de lecture inconnue "; + lec.MessageBuffer("** erreur en lecture des constantes utilisateur **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + + // en fonction du type de donnée on lit, crée et stock + if (nom == "double_") + { string nom_constante; double val=0.; + *(lec.entree) >> nom_constante >> val; + // il faut que les 3 premiers caractères de nom_constante soit un C__ + if (!((nom_constante[0]== 'C')&&(nom_constante[1]== '_')&&(nom_constante[2]== '_'))) + { cout << "\n erreur de syntaxe en lecture d'une constante de type double, les 3 premieres lettres " + << " devraientt etre un 'C__' et on a lu: "<> nom_constante >> val; +// // il faut que le premier caractère de nom_constante soit un $ +// if (nom_constante[0]!= '$') +// { cout << "\n erreur de syntaxe en lecture d'une constante de type int, la premiere lettre " +// << " devrait etre un '$' et on a lu: "<3) + cout << "\n Projet::LecConstantesUtilisateur(... " << endl ; + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + + }; //-- fin du while + lec.NouvelleDonnee(); // on prépare la nouvelle lecture + }; + }; + +// lecture éventuelle des variables globales définies par l'utilisateur +void VariablesExporter::LecVariablesUtilisateur(UtilLecture& lec) + { // on initialise les conteneurs + // -> noeuds + list_noeud_type_ddl.clear(); + list_noeud_type_ddlEtendu.clear(); + list_noeud_type_quelconque.clear(); + + // -> éléments + list_element_type_ddl.clear(); + list_element_type_particulier.clear(); + list_element_type_evoluee.clear(); + + // -> face d'éléments + list_face_element_type_quelc.clear(); + + // -> arête d'éléments + list_arete_element_type_quelc.clear(); + + // on regarde s'il y a des variables à lire + if (strstr(lec.tablcar,"Variables_utilisateurs_")!=NULL) + { lec.NouvelleDonnee(); // on se positionne sur le premier enreg + // on lit tant que l'on ne rencontre pas la ligne contenant "fin_Variables_utilisateurs_" + while (strstr(lec.tablcar,"fin_Variables_utilisateurs_")==0) + {// choix en fonction du type de variable + + string nom; + + if ((lec.entree)->rdstate() == 0) + {} // lecture normale + #ifdef ENLINUX + else if ((lec.entree)->fail()) + // on a atteind la fin de la ligne et on appelle un nouvel enregistrement + { lec.NouvelleDonnee(); // lecture d'un nouvelle enregistrement + *(lec.entree) >> nom; + } + #else + else if ((lec.entree)->eof()) + // la lecture est bonne mais on a atteind la fin de la ligne + { if(nom != "fin_Variables_utilisateurs_") + {lec.NouvelleDonnee(); }; + } + #endif + else // cas d'une erreur de lecture + { cout << "\n erreur de lecture inconnue "; + lec.MessageBuffer("** erreur en lecture des constantes utilisateur **"); + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + + // en fonction du type de donnée on lit, crée et stock + if (strstr(lec.tablcar,"Ddl_noeud_") != 0) + { Ddl_a_un_noeud dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_noeud_type_ddl.push_back(dan); + } + else if (strstr(lec.tablcar,"Ddl_etendu_a_un_noeud_") != 0) + { Ddl_etendu_a_un_noeud dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_noeud_type_ddlEtendu.push_back(dan); + } + else if (strstr(lec.tablcar,"Quelconque_a_un_noeud_") != 0) + { Quelconque_a_un_noeud dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_noeud_type_quelconque.push_back(dan); + } + else if (strstr(lec.tablcar,"Ddl_a_un_element_") != 0) + { Ddl_a_un_element dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_element_type_ddl.push_back(dan); + } + else if (strstr(lec.tablcar,"Particulier_a_un_element_") != 0) + { TypeParticulier_a_un_element dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_element_type_particulier.push_back(dan); + } + else if (strstr(lec.tablcar,"Evoluee_a_un_element_") != 0) + { TypeEvoluee_a_un_element dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_element_type_evoluee.push_back(dan); + } + else if (strstr(lec.tablcar,"Quelconque_face_element_") != 0) + { TypeQuelc_face_a_un_element dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_face_element_type_quelc.push_back(dan); + } + else if (strstr(lec.tablcar,"Quelconque_arete_element_") != 0) + { TypeQuelc_arete_a_un_element dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_arete_element_type_quelc.push_back(dan); + } + else if (strstr(lec.tablcar,"Une_composante_Grandeur_globale_") != 0) + { TypeQuelc_Une_composante_Grandeur_globale dan; + *(lec.entree) >> dan; + // on vérifie que la variable lue n'existe pas déjà + VariablesExporter::VerifNomVariable(dan.Nom_var(),true); + // stockage + list_var_glob_sur_grandeur_globale.push_back(dan); + } + + else if( strstr(lec.tablcar,"fin_Variables_utilisateurs_") + && strstr(lec.tablcar,"Quelconque_arete_element_") + && strstr(lec.tablcar,"Quelconque_face_element_") + && strstr(lec.tablcar,"Evoluee_a_un_element_") + && strstr(lec.tablcar,"Particulier_a_un_element_") + && strstr(lec.tablcar,"Ddl_a_un_element_") + && strstr(lec.tablcar,"Quelconque_a_un_noeud_") + && strstr(lec.tablcar,"Ddl_etendu_a_un_noeud_") + && strstr(lec.tablcar,"Ddl_noeud_") + && strstr(lec.tablcar,"Une_composante_Grandeur_globale_") + ) + {cout << "\n erreur de lecture du type de variable " + << " on a lu " << nom << ", type qui n'est pas etre pris en compte..."; + if (ParaGlob::NiveauImpression()>3) + cout << "\n Projet::LecVariablesUtilisateur(... " << endl ; + throw (UtilLecture::ErrNouvelleDonnee(-1)); + Sortie(1); + }; + + }; //-- fin du while + lec.NouvelleDonnee(); // on prépare la nouvelle lecture + }; + }; + +// insertion des constantes utilisateur dans les variables globales +void VariablesExporter::InsertConstUtilisateur_dans_globale() + { // on passe en revue tous les éléments de la liste + list::iterator il,ilfin = li_Q.end(); + list::const_iterator inom= li_nom.begin(); + for (il = li_Q.begin();il != ilfin;il++,inom++) + { // on regarde si la grandeur n'existe pas déjà: si oui on couine + const void* pointe = (ParaGlob::param->GrandeurGlobal(*inom)); + if (pointe != NULL) + {TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe); + cout << "\n warning *** la constante globale "<< (*inom) + << " a deja ete definie ! => " << (*(gr_quelc->Grandeur_pointee())); + cout << "\n on remplace par sa nouvelle valeur: => " << (*((*il).Grandeur_pointee())); + ParaGlob::param->Suppression_grandeur_consultable(*inom); // suppression + // puis on ajoute + ParaGlob::param->Ajout_grandeur_consultable(&(*il),*inom); + } + else // sinon on ajoute simplement + {ParaGlob::param->Ajout_grandeur_consultable(&(*il),*inom);}; + }; + }; + +// vérification que 2 nom de variables ne soient pas identique +// si avec_sortie = true -> arrêt +// si avec_sortie = false -> retour du test: true si c'est ok +// false si pb +bool VariablesExporter::VerifNomVariable(const string& nom,bool avec_sortie) const + { // -- cas des ddl aux noeuds --- + { List_io < Ddl_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddl.end(); + for (it = list_noeud_type_ddl.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: Ddl_a_un_noeud " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas des ddl étendu aux noeuds --- + { List_io < Ddl_etendu_a_un_noeud >::const_iterator it, itfin = list_noeud_type_ddlEtendu.end(); + for (it = list_noeud_type_ddlEtendu.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: Ddl_etendu_a_un_noeud " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas des grandeurs quelconques aux noeuds --- + { List_io < Quelconque_a_un_noeud >::const_iterator it, itfin = list_noeud_type_quelconque.end(); + for (it = list_noeud_type_quelconque.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: Quelconque_a_un_noeud " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas des ddl aux pti d'éléments --- + { List_io < Ddl_a_un_element >::const_iterator it, itfin = list_element_type_ddl.end(); + for (it = list_element_type_ddl.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: Ddl_a_un_element " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas des grandeurs particulières aux pti d'éléments --- + { List_io < TypeParticulier_a_un_element >::const_iterator it, itfin = list_element_type_particulier.end(); + for (it = list_element_type_particulier.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: TypeParticulier_a_un_element " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas des grandeurs évoluées aux pti d'éléments --- + { List_io < TypeEvoluee_a_un_element >::const_iterator it, itfin = list_element_type_evoluee.end(); + for (it = list_element_type_evoluee.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: TypeEvoluee_a_un_element " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas des grandeurs quelconques aux pti de faces d'éléments --- + { List_io < TypeQuelc_face_a_un_element >::const_iterator it, itfin = list_face_element_type_quelc.end(); + for (it = list_face_element_type_quelc.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: Quelconque_face_element_ " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas des grandeurs quelconques aux pti d'arête d'éléments --- + { List_io < TypeQuelc_arete_a_un_element >::const_iterator it, itfin = list_arete_element_type_quelc.end(); + for (it = list_arete_element_type_quelc.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: Quelconque_arete_element_ " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + // -- cas d'une composante d'une variable globale de type multidimentionnel--- + { List_io < TypeQuelc_Une_composante_Grandeur_globale >::const_iterator it, itfin = list_var_glob_sur_grandeur_globale.end(); + for (it = list_var_glob_sur_grandeur_globale.begin();it != itfin; it++) + if ((*it).Nom_var_const() == nom) + { cout << "\n *** erreur en lecture d'une variable utilisateur: Une_composante_Grandeur_globale_ " + << " on a deja lue une variable de meme nom = "<< nom ; + if (avec_sortie) + {Sortie(1);} + else {return false;}; + }; + }; + + // arrivée ici, cela veut dire que tout est ok + return true; + + }; + +// lecture interactive du nom de la variable: hors variable relais +string VariablesExporter::Lect_interactive_nom_var() + { string no_user(""); + while(no_user.length()==0) + { cout << "\n nom_utilisateur de la grandeur ? "; + no_user = lect_return_defaut(false,""); + if (no_user.length()==0) + {cout << "\n vous devez donner un nom !! ";} + else + {// on complète éventuellement + if (!((no_user[0]== 'V')&&(no_user[1]== '_')&&(no_user[2]== '_'))) + no_user = "V__" + no_user; + // on teste s'il y en a deux identiques + if (!VerifNomVariable(no_user,false)) + { cout << "\n ce nom de variable existe deja ! donner un autre "; + no_user = ""; + }; + }; + }; + cout << " nom lu: "<< no_user; + return no_user; +}; + +// lecture interactive du nom d'une variable relais +string VariablesExporter::Lect_interactive_nom_var_relais() + { string no_user(""); + while(no_user.length()==0) + { cout << "\n nom_utilisateur de la grandeur ? "; + no_user = lect_return_defaut(false,""); + if (no_user.length()==0) + {cout << "\n vous devez donner un nom !! ";} + else + {// on complète éventuellement + if (!((no_user[0]== 'V')&&(no_user[1]== 'R') &&(no_user[2]== '_'))) + no_user = "VR_" + no_user; + // on teste s'il y en a deux identiques + if (!VerifNomVariable(no_user,false)) + { cout << "\n ce nom de variable existe deja ! donner un autre "; + no_user = ""; + }; + }; + }; + cout << " nom lu: "<< no_user; + return no_user; +}; + + + +// insertion d'une composante d'une grandeur quelconque en globale +// sous forme d'un double +void VariablesExporter::InsertCompGrandeurQuelc + (const string& non_var,const TypeQuelconque_enum_etendu& enu) + {// on crée un conteneur d'un double + double val=0; + Grandeur_scalaire_double grand_courant(val); + // on récupère le temps + EnumTypeQuelconque eTQ = enu.EnumTQ(); + Enum_dure temps = EnumTypeQuelconqueTemps(eTQ); + + switch (temps) + {case TEMPS_0 : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_0,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,non_var); + break; + } + case TEMPS_t : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_T,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,non_var); + break; + } + case TEMPS_tdt : + {TypeQuelconque typQ1(GENERIQUE_UNE_VARIABLE_GLOB_DOUBLE_UTILISATEUR_TDT,NU_DDL,grand_courant); + ParaGlob::param->Ajout_grandeur_consultable(&typQ1,non_var); + break; + } + default : + cout << "\nErreur : valeur incorrecte du temps pour une variable ddl globale !\n"; + cout << "\n VariablesExporter::InsertCompGrandeurQuelc(... \n"; + Sortie(1); + }; + }; + + + + + + diff --git a/Maillage/VariablesExporter.h b/Maillage/VariablesExporter.h new file mode 100755 index 0000000..3dc9800 --- /dev/null +++ b/Maillage/VariablesExporter.h @@ -0,0 +1,793 @@ + +// 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: . + +/************************************************************************ +* DATE: 06/03/2023 * +* $ * +* AUTEUR: G RIO (mailto:gerardrio56@free.fr) * +* $ * +* PROJET: Herezh++ * +* $ * +************************************************************************ +* BUT: def d'une classe relative a l'exportation en variables * +* globales de grandeurs définies dans les maillages. * +* Cela concerne les constantes utilisateur et les variables * +* calculées par Herezh. * +* $ * +* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * +* VERIFICATION: * +* * +* ! date ! auteur ! but ! * +* ------------------------------------------------------------ * +* ! ! ! ! * +* $ * +* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * +* MODIFICATIONS: * +* ! date ! auteur ! but ! * +* ------------------------------------------------------------ * +* $ * +************************************************************************/ + + +#ifndef VARIABLES_EXPORTER_H +#define VARIABLES_EXPORTER_H + + +#include +#include +#ifndef ENLINUX_STREAM + #include // pour le flot en memoire centrale +#else + #include // pour le flot en memoire centrale +#endif + #include "UtilLecture.h" +#include "Enum_IO_XML.h" + + +#include "LesMaillages.h" +#include "Basiques.h" + + +/** @defgroup Les_classes_exportation_en_variables +* +* BUT:def de classes relatives a l'exportation en variables +* globales de grandeurs définies dans les maillages. +* Cela concerne les constantes utilisateur et les variables +* calculées par Herezh. +* +* \author Gérard Rio +* \version 1.0 +* \date 23/01/97 +* \brief Définition de classes relatives a l'exportation en variables +* +*/ + +/// @addtogroup Les_classes_exportation_en_variables +/// @{ +/// + +class VariablesExporter +{ + public : + friend class LesMaillages; + + //=================%%%%%%%% classes de conteneurs %%%%%%%%================= + + // classe conteneur de base pour noeud, élément etc. + class A_un_NE + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, A_un_NE &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const A_un_NE &); + + public : + A_un_NE(); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + A_un_NE(string ref + ,string nom_mail_,string nom_var_); + // constructeur de copie + A_un_NE (const A_un_NE& a); + // DESTRUCTEUR : + virtual ~A_un_NE (); + + // opérateurs + A_un_NE& operator= (const A_un_NE& a); + bool operator== (const A_un_NE& a) const; + bool operator!= (const A_un_NE& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const A_un_NE& a) const; + bool operator <= (const A_un_NE& a) const; + bool operator > (const A_un_NE& a) const; + bool operator >= (const A_un_NE& a) const; + void Affiche(); + + // retour des grandeurs + const string& Ref_const() const {return ref;}; // la ref + const string& Nom_mail_const() const {return nom_mail;}; // le nom du maillage du noeud + const string& Nom_var_const() const {return nom_var;}; // nom de la variable associée + + string& Ref_NE() {return ref;}; // la ref + string* Pointeur_Ref_NE() {return &ref;}; // la ref + string& Nom_mail() {return nom_mail;}; // le nom du maillage du noeud + string* Pointeur_Nom_mail() {return &nom_mail;}; // le nom du maillage du noeud + string& Nom_var() {return nom_var;}; // nom de la variable associée + + // récupération du pointeur de la classe + const A_un_NE* PointeurClass_const() const {return this;}; + A_un_NE* PointeurClass() {return this;}; + + + + protected : + string ref; // la ref associée + string nom_mail; // le nom du maillage du noeud ou élément + string nom_var; // nom de la variable associée + }; + + // classe conteneur pour un ddl à un noeud + class Ddl_a_un_noeud + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, Ddl_a_un_noeud &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const Ddl_a_un_noeud &); + + public : + Ddl_a_un_noeud (); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + Ddl_a_un_noeud (Ddl_enum_etendu e,string ref_noeud + , string nom_mail_,string nom_var_, Enum_dure tps); + // constructeur de copie + Ddl_a_un_noeud (const Ddl_a_un_noeud& a); + // DESTRUCTEUR : + virtual ~Ddl_a_un_noeud (); + + // opérateurs + Ddl_a_un_noeud& operator= (const Ddl_a_un_noeud& a); + bool operator== (const Ddl_a_un_noeud& a) const; + bool operator!= (const Ddl_a_un_noeud& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const Ddl_a_un_noeud& a) const; + bool operator <= (const Ddl_a_un_noeud& a) const; + bool operator > (const Ddl_a_un_noeud& a) const; + bool operator >= (const Ddl_a_un_noeud& a) const; + void Affiche(); + + // retour des grandeurs + const Ddl_enum_etendu& Enu_const() const {return enu;} ; // le ddl + const string& Ref_Num_NE_const() const {return ref_num_NE;}; // la ref de num du noeud + const string& Nom_mail_const() const {return nom_mail;}; // le nom du maillage du noeud + const string& Nom_var_const() const {return nom_var;}; // nom de la variable associée + const Enum_dure& Temps_const() const {return temps;}; // temps de validation du ddl + string* Pointeur_Nom_mail() {return &nom_mail;}; // le nom du maillage du noeud + + Ddl_enum_etendu& Enu() {return enu;} ; // le ddl + string& Ref_Num_NE() {return ref_num_NE;}; // la ref de num du noeud + string& Nom_mail() {return nom_mail;}; // le nom du maillage du noeud + string& Nom_var() {return nom_var;}; // nom de la variable associée + Enum_dure& Temps() {return temps;}; // temps de validation du ddl + + protected : + Ddl_enum_etendu enu; // le ddl + string ref_num_NE; // le num du noeud + string nom_mail; // le nom du maillage du noeud + string nom_var; // nom de la variable associée + Enum_dure temps; // temps de validation du ddl + }; + + // classe conteneur pour un ddl étendu à un noeud + class Ddl_etendu_a_un_noeud : public A_un_NE + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, Ddl_etendu_a_un_noeud &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const Ddl_etendu_a_un_noeud &); + + public : + Ddl_etendu_a_un_noeud (); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + Ddl_etendu_a_un_noeud (Ddl_enum_etendu e,string ref_noeud + , string nom_mail_,string nom_var_); + // constructeur de copie + Ddl_etendu_a_un_noeud (const Ddl_etendu_a_un_noeud& a); + // DESTRUCTEUR : + virtual ~Ddl_etendu_a_un_noeud (); + + // opérateurs + Ddl_etendu_a_un_noeud& operator= (const Ddl_etendu_a_un_noeud& a); + bool operator== (const Ddl_etendu_a_un_noeud& a) const; + bool operator!= (const Ddl_etendu_a_un_noeud& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const Ddl_etendu_a_un_noeud& a) const; + bool operator <= (const Ddl_etendu_a_un_noeud& a) const; + bool operator > (const Ddl_etendu_a_un_noeud& a) const; + bool operator >= (const Ddl_etendu_a_un_noeud& a) const; + void Affiche(); + + // retour des grandeurs + Ddl_enum_etendu Enu_const() const {return enu;} ; // le ddl + Ddl_enum_etendu& Enu() {return enu;} ; // le ddl + + protected : + Ddl_enum_etendu enu; // le ddl + }; + + // classe conteneur pour une grandeur quelconque à un noeud + class Quelconque_a_un_noeud : public A_un_NE + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, Quelconque_a_un_noeud &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const Quelconque_a_un_noeud &); + + public : + Quelconque_a_un_noeud (); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + Quelconque_a_un_noeud (TypeQuelconque_enum_etendu e,string ref_noeud + , string nom_mail_,string nom_var_,int num_ord); + // constructeur de copie + Quelconque_a_un_noeud (const Quelconque_a_un_noeud& a); + // DESTRUCTEUR : + virtual ~Quelconque_a_un_noeud (); + + // opérateurs + Quelconque_a_un_noeud& operator= (const Quelconque_a_un_noeud& a); + bool operator== (const Quelconque_a_un_noeud& a) const; + bool operator!= (const Quelconque_a_un_noeud& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const Quelconque_a_un_noeud& a) const; + bool operator <= (const Quelconque_a_un_noeud& a) const; + bool operator > (const Quelconque_a_un_noeud& a) const; + bool operator >= (const Quelconque_a_un_noeud& a) const; + void Affiche(); + + // retour des grandeurs + const TypeQuelconque_enum_etendu& Quelc_const() const {return quelc;} ; // la grandeur constante + TypeQuelconque_enum_etendu& Quelc() {return quelc;} ; // la grandeur en i/o + + const int& Num_ordre_const() const {return num_ordre;}; + int& Num_ordre() {return num_ordre;}; + + protected : + TypeQuelconque_enum_etendu quelc; // la grandeur + int num_ordre; // le numéro de la composante + }; + + // classe conteneur pour un pti d'élément + class A_un_E : public A_un_NE + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, A_un_E &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const A_un_E &); + + public : + A_un_E (); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + A_un_E (int absolu_,string ref_ + ,string nom_mail_,string nom_var_,int nbpti); + // constructeur de copie + A_un_E (const A_un_E& a); + // DESTRUCTEUR : + virtual ~A_un_E (); + + // opérateurs + A_un_E& operator= (const A_un_E& a); + bool operator== (const A_un_E& a) const; + bool operator!= (const A_un_E& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const A_un_E& a) const; + bool operator <= (const A_un_E& a) const; + bool operator > (const A_un_E& a) const; + bool operator >= (const A_un_E& a) const; + void Affiche(); + + // récupération du pointeur de la classe + const A_un_E* PointeurClass_E_const() const {return this;}; + A_un_E* PointeurClass_E() {return this;}; + + // retour des grandeurs + + const int& NBpti_const() const {return num_pti;}; // num du pti en const + int& NBpti() {return num_pti;}; // idem direct + const int& Absolue_const() const {return absolu;}; // absolu ou pas + int& Absolue() {return absolu;}; + + protected : + int num_pti; // numéro du point d'intégration + int absolu; // indique si la grandeur est dans un repère absolu ou local + }; + +// classe conteneur pour un ddl à un élément + class Ddl_a_un_element : public A_un_E + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, Ddl_a_un_element &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const Ddl_a_un_element &); + + public : + Ddl_a_un_element (); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + Ddl_a_un_element (int absolu_,Ddl_enum_etendu e,string ref_noeud + ,string nom_mail_,Enum_dure tps,string nom_var_,int nbpti); + // constructeur de copie + Ddl_a_un_element (const Ddl_a_un_element& a); + // DESTRUCTEUR : + virtual ~Ddl_a_un_element (); + + // opérateurs + Ddl_a_un_element& operator= (const Ddl_a_un_element& a); + bool operator== (const Ddl_a_un_element& a) const; + bool operator!= (const Ddl_a_un_element& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const Ddl_a_un_element& a) const; + bool operator <= (const Ddl_a_un_element& a) const; + bool operator > (const Ddl_a_un_element& a) const; + bool operator >= (const Ddl_a_un_element& a) const; + void Affiche(); + + // retour des grandeurs + const Ddl_enum_etendu& Enu_const() const {return enu;} ; // le ddl en const + Ddl_enum_etendu& Enu() {return enu;} ; // le ddl direct + const Enum_dure& Temps_const() const {return temps;}; // temps de validation du ddl + Enum_dure& Temps() {return temps;}; // temps de validation du ddl + + protected : + Ddl_enum_etendu enu; // le ddl + Enum_dure temps; // temps de validation du ddl + }; + + // classe conteneur pour un TypeQuelconque à un élément + class TypeQuelconque_a_un_element : public A_un_E + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, TypeQuelconque_a_un_element &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const TypeQuelconque_a_un_element &); + + public : + TypeQuelconque_a_un_element (); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + TypeQuelconque_a_un_element (int absolu_,TypeQuelconque_enum_etendu e,string ref_NE + ,string nom_mail_,Enum_dure tps,string nom_var_,int nbpti,int num_ord); + // constructeur de copie + TypeQuelconque_a_un_element (const TypeQuelconque_a_un_element& a); + // DESTRUCTEUR : + virtual ~TypeQuelconque_a_un_element (); + + // opérateurs + TypeQuelconque_a_un_element& operator= (const TypeQuelconque_a_un_element& a); + bool operator== (const TypeQuelconque_a_un_element& a) const; + bool operator!= (const TypeQuelconque_a_un_element& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const TypeQuelconque_a_un_element& a) const; + bool operator <= (const TypeQuelconque_a_un_element& a) const; + bool operator > (const TypeQuelconque_a_un_element& a) const; + bool operator >= (const TypeQuelconque_a_un_element& a) const; + void Affiche(); + + // récupération du pointeur de la classe + const TypeQuelconque_a_un_element* PointeurClass_Quelc_const() const {return this;}; + TypeQuelconque_a_un_element* PointeurClass_Quelc() {return this;}; + + // retour des grandeurs + const TypeQuelconque_enum_etendu& Quelc_const() const {return quelc;} ; // la grandeur constante + TypeQuelconque_enum_etendu& Quelc() {return quelc;} ; // la grandeur en i/o + const int& Num_ordre_const() const {return num_ordre;}; + int& Num_ordre() {return num_ordre;}; + + protected : + TypeQuelconque_enum_etendu quelc; // la grandeur + int num_ordre; // le numéro de la composante + }; + + // classe conteneur pour les grandeurs particulières à un élément + class TypeParticulier_a_un_element : public TypeQuelconque_a_un_element + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, TypeParticulier_a_un_element &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const TypeParticulier_a_un_element &); + + public : + TypeParticulier_a_un_element(): TypeQuelconque_a_un_element() {}; // constructeur par défaut + // constructeur fonction de toutes les grandeurs + TypeParticulier_a_un_element (int absolu_,TypeQuelconque_enum_etendu e,string ref_noeud + ,string nom_mail_,Enum_dure tps,string nom_var_,int nbpti,int num_ord): + TypeQuelconque_a_un_element(absolu_,e,ref_noeud,nom_mail_,tps,nom_var_,nbpti,num_ord) {} ; + // constructeur de copie + TypeParticulier_a_un_element(const TypeParticulier_a_un_element& a): + TypeQuelconque_a_un_element(a) {}; + // DESTRUCTEUR : + virtual ~TypeParticulier_a_un_element() {}; + + // opérateurs + TypeParticulier_a_un_element& operator= (const TypeParticulier_a_un_element& a) + {(*PointeurClass_Quelc())= (*a.PointeurClass_Quelc_const());}; + bool operator== (const TypeParticulier_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) == (*a.PointeurClass_Quelc_const()));}; + bool operator!= (const TypeParticulier_a_un_element& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const TypeParticulier_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) < (*a.PointeurClass_Quelc_const()));}; + bool operator <= (const TypeParticulier_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) <= (*a.PointeurClass_Quelc_const()));}; + bool operator > (const TypeParticulier_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) > (*a.PointeurClass_Quelc_const()));}; + bool operator >= (const TypeParticulier_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) == (*a.PointeurClass_Quelc_const()));}; + void Affiche(); + }; + + // classe conteneur pour les grandeurs évoluées à un élément + class TypeEvoluee_a_un_element : public TypeQuelconque_a_un_element + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, TypeEvoluee_a_un_element &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const TypeEvoluee_a_un_element &); + + public : + TypeEvoluee_a_un_element(): TypeQuelconque_a_un_element() {}; // constructeur par défaut + // constructeur fonction de toutes les grandeurs + TypeEvoluee_a_un_element (int absolu_,TypeQuelconque_enum_etendu e,string ref_noeud + ,string nom_mail_,Enum_dure tps,string nom_var_,int nbpti,int num_ord): + TypeQuelconque_a_un_element(absolu_,e,ref_noeud,nom_mail_,tps,nom_var_,nbpti,num_ord) {} ; + // constructeur de copie + TypeEvoluee_a_un_element(const TypeEvoluee_a_un_element& a): + TypeQuelconque_a_un_element(a) {}; + // DESTRUCTEUR : + virtual ~TypeEvoluee_a_un_element() {}; + + // opérateurs + TypeEvoluee_a_un_element& operator= (const TypeEvoluee_a_un_element& a) + {(*PointeurClass_Quelc())= (*a.PointeurClass_Quelc_const());}; + bool operator== (const TypeEvoluee_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) == (*a.PointeurClass_Quelc_const()));}; + bool operator!= (const TypeEvoluee_a_un_element& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const TypeEvoluee_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) < (*a.PointeurClass_Quelc_const()));}; + bool operator <= (const TypeEvoluee_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) <= (*a.PointeurClass_Quelc_const()));}; + bool operator > (const TypeEvoluee_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) > (*a.PointeurClass_Quelc_const()));}; + bool operator >= (const TypeEvoluee_a_un_element& a) const + {return ((*PointeurClass_Quelc_const()) == (*a.PointeurClass_Quelc_const()));}; + void Affiche(); + }; + + // classe conteneur pour un TypeQuelconque à une face ou arête + class TypeQuelconque_a_Face_arete : public TypeQuelconque_a_un_element + { public : + TypeQuelconque_a_Face_arete (); // constructeur par défaut + // constructeur fonction de toutes les grandeurs + TypeQuelconque_a_Face_arete (int absolu_,TypeQuelconque_enum_etendu e,string ref_element + ,string nom_mail_,int nbFA, Enum_dure tps,string nom_var_,int nbpti,int num_ord); + // constructeur de copie + TypeQuelconque_a_Face_arete (const TypeQuelconque_a_Face_arete& a); + // DESTRUCTEUR : + virtual ~TypeQuelconque_a_Face_arete (); + + // opérateurs + TypeQuelconque_a_Face_arete& operator= (const TypeQuelconque_a_Face_arete& a); + bool operator== (const TypeQuelconque_a_Face_arete& a) const; + bool operator!= (const TypeQuelconque_a_Face_arete& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const TypeQuelconque_a_Face_arete& a) const; + bool operator <= (const TypeQuelconque_a_Face_arete& a) const; + bool operator > (const TypeQuelconque_a_Face_arete& a) const; + bool operator >= (const TypeQuelconque_a_Face_arete& a) const; + + // récupération du pointeur de la classe + const TypeQuelconque_a_Face_arete* PointClass_QuelcFA_const() const {return this;}; + TypeQuelconque_a_Face_arete* PointClass_QuelcFA() {return this;}; + + // retour des grandeurs + const int& Num_FA_const() const {return num_FA;} ; // la grandeur constante + int& Num_FA() {return num_FA;} ; // la grandeur en i/O + + protected : + int num_FA; // ref de numéro de la face ou de l'arête + }; + + // classe conteneur pour les grandeurs quelconque à une face d'élément + class TypeQuelc_face_a_un_element : public TypeQuelconque_a_Face_arete + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, TypeQuelc_face_a_un_element &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const TypeQuelc_face_a_un_element &); + + public : + TypeQuelc_face_a_un_element(): TypeQuelconque_a_Face_arete() {}; // constructeur par défaut + // constructeur fonction de toutes les grandeurs + TypeQuelc_face_a_un_element (int absolu_,TypeQuelconque_enum_etendu e,string ref_element + ,string nom_mail_,int nbFA, Enum_dure tps,string nom_var_,int nbpti,int num_ord): + TypeQuelconque_a_Face_arete(absolu_,e,ref_element,nom_mail,nbFA,tps,nom_var_,nbpti,num_ord) + {} ; + // constructeur de copie + TypeQuelc_face_a_un_element(const TypeQuelc_face_a_un_element& a): + TypeQuelconque_a_Face_arete(a) {}; + // DESTRUCTEUR : + virtual ~TypeQuelc_face_a_un_element() {}; + + // opérateurs + TypeQuelc_face_a_un_element& operator= (const TypeQuelc_face_a_un_element& a) + {(*PointClass_QuelcFA())= (*a.PointClass_QuelcFA_const());}; + bool operator== (const TypeQuelc_face_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) == (*a.PointClass_QuelcFA_const()));}; + bool operator!= (const TypeQuelc_face_a_un_element& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const TypeQuelc_face_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) < (*a.PointClass_QuelcFA_const()));}; + bool operator <= (const TypeQuelc_face_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) <= (*a.PointClass_QuelcFA_const()));}; + bool operator > (const TypeQuelc_face_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) > (*a.PointClass_QuelcFA_const()));}; + bool operator >= (const TypeQuelc_face_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) == (*a.PointClass_QuelcFA_const()));}; + void Affiche(); + }; + + // classe conteneur pour les grandeurs quelconque à une arête d'élément + class TypeQuelc_arete_a_un_element : public TypeQuelconque_a_Face_arete + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, TypeQuelc_arete_a_un_element &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const TypeQuelc_arete_a_un_element &); + + public : + TypeQuelc_arete_a_un_element(): TypeQuelconque_a_Face_arete() {}; // constructeur par défaut + // constructeur fonction de toutes les grandeurs + TypeQuelc_arete_a_un_element (int absolu_,TypeQuelconque_enum_etendu e,string ref_element + ,string nom_mail_,int nbFA, Enum_dure tps,string nom_var_,int nbpti,int num_ord): + TypeQuelconque_a_Face_arete(absolu_,e,ref_element,nom_mail,nbFA,tps,nom_var_,nbpti,num_ord) + {} ; + // constructeur de copie + TypeQuelc_arete_a_un_element(const TypeQuelc_arete_a_un_element& a): + TypeQuelconque_a_Face_arete(a) {}; + // DESTRUCTEUR : + virtual ~TypeQuelc_arete_a_un_element() {}; + + // opérateurs + TypeQuelc_arete_a_un_element& operator= (const TypeQuelc_arete_a_un_element& a) + {(*PointClass_QuelcFA())= (*a.PointClass_QuelcFA_const());}; + bool operator== (const TypeQuelc_arete_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) == (*a.PointClass_QuelcFA_const()));}; + bool operator!= (const TypeQuelc_arete_a_un_element& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const TypeQuelc_arete_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) < (*a.PointClass_QuelcFA_const()));}; + bool operator <= (const TypeQuelc_arete_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) <= (*a.PointClass_QuelcFA_const()));}; + bool operator > (const TypeQuelc_arete_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) > (*a.PointClass_QuelcFA_const()));}; + bool operator >= (const TypeQuelc_arete_a_un_element& a) const + {return ((*PointClass_QuelcFA_const()) == (*a.PointClass_QuelcFA_const()));}; + void Affiche(); + }; + + + // classe conteneur pour une composante d'une grandeur globale + class TypeQuelc_Une_composante_Grandeur_globale + { // surcharge de l'operator de lecture avec le type + friend istream & operator >> (istream &, TypeQuelc_Une_composante_Grandeur_globale &); + // surcharge de l'operator d'ecriture + friend ostream & operator << (ostream &, const TypeQuelc_Une_composante_Grandeur_globale &); + + public : + TypeQuelc_Une_composante_Grandeur_globale(): var() {}; // constructeur par défaut + // constructeur fonction de toutes les grandeurs + TypeQuelc_Une_composante_Grandeur_globale (string nom_var, string nom_glob, int num_ord): + var(nom_var,nom_glob,num_ord) + {} ; + // constructeur de copie + TypeQuelc_Une_composante_Grandeur_globale(const TypeQuelc_Une_composante_Grandeur_globale& a): + var(a.var) {}; + // DESTRUCTEUR : + virtual ~TypeQuelc_Une_composante_Grandeur_globale() {}; + + // opérateurs + TypeQuelc_Une_composante_Grandeur_globale& operator= (const TypeQuelc_Une_composante_Grandeur_globale& a) + {var = a.var;}; + bool operator== (const TypeQuelc_Une_composante_Grandeur_globale& a) const + {return (var == a.var);}; + bool operator!= (const TypeQuelc_Une_composante_Grandeur_globale& a) const + {if ( (*this)==a ) return true; else return false;}; + bool operator < (const TypeQuelc_Une_composante_Grandeur_globale& a) const + {return (var < a.var);}; + bool operator <= (const TypeQuelc_Une_composante_Grandeur_globale& a) const + {return (var <= a.var);}; + bool operator > (const TypeQuelc_Une_composante_Grandeur_globale& a) const + {return (var > a.var);}; + bool operator >= (const TypeQuelc_Une_composante_Grandeur_globale& a) const + {return (var >= a.var);}; + void Affiche(); + + // retour des grandeurs + const string& Nom_var_const() const {return var.nom1;}; // nom de la variable associée + string& Nom_var() {return var.nom1;}; // nom de la variable associée + const string& Nom_grandeur_globale_const() const {return var.nom2;}; // nom de la grandeur globale associé + string& Nom_grandeur_globale() {return var.nom2;}; // nom de la grandeur globale associé + const int& Indice_const() const {return var.n;}; + int& Indice() {return var.n;}; + + Deux_String_un_entier Deux_String_un_entier_const() const {return var;} ; + + Deux_String_un_entier& Deux_String_un_entier_() {return var;} ; + + protected : + Deux_String_un_entier var ; + // var.nom1 -> nom de la variable + // var.nom2 -> nom de la grandeur globale + // var.n -> le numéro de la composante + }; + + + + // METHODES : + +//=================%%%%%%%% la classe principale %%%%%%%%================= + + // CONSTRUCTEURS : + + // Constructeur par defaut + VariablesExporter (); + + // Constructeur de copie, cependant ici il n'y a pas de création de noeud ni d'élément + // c'est seulement une création de nouveaux conteneurs de pointeurs + // cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut + // ensuite les définir + VariablesExporter (const VariablesExporter& var); + + // DESTRUCTEUR : + ~VariablesExporter (); + // lecture + void LectureVariablesExporter(UtilLecture * entreePrinc); + + // insertion des constantes et variables utilisateurs vers globales + void InsertConstVarUtilisateur_dans_globale(); + + // initialisation des conteneurs quelconques + // création des conteneurs aux noeuds s'il s'agit d'une variable + // associée à un vecteur global (au sens des algorithmes globaux) + void InitialisationConteneursQuelconques(LesMaillages& lesMail,const List_io < TypeQuelconque >& listeVecGlob,const LesReferences& lesRef); + + // ramène les liste des infos qui seront consultés pour les noeuds + const List_io < Ddl_a_un_noeud >& List_noeud_type_ddl() const {return list_noeud_type_ddl;}; // ddl pur aux noeuds + const List_io < Ddl_etendu_a_un_noeud >& List_noeud_type_ddlEtendu() const {return list_noeud_type_ddlEtendu;}; // idem pour les ddl étendu + const List_io & List_noeud_type_quelconque() const {return list_noeud_type_quelconque;}; // idem en quelconque + + // affichage et definition interactive des commandes + void Info_commande_VariablesExporters(UtilLecture * entreePrinc); + + // Affiche + void Affiche () const ; + + // Surcharge de l'operateur = : realise l'egalite de deux instances + VariablesExporter& operator= (VariablesExporter& var); + + // test si toutes les informations sont completes + // = true -> complet + // = false -> incomplet + bool Complet_VariablesExporter(const LesReferences& lesRef); + + // mises à jour de constantes globales définies par l'utilisateur + // permet de changer les valeurs, lors d'une suite .info par exemple + void MiseAjourConstantesUtilisateur(UtilLecture& lec); + + // renseigne les variables définies par l'utilisateur + // via les valeurs calculées par Herezh + void RenseigneVarUtilisateur(LesMaillages& lesMail,const LesReferences& lesRef); + + //----- lecture écriture dans base info ----- + // cas donne le niveau de la récupération + // = 1 : on récupère tout + // = 2 : on récupère uniquement les données variables (supposées comme telles) + void Lecture_base_info(ifstream& ent,const int cas); + // cas donne le niveau de sauvegarde + // = 1 : on sauvegarde tout + // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) + void Ecriture_base_info(ofstream& sort,const int cas); + // sortie du schemaXML: en fonction de enu + static void SchemaXML_VariablesExporters(UtilLecture * entreePrinc,const Enum_IO_XML enu) ; + + protected : + + // données: + // ---- les constantes utilisateur + list li_Q; // les constantes + list li_nom; // le nom des constantes + + // ------- les variables + + // -> noeuds + List_io < Ddl_a_un_noeud > list_noeud_type_ddl; // ddl pur aux noeuds + List_io < Ddl_etendu_a_un_noeud > list_noeud_type_ddlEtendu; // idem pour les ddl étendu + List_io list_noeud_type_quelconque; // idem en quelconque + + // -> éléments + List_io < Ddl_a_un_element > list_element_type_ddl; // ddl pur aux pti d'élément + // idem pour les grandeurs particulières et évoluées + List_io < TypeParticulier_a_un_element > list_element_type_particulier; + List_io < TypeQuelconque > list_quelc_element_type_particulier; // les conteneurs associés + + List_io < TypeEvoluee_a_un_element > list_element_type_evoluee; + List_io < TypeQuelconque > list_quelc_element_type_evoluee; // les conteneurs associés + + // -> face d'éléments + List_io list_face_element_type_quelc; + List_io < TypeQuelconque > list_quelc_face_element_type_quelc; // les conteneurs associés + + // -> arête d'éléments + List_io list_arete_element_type_quelc; + List_io < TypeQuelconque > list_quelc_arete_element_type_quelc; // les conteneurs associés + + bool initiaConteneurQuelconque; // pour gérer une seule initialisation + + // -> une composante d'une variable globale de type multidimentionnel + List_io list_var_glob_sur_grandeur_globale; + + + // méthodes + + //---- constantes utilisateurs + // lecture éventuelle de constantes globales définies par l'utilisateur + void LecConstantesUtilisateur(UtilLecture& lec); + // insertion des constantes utilisateur dans les variables globales + void InsertConstUtilisateur_dans_globale(); + + // def de constantes utilisateur pour une sortie sur un fichier de commande + void Info_commande_ConstantesUtilisateur(UtilLecture * lec); + + // ---- variables utilisateur + // lecture éventuelle des variables globales définies par l'utilisateur + void LecVariablesUtilisateur(UtilLecture& lec); + + // def de variables utilisateur pour une sortie sur un fichier de commande + void Info_commande_VariablesUtilisateur(UtilLecture * lec); + + // insertion et stockage des variables au niveau de ParaGlob + void Insert_VarUtilisateur_dans_globale(); + + // vérification que 2 nom de variables ne soient pas identique + // si avec_sortie = true -> arrêt + // si avec_sortie = false -> retour du test: true si c'est ok + // false si pb + bool VerifNomVariable(const string& nom,bool avec_sortie) const; + + // lecture interactive du nom de la variable: hors variable relais + string Lect_interactive_nom_var(); + + // lecture interactive du nom d'une variable relais + string Lect_interactive_nom_var_relais(); + + // insertion d'une composante d'une grandeur quelconque en globale + // sous forme d'un double + void InsertCompGrandeurQuelc(const string& non_var,const TypeQuelconque_enum_etendu& enu); + +}; +/// @} // end of group + + + +#endif