Herezh_dev/Maillage/DdlLim.cc
2023-05-03 17:23:49 +02:00

1600 lines
70 KiB
C++

// 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) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "DdlLim.h"
#include <fstream>
#include <sstream>
#include <cstring>
# include <iostream>
using namespace std; //introduces namespace std
#include <stdlib.h>
#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 <Ddlbloque> 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 <Ddlbloque>::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 <Ddlbloque>::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 <string> 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 <int> 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: "<<nom_courbe<<" ";}
else if (sortie_cote == true)
{sort << valeur_du_ddl<<" ";};
if (nom_fonction_nD != "_")
{sort << " Fonction_nD_CHARGE: "<<nom_fonction_nD<<" ";};
if (echelle != ConstMath::trespetit)
sort << " ECHELLE: "<< echelle<<" ";
if (sortie_cote)
sort << " ' ";
};
}
else if (condition_mvt_solide)
{ // cas d'un mouvement solide
sort << nom_des_ddl ;
sort <<flux.str();
if (nom_courbe != "_")
{sort << " COURBE_CHARGE: "<<nom_courbe<<" ";};
if (nom_fonction_nD != "_")
{sort << " Fonction_nD_CHARGE: "<<nom_fonction_nD<<" ";};
if (echelle != ConstMath::trespetit)
sort << " ECHELLE: "<< echelle<<" ";
}
else if (champ_valeurs)
{ // cas d'un champ de valeur
sort << str_champ_valeurs ;
}
else // cas d'une condition de tangence
{ sort << condition_tangence;};
if (temps_mini != (- ConstMath::trespetit))
sort << " TEMPS_MINI= "<< temps_mini<<" ";
if (temps_maxi != ConstMath::tresgrand)
sort << " TEMPS_MAXI= "<< temps_maxi<<" ";
if (blocage_relatif)
sort << " BLOCAGE_RELATIF_ "<<endl;
break;
};
int num = ChangeEntier(rep);
if (Minuscules(rep) == "?")
num = 13;
bool choix_valide=false;
if ((num >= 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 "<<repi;
if ((repi == "1")) {nom_des_ddl = " UX ";}
else if ((repi == "2")) {nom_des_ddl = " UY ";}
else if ((repi == "3")) {nom_des_ddl = " UZ ";}
else { cout << "\n *** choix non valide !";break;};
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;
};
index.Change_taille(9);
index(1) = 1; index(2) = 4; index(3) = 5; index(4) = 6;
index(5) = 7;index(6) = 8;index(7) = 9;index(8) = 14;
index(9) = 16;
break;
}
case 2: // un ddl autre qu'un déplacement
{ string repi="";
cout << "\n nom du ddl ? \n";
repi=lect_chaine(); cout << " valeur lue "<<repi;
if (!ExisteEnum_ddl(repi))
{cout << "\n *** erreur, ce ddl n'existe pas ****";
break;
};
nom_des_ddl = repi;
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;
};
index.Change_taille(9);
index(1) = 1; index(2) = 4; index(3) = 5; index(4) = 6;
index(5) = 7;index(6) = 8;index(7) = 9;index(8) = 14;
index(9) = 16;
break;
}
case 3: // une valeur de ddl
{ cout << "\n valeur du ddl (un reel) ? ";
valeur_du_ddl=lect_double();cout << " valeur lue ="<< valeur_du_ddl;
index.Change_taille(5);
index(1) = 1; index(2) = 7; index(3) = 8;
index(4) = 9;index(5) = 14;
break;
}
case 4: // courbe de charge
{ cout << "\n nom de la courbe de charge ? ";
nom_courbe= lect_chaine();cout << " nom lu = "<< nom_courbe;
index.Change_taille(7);
index(1) = 1;index(2) = 6; index(3) = 7; index(4) = 8;index(5) = 9;
index(6) = 14;index(7) = 16;
break;
}
case 5: // l'echelle
{ cout << "\n valeur de l'echelle (un reel) ? ";
echelle=lect_double();cout << " valeur lue ="<< echelle;
index.Change_taille(6);
index(1) = 1;index(2) = 7; index(3) = 8; index(4) = 9;index(5) = 14;
index(6) = 16;
break;
}
case 6: // temps mini
{ cout << "\n valeur du temps mini (un reel) ? ";
temps_mini=lect_double();cout << " valeur lue ="<< temps_mini;
index.Change_taille(5);
index(1) = 1;index(2) = 7; index(3) = 8; index(4) = 9;index(5) = 14;
break;
}
case 7: // temps maxi
{ cout << "\n valeur du temps maxi (un reel) ? ";
temps_maxi=lect_double();cout << " valeur lue ="<< temps_maxi;
index.Change_taille(5);
index(1) = 1;index(2) = 7; index(3) = 8; index(4) = 9;index(5) = 14;
break;
}
case 8: // blocage relatif
{cout << "\n --> 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 "<<compo
<< "\n (1) valeur nulle "
<< "\n (2) valeur non nulle "
<< "\n (3) courbe de charge "
<< "\n (4) fonction nD de charge \n";
repi=lect_chaine(); cout << " valeur lue "<<repi;
if ((repi == "1"))
{condition_tangence += " "+compo+" ";
choix_valide=true;
}
else if ((repi == "2"))
{condition_tangence += "' "+compo+"= ";
cout << "\n valeur de "<<compo<<" ? ";
double val;
val=lect_double();cout << " valeur lue ="<< val;
condition_tangence += (ChangeReelSTring(val))+" ' ";
choix_valide=true;
}
else if ((repi == "3"))
{condition_tangence += "' "+compo+"= COURBE_CHARGE: ";
cout << "\n nom de la courbe de charge ? ";
string nom_c;
nom_c= lect_chaine();cout << " nom lu = "<< nom_c;
condition_tangence += nom_c;
cout << "\n echelle (un reel) ? ";
double val;
val=lect_double();cout << " valeur lue ="<< val;
condition_tangence += " ECHELLE: "+(ChangeReelSTring(val))+" ' ";
choix_valide=true;
}
else if ((repi == "4"))
{condition_tangence += "' "+compo+"= Fonction_nD_CHARGE: ";
cout << "\n nom de la fonction nD de charge ? ";
string nom_c;
nom_c= lect_chaine();cout << " nom lu = "<< nom_c;
condition_tangence += nom_c;
choix_valide=true;
}
else { cout << "\n *** choix non valide !";choix_valide=false;};
};
};
index.Change_taille(5);
index(1) = 1;index(2) = 7; index(3) = 8; index(4) = 9;index(5) = 14;
break;
}
case 10: // mouvement solide imposé
{cout << "\n --> 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 "<<i<<" ? \n";
nom_ddl= lect_chaine(); cout << " nom lue "<<nom_ddl;
if (!ExisteEnum_ddl(nom_ddl))
{cout << "\n *** erreur, ce ddl n'existe pas ****, on sort de la condition !!";
erreur = true;
break;
};
str_champ_valeurs += " ' "+nom_ddl+"= ";
// maintenant la valeur
cout << "\n (1) valeur numerique ? "
<< "\n (2) courbe de charge ? "
<< "\n (4) fonction nD de charge ? ";
repa=lect_chaine(); cout << " rep lue: "<< repa;
if (repa=="1")
{ double val= 0.;cout << "\n valeur ? ";
val=lect_double();cout << " valeur lue: "<< val;
str_champ_valeurs += (ChangeReelSTring(val))+" ' \n";
}
else if (repa=="2")
{ cout << "\n nom de la courbe de charge ? ";
string nom;
nom= lect_chaine();cout << " nom lu = "<< nom;
str_champ_valeurs += " COURBE_CHARGE: "+nom+" ' \n";
}
else if (repa=="3")
{ cout << "\n nom de la fonction nD de charge ? ";
string nom;
nom= lect_chaine();cout << " nom lu = "<< nom;
str_champ_valeurs += " Fonction_nD_CHARGE: "+nom+" ' \n";
};
};
if (erreur)
break; // on sort s'il y a eu une erreur
str_champ_valeurs += "fin_champ_de_ ";
champ_valeurs=true;
index.Change_taille(5);
index(1) = 1;index(2) = 7; index(3) = 8; index(4) = 9;index(5) = 14;
break;
}
case 12: // liste des ddl existants
{cout << "\n --> 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 "<<repi;
if ((repi == "1")) {nom_des_ddl += " UX ";}
else if ((repi == "2")) {nom_des_ddl += " UY ";}
else if ((repi == "3")) {nom_des_ddl += " UZ ";}
else if ((Minuscules(repi) == "f")||(Minuscules(repi) == "0")) {}
else { cout << "\n *** choix non valide !";};
};
valeur_du_ddl=0.;
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;
};
index.Change_taille(7);
index(1) = 1; index(2) = 5; index(3) = 6; index(4) = 7;
index(5) = 8;index(6) = 9;index(7) = 14;
break;
}
case 15: // fonction nD de charge
{ cout << "\n nom de la fonction nD de charge ? ";
nom_fonction_nD= lect_chaine();cout << " nom lu = "<< nom_fonction_nD;
index.Change_taille(7);
index(1) = 1;index(2) = 6; index(3) = 7; index(4) = 8;index(5) = 9;
index(6) = 14;index(7) = 5;
break;
}
default:
cout << "\n le cas "<<rep<<" n'est pas traite !!, bizarre, il faut se plaindre !! ";
};
}
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 des mots cles proposes !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour sortir ";
};
}; //-- fin du while
sort << flush;
};
//------------------------------ FONCTIONS PROTEGEES --------------------
// verification en fonction de la dimension du pb
// par exemple en dim 2 d'existance des UZ ou des X3 etc..
void DdlLim::VerifDimDdl()
{ //pour l'instant ne fait rien
};
// ====================================================================
// classe Ddlbloque
// ====================================================================
// surcharge de l'operateur d'ecriture
ostream & operator << (ostream & sort,const DdlLim::Ddlbloque & a)
{ // écriture du type
sort << "Ddlbloque ";
// les données
sort << a.ddl << " " << a.co_charge << " " << a.echelle << " "<< a.f_charge << " " ;
return sort;
};
// surcharge de l'operator de lecture
istream & operator >> (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::Ddlbloque> 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 <Ddlbloque> 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::Ddlbloque> 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 <Ddlbloque> 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;
};