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