Herezh_dev/herezh_pp/Maillage/LesCondLim2.cc

1966 lines
103 KiB
C++
Executable file

// 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-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "LesCondLim.h"
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "CharUtil.h"
#include "TypeQuelconqueParticulier.h"
// retourne la liste des types de ddl actuellement imposés
// aux noeuds pour chaque maillage, la liste est exhaustive
// elle contiend tous les types au moins une fois utilisée
// cela ne signifie pas que le ddl en question soit présent
// pour tous les noeud du maillage considéré
// - le tableau de retour est indicé par le numéro de maillage correspondant
// - il y a une liste par maillage
Tableau <List_io < Ddl_enum_etendu> > LesCondLim::Les_type_de_ddl_en_reaction() const
{ // définition du tableau de retour
Tableau <List_io <Ddl_enum_etendu> > tab_li(nb_maillage);
// on boucle sur les réactions en cours pour remplir le tableau
int nb_reac=reaction.Taille();
for (int i=1;i<=nb_reac;i++)
{ List_io <Ddl_enum_etendu>& li=tab_li(reaction(i).numMail);
Ddl_enum_etendu ddl_enu = (reaction(i).ddl.Id_nom());
if (find(li.begin(),li.end(),ddl_enu) == li.end())
li.push_back(ddl_enu);
};
// retour du tableau de listes
return tab_li;
};
/* // retourne les réactions aux conditions limites à un noeud noe d'un maillage mail
// en paramètre il y a un pointeur sur la liste de retour, pour éviter la création
// d'une liste intermédiaire
// s'il n'y a pas de conditions limites : retour d'une liste vide
const list<const LesCondLim::ReactStoc*>& LesCondLim::Reaction_noeud_mail(int numNoeud,int numMail) const
{ string cle("mail"+ChangeEntierSTring(numMail)+"noeud"+ChangeEntierSTring(numNoeud));
map < string, list<const ReactStoc*> , std::less <string> >::const_iterator it = map_reaction.find(cle);
if (it != map_reaction.end())
{ return (*it).second;};
// sinon pas d'existence donc retour d'une liste vide
const list<const LesCondLim::ReactStoc*> li; // construction d'une liste vide
return li;
}; */
// retourne la liste des torseurs de réaction actuellement actif pour les maillages
// appelons tab_lili la liste:
// - tab_lili(i) concerne le maillage nb i
// - les éléments de tab_lili(i) sont les noms des références qui conduisent à un torseur de réaction
// actif, et un indice de gestion utilisé par LesCondLim pour retrouver
// rapidemment les informations
Tableau < List_io <String_et_entier > > LesCondLim::TabListTorseurReaction(const LesMaillages & lesmail) const
{ // def de la grandeur de retour
Tableau < List_io <String_et_entier > > tab_lili(nb_maillage);
string nom; // une variable de travail
// on balaie le tableau des torseur
int ttail = tab_torseurReac.Taille(); // tabBloq, tab_iocondiline et tab_torseurReac n'ont pas la même dimension
for (int i=1;i<= ttail;i++)
{ TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier
if (torseurReac.existe_torseur_reac)
{if (torseurReac.bloque_ou_CLL)
// cas où le torseur provient d'une condition ddl bloquée
{DdlLim& tabBloq_i = tabBloq(*(ttorBloq(i).begin())); // pour simplifier
if (tabBloq_i.NomMaillage() != NULL)
{ const string& nom_maillage = *(tabBloq_i.NomMaillage()); // nom de maillage lue
tab_lili(lesmail.NumMaillage(nom_maillage)).push_back(String_et_entier(tabBloq_i.NomRef(),i));
}
else
{tab_lili(1).push_back(String_et_entier(tabBloq_i.NomRef(),i));
};
}
else
// cas où le torseur provient d'une condition CLL
{I_O_Condilineaire& iocondiline_i = tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier
if (iocondiline_i.NomMaillage() != NULL)
// cas où on considère les noms de maillage
{ int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier
if (num_ref == 1)
{ // cas d'une référence principale de CLL
const string& nom_maillage = *(iocondiline_i.NomMaillage());
tab_lili(lesmail.NumMaillage(nom_maillage)).push_back
(String_et_entier(iocondiline_i.NomRef()+"_CLL",i));
}
else
{// cas d'une référence associé
// on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris
// la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1
// qui correspond à la référence principale
const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux-1);
tab_lili(lesmail.NumMaillage(nom_maillage)).push_back
(String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i));
};
}
else
{// cas où on ne considère pas les noms de maillage
int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier
if (num_ref == 1)
{// cas d'une référence principale de CLL
tab_lili(1).push_back(String_et_entier(iocondiline_i.NomRef()+"_CLL",i));
}
else
{// cas d'une référence associé
// on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris
// la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1
// qui correspond à la référence principale
tab_lili(1).push_back
(String_et_entier(iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)+"_CLL",i));
};
};
};
};
};
// retour des infos
return tab_lili;
};
// affichage et definition interactive des commandes pour les conditions limites CL
void LesCondLim::Info_commande_LesCondLim1(UtilLecture & entreePrinc)
{
cout << "\n# ----- definition des conditions limites cinematiques ----- ";
bool plusieurs_maillages = false;
string rep="_";
ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
// écriture de l'entête
sort << "\n blocages #------------# "
<< "\n#-----------------------------------------------------------"
<< "\n# nom du maillage | Ref noeud | Blocages"
<< "\n#-----------------------------------------------------------";
// def des conditions
try
{cout << "\n cas d'un seul maillage (par defaut) : rep o "
<< "\n cas de plusieurs maillages : rep n ";
rep = lect_return_defaut(true,"o");
if (rep == "n")
{ plusieurs_maillages = true; cout << "\n --> les prochaines CL seront associees a un nom de maillage ";};
rep="_"; // init
// boucle globale
while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
{ cout << "\n (0 ou f) (fin) "
<< "\n (1) def d'une nouvelle condition "
<< "\n ";
rep = lect_return_defaut(false,"f");
if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
break;
int num = ChangeEntier(rep);
bool choix_valide=false;
if ((num >= 0)&&(num<=1))
{ choix_valide=true; }
else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour arreter le programme";
choix_valide=false;
};
switch (num)
{ case 0: // sortie
{ break;} // normalement cela a déjà été filtré avant
case 1: // def d'une liste d'elements associe a un nom de loi
{ DdlLim unddl; // init
unddl.Info_commande_DdlLim(sort,plusieurs_maillages);
break;
}
default:
cout << "\n le cas "<<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 ";
};
sort << flush;
};
// affichage et definition interactive des commandes pour les conditions limites CLL
void LesCondLim::Info_commande_LesCondLim2(UtilLecture & entreePrinc)
{
cout << "\n# ----- definition des conditions limites lineaires ----- ";
bool plusieurs_maillages = false;
string rep="_";
ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
// écriture de l'entête
sort << "\n condition_limite_lineaire_ #------------# "
<< "\n#-----------------------------------------------------------"
<< "\n# nom du maillage | Ref noeud | CLL "
<< "\n#-----------------------------------------------------------";
// def des conditions
try
{cout << "\n cas d'un seul maillage (par defaut) : rep o "
<< "\n cas de plusieurs maillages : rep n ";
rep = lect_return_defaut(true,"o");
if (rep == "n")
{ plusieurs_maillages = true; cout << "\n --> les prochaines CLL seront associees a un nom de maillage ";};
rep="_"; // init
// boucle globale
while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
{ cout << "\n (0 ou f) (fin) "
<< "\n (1) def d'une nouvelle condition "
<< "\n ";
rep = lect_return_defaut(false,"f");
if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
break;
int num = ChangeEntier(rep);
bool choix_valide=false;
if ((num >= 0)&&(num<=1))
{ choix_valide=true; }
else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour arreter le programme";
choix_valide=false;
};
switch (num)
{ case 0: // sortie
{ break;} // normalement cela a déjà été filtré avant
case 1: // def d'une liste d'elements associe a un nom de loi
{ I_O_Condilineaire uneCLL; // init
uneCLL.Info_commande_conditionLineaire(sort,plusieurs_maillages);
break;
}
default:
cout << "\n le cas "<<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 ";
};
sort << flush;
};
// affichage et definition interactive des commandes pour les initialisations
void LesCondLim::Info_commande_LesCondLim3(UtilLecture & entreePrinc)
{ cout << "\n *** warning : la partie initialisation n'est pas encore operationnelle *** ";
return;
cout << "\n# ----- definition des conditions limites cinematiques ----- ";
bool plusieurs_maillages = false;
string rep="_";
ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
// écriture de l'entête
sort << "\n blocages #------------# "
<< "\n#-----------------------------------------------------------"
<< "\n# nom du maillage | Ref noeud | Blocages"
<< "\n#-----------------------------------------------------------"
<< flush;
// def des conditions
try
{cout << "\n cas d'un seul maillage (par defaut) : rep o "
<< "\n cas de plusieurs maillages : rep n ";
rep = lect_return_defaut(true,"o");
if (rep == "n")
{ plusieurs_maillages = true; cout << "\n --> les prochaines CL seront associees a un nom de maillage ";};
rep="_"; // init
// boucle globale
while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
{ cout << "\n (0 ou f) (fin) "
<< "\n (1) def d'une nouvelle condition "
<< "\n ";
rep = lect_return_defaut(false,"f");
if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
break;
int num = ChangeEntier(rep);
bool choix_valide=false;
if ((num >= 0)&&(num<=1))
{ choix_valide=true; }
else { cout << "\n Erreur on attendait un entier entre 0 et 1 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour arreter le programme";
choix_valide=false;
};
switch (num)
{ case 0: // sortie
{ break;} // normalement cela a déjà été filtré avant
case 1: // def d'une liste d'elements associe a un nom de loi
{ DdlLim unddl; // init
unddl.Info_commande_DdlLim(sort,plusieurs_maillages);
break;
}
default:
cout << "\n le cas "<<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 ";
};
sort << flush;
};
// -------------- fonctions internes privées -------------------------
void LesCondLim::Init_appart_groupe(bool une_variable,Enum_ddl enu,bool fixe,Noeud& noe, int cas,bool choix)
{ // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
// on vérifie que le ddl appartient au groupe
if (Dans_combinaison(cas,enu)) // cas d'un ddl du groupe
{ // le ddl appartient au groupe
// récup des enu_ddl équivalent au groupe
Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
int taille = tmc.Taille();
for (int i=1;i<=taille;i++)
{if(tmc(i) != enu) // on ne traite que les cas différents du ddl principal
{ if (noe.Existe_ici(tmc(i)))
{ // le ddl existe déjà, on le met à fixe
// mais on ne change pas sa valeur
if (fixe)
{ noe.Change_fixe(tmc(i),true);}
// en fait on ne met pas à libre si fixe en false, on ne vérifie pas qu'il y a superposition
// de plusieurs initialisations en libre, celle-ci pouvant venir de plusieurs raisons que l'on ne peut
// pas gérer ici : par exemple au moment de la création des éléments il y a mise en place des ddl à libre
// avant l'initialisation donc si l'on impose par exemple la vitesse, X sera en souslibre !!
// else
// { noe.Change_fixe(tmc(i),false);}
}
else
// sinon on le cré, et on met à zéro
{ if (fixe)
{ if (une_variable) { Ddl inter(tmc(i),0.0,HSFIXE); noe.PlusDdl(inter);}
else { Ddl inter(tmc(i),0.0,HS_LISIBLE_FIXE); noe.PlusDdl(inter);};
}
else
{ if (une_variable) { Ddl inter(tmc(i),0.0,HSLIBRE); noe.PlusDdl(inter);}
else { Ddl inter(tmc(i),0.0,HS_LISIBLE_LIBRE); noe.PlusDdl(inter);};
};
noe.Change_val_0(tmc(i),0.);
noe.Change_val_t(tmc(i),0.);
if (choix)
noe.Change_val_tdt(tmc(i),0.);
};
};
};
}; //-- fin du cas ou le ddl fait partie d'une combinaison
};
// mise en place du blocage sur un ddl ou un groupe si besoin est
void LesCondLim::Mise_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas)
{
// traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
// on vérifie que le ddl appartient au groupe sinon traitement simple
if (Dans_combinaison(cas,enu))
{ // le ddl appartient au groupe, on modifie globalement
// récup des enu_ddl équivalent au groupe
Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
int taille = tmc.Taille();
for (int i=1;i<=taille;i++)
noe.Change_fixe(tmc(i),true);
// le ddl du tableau des ddl bloqués est mis en service
(ddlbloqu.ElemLim(nd)).Met_en_service();
}
else // le ddl fixé n'appartient pas au groupe on le traite isolément
{ noe.Change_fixe(enu,true); // le noeud est fixé
// le ddl du tableau est mis en service
(ddlbloqu.ElemLim(nd)).Met_en_service();
};
};
// on retire le blocage sur un ddl ou un groupe si besoin est
void LesCondLim::Retire_cl(int nd,DdlLim& ddlbloqu,Enum_ddl enu,Noeud& noe, int cas)
{ // traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
// on vérifie que le ddl appartient au groupe sinon traitement simple
if (Dans_combinaison(cas,enu))
{ // le ddl appartient au groupe, on modifie globalement
// récup des enu_ddl équivalent au groupe
Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
int taille = tmc.Taille();
for (int i=1;i<=taille;i++)
noe.Change_fixe(tmc(i),false);
// le ddl du tableau des ddl bloqués est mis hors service
(ddlbloqu.ElemLim(nd)).Met_hors_service();
}
else // le ddl fixé n'appartient pas au groupe on le traite isolément
{ noe.Change_fixe(enu,false); // le noeud est libéré
// le ddl du tableau est mis hors service
(ddlbloqu.ElemLim(nd)).Met_hors_service();
};
};
// vérification qu'il n'y a pas de surcharge de blocage
// choix indique si l'on vérifie à t ou à tdt
void LesCondLim::Verif_surcharge_blocage
(const LesMaillages * lesMail,const LesReferences* lesRef,const double& temps,int cas)
{ // prépa retour
bool erreur_blocage = false;
Tableau <Enum_ddl> tmc; // tableau de travail
int tabBloqTaille =tabBloq.Taille();
// on parcours le tableau de ddl bloques
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (!((ref.Indic() == 4) && // dans le cas des conditions de tangence sur
(tabBloq_i.TypeDeCL()==TANGENTE_CL) ) // les arrêtes on n'applique pas ces vérifs
)
{int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
{Ddl ddl = tabBloq_i.ElemLim(nd);
// pour le ddlLim, si le temps est inférieur au temps actif
// ou si d'une part le temps n'est pas actif et qu'au pas précédent
// il n'était pas également actif on ne fait rien
if (tabBloq_i.Pas_a_prendre_en_compte(temps)) break;
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// on regarde si l'on a fixé plusieurs fois ou libéré plusieurs foix
// cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
// récup des enu_ddl équivalent au groupe, pour l'instant on n'a que la combinaison 1 qui comporte plus d'un élément
if (Dans_combinaison(cas,ddl.Id_nom()))
{tmc = MemeCombinaison(cas,ddl.Id_nom());}
else
// sinon pour l'instant on fait comme si cas == 0 c'est à dire pas de combinaison
{tmc = MemeCombinaison(0,ddl.Id_nom());};
int tailletmc = tmc.Taille();
for (int itc=1;itc <= tailletmc;itc++)
{if (noe.Ddl_sous_ou_sur_fixe(tmc(itc)))
// cas d'un problème éventuel
{ // message d'avertissement
if (ParaGlob::NiveauImpression() >= 6)
cout << "\n ***** ATTENTION *****, le ddl " << ddl.Nom() << " du noeud " << noe.Num_noeud()
<< " du maillage " << lesMail->NomMaillage(noe.Num_Mail()) << " est bloque plusieurs fois";
if (ParaGlob::NiveauImpression() >= 7)
cout << ", cela indique que plusieurs conditions limites sont supperposees";
if (ParaGlob::NiveauImpression() >= 8)
{ cout << " \n temps = " << temps << ", reference de blocage, et ddl limite correspondant";
ref.Affiche(); tabBloq_i.Affiche();
cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
}
// remise à normal du ddl pour que le calcul puisse continuer
noe.Retour_a_la_normal_sur_ou_sous_fixe(tmc(itc));
erreur_blocage = true; // pour un traitement global d'erreur éventuel
};
}; //-- fin du for (int itc=1;itc <= tailletmc;itc++)
}; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++)
}; //-- fin du for (int nn =1; nn<= reftaille;nn++)
}; //-- fin du if (!((ref.Indic() == 4) &&(tabBloq_i.TypeDeCL()==TANGENTE_CL) )
}; //-- fin du for (int i=1;i<= tabBloqTaille;i++)
};
// fourni la liste des ddl associé de même dim, pour un du groupe et en fonction du cas d'association
// ramène une référence sur tab_travail qui est mis à jour
Tableau <Ddl>& LesCondLim::Ddl_associe (Ddl& ddl,Noeud& noe,Tableau <Ddl>& tab_travail,int cas)
{ // cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)) ddl.Change_nom(UxyzXi(ddl.Id_nom()));
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX)) ddl.Change_nom(UxyzXi(ddl.Id_nom()));
Enum_ddl enu = ddl.Id_nom(); // pour simplifier
// traitement en fonction de cas qui représente le cas d'association de plusieurs ddl
// on vérifie que le ddl appartient au groupe sinon traitement simple
if (Dans_combinaison(cas,enu))
{ // le ddl appartient au groupe, on modifie globalement
// récup des enu_ddl équivalent au groupe
Tableau <Enum_ddl> tmc = MemeCombinaison(cas,enu);
int taille = tmc.Taille();
for (int i=1;i<=taille;i++)
{ ddl.Change_nom(tmc(i));
tab_travail(i) = ddl;
}
}
else // le ddl fixé n'appartient pas au groupe on le traite isolément
{ tab_travail.Change_taille(1);
tab_travail(1) = ddl;
};
return tab_travail;
};
// cas particulier des mouvements solides, dans le second passage pour la méthode MiseAJour_tdt
void LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(const double& mult_gene,LesMaillages * lesMail
,const double& deltat,int cas
,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD,const double& coef
,DdlLim& tabBloq_i,const ReferenceNE & ref,const double& temps,Enum_ddl en_ddl)
{ bool tous_les_blocages = true;
if (en_ddl != NU_DDL) tous_les_blocages = false;
int reftaille = ref.Taille();
int dima = ParaGlob::Dimension();
if(ParaGlob::AxiSymetrie())
// cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
// dimension-1 coordonnées donc on décrémente
dima--;
// on regarde si les temps dépendent d'une fct nD
// si oui on modifie les bornes du ddl
if (tabBloq_i.Temps_depend_nD())
LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD);
// pour le ddlLim, si le temps est inférieur au temps actif
// ou si d'une part le temps n'est pas actif et qu'au pas précédent
// il n'était pas également actif on ne fait rien
if (tabBloq_i.Pas_a_prendre_en_compte(temps))
return;
bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier
if (!actif_pour_le_temps)
return; // je ne vois pas trop pourquoi, mais semble cohérent avec le prog général (à voir)
// petite vérif
int tabBloqitaille = tabBloq_i.Taille(); // normalement il y a uniquement les déplacements
#ifdef MISE_AU_POINT
if (tabBloqitaille != dima)
{ cout << "\nErreur : le nombre de ddl bloque pour un mouvement solide doit etre egale a la dimension du pb "
<< " ici ParaGlob::Dimension() = " << dima << " et le nombre de ddl bloque = " << tabBloqitaille ;
cout << " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... ";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
Sortie(1);
};
#endif
// --- dans le cas où il y a des centres de rotation qui sont des positions de noeud, on renseigne
// a) récupération des centres de rotation noeud, éventuellement
const list <String_et_entier>& lis_centre_noeud = (tabBloq_i.MouvementSolide())->Liste_ident_centreNoeud();
if (lis_centre_noeud.size() != 0)
{ list <String_et_entier>::const_iterator ict,ictfin=lis_centre_noeud.end();
list <Coordonnee> list_coor; // liste des coordonnées des noeuds centre de rotation
for (ict = lis_centre_noeud.begin();ict!=ictfin;ict++)
{if ((*ict).nom == "")
// cas où on n'a pas de nom de maillage
{ list_coor.push_back(lesMail->Noeud_LesMaille(1, (*ict).n).Coord2()); }
else // cas où on a plusieurs maillages
{ int num_maill= lesMail->NumMaillage((*ict).nom);
list_coor.push_back(lesMail->Noeud_LesMaille(num_maill, (*ict).n).Coord2());
};
};
// b) maintenant on passe l'info au mouvement solide
(tabBloq_i.MouvementSolide())->RenseigneCentreNoeud(list_coor);
};
// maintenant soit le ddlLim est actif ou il change de statut: actif à non actif
// on boucle sur les noeuds de la référence
for (int nn =1; nn<= reftaille;nn++)
{// ici on travaille sur les dima ddl de déplacements en même temps:
// mais on se sert du premier comme indicateur
Ddl ddl = tabBloq_i.ElemLim(1); // le premier ddl normalement est UX
// on fait une manip sur les UX <-> Xi pour distinguer les cas méca du solide et les autres
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
if (noe.Existe_ici(X1))
// cas de deplacements imposes en entraine on change donc les Ui en Xi
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
bool a_considerer = tous_les_blocages;
if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux
{if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;};
if (a_considerer)
{ // def du point qui contiendra les coordonnées finales après rotation
Coordonnee M(dima);
// traitement en fonction du cas où il y courbe de charge ou pas
if ((tabBloq_i.Nom_courbe(1) != "")&&(tabBloq_i.NomF_charge(1) == ""))
{ // cas d'une courbe de charge, récup de la courbe
// pour les mouvements solides la courbe de charge et l'échelle sont stockées dans le premier ddl
Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1));
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat
M = noe.Coord1(); // on travaille donc à partir des coordonnées à t
double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1)
* ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ;
(tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
}
else
{ // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent
// et ici on considère la totalité du chargement de 0 au temps actuel
M = noe.Coord0(); // on travaille donc avec les coordonnées initiales
double amplitude = mult_gene * (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(1);
(tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
};
}
else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) == ""))
{ // cas d'une fonction nD de charge, récup
Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1));
// on commence par récupérer les conteneurs des grandeurs à fournir
List_io <Ddl_enum_etendu>& li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire();
List_io <TypeQuelconque >& li_quelc = pt_fctnD->Li_equi_Quel_evolue();
// on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire
Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
(noe, TEMPS_tdt,li_enu_scal));
// on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur
Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc);
// calcul de la valeur et retour dans tab_ret
Tableau <double> & tab_ret = pt_fctnD->Valeur_FnD_Evoluee
(&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
#ifdef MISE_AU_POINT
if (tab_ret.Taille() != 1)
{cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte "
<< "\n *** blocage via une fonction nD pour l'evolution d'un mouvement solide "
<< " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... ";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
Sortie(1);
};
#endif
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // pour l'instant a priori ce n'est pas possible car le temps
// est une variable globale que l'on ne peut pas modifier pour les fonctions nD
// il faut donc utiliser conjointement une courbe1D pour le temps et la fonction nD pour le reste
cout << "\n *** blocage relatif d'un mouvement solide avec uniquement une fonction nD: ce n'est pas possible"
<< " pour avoir un blocage relatif il faut utiliser conjointement une courbe de charge "
<< " pour le temps et une fonction nD pour le reste !!!!"
<< " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... ";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
Sortie(1);
}
else
{ // la fonction donne la valeur de l'amplitude de 0 au temps présent
// et ici on considère la totalité du chargement de 0 au temps actuel
M = noe.Coord0(); // on travaille donc avec les coordonnées initiales
double amplitude = mult_gene * (tab_ret(1)) * tabBloq_i.Echelle_courbe(1);
(tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
};
}
else if ((tabBloq_i.NomF_charge(1) != "")&&(tabBloq_i.Nom_courbe(1) != ""))
{ // cas d'une fonction nD de charge, récup
Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(1));
// on commence par récupérer les conteneurs des grandeurs à fournir
List_io <Ddl_enum_etendu>& li_enu_scal = pt_fctnD->Li_enu_etendu_scalaire();
List_io <TypeQuelconque >& li_quelc = pt_fctnD->Li_equi_Quel_evolue();
// on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire
Tableau <double> val_ddl_enum(Valeur_multi_interpoler_ou_calculer
(noe, TEMPS_tdt,li_enu_scal));
// on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur
Valeurs_Tensorielles_interpoler_ou_calculer(noe, TEMPS_tdt,li_quelc);
// calcul de la valeur et retour dans tab_ret
Tableau <double> & tab_ret = pt_fctnD->Valeur_FnD_Evoluee
(&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
#ifdef MISE_AU_POINT
if (tab_ret.Taille() != 1)
{cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte "
<< "\n *** blocage via une fonction nD pour l'evolution d'un mouvement solide "
<< " \n LesCondLim::MiseAjour_tdt_second_passage_mvtSolide(... ";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
Sortie(1);
};
#endif
// idem pour la courbe 1D
Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(1));
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // mise à jour de la valeur de l'incrément (et non ce sa valeur) sur deltat
M = noe.Coord1(); // on travaille donc à partir des coordonnées à t
double amplitude = mult_gene * tabBloq_i.Echelle_courbe(1) * tab_ret(1)
* ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat))) ;
(tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
}
else
{ // la courbe donne en fonction du temps la valeur de l'amplitude de 0 au temps présent
// et ici on considère la totalité du chargement de 0 au temps actuel
M = noe.Coord0(); // on travaille donc avec les coordonnées initiales
double amplitude = mult_gene * (pt_courbe->Valeur(temps))
* tab_ret(1) * tabBloq_i.Echelle_courbe(1);
(tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,amplitude);
};
}
else
// cas d'un mouvement à valeur fixe, on calcul l'accroissement par rapport au pas précédent
// coef intègre le multiplicateur global: mult_gene, et intègre l'acroissement par rapport au pas précédent
{ M = noe.Coord1();
(tabBloq_i.Const_MouvementSolide())->AppliqueMvtSolide (M,coef);
};
// maintenant on s'occupe de la mise à jour ou non des positions du noeud
for (int nd=1;nd<= tabBloqitaille ;nd++) // en fait ici nd =1 pour UX, =2 pour UY et =3 pour UZ
{Ddl ddl = tabBloq_i.ElemLim(nd);
if (noe.Existe_ici(X1))
// cas de deplacements imposes en entraine on change donc les Ui en Xi
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier
bool une_variable = noe.UneVariable(ddlenu); // pour simplifier
// cas des variables: si le ddl du noeud est en service on continue sinon on ne fait rien
// ou cas d'une donnée et le temps actif, mais si on arrive ici le temps est forcément actif
if ( ( une_variable && noe.En_service(ddlenu)) ||(!une_variable) )
{ // gestion des surcharges de blocage
// au second passage on fixe les ddl actifs
Mise_cl(nd,tabBloq_i,ddlenu,noe,cas);
// on met à jour les coordonnées finales
noe.Change_val_tdt(ddlenu,M(nd)); // car nd =1 pour UX, =2 pour UY, =3 pour UZ
};//-- fin du test si le ddl du noeud est en service
}; //-- fin de la boucle sur tabBloq_i
};//-- fin du test si le noeud est à considérer ou pas
}; //-- fin de la boucle sur nn
};
// mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
// --> pour au final obtenir le torseur des efforts globaux résultant de l'application d'un DdlLim
void LesCondLim::CalculTorseurReaction(TorseurReac& tr, const Noeud& noe, ReactStoc& reac)
{ int dimension = ParaGlob::Dimension();
if(ParaGlob::AxiSymetrie())
// cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
// dimension-1 coordonnées donc on décrémente
dimension--;
switch (dimension)
{ case 1: // pas de moment, et uniquement une résultante suivant x
if (reac.ddl.Id_nom() == X1) tr.resultante(1) += reac.ddl.Valeur();
break;
case 2 : // un moment autour de z, et deux composantes de résultante
// le moment est en dim 2, on stocke le moment dans la première composante !!!
switch (reac.ddl.Id_nom())
{ case X1:
{ tr.resultante(1) += reac.ddl.Valeur();
tr.moment(1) -= noe.Valeur_tdt(X2) * reac.ddl.Valeur(); // correspond à z
break;
};
case X2:
{ tr.resultante(2) += reac.ddl.Valeur();
tr.moment(1) += noe.Valeur_tdt(X1) * reac.ddl.Valeur(); // correspond à z
break;
};
default: break;
}
break;
case 3 : // 3 composante de moment et de résultante
switch (reac.ddl.Id_nom())
{ case X1:
{ tr.resultante(1) += reac.ddl.Valeur();
tr.moment(2) += noe.Valeur_tdt(X3) * reac.ddl.Valeur();
tr.moment(3) -= noe.Valeur_tdt(X2) * reac.ddl.Valeur();
break;
};
case X2:
{ tr.resultante(2) += reac.ddl.Valeur();
tr.moment(1) -= noe.Valeur_tdt(X3) * reac.ddl.Valeur();
tr.moment(3) += noe.Valeur_tdt(X1) * reac.ddl.Valeur();
break;
};
case X3:
{ tr.resultante(3) += reac.ddl.Valeur();
tr.moment(1) += noe.Valeur_tdt(X2) * reac.ddl.Valeur();
tr.moment(2) -= noe.Valeur_tdt(X1) * reac.ddl.Valeur();
break;
};
default: break;
}
break;
// les autres cas ne sont pas pris en compte
};
};
// mise en place des conditions linéaires imposées par les données d'entrée
// expression de la raideur et du second membre dans un nouveau repere
// ramène si oui ou non, il y a eu un changement effectué
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
// mais sans sauvegarde (correspond par exemple à une partie de vecglob)
bool LesCondLim::CoLinCHrepere_int(Mat_abstraite & matglob,Vecteur& vecglob
,const Nb_assemb& nb_casAssemb,Vecteur* vec2)
{ // on boucle sur le tableau de conditions limites linéaires enregistré
// et pour chaque element on impose une condition lineaire
bool modification = false; // init du retour
int tabTaille = tab_CLinApplique.Taille();
for (int i=1;i<= tabTaille; i++)
{int sous_taille = tab_CLinApplique(i).Taille();
for (int j=1; j<= sous_taille; j++)
{ Condilineaire& condi = tab_CLinApplique(i)(j);
//debug
//cout << "\n LesCondLim::CoLinCHrepere_int " << condi;
//fin debug
// on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
if (condi.Iddl() > -1)
{ // calcul des pointeurs d'assemblage
condi.ConditionPourPointeursAssemblage(nb_casAssemb);
// application de la condition
condlim(nb_casAssemb.n).CondlineaireCHRepere
( matglob,vecglob,condi.Pt_t(),condi.Val(),0.,vec2); // ancienne version
// la valeur imposée est systématiquement 0 comme pour le cas des autres conditions bloquée
// car la résolution donnera delta_ddl' qui doit être null pour les ddl imposés
modification=true;
};
};
};
// affichage éventuelle de la matrice de raideur et du second membre
if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0))
{ string entete = " affichage de la matrice apres changements de reperes dus aux conditions lineaires ";
matglob.Affichage_ecran(entete);
entete = " affichage du second membre apres changements de reperes dus aux conditions lineaires ";
vecglob.Affichage_ecran(entete);
};
// retour du fait qu'il y a eu ou non une modification faite
return modification;
};
// effacement du marquage de ddl bloque du au conditions lineaire extérieures (hors du contact par exemple)
void LesCondLim::EffMarque()
{ // préparation
// on boucle sur le tableau des conditions limites linéaires imposées réellement
int tabTaille = tab_CLinApplique.Taille();
for (int icondli=1;icondli<= tabTaille; icondli++)
{ Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli);
int nbcondi = t_condiAppli.Taille();
// on boucle sur les conditions
for (int ico=1;ico<=nbcondi;ico++)
{ Condilineaire & condi = t_condiAppli(ico); // pour simplifier
// on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
if (condi.Iddl() > -1)
{ // récup du noeud principal
Noeud * noe=condi.Noe();
noe->Change_fixe(condi.Tab_Enum()(1),false);
};
};
};
};
// def de la largeur de bande en fonction des conditions linéaire limite en entrée
// casAssemb : donne le cas d'assemblage en cours
// les condi linéaires ne donnent pas des largeurs de bande sup et inf égales !!!
// demi = la demi largeur de bande ,
// total = le maxi = la largeur sup + la largeur inf +1
// cumule = la somme des maxis, ce qui donnera la largeur finale, due à des multiples multiplications: une par conditions linéaires
// dans le cas où on tiens compte des conditions linéaires par rotation (c-a-d sans multiplicateur ou pénalisation)
// en retour, ramène un booleen qui :
// = true : si la largeur de bande en noeud est supérieure à 1
// = false : si non, ce qui signifie dans ce cas qu'il n'y a pas d'augmentation de la largeur
// en noeud
bool LesCondLim::Largeur_Bande(int& demi,int& total,const Nb_assemb& casAssemb
,LesMaillages * lesMail,LesReferences* lesRef,int& cumule)
{ demi = total = cumule = 0; // initialisation
bool retour = false; // par défaut
int nb_ass = casAssemb.n;
// on boucle sur le tableau et pour chaque condition
int tabTaille = tab_iocondiline.Taille(); // le nombre de condition
for (int icondli=1;icondli<= tabTaille; icondli++)
{I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier
// recup de la reference principal correspondant au mot cle
const ReferenceNE & refp =
((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
int nb_n_princ = refp.Taille();
// recup du tableau des références secondaires associées si elles existent
const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
int tailrefasso = nomRefassocie.Taille();
Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
Tableau <int> tab_numMail_associe(tailrefasso);
if (tailrefasso != 0)
{retour = true; // comme il y a des ref associés, la largeur en noeud sera > à 1
for (int k=1;k<=tailrefasso;k++)
{const string * nom_maillage=NULL;
if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
const ReferenceNE & refasso =
((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
tab_numMail_associe(k)= refasso.Nbmaille();
};
};
// on boucles sur les noeuds de la ref principale
int tail_t_noe = tailrefasso+1;
Tableau <Noeud *> t_noe(tail_t_noe); // tableau de travail
// dans la boucle qui suit on définit t_noe, c'est à dire l'ensemble des noeuds
// concernés par la condition linéaire.
// puis avec ce tableau, on en déduit la largeur de bande associée
for (int in=1;in<=nb_n_princ;in++)
{ // récup du noeud principal
Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
t_noe(1)= &noe;
// on ne continue que si le type de ddl de la condition limite est actif pour le noeud
// et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte
// on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
if (enu_condline==UX) enu_condline = X1; // les ui sont géré avec les xi
if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline))
{// récupération des noeuds associés, on utilise le même indice dans les ref associées que
// dans la ref principale
for (int ia = 1;ia<=tailrefasso;ia++)
t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));
// maintenant on va effectivement pouvoir calculer la largeur de bande correspondant
// aux noeuds du tableau t_noe
// 1) on a par défaut au moins une relation entre les ddl du noeud principal
int diprinc = noe.NB_ddl_actif_casAssemb(nb_ass);
if ( diprinc-1 > demi) demi = diprinc-1;
if ( (2*diprinc-1) > total) total = 2*diprinc-1;
cumule += 2*diprinc-1;
// 2) maintenant on s'occupe de la relation entre les différents noeuds de numéros différencts
int maxiPourLaCondition=0; // stocke le maxi pour chaque condition linéaire
for (int inoe=1; inoe<= tail_t_noe;inoe++)
for ( int jnoe=inoe+1; jnoe<=tail_t_noe;jnoe++)
{ Noeud & nne = *(t_noe(inoe));
Noeud & nno = *(t_noe(jnoe));
int di=0;
if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass))
{ di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass)
+ nne.NB_ddl_actif_casAssemb(nb_ass);
}
else
{ di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass)
+ nno.NB_ddl_actif_casAssemb(nb_ass);
};
if ( di > demi) demi = di;
if ( di > maxiPourLaCondition) maxiPourLaCondition = di;
if ( di > total) total = di;
// cumule += di;
};
cumule += maxiPourLaCondition;
};
}; // -- fin de la boucle sur les noeuds de la liste principale
}; // -- fin de la boucle sur le tableau des conditions linéaire
// prise en compte de la diagonale
demi += 1; total += 1;
// retour
return retour;
};
// dimensionnement du tableau des torseurs ainsi que des tableaux ttRG et ttorBloq
// en fonction de tabBloq (utilisé plusieurs fois), puis de ttRGCLL en fonction de tab_iocondiline
void LesCondLim::DimensionneTorseurs()
{ // dimensionnement du tableau des torseurs résultants
// 1) on s'occupe tout d'abord des ddl bloqués
int taille = tabBloq.Taille();
ttRG.Change_taille(taille);
int dima = ParaGlob::Dimension();
if(ParaGlob::AxiSymetrie())
// cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
// dimension-1 coordonnées donc on décrémente
dima--;
// on remplit le tableau ttRG
list <Deux_String> li_nomRef; // liste de travail:
list <string> li_nomRef_CL; // idem, mais spécifique aux CL
// sert ensuite pour définir ttRG_noms_ref
int taille_tors=0;
// on en profite pour définir un tableau de nom de ref qui contiendra les infos
// en string nécessaires pour cibler les composantes du torseur, externalisées comme
// grandeurs globales
for (int i=1;i<=taille;i++)
if (tabBloq(i).Existe_ici_un_deplacement())
{// on a un candidat possible, on regarde si la référence n'existe pas
Deux_String candid(tabBloq(i).NomRef(),tabBloq(i).NomRef()); // le premier string ici est pour remplir
string nom_Ref_CL(tabBloq(i).NomRef());
bool avec_nom_maillage=false;
if (tabBloq(i).NomMaillage() != NULL)
{candid.nom1 = *(tabBloq(i).NomMaillage());avec_nom_maillage=true;
nom_Ref_CL = *(tabBloq(i).NomMaillage()) +"_"+ nom_Ref_CL;
};
list <Deux_String>::iterator ili,ilifin=li_nomRef.end();
int it=1; // future position dans le tableau tab_torseurReac
for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++)
if (*ili == candid) break;
if (ili == li_nomRef.end())
{// aucun élément trouvé, on ajoute un nouveau
li_nomRef.push_back(candid);
li_nomRef_CL.push_back(nom_Ref_CL);
taille_tors++; ttRG(i)=taille_tors;
}
else // on a trouvé un élément identique déjà existant de numéro it
{ttRG(i)=it;};
};
// 2) puis on s'occupe des CLL
int taille_tors_CLL=0;
list <string> li_nomRef_CLL; // liste de travail, mais spécifique aux CLL
// sert ensuite pour définir ttRGCLL_noms_ref
// on boucle sur le tableau initiale des conditions lineaires en entrée
int tabCLLTaille = tab_iocondiline.Taille();
ttRGCLL.Change_taille(tabCLLTaille); // premier dimensionnement
// on en profite pour définir un tableau de nom de ref qui contiendra les infos
// en string nécessaires pour cibler les composantes du torseur, externalisées comme
// grandeurs globales
for (int icondli=1;icondli<= tabCLLTaille; icondli++)
{I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier
// on regarde s'il faut considérer la condition linéaire, en fonction de en_ddl
Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1)))
{// récup des références secondaires éventuelles
const Tableau <string> & tabnomRef = iocondiline_i.ReferenceAssociees();
int tabnomRefTaille = tabnomRef.Taille();
const Tableau <string > & nom_mail_associe = iocondiline_i.NomMaillageAssociees();
// second dimensionnement
ttRGCLL(icondli).Change_taille(tabnomRefTaille+1);
// maintenant on rempli le tableau
// a) tout d'abord la ref principal (on encapsule)
{Deux_String candid(iocondiline_i.NomRef()+"CLL",iocondiline_i.NomRef()+"CLL");
string nom_Ref_CLL(iocondiline_i.NomRef()+"CLL");
bool avec_nom_maillage=false;
if (iocondiline_i.NomMaillage() != NULL)
{candid.nom1 = *(iocondiline_i.NomMaillage());avec_nom_maillage=true;
nom_Ref_CLL = *(iocondiline_i.NomMaillage()) +"_"+ nom_Ref_CLL;
};
// on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un
list <Deux_String>::iterator ili,ilifin=li_nomRef.end();
int it=1; // future position dans le tableau tab_torseurReac
for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++)
if (*ili == candid) break;
if (ili == li_nomRef.end())
{// aucun élément trouvé, on ajoute un nouveau
li_nomRef.push_back(candid);
li_nomRef_CLL.push_back(nom_Ref_CLL);
taille_tors++; taille_tors_CLL++; ttRGCLL(icondli)(1)=taille_tors;
}
else // on a trouvé un élément identique déjà existant de numéro it
{ttRGCLL(icondli)(1)=it;
};
}; // fin encapsulage
// b) maintenant on regarde les références secondaires
for (int ir=1;ir<=tabnomRefTaille;ir++)
{ Deux_String candid(tabnomRef(ir)+"CLL",tabnomRef(ir)+"CLL");
string nom_Ref_CLL(tabnomRef(ir)+"CLL");
if (iocondiline_i.NomMaillage() != NULL)
{candid.nom1 = nom_mail_associe(ir);
nom_Ref_CLL = nom_mail_associe(ir) +"_"+ nom_Ref_CLL;
};
// on regarde s'il existe déjà un élément adoc ou s'il faut en ajouter un
list <Deux_String>::iterator ili,ilifin=li_nomRef.end();
int it=1; // future position dans le tableau tab_torseurReac
for (ili=li_nomRef.begin();ili!=ilifin;ili++,it++)
if (*ili == candid) break;
if (ili == li_nomRef.end())
{// aucun élément trouvé, on ajoute un nouveau
li_nomRef.push_back(candid);
li_nomRef_CLL.push_back(nom_Ref_CLL);
taille_tors++;taille_tors_CLL++; ttRGCLL(icondli)(ir+1)=taille_tors;
}
else // on a trouvé un élément identique déjà existant de numéro it
{ttRGCLL(icondli)(ir+1)=it;};
}; // fin boucle sur les références secondaires
}; //-- fin du test if ((Meme_famille(enu_condline,UX))||(Meme_famille(enu_condline,X1)))
}; //-- fin de la boucle sur les conditions linéaires
// maintenant on dimensionne le tableau de torseurs
int taille_tors_bloqu = taille_tors - taille_tors_CLL;
tab_torseurReac.Change_taille(taille_tors);
for (int ia=1;ia<=taille_tors;ia++)
{tab_torseurReac(ia).Activation(dima);
// on définit si le torseur correspond à un ddl bloqué ou une CLL
if (ia > taille_tors_bloqu)
{tab_torseurReac(ia).bloque_ou_CLL = false;}
else
{tab_torseurReac(ia).bloque_ou_CLL = true;}
};
// maintenant on dimensionne et rempli ttorBloq
ttorBloq.Change_taille(taille_tors_bloqu);
for (int ib=1;ib<=taille;ib++)
if (ttRG(ib) != 0 )
ttorBloq(ttRG(ib)).push_back(ib); // cas d'une ref qui contient un déplacement
// et ensuite on dimensionne et rempli ttorCLL
ttorCLL.Change_taille(taille_tors);
for (int ib=1;ib<=tabCLLTaille;ib++)
{ int tai = ttRGCLL(ib).Taille();
for (int j=1;j<=tai;j++)
if (ttRGCLL(ib)(j) != 0 )
ttorCLL(ttRGCLL(ib)(j)).push_back(DeuxEntiers(ib,j)); // cas d'une ref qui contient un déplacement
};
// on définit les tableaux ttRG_noms_ref et ttRGCLL_noms_ref
int nb_RG_noms_ref = li_nomRef_CL.size();
ttRG_noms_ref.Change_taille(nb_RG_noms_ref);
{list <string>::iterator ili,ilifin=li_nomRef_CL.end();
int i=1;
for (ili = li_nomRef_CL.begin();ili != ilifin; ili++,i++)
ttRG_noms_ref(i)=(*ili);
};
ttRGCLL_noms_ref.Change_taille(li_nomRef_CLL.size());
{list <string>::iterator ili,ilifin=li_nomRef_CLL.end();
int i=1;
for (ili = li_nomRef_CLL.begin();ili != ilifin; ili++,i++)
ttRGCLL_noms_ref(i)=(*ili);
};
// on va maintenant définir des grandeurs globales qui permettront de récupérer les réactions par
// exemple via des fonctions nD
Ddl_enum_etendu ddl("comp_tors_reaction");
Ddl_etendu v(ddl);
int taille_tors_bloquplus1 = taille_tors_bloqu +1;
{int il = 1;
for (int ia=1;ia<taille_tors_bloquplus1;ia++,il++)
{// cas d'un blocage de ddl
// on va construire la chaine de caractère qui représente la composante
// 1) la résultante
int dimaPlus1 = dima+1;
for (int ic= 1; ic < dimaPlus1; ic++)
{string nom_ref="tors_"+ttRG_noms_ref(il)+"_Re_"+ChangeEntierSTring(ic);
Grandeur_Ddl_etendu grand_courant(v,nom_ref);
// on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
// et on récupère un exemplaire
TypeQuelconque_enum_etendu enuType =
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
// on définit le type quelconque associé
TypeQuelconque typQ(enuType,X1,grand_courant);
// et on ajoute une grandeur globale qui sera indexée par le nom de référence
// si celle-ci n'existe pas déjà
if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);
}
// 2) le moment
for (int ic= 1; ic < dimaPlus1; ic++)
{string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
Grandeur_Ddl_etendu grand_courant(v,nom_ref);
// on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
// et on récupère un exemplaire
TypeQuelconque_enum_etendu enuType =
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
// on définit le type quelconque associé
TypeQuelconque typQ(enuType,X1,grand_courant);
// et on ajoute une grandeur globale qui sera indexée par le nom de référence
// si celle-ci n'existe pas déjà
if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);
}
};
};
// maintenant on s'occupe des conditions concernant les CLL
{int taille_torsPlusUn = taille_tors+1;
int il = 1;
for (int ia=taille_tors_bloquplus1;ia<taille_torsPlusUn;ia++,il++)
{// cas d'un blocage de ddl
// on va construire la chaine de caractère qui représente la composante
// 1) la résultante
int dimaPlus1 = dima+1;
for (int ic= 1; ic < dimaPlus1; ic++)
{string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Re_"+ChangeEntierSTring(ic);
Grandeur_Ddl_etendu grand_courant(v,nom_ref);
// on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
// et on récupère un exemplaire
TypeQuelconque_enum_etendu enuType =
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
// on définit le type quelconque associé
TypeQuelconque typQ(enuType,X1,grand_courant);
// et on ajoute une grandeur globale qui sera indexée par le nom de référence
// si celle-ci n'existe pas déjà
if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);
}
// 2) le moment
for (int ic= 1; ic < dimaPlus1; ic++)
{string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
Grandeur_Ddl_etendu grand_courant(v,nom_ref);
// on ajoute éventuellement un TypeQuelconque_enum_etendu s'il n'existe pas
// et on récupère un exemplaire
TypeQuelconque_enum_etendu enuType =
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(COMP_TORSEUR_REACTION,nom_ref,SCALAIRE_DOUBLE);
// on définit le type quelconque associé
TypeQuelconque typQ(enuType,X1,grand_courant);
// et on ajoute une grandeur globale qui sera indexée par le nom de référence
// si celle-ci n'existe pas déjà
if (ParaGlob::param->GrandeurGlobal(nom_ref) == NULL)
ParaGlob::param->Ajout_grandeur_consultable(&typQ,nom_ref);
}
};
};
//--- débug ---
//cout << "\n " << ttorCLL << endl;
//--- fin débug ---
};
// DdlLim : mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD
void LesCondLim::Mise_a_jour_t_minmax_ddlLim(Noeud& noe,DdlLim& ddlLim,LesFonctions_nD* lesFonctionsnD)
{// on regarde le temps min
string nom_t_min = ddlLim.Nom_fctnD_tmin();
if (nom_t_min != "")
{ Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_min); // récup de la fonction
// récup des valeurs au noeud, pour alimenter la fonction
Tableau <double> tab(noe.Valeur_multi_et_Tensorielle
(fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue())
);
// appel fonction
Tableau <double> & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL);
ddlLim.Mise_a_jour_tmin(tab_ret(1));
#ifdef MISE_AU_POINT
// on vérifie que la fonction est scalaire
if (tab_ret.Taille() != 1)
{ cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min
<< " qui gere le temps mini "
<< " elle retourne une grandeur vectorielle "
<< " ce n'est pas normal !! , on arrete le calcul "
<< "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
Sortie(1);
};
#endif
}
string nom_t_max = ddlLim.Nom_fctnD_tmax();
if (nom_t_max != "")
{ Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_max); // récup de la fonction
// récup des valeurs au noeud, pour alimenter la fonction
Tableau <double> tab(noe.Valeur_multi_et_Tensorielle
(fct->Li_enu_etendu_scalaire(),fct->Li_equi_Quel_evolue())
);
// appel fonction
Tableau <double> & tab_ret = fct->Valeur_FnD_Evoluee(&tab,&fct->Li_enu_etendu_scalaire(),&fct->Li_equi_Quel_evolue(),NULL,NULL);
ddlLim.Mise_a_jour_tmax(tab_ret(1));
#ifdef MISE_AU_POINT
// on vérifie que la fonction est scalaire
if (tab_ret.Taille() != 1)
{ cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max
<< " qui gere le temps maxi "
<< " elle retourne une grandeur vectorielle "
<< " ce n'est pas normal !! , on arrete le calcul "
<< "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
Sortie(1);
};
#endif
}
};
// DdlLim général: mise à jour des temps min et temps max, lorsque ceci dépendent de fonction nD
// ici les fct nD doivent dépendre uniquement de grandeur générale
void LesCondLim::Mise_a_jour_t_minmax_ddlLim(DdlLim& ddlLim,LesFonctions_nD* lesFonctionsnD)
{// on regarde le temps min
string nom_t_min = ddlLim.Nom_fctnD_tmin();
if (nom_t_min != "")
{ Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_min); // récup de la fonction
// appel fonction
Tableau <double> & tab_ret = fct->Valeur_pour_variables_globales();
ddlLim.Mise_a_jour_tmin(tab_ret(1));
#ifdef MISE_AU_POINT
// on vérifie que la fonction est scalaire
if (tab_ret.Taille() != 1)
{ cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_min
<< " qui gere le temps mini "
<< " elle retourne une grandeur vectorielle "
<< " ce n'est pas normal !! , on arrete le calcul "
<< "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
Sortie(1);
};
#endif
}
string nom_t_max = ddlLim.Nom_fctnD_tmax();
if (nom_t_max != "")
{ Fonction_nD * fct = lesFonctionsnD->Trouve(nom_t_max); // récup de la fonction
// appel fonction
Tableau <double> & tab_ret = fct->Valeur_pour_variables_globales();
ddlLim.Mise_a_jour_tmax(tab_ret(1));
#ifdef MISE_AU_POINT
// on vérifie que la fonction est scalaire
if (tab_ret.Taille() != 1)
{ cout << "\n *** pb dans les parametres de passage pour l'appel de la fonction nD " << nom_t_max
<< " qui gere le temps maxi "
<< " elle retourne une grandeur vectorielle "
<< " ce n'est pas normal !! , on arrete le calcul "
<< "\n LesCondLim::Mise_a_jour_t_minmax_ddlLim(..."<<endl;
Sortie(1);
};
#endif
}
};
// mise en place de la répercussion sur les noeuds des conditions linéaires, imposées externes (par les données d'entrées),
// ne prend pas en charge par exemple les CL dues aux contacts(gérés par CL)
// pour les paramètres de passage de la méthode: idem méthode MiseAJour_tdt
void LesCondLim::MiseAJour_condilineaire_tdt
(const double& ,LesMaillages * lesMail,const double& deltat,LesReferences* lesRef
,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
,const double& ,bool& ch_statut
,int ,Enum_ddl en_ddl )
{
// //----- debug
// cout << "\n ****1 LesCondLim::MiseAJour_condilineaire_tdt \n temps = " << temps << "\n";
// cout << tab_iocondiline;
// //--- fin debug
tempsCLL.Mise_en_route_du_comptage(); // temps cpu
// préparation
bool tous_les_blocages = true;
if (en_ddl != NU_DDL) tous_les_blocages = false;
// 1--- on boucle sur le tableau et pour chaque element on calcule une condition lineaire
// on n'impose pas la cl (à tdt) à mesure du balayage car, si une condition dépend de noeuds qui eux même font partie
// d'une autre condition, on utiliserait une partie des nouvelles valeurs et une partie des valeurs de l'itérations précédente !! erreur
// il y a une exception: celle des conditions de projection, qui sont effectuées dans l'ordre d'apparition. Cela peut poser des pbs si les surfaces
// de projection vont elles-même être modifiées par les conditions linéaires finales. Mais l'inverse pourrait également être vrai, donc c'est un peu
// inextricable. Donc, on laisse ainsi pour l'instant
int tabTaille = tab_iocondiline.Taille();
for (int icondli=1;icondli<= tabTaille; icondli++)
{I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier
// on regarde s'il faut considérer la condition linéaire, en fonction de en_ddl
bool a_considerer = tous_les_blocages;
Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
if (enu_condline==UX) enu_condline = X1; // les ui sont géré avec les xi
if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux
{if (Meme_famille(en_ddl,enu_condline)) a_considerer = true;};
// I) --- un premier passage sur les changements de statut ---
// recup de la reference principal correspondant au mot cle
const ReferenceNE & refp =
((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
int nb_n_princ = refp.Taille();
Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli);
t_condiAppli.Change_taille(0); // a priori 0 c'est-à-dire qu'il n'y en a pas
// on boucle sur les noeuds de la référence principale
for (int in=1;in<=nb_n_princ;in++)
{ // récup du noeud principal
Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
if (a_considerer)
{ bool actif_pour_le_temps = iocondiline_i.Temps_actif(temps); // pour simplifier
//debug
//cout << "\n LesCondLim::MiseAJour_condilineaire_tdt "
// << " actif_pour_le_temps= "<< actif_pour_le_temps << endl;
//fin debug
if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline))
{ if ((!actif_pour_le_temps) && (iocondiline_i.Etat_validation()))
// cas du temps non actif, mais qui était actif au pas précédent
{ ch_statut = true; }
else if ((actif_pour_le_temps) && (!iocondiline_i.Etat_validation()))
{ ch_statut = true; };
}; //-- fin du test si le noeud est à considérer ou pas
};
}; // fin de la boucle sur les noeuds de la ref principale
// II) ---- un deuxième passage pour le traitement des conditions limites de projection ---
// sur un plan ou une droite
// ** je ne comprends pas pourquoi il faut l'usine à gaz Pas_a_prendre_en_compte( qui fait que si au
// temps précédent c'était actif, alors au temps actuel, même en dehors de l'intervalle c'est également à considérer
// cela conduit à des erreurs donc je supprime et met un cas plus restrictif : Pas_a_prendre_en_compte_dans_intervalle(
// mais il faudrait également changer dans tous les chargement les fct du même type : Pas_a_prendre_en_compte(
// if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte(temps))
if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte_dans_intervalle(temps))
&& (iocondiline_i.PlanDroite()))
{// construction des données nécessaires
// on regarde si l'on utilise un noeud rotation
const String_et_entier* mailEtNumCentreNoeud = iocondiline_i.RefNoeudRotation();
if ( mailEtNumCentreNoeud != NULL) // utilisation d'un noeud rotation, on renseigne
{ if (mailEtNumCentreNoeud->nom == "")
// cas par défaut de noeud du premier maillage
{iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(1,mailEtNumCentreNoeud->n)));}
else
// sinon il y a un nom de maillage
{int imail = lesMail->NumMaillage(mailEtNumCentreNoeud->nom);
iocondiline_i.ChangeCentreNoeudRotation(&(lesMail->Noeud_LesMaille(imail,mailEtNumCentreNoeud->n)));};
};
// on regarde s'il y a des fonctions de charge si oui on renseigne
int nbfct = iocondiline_i.ExisteFonctionChargeCoef();
if (nbfct)
{Vecteur valfct(nbfct),deltatvalfct(nbfct);
for (int ifct = 1; ifct <= nbfct; ifct++)
{Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct));
valfct(ifct)=pt_courbe->Valeur(temps);
deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat)));
};
// on renseigne la condition limite
iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct);
// on actualise la direction actuelle ou normale pour plan droite
iocondiline_i.ActualiseDirectionPlanDroite();
};
int dima = ParaGlob::Dimension();
if(ParaGlob::AxiSymetrie())
// cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
// dimension-1 coordonnées donc on décrémente
dima--;
int posi = Id_nom_ddl("X1") -1; // position du ddl X1
// on boucle sur les noeuds de la référence principale pour appliquer la condition
for (int in=1;in<=nb_n_princ;in++)
{ // récup du noeud principal
Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
//si le noeud est par ailleurs bloqué, ce n'est pas possible (sauf cas particulier
// non pris en compte car c'est trop spécifique, il faut utiliser une CL classique à la place
// d'utiliser ce type de condition linéaire, on test donc pour éviter des déconvenues
int indi = 0;
switch (dima)
{ case 3: if (noe.Ddl_fixe(Enum_ddl(posi+3)))
{ indi=3;
if (!iocondiline_i.Coherence_condi_PlanDroite(indi))
{break;}
else {indi = 0;}; // on remet à 0 si c'est cohérent
}
case 2: if (noe.Ddl_fixe(Enum_ddl(posi+2)))
{ indi=2;
if (!iocondiline_i.Coherence_condi_PlanDroite(indi))
{break;}
else {indi = 0;}; // on remet à 0 si c'est cohérent
}
case 1: if (noe.Ddl_fixe(Enum_ddl(posi+1)))
{ indi=1;
if (!iocondiline_i.Coherence_condi_PlanDroite(indi))
{break;}
else {indi = 0;}; // on remet à 0 si c'est cohérent
}
default: break;
};
if (indi)
{ // cas où il existe un blocage sur le noeud, la condition linéaire n'est pas licite
cout << "\n erreur concernant une condition lineaire par projection "
<< ", le noeud : "<<noe.Num_noeud() <<" du maillage "<< noe.Num_Mail() <<", est "
<< " deja bloque suivant la direction "<< indi << " on ne peut pas appliquer "
<< " une condition de projection normale ";
if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
Sortie(1);
};
// on ne continue que si le type de ddl de la condition limite est actif pour le noeud
// et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte
// on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline))
{// on met la condition limite en déplacement sur les coordonnées de la référence
Coordonnee M = noe.Coord2();
iocondiline_i.ProjectionSurPlanDroite_et_calValCondiLin(M);
noe.Change_coord2(M);
// il n'y a pas d'indication de blocage. Ce sera fait lors de la mise en place
// sur le second membre et sur la matrice
}; // -- fin du cas ou c'est une variable et qu'elle est active
}; // -- fin de la boucle sur les noeuds de la ref principal
}; // -- fin du test pour savoir si c'est une condition de projection ou non
// III) --- un troisième passage pour la construction des coeffs actifs pour l'application pratique -----
// de la condition
bool construction_effectuee=false; // pour savoir s'il y a une construction effective ou non
// ** je ne comprends pas pourquoi il faut l'usine à gaz Pas_a_prendre_en_compte( qui fait que si au
// temps précédent c'était actif, alors au temps actuel, même en dehors de l'intervalle c'est également à considérer
// cela conduit à des erreurs donc je supprime et met un cas plus restrictif : Pas_a_prendre_en_compte_dans_intervalle(
// mais il faudrait également changer dans tous les chargement les fct du même type : Pas_a_prendre_en_compte(
// if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte(temps))
if ((a_considerer) && (!iocondiline_i.Pas_a_prendre_en_compte_dans_intervalle(temps)))
{// construction des données nécessaires à l'appel de ConstructionCondition
// recup du tableau des références secondaires associées si elles existent
const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
int tailrefasso = nomRefassocie.Taille();
Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
Tableau <int> tab_numMail_associe(tailrefasso);
if (tailrefasso != 0)
{for (int k=1;k<=tailrefasso;k++)
{const string * nom_maillage=NULL;
if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
const ReferenceNE & refasso =
((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
tab_numMail_associe(k)= refasso.Nbmaille();
};
};
// -- maintenant que l'est là, il y a de bonnes raisons de penser que les conditions sont effectives
// on dimensionne correctement le tableau finale
t_condiAppli.Change_taille(nb_n_princ); // mise à jour de la taille au cas où
// éventuellement, due à la non activité des ddl, la condition peut néanmoins ne pas être construite
// par défaut on met le Iddl() en négatif, histoire de rendre par défaut la condition non exploitable
// ceci sera changé durant la construction effective, si elle a lieu. D'autre part au moment de l'utilisation de la condition
// le test sur le Iddl() permettra de savoir si la condition est exploitable ou non
for (int ijk=1;ijk<=nb_n_princ;ijk++)
t_condiAppli(ijk).ChangeIddl()=-1;
// on boucles sur les noeuds de la ref principale
Tableau <Noeud *> t_noe(tailrefasso+1); // tableau de travail
// l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds
// concernés par la condition linéaire.
for (int in=1;in<=nb_n_princ;in++)
{ // récup du noeud principal
Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
t_noe(1)= &noe;
// on ne continue que si le type de ddl de la condition limite est actif pour le noeud
// et que c'est une variable, si ce n'est pas une variable on n'en tient pas compte
// on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
if (noe.UneVariable(enu_condline) && noe.En_service(enu_condline))
{// récupération des noeuds associés, on utilise le même indice dans les ref associées que
// dans la ref principale
for (int ia = 1;ia<=tailrefasso;ia++)
t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));
// on commence par voir s'il y a des fonctions de charge si oui on renseigne
int nbfct = iocondiline_i.ExisteFonctionChargeCoef();
if (nbfct)
{Vecteur valfct(nbfct),deltatvalfct(nbfct);
for (int ifct = 1; ifct <= nbfct; ifct++)
{Courbe1D * pt_courbe = lesCourbes1D->Trouve(iocondiline_i.NomFctch(ifct));
valfct(ifct)=pt_courbe->Valeur(temps);
deltatvalfct(ifct)=((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat)));
};
// on renseigne la condition limite
iocondiline_i.Valeur_fonctionChargeCoef(valfct,deltatvalfct);
};
// on calcul les coefs effectifs de condition limite
Condilineaire & condi = t_condiAppli(in); // pour simplifier
// on constuit la condition et on impose la valeur c-a-d:
// on met en place la condition limite sur le ddl ddl_i du noeud principal
// qui correspond au ddl_i' dans le nouveau repèrere qui recevra la condition bloqué
// en fait ddl_i sera la seul modification de ddl due à la mise en place de la CLL
iocondiline_i.ConstructionCondition(t_noe,condi);
construction_effectuee = true; // on enregistre
}; // -- fin du cas ou c'est une variable et qu'elle est active
}; // -- fin de la boucle sur les noeuds de la ref principal
}; // -- fin du test pour savoir s'il faut considérer la condition linéaire ou pas
}; //-- fin de la boucle sur l'ensemble des conditions linéaire
// 2--- on boucle sur toutes les conditions linéaires effectives, pour imposer les blocages
for (int icondli=1;icondli<= tabTaille; icondli++)
{Tableau < Condilineaire > & t_condiAppli = tab_CLinApplique(icondli);
int taille = t_condiAppli.Taille();
for (int i=1;i<=taille;i++)
{ double Uk_impose = t_condiAppli(i).Val_Uk_impose(); // récup de la valeur a imposer
// dans le cas où c'est une condition de projection, la condition a déjà été effectuée
// donc il ne faut pas la faire ici: le test de Uk_impose, permet de le savoir
if (Uk_impose != ConstMath::tresgrand)
{ Noeud* noe = t_condiAppli(i).Noe(); // pour simplifier
Enum_ddl leEnuAChanger = t_condiAppli(i).Tab_Enum()(1); // le enu a changer
noe->Change_val_tdt(leEnuAChanger,Uk_impose);
};
};
};
tempsCLL.Arret_du_comptage(); // temps cpu
};
// création d'un tableau de condition linéaire, correspondant à toutes les conditions linéaires d'entrées
// qu'elles soient actives ou pas (a priori cette méthode est conçu pour donner des infos relativement à la largeur
// de bandes en noeuds due aux CLL)
// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL,
Tableau <Tableau <Condilineaire> > LesCondLim::ConnectionCLL
(const LesMaillages * lesMail,const LesReferences* lesRef) const
{
// on boucle sur le tableau et pour chaque element on impose une condition lineaire
int tabTaille = tab_iocondiline.Taille();
Tableau <Tableau <Condilineaire> > t_connectionCLL(tabTaille);
for (int icondli=1;icondli<= tabTaille; icondli++)
{I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier
Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
// recup de la reference principal correspondant au mot cle
const ReferenceNE & refp =
((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
int nb_n_princ = refp.Taille();
Tableau <Condilineaire>& connectionCLL = t_connectionCLL(icondli); // pour simplifier
connectionCLL.Change_taille(nb_n_princ); // mise à jour de la taille
// ---- traitement des conditions limites de projection ---
// sur un plan ou une droite
if (iocondiline_i.PlanDroite())
{Tableau <Noeud *> t_noe(1); // tableau de travail
for (int in=1;in<=nb_n_princ;in++)
{ // récup du noeud principal
t_noe(1)= &lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
// s'il s'agit d'un ddl de déplacement, il faut le changer en Xi
Enum_ddl enu = enu_condline; // init
if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX))
enu = UxyzXi(enu_condline);
// on ne continue que si le type de ddl de la condition limite est une variable
// on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
if (t_noe(1)->UneVariable(enu))
// on renseigne la condition uniquement sur le tableau de noeud
{ connectionCLL(in).ChangeTabNoeud(t_noe); };
}; // -- fin de la boucle sur les noeuds de la ref principal
}// -- fin du test pour savoir si c'est une condition de projection ou non
// --- cas des conditions linéaires générales ---------
else
{// recup du tableau des références secondaires associées si elles existent
const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
int tailrefasso = nomRefassocie.Taille();
Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
Tableau <int> tab_numMail_associe(tailrefasso);
if (tailrefasso != 0)
{for (int k=1;k<=tailrefasso;k++)
{const string * nom_maillage=NULL;
if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
const ReferenceNE & refasso =
((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
tab_numMail_associe(k)= refasso.Nbmaille();
};
};
// on boucles sur les noeuds de la ref principale
Tableau <Noeud *> t_noe(tailrefasso+1); // tableau de travail
// l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds
// concernés par la condition linéaire.
for (int in=1;in<=nb_n_princ;in++)
{ // récup du noeud principal
Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
t_noe(1)= &noe;
Condilineaire& condCLL = connectionCLL(in); // pour simplifier
// s'il s'agit d'un ddl de déplacement, il faut le changer en Xi
Enum_ddl enu = enu_condline; // init
if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX))
enu = UxyzXi(enu_condline);
// on ne continue que si le type de ddl de la condition limite est une variable,
// on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
if (noe.UneVariable(enu) )
{// récupération des noeuds associés, on utilise le même indice dans les ref associées que
// dans la ref principale
for (int ia = 1;ia<=tailrefasso;ia++)
t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));
};
// on renseigne la condition uniquement sur le tableau de noeud
condCLL.ChangeTabNoeud(t_noe);
}; // -- fin du cas ou c'est une variable
}; // -- fin de la boucle sur les noeuds de la ref principal
}; //-- fin de la boucle sur l'ensemble des conditions linéaire
// retour
return t_connectionCLL;
};
// idem ConnectionCLL avec une liste, mais spécifiquement les conditions de type "stricte_egalite" entre ddl de noeud
// correspondant à toutes les conditions linéaires d'entrées actives uniquement
// (a priori cette méthode est conçu pour donner des infos pour condenser les pointeurs d'assemblages:
// LesMaillages::MiseAJourPointeurAssemblage() )
// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL, et le type enumere de ddl
list <Condilineaire> LesCondLim::ConnectionCLL_stricte_egalite
(const LesMaillages * lesMail,const LesReferences* lesRef) const
{
// def de la liste de retour
list <Condilineaire> list_condi;
// on boucle sur le tableau et pour chaque element on analyse la condition lineaire
int tabTaille = tab_iocondiline.Taille();
for (int icondli=1;icondli<= tabTaille; icondli++)
{I_O_Condilineaire& iocondiline_i = tab_iocondiline(icondli); // pour simplifier
Enum_ddl enu_condline= iocondiline_i.TypeEnu(); // pour simplifier
Tableau <Enum_ddl> tab_enu(1); tab_enu(1) = enu_condline; // servira pour construire les Condilineaires
// recup de la reference principal correspondant au mot cle
const ReferenceNE & refp =
((ReferenceNE &) lesRef->Trouve(iocondiline_i.NomRef(),iocondiline_i.NomMaillage()));
int nb_n_princ = refp.Taille();
// --- on ne continue que s'il s'agit d'une condition stricte_egalite et que la condition
// est active pour le temps actuel
if ((iocondiline_i.StricteEgalite())
&& (iocondiline_i.Temps_actif(ParaGlob::Variables_de_temps().TempsCourant())))
{// recup du tableau des références secondaires associées si elles existent
const Tableau <string>& nomRefassocie = iocondiline_i.ReferenceAssociees();
const Tableau <string > & nomMaillageAsoociees = iocondiline_i.NomMaillageAssociees();
int tailrefasso = nomRefassocie.Taille();
Tableau <const Tableau <int> * > tab_numNoeud_associe(tailrefasso);
Tableau <int> tab_numMail_associe(tailrefasso);
if (tailrefasso != 0)
{for (int k=1;k<=tailrefasso;k++)
{const string * nom_maillage=NULL;
if (iocondiline_i.NomMaillage() != NULL) nom_maillage=&nomMaillageAsoociees(k);
const ReferenceNE & refasso =
((ReferenceNE &) lesRef->Trouve(nomRefassocie(k),nom_maillage));
tab_numNoeud_associe(k) = & refasso.Tab_num(); // recup tableau des autres noeuds associés
tab_numMail_associe(k)= refasso.Nbmaille();
};
};
// on boucles sur les noeuds de la ref principale
Tableau <Noeud *> t_noe(tailrefasso+1); // tableau de travail
// l'objectif de la boucle qui suit est de définir t_noe, c'est à dire l'ensemble des noeuds
// concernés par la condition linéaire.
for (int in=1;in<=nb_n_princ;in++)
{ // récup du noeud principal
Noeud & noe=lesMail->Noeud_LesMaille(refp.Nbmaille(),refp.Numero(in));
t_noe(1)= &noe;
// s'il s'agit d'un ddl de déplacement, il faut le changer en Xi
Enum_ddl enu = enu_condline; // init
if (t_noe(1)->Existe_ici(X1) && (PremierDdlFamille(enu_condline)==UX))
enu = UxyzXi(enu_condline);
// on ne continue que si le type de ddl de la condition limite est une variable,
// on ne test que le premier s'il s'agit d'un vecteur (car a priori tout le type est actif en même temps)
if (noe.UneVariable(enu) )
{// récupération des noeuds associés, on utilise le même indice dans les ref associées que
// dans la ref principale
for (int ia = 1;ia<=tailrefasso;ia++)
t_noe(ia+1) = &(lesMail->Noeud_LesMaille(tab_numMail_associe(ia),(*tab_numNoeud_associe(ia))(in)));
};
// on renseigne une condition uniquement sur le tableau de noeud
Condilineaire condi_stric_egal(tab_enu,t_noe);
list_condi.push_back(condi_stric_egal);
}; // -- fin du cas ou c'est une variable
}; // -- fin de la boucle sur les noeuds de la ref principal
}; //-- fin de la boucle sur l'ensemble des conditions linéaire
// retour
return list_condi;
};
// récupération de valeurs à un noeud pour les grandeur enu
// ici il s'agit de grandeur scalaires
Tableau <double> LesCondLim::Valeur_multi_interpoler_ou_calculer
(const Noeud& noe, Enum_dure temps,const List_io<Ddl_enum_etendu>& enu)
{
// recup de l'incrément de temps
double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
double unSurDeltat=0;
if (Abs(deltat) >= ConstMath::trespetit)
{unSurDeltat = 1./deltat;}
else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
{ // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
if (unSurDeltat < 0)
{ cout << "\n le pas de temps est négatif !! "; };
unSurDeltat = ConstMath::tresgrand;
};
// le tableau de retour
Tableau <double> tab_ret (enu.size());
// on balaie la liste des grandeurs à sortir
List_io<Ddl_enum_etendu>::const_iterator ie,iefin=enu.end();
int it; // it est l'indice dans le tableau de retour
for (it=1,ie=enu.begin(); ie!=iefin;ie++,it++)
{ if ((Meme_famille((*ie).Enum(),X1)) && ((*ie).Nom_vide()))
{switch (temps)
{case TEMPS_0 : tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1);break;
case TEMPS_t : tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1);break;
case TEMPS_tdt : tab_ret(it)= noe.Coord2()((*ie).Enum() - X1 +1);break;
default :
cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n";
Sortie(1);
};
}
else if ((Meme_famille((*ie).Enum(),UX)) && ((*ie).Nom_vide()))
{int i_cor = (*ie).Enum() - UX +1; // l'indice de coordonnée
switch (temps)
{case TEMPS_0 : tab_ret(it)= 0.;break;
case TEMPS_t : tab_ret(it)= noe.Coord1()(i_cor)-noe.Coord0()(i_cor);break;
case TEMPS_tdt : tab_ret(it)= noe.Coord2()(i_cor)-noe.Coord0()(i_cor);break;
default :
cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
cout << "\nLesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n";
Sortie(1);
};
}
// cas particulier de la position à t, indépendamment du temps
else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 123)
{tab_ret(it)= noe.Coord1()((*ie).Enum() - X1 +1);
}
// cas particulier de la position à t0, indépendamment du temps
else if (Ddl_enum_etendu::PremierDdlEnumEtenduFamille(*ie).Position() == 126)
{tab_ret(it)= noe.Coord0()((*ie).Enum() - X1 +1);
}
else if ((*ie).Nom_vide())
{// il s'agit d'un ddl pur on le récupère directement
switch (temps)
{case TEMPS_0 : tab_ret(it)= noe.Valeur_0((*ie).Enum());break;
case TEMPS_t : tab_ret(it)= noe.Valeur_t((*ie).Enum());break;
case TEMPS_tdt : tab_ret(it)= noe.Valeur_tdt((*ie).Enum());break;
default :
cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
cout << "LesCondLim::Valeur_multi_interpoler_ou_calculer(.. \n";
Sortie(1);
};
}
// --- a complèter ----
else
{ tab_ret(it) = 0.;
cout << "\n cas de ddl actuellement non traite "
<< "\n pas de ddl " << (*ie).Nom() << " au noeud "
<< noe.Num_noeud() <<" du maillage "<< noe.Num_Mail()
<< "\n ou cas non implante pour l'instant, on retourne 0"
<< "\n LesCondLim::Valeur_multi_interpoler_ou_calculer(.. ";
};
};// -- fin de la boucle sur la liste de Ddl_enum_etendu
// liberation des tenseurs intermediaires
LibereTenseur();
return tab_ret;
};
// récupération de valeurs à un noeud pour les grandeur enu
// ici il s'agit de grandeurs tensorielles
void LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer
(const Noeud& noe, Enum_dure temps,List_io<TypeQuelconque>& enu)
{ // ----- def de grandeurs de travail
int dim_espace = ParaGlob::Dimension();
// on initialise ces variables booléennes et les conteneurs
List_io<TypeQuelconque>::iterator ipq,ipqfin=enu.end();
for (ipq=enu.begin();ipq!=ipqfin;ipq++)
{TypeQuelconque_enum_etendu enuq = (*ipq).EnuTypeQuelconque().EnumTQ();
switch (enuq.Position())
{ case POSITION_GEOMETRIQUE :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
Coordonnee* M = gr.ConteneurCoordonnee();
switch (temps)
{case TEMPS_0 : (*M)= noe.Coord0();break;
case TEMPS_t : (*M)= noe.Coord1();break;
case TEMPS_tdt : (*M)= noe.Coord2();break;
default :
cout << "\nErreur : valeur incorrecte du temps !\n";
cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
Sortie(1);
};
break;
}
case POSITION_GEOMETRIQUE_t :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
Coordonnee* M = gr.ConteneurCoordonnee();
(*M)= noe.Coord1();
break;
}
case POSITION_GEOMETRIQUE_t0 :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
Coordonnee* M = gr.ConteneurCoordonnee();
(*M)= noe.Coord0();
break;
}
case DEPLACEMENT :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
Coordonnee* M = gr.ConteneurCoordonnee();
switch (temps)
{case TEMPS_0 : M->Zero();break;
case TEMPS_t : (*M)= noe.Coord1()-noe.Coord0();break;
case TEMPS_tdt : (*M)= noe.Coord2()-noe.Coord0();break;
default :
cout << "\nErreur : valeur incorrecte du temps !\n";
cout << "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
Sortie(1);
};
break;
}
case FORCE_GENE_EXT : case FORCE_GENE_INT : case VECT_PRESSION : case VECT_FORCE_VOLUM :
case VECT_DIR_FIXE : case VECT_SURF_SUIV : case VECT_HYDRODYNA_Fn : case VECT_HYDRODYNA_Ft :
case VECT_HYDRODYNA_T : case VECT_LINE : case VECT_LINE_SUIV : case VECT_REAC : case VECT_REAC_N :
case FORCE_CONTACT : case FORCE_GENE_TOT: case RESIDU_GLOBAL:
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
Coordonnee* F = gr.ConteneurCoordonnee();
// on vérifie l'existante
#ifdef MISE_AU_POINT
if (!(noe.Existe_ici(enuq)))
{cout << "\nErreur : " << enuq.Nom() << " n'existe pas au noeud "
<< noe.Num_noeud() << " du maillage "<< noe.Num_Mail()
<< "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
Sortie(1);
};
#endif
// récupération de la grandeur quelconque
const TypeQuelconque& toto = noe.Grandeur_quelconque(enuq);
const Grandeur_coordonnee& titi = *((const Grandeur_coordonnee* ) toto.Const_Grandeur_pointee());
(*F) = titi.ConteneurCoordonnee_const(); // ouf
break;
}
case VITESSE :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
Coordonnee* V = gr.ConteneurCoordonnee();
// on vérifie l'existante
#ifdef MISE_AU_POINT
if (!(noe.Existe_ici(V1)))
{cout << "\nErreur : la vitesse n'existe pas au noeud "
<< noe.Num_noeud() << " du maillage "<< noe.Num_Mail()
<< "\nLesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(.. \n";
if (tempsCL.Comptage_en_cours()) tempsCL.Arret_du_comptage();
if (tempsCLL.Comptage_en_cours()) tempsCLL.Arret_du_comptage();
Sortie(1);
};
#endif
// récupération de la vitesse
switch (temps)
{ case TEMPS_0 :
{switch (dim_espace)
{case 3: (*V)(3) = noe.Valeur_0(V3);
case 2: (*V)(2) = noe.Valeur_0(V2);
case 1: (*V)(1) = noe.Valeur_0(V1);
break;
default: break;
};
break;
}
case TEMPS_t :
{switch (dim_espace)
{case 3: (*V)(3) = noe.Valeur_t(V3);
case 2: (*V)(2) = noe.Valeur_t(V2);
case 1: (*V)(1) = noe.Valeur_t(V1);
break;
default: break;
};
break;
}
case TEMPS_tdt :
{switch (dim_espace)
{case 3: (*V)(3) = noe.Valeur_tdt(V3);
case 2: (*V)(2) = noe.Valeur_tdt(V2);
case 1: (*V)(1) = noe.Valeur_tdt(V1);
break;
default: break;
};
break;
}
default: break;
};
break;
}
default :
{// on initialise la grandeur pour éviter d'avoir des valeurs aléatoires
((*ipq).Grandeur_pointee())->InitParDefaut();
if (ParaGlob::NiveauImpression() > 0)
{cout << "\nWarning : attention cas non traite: "
<< (*ipq).EnuTypeQuelconque().NomPlein() << "!\n";
// on initialise la grandeur pour éviter d'avoir des valeurs aléatoires
if (ParaGlob::NiveauImpression() > 5)
cout << "\n LesCondLim::Valeurs_Tensorielles_interpoler_ou_calculer(....";
};
}
};
};
// liberation des tenseurs intermediaires
LibereTenseur();
};