1972 lines
103 KiB
C++
1972 lines
103 KiB
C++
|
|
|
|
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
#include "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)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return true;
|
|
#endif
|
|
|
|
// 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();
|
|
};
|
|
|
|
|