Herezh_dev/Maillage/LesCondLim.cc

3039 lines
167 KiB
C++
Raw Normal View History

// 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.
//
2023-05-03 17:23:49 +02:00
// 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 "CharUtil.h"
#include "SfeMembT.h"
#include "TypeQuelconqueParticulier.h"
// --- conteneur pour les réactions -----
// surcharge de l'operator de lecture typée
istream & operator >> (istream & ent , LesCondLim::ReactStoc & a)
{ // lecture du type et vérification
string nom_type;
ent >> nom_type;
if (nom_type != "ReactStoc")
Sortie(1);
// lecture des infos
ent >> a.numMail >> a.numNoeud >> a.ddl >> a.casAss;
return ent;
};
// surcharge de l'operator d'ecriture typée
ostream & operator << (ostream & sort , const LesCondLim::ReactStoc & a)
{ // écriture du type
sort << "ReactStoc ";
// les données
sort << a.numMail << " " << a.numNoeud << " " << a.ddl <<" "<< a.casAss;
return sort;
};
// surcharge de l'operator de lecture typée
istream & operator >> (istream & ent , LesCondLim::TorseurReac & a)
{ // lecture du type et vérification
string nom_type;
ent >> nom_type;
if (nom_type != "TorseurReac")
Sortie(1);
// lecture des infos
ent >> a.existe_torseur_reac >> a.resultante >> a.moment ;
return ent;
};
// surcharge de l'operator d'ecriture typée
ostream & operator << (ostream & sort , const LesCondLim::TorseurReac & a)
{ // écriture du type
sort << " TorseurReac ";
// les données
sort << a.existe_torseur_reac << " " << a.resultante << " " << a.moment <<" ";
return sort;
};
// --- fin conteneur pour les réactions -----
// CONSTRUCTEURS :
LesCondLim::LesCondLim () : // par defaut
tabBloq(),tabInit(),condlim()
,reaction(),reaction_CLin(),reactionApresCHrepere()
,tab_torseurReac(),ttRG(),ttorBloq()
,tab_iocondiline(),tab_CLinApplique(),ttRGCLL(),ttorCLL()
,ttRG_noms_ref(),ttRGCLL_noms_ref()
// ,map_reaction()
,nb_maillage(0)
,tempsCL(),tempsCLL()
{ };
// DESTRUCTEUR :
LesCondLim::~LesCondLim ()
{ };
// METHODES PUBLIQUES :
// lecture des conditions limites : ddl bloque
void LesCondLim::Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef)
{ MotCle motCle; // ref aux mots cle
// on se positionne sur un mot cle
while ( !motCle.SimotCle(entreePrinc.tablcar))
entreePrinc.NouvelleDonnee();
bool sortie_info = false;
if ( (strstr(entreePrinc.tablcar,"blocages")!=NULL) ) // à rajouter tous les cas de lectures éventuelles
{if (ParaGlob::NiveauImpression() >= 4)
cout << " debut de la lecture des conditions limites ddl bloque " << endl;
sortie_info = true;
};
// def d'une instance de classe de lecture de Ddl
LectBloc <DdlLim> lecDdl;
// lecture eventuelle des blocages en condition limite
lecDdl.Lecture(entreePrinc,lesRef,"blocages",
"lecture des blocages de ddl en condition limite",tabBloq);
// dimensionnement du tableau des torseurs résultants
LesCondLim::DimensionneTorseurs();
if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info)
cout << " fin de la lecture des conditions limites ddl bloque " << endl;
};
// lecture des conditions limites linéaire
void LesCondLim::Lecture2(UtilLecture & entreePrinc,LesReferences& lesRef)
{ MotCle motCle; // ref aux mots cle
// on se positionne sur un mot cle
while ( !motCle.SimotCle(entreePrinc.tablcar))
entreePrinc.NouvelleDonnee();
bool sortie_info = false;
if ( (strstr(entreePrinc.tablcar,"condition_limite_lineaire_")!=NULL) ) // à rajouter tous les cas de lectures éventuelles
{if (ParaGlob::NiveauImpression() >= 4)
cout << " debut de la lecture des conditions limites lineaires " << endl;
sortie_info = true;
};
// def d'une instance de classe de lecture de Ddl
LectBloc <I_O_Condilineaire> lecI_O_Condli;
// lecture eventuelle des conditions linéaire en condition limite
lecI_O_Condli.Lecture(entreePrinc,lesRef,"condition_limite_lineaire_",
"lecture des conditions limites lineaires ",tab_iocondiline);
// mise à jour de la dimension du tableau associé: tab_CLinApplique
tab_CLinApplique.Change_taille(tab_iocondiline.Taille());
// dimensionnement du tableau des torseurs résultants
LesCondLim::DimensionneTorseurs();
if ((ParaGlob::NiveauImpression() >= 4)&& sortie_info)
cout << " fin de la lecture des conditions limites lineaire " << endl;
};
// lecture des conditions limites : initialisation
void LesCondLim::Lecture3(UtilLecture & entreePrinc,LesReferences& lesRef)
{ MotCle motCle; // ref aux mots cle
// on se positionne sur un mot cle
while ( !motCle.SimotCle(entreePrinc.tablcar))
entreePrinc.NouvelleDonnee();
bool sortie_info = false;
if ( (strstr(entreePrinc.tablcar,"initialisation")!=NULL) ) // à rajouter tous les cas de lectures éventuelles
{if (ParaGlob::NiveauImpression() >= 4)
cout << " debut de la lecture des conditions d'initialisation " << endl;
sortie_info = true;
};
// def d'une instance de classe de lecture de Ddl
LectBloc <DdlLim> lecDdl;
// lecture eventuelle des conditions limites d'initialisation
lecDdl.Lecture(entreePrinc,lesRef,"initialisation",
"lecture des conditions limites d\'initialisation",tabInit);
if ((ParaGlob::NiveauImpression() >= 4) && sortie_info)
cout << " fin de la lecture des conditions d'initialisation " << endl;
//debug
//Affiche();
//fin debug
};
// affichage des informations concernant les conditions limites
void LesCondLim::Affiche() const // affichage de tous les infos
{ Affiche1();
Affiche2();
Affiche3();
};
void LesCondLim::Affiche1() const
{ if (tabBloq.Taille() != 0)
{cout << "\n ******** conditions limites : ddl bloque ******** \n";
cout << tabBloq.Taille() << " reference de conditions limites lue \n";
int tabBloqTaille = tabBloq.Taille();
for (int i=1; i<=tabBloqTaille; i++)
tabBloq(i).Affiche();
cout << "\n\n";
}
};
void LesCondLim::Affiche2() const
{
if (tabInit.Taille() != 0)
{cout << "\n ******** conditions limites : lineaire ******** \n";
cout << tab_iocondiline.Taille() << " reference de conditions limites lue \n";
int tabInitTaille = tabInit.Taille();
for (int i=1; i<=tabInitTaille; i++)
tabInit(i).Affiche();
cout << "\n\n";
}
};
void LesCondLim::Affiche3() const
{
if (tabInit.Taille() != 0)
{cout << "\n ******** conditions limites : initialisation ******** \n";
cout << tabInit.Taille() << " reference de conditions limites lue \n";
int tabInitTaille = tabInit.Taille();
for (int i=1; i<=tabInitTaille; i++)
tabInit(i).Affiche();
cout << "\n\n";
}
};
// introduction des données et variables pour leurs emplois futures, avec init par défaut
void LesCondLim::IntroductionDonnees(LesMaillages * lesMail,LesReferences* lesRef
,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD)
{
tempsCL.Mise_en_route_du_comptage(); // temps cpu
// 1) on parcours le tableau de ddl d'initialisation
int tabInitTaille = tabInit.Taille();
for (int i=1;i<= tabInitTaille;i++)
{ DdlLim& tabInit_i = tabInit(i);
// recup de la reference correspondant au mot cle
const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage());
if ((refinitial.Indic() == 4) &&
(tabInit_i.TypeDeCL()==TANGENTE_CL))
{// cas des références d'arêtes, avec des conditions initiales de tangente imposée
// ici on vérifie que les données d'entrées sont cohérentes, c'est tout
const ReferenceAF & ref = ((ReferenceAF &) refinitial);
// on renseigne les éléments ad hoc
int refTaille = ref.Taille();
for (int ne =1; ne<= refTaille;ne++)
{int tabInitiTaille = tabInit_i.Taille();
// dans le cas d'une référence de champ on vérifie le nombre de ddlLim
if ((tabInit_i.Champ()) && (tabInitiTaille != ref.Taille()))
{cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
<< " que le nombre d'element de la reference associee !! "
<< "\n void LesCondLim::IntroductionDonnees(... ";
cout << " condition limite : "; tabInit_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
// dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
// sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabInitiTaille;// début normale
if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;};
for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
// affectation de la valeur d'initialisation
{ Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl
Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl
Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl
// on vérifie qu'il s'agit bien de 3 coordonnées
if (ddl1.Id_nom()!=X1)
{cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 "
<< "\n void LesCondLim::IntroductionDonnees(... ";
cout << " condition limite : "; tabInit_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
if (ddl2.Id_nom()!=X2)
{cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 "
<< "\n void LesCondLim::IntroductionDonnees(... ";
cout << " condition limite : "; tabInit_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
if (ddl3.Id_nom()!=X3)
{cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 "
<< "\n void LesCondLim::IntroductionDonnees(... ";
cout << " condition limite : "; tabInit_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
// on vérifie que le numéro de l'arête existe bien
int num_elem = ref.NumeroElem(ne);
int num_ar = ref.NumeroFA(ne);
// récup de l'élément
Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem);
if (!(el.AreteExiste(num_ar)))
{cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar
<< " pour l'element " << num_elem << " n'existe pas !! "
<< "\n void LesCondLim::IntroductionDonnees(... ";
cout << " condition limite : "; tabInit_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
// on vérifie que c'est un élément sfe
if (!(ElementSfe(el.Id_interpolation())))
{cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre "
<< " de type SFE : et non l'element= "; el.Affiche(1);
cout << "\n void LesCondLim::IntroductionDonnees(... ";
cout << " condition limite : "; tabInit_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
}// fin boucle sur tabInit_i
}// fin boucle sur les éléments de la référence
} // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE
else if (refinitial.Indic() != 1)
// cas d'element
{ cout << "\n introduction autre que des noeuds, pas d\'action implentee a ce sujet !!";
cout << "void LesCondLim::IntroductionDonnees(... " << endl;
tempsCL.Arret_du_comptage();
Sortie(1);
}
else
// cas de noeuds
{// traitement proprement dit
const ReferenceNE & ref = ((ReferenceNE &) refinitial);
int refTaille = ref.Taille();
for (int nn =1; nn<= refTaille;nn++)
{int tabInitiTaille = tabInit_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabInitiTaille;// début normale
if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// affectation de la valeur d'initialisation
{ Ddl ddl = tabInit_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// ---modif 10 sep 2017
// cas ou le ddl n'existe pas
// on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre
// c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose
// on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas
// mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour
// or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être
// utilisé à t et tdt, donc il ne faut pas le mettre en HS
// par contre on le met en lisible c-a-d en donnée par défaut
ddl.ChangeVariable_a_Donnee();
if (!(noe.Existe_ici(ddl.Id_nom())))
// cas ou le ddl n'existe pas
// si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
// { if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
{ if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
{ // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis
// initialisation a zero et on indique qu'il est hors service (non !! voir la modif 10 sept 2017)
noe.PlusDdl(ddl);
noe.Change_val_0(ddl.Id_nom(),0.);
noe.Change_val_t(ddl.Id_nom(),0.);
// ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service
// ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom());
noe.Met_en_service(ddl.Id_nom());
noe.Change_fixe(ddl.Id_nom(),true);
}
} // fin du if (!(noe.Existe_ici(ddl.Id_nom())))
} // fin de la boucle sur les ddl
} // fin de la boucle sur les noeuds de la référence
} // fin du traitement pour les noeuds
} // fin de la boucle sur le tableau générale d'initialisation
// 2) cas des ddl imposes on verifie leurs existences et on crée si besoin
// on parcours le tableau de ddl bloques
// mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt
int tabBloqTaille = tabBloq.Taille();
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
if ((refinitial.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) )
{// cas des références d'arêtes, avec des conditions de tangente imposée
// on s'occupe de vérifier la cohérence de l'entrée des données, c'est tout
const ReferenceAF & ref = ((ReferenceAF &) refinitial);
// on renseigne les éléments ad hoc
int refTaille = ref.Taille();
for (int ne =1; ne<= refTaille;ne++)
{int tabBloqiTaille = tabBloq_i.Taille();
// dans le cas d'une référence de champ on vérifie le nombre de ddlLim
if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
{cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
<< " que le nombre d'element de la reference associee !! "
<< "\n void LesCondLim::IntroductionDonnees(... ";
cout << " condition limite : "; tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
}
// dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
// sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqiTaille;// début normale
if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;};
for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
// affectation de la valeur d'initialisation
{ Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl
Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl
Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl
// on vérifie qu'il s'agit bien de 3 coordonnées
if (ddl1.Id_nom()!=X1)
{cout << "\n erreur: pour l'encastrement ou la symetrie, le premier ddl doit etre X1 "
<< "\n void LesCondLim::InitialDonnees(... ";
cout << " condition limite : "; tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
if (ddl2.Id_nom()!=X2)
{cout << "\n erreur: pour l'encastrement ou la symetrie, le deuxieme ddl doit etre X2 "
<< "\n void LesCondLim::InitialDonnees(... ";
cout << " condition limite : "; tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
if (ddl3.Id_nom()!=X3)
{cout << "\n erreur: pour l'encastrement ou la symetrie, le troisieme ddl doit etre X3 "
<< "\n void LesCondLim::InitialDonnees(... ";
cout << " condition limite : "; tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
// on vérifie que le numéro de l'arête existe bien
int num_elem = ref.NumeroElem(ne);
int num_ar = ref.NumeroFA(ne);
// récup de l'élément
Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),num_elem);
if (!(el.AreteExiste(num_ar)))
{cout << "\n erreur: pour l'encastrement ou la symetrie, l'arete nb : " << num_ar
<< " pour l'element " << num_elem << " n'existe pas !! "
<< "\n void LesCondLim::InitialDonnees(... ";
cout << " condition limite : "; tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
// on vérifie que c'est un élément sfe
if (!(ElementSfe(el.Id_interpolation())))
{cout << "\n erreur: pour l'encastrement ou la symetrie, les elements doivent etre "
<< " de type SFE : et non l'element= "; el.Affiche(1);
cout << "\n void LesCondLim::InitialDonnees(... ";
cout << " condition limite : "; tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
}// fin boucle sur tabBloq_i
}// fin boucle sur les noeuds de la référence
} // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE
else if (refinitial.Indic() != 1) // cas d'une autre référence que des noeuds
// cas d'element
{ cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!";
cout << "\n void LesCondLim::InitialDonnees(... " << endl;
tempsCL.Arret_du_comptage();
Sortie (1);
}
else
// cas de noeuds
{const ReferenceNE & ref = ((ReferenceNE &) refinitial);
int refTaille = ref.Taille();
for (int nn =1; nn<= refTaille;nn++)
{int tabBloqiTaille = tabBloq_i.Taille();
// dans le cas d'une référence de champ on vérifie le nombre de ddlLim
if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
{cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
<< " que le nombre de noeud de la reference associee !! "
<< "\n void LesCondLim::InitialDonnees(... ";
cout << " condition limite : "; tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
}
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqiTaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// affectation de la valeur d'initialisation
{ Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl
// récup du noeud
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// on regarde si les temps dépendent d'une fct nD
// si oui on modifie les bornes du ddl
if (tabBloq_i.Temps_depend_nD())
LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
// on regarde si le temps est actif ou pas
if ((tabBloq_i.Temps_actif(0.))) {tabBloq_i.ElemLim(nd).Met_en_service();}
else { tabBloq_i.ElemLim(nd).Met_hors_service();};
// dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé
// on regarde du coté du noeuds
if (!noe.Existe_ici(ddl.Id_nom()))
// cas ou il faut creer un ddl sup
// si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
// {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
{ if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
{// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis
// initialisation a zero et on indique qu'il est hors service
// ---modif 10 sep 2017
// cas ou le ddl n'existe pas
// on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre
// c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose
// on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas
// mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour
// or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être
// utilisé à t et tdt, donc il ne faut pas le mettre en HS
// par contre on le met en lisible c-a-d en donnée par défaut
ddl.ChangeVariable_a_Donnee();
noe.PlusDdl(ddl);
noe.Change_val_0(ddl.Id_nom(),0.);
noe.Change_val_t(ddl.Id_nom(),0.);
// ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service
// ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom());
noe.Met_en_service(ddl.Id_nom());
noe.Change_fixe(ddl.Id_nom(),true);
};
};
// pour le reste on ne fait rien, se sera géré par les mises à jour
// en fonction de l'évolution du temps
} // fin boucle sur tabBloq_i
} // fin boucle sur les noeuds de la référence
} // fin du cas des noeuds
} // fin bouble sur tabBloq
// définition du nombre de maillage en cours dans le calcul
nb_maillage=lesMail->NbMaillage();
tempsCL.Arret_du_comptage(); // temps cpu
};
// initialisation des ddl avec le tableau de ddl d'init
// verif de l'existence de tous les ddl (initialisation et imposes)
// ajout si necessaire
// choix =false : indique qu'il faut initialiser que les ddl t
// choix = true : indique qu'il faut initialiser les ddl a t et t+dt
// vérification de l'existence des courbes de charge adoc si nécessaire
// idem pour les fonctions nD de charge adoc si nécessaire
// cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque
// le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont
// leur statut modifié de manière équivalente
// =0 pas d'association
// =1 association X V GAMMA
void LesCondLim::Initial(LesMaillages * lesMail,LesReferences* lesRef
,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
,bool choixtdt,int cas)
{
tempsCL.Mise_en_route_du_comptage(); // temps cpu
// 1) on parcours le tableau de ddl d'initialisation
int tabInitTaille = tabInit.Taille();
for (int i=1;i<= tabInitTaille;i++)
{ DdlLim& tabInit_i = tabInit(i);
// recup de la reference correspondant au mot cle
const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage());
if ((refinitial.Indic() == 4) &&
(tabInit_i.TypeDeCL()==TANGENTE_CL) )
{// cas des références d'arêtes, avec des conditions de tangente imposée
const ReferenceAF & ref = ((ReferenceAF &) refinitial);
// on renseigne les éléments ad hoc
int refTaille = ref.Taille();
for (int ne =1; ne<= refTaille;ne++)
{int tabInitiTaille = tabInit_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
// sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabInitiTaille;// début normale
if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;};
for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
// affectation de la valeur d'initialisation
{ Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl
Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl
Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl
// récup de l'élément
Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
SfeMembT & elsfe = (SfeMembT&) el;
// on renseigne l'élément
Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur());
elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );
}// fin boucle sur tabInit_i
}// fin boucle sur les éléments de la référence
} // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE
else if (refinitial.Indic() != 1)
// cas d'element
{ cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!";
cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
tempsCL.Arret_du_comptage();
Sortie(1);
}
else
// cas de noeuds
{// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon
// la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout
// cas peut de fois,
const ReferenceNE & ref = ((ReferenceNE &) refinitial);
// traitement proprement dit
int refTaille = ref.Taille();
for (int nn =1; nn<= refTaille;nn++)
{int tabInitiTaille = tabInit(i).Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabInitiTaille;// début normale
if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// affectation de la valeur d'initialisation
{ Ddl ddl = tabInit_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// on vérifie que le ddl est compatible avec la dimension sinon message d'erreur
if (!CompatDim(ddl.Id_nom()))
{cout << "\n *** erreur, le ddl d'initialisation : " << ddl.Nom()
<< " pour la reference " << ref.Nom()
<< " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension()
<< ") de l'espace de travail " ;
if (ParaGlob::NiveauImpression()>6)
cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ;
cout << endl;
tempsCL.Arret_du_comptage();
Sortie (1);
};
if (noe.Existe_ici(ddl.Id_nom()))
// cas ou le ddl existe deja
{ noe.Change_val_t(ddl.Id_nom(),ddl.Valeur());
if (choixtdt)
noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur());
// mise a jour des ddl aux temps 0 pour tous les ddl sauf ceux de position
// car ces derniers sont les seuls dont la position initiale est déterminées à la lecture
// du maillage
if (!(Meme_famille(ddl.Id_nom(),X1)))
noe.Change_val_0(ddl.Id_nom(),ddl.Valeur());
// on regarde s'il fait partie de la combinaison
// si oui on met en place les ddl correspondant à HSLIBRE
Enum_ddl en = ddl.Id_nom();
Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt);
}
else
// cas ou le ddl n'existe pas
{ // tout d'abord on regarde si c'est un déplacement
// if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
{if(!CompatDim(ddl.Nom())) // vérif de dimension
{ cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
<< " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
cout << " \n cas des ddl bloquees ";
cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
tempsCL.Arret_du_comptage();
Sortie (1);
};
// cas ok on impose le déplacement sur le Xi correspondant
Enum_ddl en = ddl.Id_nom();
//on cherche l'equivalent Ui en Xi
en = UxyzXi(en);
noe.Ajout_val_t(en,ddl.Valeur());
// mise a jour des ddl aux autres temps
// noe.Ajout_val_0(en,ddl.Valeur());
if (choixtdt)
noe.Ajout_val_tdt(en,ddl.Valeur());
// puis on regarde si le ddl initial fait partie de la combinaison
// si oui on met en place les ddl correspondant à HSLIBRE
Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt);
}
else
{ // cas ou il faut creer un ddl sup
//noe.PlusDdl(ddl);
cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues"
<< " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
cout << "\n cas des ddl d'initialisation ";
cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
tempsCL.Arret_du_comptage();
Sortie (1);
};
};
};
};
};
};
// 2) cas des ddl imposes on verifie leurs existences
// on vérifie également l'existence des courbes de charge adoc si nécessaire
// idem pour les fonctions nD de charge adoc si nécessaire
// on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple
// vitesse et position ou accélération pour un même ddl
// on parcours le tableau de ddl bloques
// mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt
int tabBloqTaille = tabBloq.Taille();
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
if ((refinitial.Indic() == 4) &&
(tabBloq_i.TypeDeCL()==TANGENTE_CL) )
{// cas des références d'arêtes, avec des conditions de tangente imposée
// ici on s'occupe de renseigner les éléments
const ReferenceAF & ref = ((ReferenceAF &) refinitial);
// on renseigne les éléments ad hoc
int refTaille = ref.Taille();
for (int ne =1; ne<= refTaille;ne++)
{int tabBloqiTaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
// sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqiTaille;// début normale
if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;};
for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
// affectation de la valeur d'initialisation
{ Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl
Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl
Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl
// récup de l'élément
Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
SfeMembT & elsfe = (SfeMembT&) el;
// on regarde si les temps dépendent d'une fct nD
// si oui on modifie les bornes du ddl
if (tabBloq_i.Temps_depend_nD())
LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD);
// on continue que si le temps est actif ou pas
if ((tabBloq_i.Temps_actif(0.)))
{ // on renseigne l'élément
Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur());
elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );
};
};// fin boucle sur tabBloq_i
};// fin boucle sur les noeuds de la référence
} // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE
else if (refinitial.Indic() != 1)
// cas autre d'element par exemple
{ cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!";
cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
tempsCL.Arret_du_comptage();
Sortie (1);
}
else
// cas de noeuds
{const ReferenceNE & ref = ((ReferenceNE &) refinitial);
int refTaille = ref.Taille();
for (int nn =1; nn<= refTaille;nn++)
{int tabBloqiTaille = tabBloq_i.Taille();
/* // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim
if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
{cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
<< " que le nombre de noeud de la reference associee !! ";
cout << " condition limite : "; tabBloq_i.Affiche();
Sortie(1);
}*/
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqiTaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// affectation de la valeur d'initialisation
{ Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl
// on vérifie que le ddl est compatible avec la dimension sinon message d'erreur
if (!CompatDim(ddl.Id_nom()))
{cout << "\n *** erreur, le ddl de blocage : " << ddl.Nom()
<< " pour la reference " << ref.Nom()
<< " n'est pas compatible avec la dimension ( " << ParaGlob::Dimension()
<< ") de l'espace de travail " ;
if (ParaGlob::NiveauImpression()>6)
cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " ;
cout << endl;
tempsCL.Arret_du_comptage();
Sortie (1);
};
// récup du noeud
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// on regarde si les temps dépendent d'une fct nD
// si oui on modifie les bornes du ddl
if (tabBloq_i.Temps_depend_nD())
LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
// on regarde si le temps est actif ou pas
if ((tabBloq_i.Temps_actif(0.)))
{ // on n'intervient que si le temps initial est actif
tabBloq_i.ElemLim(nd).Met_en_service();
// récup du noeud
string nom_courbe = tabBloq_i.Nom_courbe(nd);
Courbe1D * pt_courbe = NULL;
if (nom_courbe != "")
// cas de l'existence d'une courbe de charge
// appel pour récupérer la courbe (juste pour la vérif
// car on ne s'en sert pas aprés !)
{ pt_courbe = lesCourbes1D->Trouve(nom_courbe);
};
// idem pour les fonctions nD
string nom_fctnD = tabBloq_i.NomF_charge(nd);
Fonction_nD * pt_fctnD = NULL;
if (nom_fctnD != "")
// cas de l'existence d'une fonction de charge
// appel pour récupérer la fct (juste pour la vérif
// car on ne s'en sert pas aprés !)
{ pt_fctnD = lesFonctionsnD->Trouve(nom_fctnD);
};
// maintenant on regarde du coté des noeuds
if (!noe.Existe_ici(ddl.Id_nom()))
// cas ou il faut creer un ddl sup
// on regarde le cas eventuel des coordonnees entrainees
// si on est en entraine et que le ddl a imposer est un Ui
// alors on ne verifie que les dimensions et on indique le blocage
// {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
{if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
{ // cas d'un ddl de déplacement, et que le ddl X1 existe déjà
if(!CompatDim(ddl.Nom()))
{ cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
<< " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ;
cout << " \n cas des ddl bloquees ";
cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
tempsCL.Arret_du_comptage();
Sortie (1);
}
else // cas ou c'est Xi le ddl bloque, on indique le blocage
{ Enum_ddl en = ddl.Id_nom();
//on cherche l'equivalent Ui en Xi
en = UxyzXi(en);
noe.Change_fixe(en,true);
// on regarde s'il fait partie de la combinaison et on fixe les blocages
Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt);
}
}
else
// cas d'un ddl inexistant diff de U, création puis initialisation a zero
{ noe.PlusDdl(ddl);
noe.Change_val_0(ddl.Id_nom(),0.);
noe.Change_val_t(ddl.Id_nom(),0.);
if (choixtdt)
noe.Change_val_tdt(ddl.Id_nom(),0.);
// puis on indique que le ddl est bloque
noe.Change_fixe(ddl.Id_nom(),true);
// on regarde s'il fait partie de la combinaison et on fixe les blocages
Enum_ddl en = ddl.Id_nom();
Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt);
}
}
else // cas ou le ddl existe
// on indique que le ddl est bloque, mais on ne change pas sa valeur
// ce sera fait au moment de la mise à jour à tdt
{ // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1)
// dans ce cas il est libre, on peut le bloquer sans pb,
// soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement
noe.Change_fixe(ddl.Id_nom(),true);
// on regarde s'il fait partie de la combinaison et on fixe les blocages
Enum_ddl en = ddl.Id_nom();
Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt);
};
}
else
{// si le ddl bloqué n'est pas actif pour le temps 0.
tabBloq_i.ElemLim(nd).Met_hors_service();
// dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé
// récup du noeud
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// on regarde du coté du noeuds
if (!noe.Existe_ici(ddl.Id_nom()))
// cas ou il faut creer un ddl sup
// on regarde le cas eventuel des coordonnees entrainees
// si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
// {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
{if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
{ // sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis
// initialisation a zero et on indique qu'il est hors service (non cf modif qui suit)
// ---modif 10 sep 2017
// cas ou le ddl n'existe pas
// on le met en service et comme on ne sait pas s'il va être actif ou pas, on le met libre
// c'est-à-dire qu'il n'est pas pour l'instant imposé à quelque chose
// on fait cela, et ce qu'il y avait avant, car sinon, le ddl au niveau des noeuds n'est pas
// mis à jour de t à tdt car seule les ddl qui ne sont pas HS, sont mis à jour
// or le fait que le ddl soit géré par une condition limite fait qu'il est succeptible d'être
// utilisé à t et tdt, donc il ne faut pas le mettre en HS
// par contre on le met en lisible c-a-d en donnée par défaut
Ddl ddl_inter(ddl); // pour pas que cela influe sur les autres noeuds
ddl_inter.ChangeVariable_a_Donnee();
noe.PlusDdl(ddl_inter);
noe.Change_val_0(ddl_inter.Id_nom(),0.);
noe.Change_val_t(ddl_inter.Id_nom(),0.);
if (choixtdt) noe.Change_val_tdt(ddl_inter.Id_nom(),0.);
// ---modif 10 sep 2017 // puis on indique que le ddl est bloque et hors service
// ---modif 10 sep 2017 noe.Met_hors_service(ddl.Id_nom());
noe.Met_en_service(ddl.Id_nom());
noe.Change_fixe(ddl.Id_nom(),true);
};
};
// pour le reste on ne fait rien, se sera géré par les mises à jour
// en fonction de l'évolution du temps
}; // fin du cas ddl bloqué et pas actif pour le temps 0.
};
};
};
};
// on initialise la situation de blocage et condition linéaires
Validation_blocage (lesRef,0.);
// vérif qu'il n'y a pas de surcharge de blocage
Verif_surcharge_blocage(lesMail,lesRef,0.,cas);
// pour le tps cpu, il y a une petite part de CLL, mais on la néglige
tempsCL.Arret_du_comptage(); // temps cpu
};
//// mise à jour de l'initialisation, par exemple après un restart
//// même paramètres que Initial, par contre ici il n'y a aucune création
//void LesCondLim::Re_initial(LesMaillages * lesMail,LesReferences* lesRef,LesCourbes1D* lesCourbes1D
// ,bool choixtdt,int cas)
// { // 1) on parcours le tableau de ddl d'initialisation
// int tabInitTaille = tabInit.Taille();
// for (int i=1;i<= tabInitTaille;i++)
// { DdlLim& tabInit_i = tabInit(i);
// // recup de la reference correspondant au mot cle
// const Reference & refinitial = lesRef->Trouve(tabInit_i.NomRef(),tabInit_i.NomMaillage());
// if ((refinitial.Indic() == 4) &&
// (tabInit_i.TypeDeCL()==TANGENTE_CL) )
// {// cas des références d'arêtes, avec des conditions de tangente imposée
// const ReferenceAF & ref = ((ReferenceAF &) refinitial);
// // on renseigne les éléments ad hoc
// int refTaille = ref.Taille();
// for (int ne =1; ne<= refTaille;ne++)
// {int tabInitiTaille = tabInit_i.Taille();
// // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
// // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
// int idebut=1; int ifinfin = tabInitiTaille;// début normale
// if (tabInit_i.Champ()) {idebut = ne; ifinfin = ne;};
// for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
// // affectation de la valeur d'initialisation
// { Ddl ddl1 = tabInit_i.ElemLim(nd); // récup des 3 ddl
// Ddl ddl2 = tabInit_i.ElemLim(nd+1); // récup des 3 ddl
// Ddl ddl3 = tabInit_i.ElemLim(nd+2); // récup des 3 ddl
// // récup de l'élément
// Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
// SfeMembT & elsfe = (SfeMembT&) el;
// // on renseigne l'élément
// Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur());
// elsfe.DefCondLim(tabInit_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );
//
// }// fin boucle sur tabInit_i
// }// fin boucle sur les éléments de la référence
// } // ---- fin du cas des conditions initiales d'encastrement ou de symétrie pour les SFE
//
// else if (refinitial.Indic() != 1)
// // cas d'element
// { cout << "\n initialisation autre que des noeuds, pas d\'action implentee a ce sujet !!";
// cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
// Sortie(1);
// }
// else
// // cas de noeuds
// {// on définit des tableaux intermédiaires qui servent pour la vérification qu'il n'y ait pas de doublon
// // la procédure est un peu couteuse en place mémoire mais elle n'est appelée qu'une seule fois ou en tout
// // cas peut de fois,
// const ReferenceNE & ref = ((ReferenceNE &) refinitial);
// // traitement proprement dit
// int refTaille = ref.Taille();
// for (int nn =1; nn<= refTaille;nn++)
// {int tabInitiTaille = tabInit(i).Taille();
// // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
// int idebut=1; int ifinfin = tabInitiTaille;// début normale
// if (tabInit_i.Champ()) {idebut = nn; ifinfin = nn;};
// for (int nd=idebut;nd<= ifinfin ;nd++)
// // affectation de la valeur d'initialisation
// { Ddl ddl = tabInit_i.ElemLim(nd);
// Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// if (noe.Existe_ici(ddl.Id_nom()))
// // cas ou le ddl existe deja
// { noe.Change_val_t(ddl.Id_nom(),ddl.Valeur());
// if (choixtdt)
// noe.Change_val_tdt(ddl.Id_nom(),ddl.Valeur());
// // mise a jour des ddl aux temps 0 pour tous les ddl sauf ceux de position
// // car ces derniers sont les seuls dont la position initiale est déterminées à la lecture
// // du maillage
// if (!(Meme_famille(ddl.Id_nom(),X1)))
// noe.Change_val_0(ddl.Id_nom(),ddl.Valeur());
// // on regarde s'il fait partie de la combinaison
// // si oui on met en place les ddl correspondant à HSLIBRE
// Enum_ddl en = ddl.Id_nom();
// Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt);
// }
// else
// // cas ou le ddl n'existe pas
// { // tout d'abord on regarde si c'est un déplacement
// // if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
// if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
// { if(!CompatDim(ddl.Nom())) // vérif de dimension
// { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
// << " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
// cout << " \n cas des ddl bloquees ";
// cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
// Sortie (1);
// }
// // cas ok on impose le déplacement sur le Xi correspondant
// Enum_ddl en = ddl.Id_nom();
// //on cherche l'equivalent Ui en Xi
// en = UxyzXi(en);
// noe.Ajout_val_t(en,ddl.Valeur());
// // mise a jour des ddl aux autres temps
// // noe.Ajout_val_0(en,ddl.Valeur());
// if (choixtdt)
// noe.Ajout_val_tdt(en,ddl.Valeur());
// // puis on regarde si le ddl initial fait partie de la combinaison
// // si oui on met en place les ddl correspondant à HSLIBRE
// Init_appart_groupe(ddl.UneVariable(),en,false,noe,cas,choixtdt);
// }
// else
// { // cas ou il faut creer un ddl sup
// //noe.PlusDdl(ddl);
// cout << "\n erreur, ce ddl ne fait pas partie des ddl attribues"
// << " par les elements donc inutiles !! ddl = " << ddl.Nom() ;
// cout << "\n cas des ddl d'initialisation ";
// cout << "\n void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
// Sortie (1);
// }
// }
// }
// }
// }
// }
// // 2) cas des ddl imposes on verifie leurs existences
// // on vérifie également l'existence des courbes de charge adoc si nécessaire
// // on vérifie qu'il n'y a pas de surcharge de ddl bloqué: par exemple
// // vitesse et position ou accélération pour un même ddl
// // on parcours le tableau de ddl bloques
// // mais on ne met pas les valeurs en places, ce sera fait lors de la mise à jour à tdt
// int tabBloqTaille = tabBloq.Taille();
// for (int i=1;i<= tabBloqTaille;i++)
// { DdlLim& tabBloq_i = tabBloq(i);
// // recup de la reference correspondant au mot cle
// const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
// if ((refinitial.Indic() == 4) &&
// (tabBloq_i.TypeDeCL()==TANGENTE_CL) )
// {// cas des références d'arêtes, avec des conditions de tangente imposée
// // ici on s'occupe de renseigner les éléments
// const ReferenceAF & ref = ((ReferenceAF &) refinitial);
// // on renseigne les éléments ad hoc
// int refTaille = ref.Taille();
// for (int ne =1; ne<= refTaille;ne++)
// {int tabBloqiTaille = tabBloq_i.Taille();
// // dans le cas d'un champ, pour chaque ddl on a un élément associé, il ne faut donc pas itérer
// // sur les éléments, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
// int idebut=1; int ifinfin = tabBloqiTaille;// début normale
// if (tabBloq_i.Champ()) {idebut = ne; ifinfin = ne;};
// for (int nd=idebut;nd<= ifinfin ;nd+=3) // on va de 3 en 3
// // affectation de la valeur d'initialisation
// { Ddl ddl1 = tabBloq_i.ElemLim(nd); // récup des 3 ddl
// Ddl ddl2 = tabBloq_i.ElemLim(nd+1); // récup des 3 ddl
// Ddl ddl3 = tabBloq_i.ElemLim(nd+2); // récup des 3 ddl
// // récup de l'élément
// Element & el=lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
// SfeMembT & elsfe = (SfeMembT&) el;
// // on continue que si le temps est actif ou pas
// if ((tabBloq_i.Temps_actif(0.)))
// { // on renseigne l'élément
// Coordonnee3 vpla(ddl1.Valeur(),ddl2.Valeur(),ddl3.Valeur());
// elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );
// };
// }// fin boucle sur tabBloq_i
// }// fin boucle sur les noeuds de la référence
// } // ---- fin du cas des conditions d'encastrement ou de symétrie pour les SFE
//
// else if (refinitial.Indic() != 1)
// // cas autre d'element par exemple
// { cout << "\n blocage autre que des noeuds, pas d\'action implentee a ce sujet !!";
// cout << "void LesCondLim::Initial(LesMaillages * lesMail) " << endl;
// Sortie (1);
// }
// else
// // cas de noeuds
// {const ReferenceNE & ref = ((ReferenceNE &) refinitial);
// int refTaille = ref.Taille();
// for (int nn =1; nn<= refTaille;nn++)
// {int tabBloqiTaille = tabBloq_i.Taille();
// /* // dans le cas d'une référence de champ on vérifie ne nombre de ddlLim
// if ((tabBloq_i.Champ()) && (tabBloqiTaille != ref.Taille()))
// {cout << "\n erreur: la condition limite de champ n'a pas le meme nombre de ddl bloque"
// << " que le nombre de noeud de la reference associee !! ";
// cout << " condition limite : "; tabBloq_i.Affiche();
// Sortie(1);
// }*/
// // dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// // sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
// int idebut=1; int ifinfin = tabBloqiTaille;// début normale
// if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
// for (int nd=idebut;nd<= ifinfin ;nd++)
// // affectation de la valeur d'initialisation
// { Ddl ddl = tabBloq_i.ElemLim(nd); // récup du ddl
// // on regarde si le temps est actif ou pas
// if ((tabBloq_i.Temps_actif(0.)))
// { // on n'intervient que si le temps initial est actif
// tabBloq_i.ElemLim(nd).Met_en_service();
// // récup du noeud
// Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// string nom_courbe = tabBloq_i.Nom_courbe(nd);
// Courbe1D * pt_courbe = NULL;
// if (nom_courbe != "")
// // cas de l'existence d'une courbe de charge
// // appel pour récupérer la courbe (juste pour la vérif
// // car on ne s'en sert pas aprés !)
// { pt_courbe = lesCourbes1D->Trouve(nom_courbe);
// }
// // maintenant on regarde du coté des noeuds
// if (!noe.Existe_ici(ddl.Id_nom()))
// // cas ou il faut creer un ddl sup
// // on regarde le cas eventuel des coordonnees entrainees
// // si on est en entraine et que le ddl a imposer est un Ui
// // alors on ne verifie que les dimensions et on indique le blocage
// // {if ((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL)))
// {if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
// { // cas d'un ddl de déplacement, et que le ddl X1 existe déjà
// if(!CompatDim(ddl.Nom()))
// { cout << "\n erreur, ce ddl de fait pas partie des ddl attribues"
// << " par les elements pour la dimension en cours donc inutiles !! ddl = " << ddl.Nom() ;
// cout << " \n cas des ddl bloquees ";
// cout << "\nvoid LesCondLim::Initial(LesMaillages * lesMail) " << endl;
// Sortie (1);
// }
// else // cas ou c'est Xi le ddl bloque, on indique le blocage
// { Enum_ddl en = ddl.Id_nom();
// //on cherche l'equivalent Ui en Xi
// en = UxyzXi(en);
// noe.Change_fixe(en,true);
// // on regarde s'il fait partie de la combinaison et on fixe les blocages
// Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt);
// }
// }
// else
// // cas d'un ddl inexistant diff de U, création puis initialisation a zero
// { noe.PlusDdl(ddl);
// noe.Change_val_0(ddl.Id_nom(),0.);
// noe.Change_val_t(ddl.Id_nom(),0.);
// if (choixtdt)
// noe.Change_val_tdt(ddl.Id_nom(),0.);
// // puis on indique que le ddl est bloque
// noe.Change_fixe(ddl.Id_nom(),true);
// // on regarde s'il fait partie de la combinaison et on fixe les blocages
// Enum_ddl en = ddl.Id_nom();
// Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt);
// }
// }
// else // cas ou le ddl existe
// // on indique que le ddl est bloque, mais on ne change pas sa valeur
// // ce sera fait au moment de la mise à jour à tdt
// { // comme le ddl existe déjà, deux solutions: soit il provient de l'initialisation 1)
// // dans ce cas il est libre, on peut le bloquer sans pb,
// // soit il a déjà été bloquer, dans ce cas on le surbloque se qui déclanchera un message d'avertissement
// noe.Change_fixe(ddl.Id_nom(),true);
// // on regarde s'il fait partie de la combinaison et on fixe les blocages
// Enum_ddl en = ddl.Id_nom();
// Init_appart_groupe(ddl.UneVariable(),en,true,noe,cas,choixtdt);
// }
// }
// else
// {// si le ddl bloqué n'est pas actif pour le temps 0.
// tabBloq_i.ElemLim(nd).Met_hors_service();
// // dans le cas où le ddl n'existe pas on le crée pour qu'il puisse ensuite être utilisé
// // récup du noeud
// Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// // on regarde du coté du noeuds
// if (!noe.Existe_ici(ddl.Id_nom()))
// // cas ou il faut creer un ddl sup
// // on regarde le cas eventuel des coordonnees entrainees
// // si cas d'un ddl de déplacement, et que le ddl X1 existe déjà, pas de pb, on ne fait rien
// // {if (!((noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))))
// {if (!((noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))))
// {// sinon cas d'un ddl inexistant diff de U ou qu'il n'y a pas de X1, alors création puis
// // initialisation a zero et on indique qu'il est hors service
// noe.PlusDdl(ddl);
// noe.Change_val_0(ddl.Id_nom(),0.);
// noe.Change_val_t(ddl.Id_nom(),0.);
// if (choixtdt) noe.Change_val_tdt(ddl.Id_nom(),0.);
// // puis on indique que le ddl est bloque et hors service
// noe.Met_hors_service(ddl.Id_nom());
// noe.Change_fixe(ddl.Id_nom(),true);
// }
// }
// // pour le reste on ne fait rien, se sera géré par les mises à jour
// // en fonction de l'évolution du temps
// } // fin du cas ddl bloqué et pas actif pour le temps 0.
// }
// }
// }
// }
// // on initialise la situation de blocage et condition linéaires
// Validation_blocage (lesRef,0.);
// // vérif qu'il n'y a pas de surcharge de blocage
// Verif_surcharge_blocage(lesMail,lesRef,0.,cas);
// };
// incrementation des coordonnees a t+dt et des ddl en fonctions des ddl imposes
// et du chargement
// coef: est un facteur multiplicatif des ddl sans courbes de charge,
// est supposé intégrer déjà le multiplicateur général
// en fait du chargement impose
// mult_gene : multiplicateur général de tous les chargements
// deltat : le pas de temps en cours
// temps : le temps courant où sont calculées les conditions
// ch_statut : indique s'il y a changement ou non de statut des conditions limites (pour les ddl aux noeuds)
// c-a-d un ddl qui passe de bloqué à non bloqué ou inversement: il s'agit uniquement des ddl aux noeuds
// c-a-d ceux qui ont une influence sur la mise en place des cl sur la raideur et le résidu
// cas : indique le cas d'association de ddl en cours, ces ddl sont gérés globalement, c-a-d lorsque
// le statut d'un ddl est modifié (de bloqué à non bloqué par exemple) tous les ddl associés ont
// leur statut modifié de manière équivalente
// =0 pas d'association
// =1 association X V GAMMA
// lorsque en_ddl est égal à NU_DDL, cela signifie que l'on met les conditions limites sur tous les
// ddl de noeud actifs
// lorsque en_ddl est différent de NU_DDL, il donne le type des seules ddl pour lesquels on met les
// conditions de blocage: par exemple X1 -> blocage sur X1,X2,X3 selon la dimension
void LesCondLim::MiseAJour_tdt
(const double& mult_gene,LesMaillages * lesMail,const double& deltat,const LesReferences* lesRef
,const double& temps,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
,const double& coef,bool& ch_statut
,int cas,Enum_ddl en_ddl)
{
tempsCL.Mise_en_route_du_comptage(); // temps cpu
// préparation
bool tous_les_blocages = true;
if (en_ddl != NU_DDL) tous_les_blocages = false;
// la mise en place des blocages s'effectue en deux temps, ceci pour préparer la vérification
// de la non sur imposition de ddl: ceci pour les ddl aux noeuds
// 1- au premier passage : on met en libre les ddl qui sont relachés, on met tous les ddl actifs
// en libre
// 2- au second passage : les ddl au temps actifs sont fixés (et éventuellement surfixé si pb)
//
// pour les ddl d'encastrement ou de symétrie pour les sfe, tout ce fait au premier passage uniquement
// ---- premier passage ----
int tabBloqTaille =tabBloq.Taille();
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// on regarde si les temps dépendent d'une fct nD
// si oui on modifie les bornes du ddl
if (tabBloq_i.Temps_depend_nD())
LesCondLim::Mise_a_jour_t_minmax_ddlLim(tabBloq_i,lesFonctionsnD);
// pour le ddlLim, si le temps est inférieur au temps actif
// ou si d'une part le temps n'est pas actif et qu'au pas précédent
// il n'était pas également actif on ne fait rien
if (!(tabBloq_i.Pas_a_prendre_en_compte(temps)))
{bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier
// recup de la reference correspondant au mot cle
const Reference & refinitial = lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage());
if ((refinitial.Indic() == 4) &&
(tabBloq_i.TypeDeCL()==TANGENTE_CL) )
{// cas des références d'arêtes, avec des conditions de tangente imposée
bool devient_actif = (actif_pour_le_temps && (!tabBloq_i.Etat_validation()));
bool devient_inactif = ((!actif_pour_le_temps) && (tabBloq_i.Etat_validation()));
// on n'intervient que s'il y a un changement d'état
if (devient_actif || devient_inactif)
{//int tabBloqitaille = tabBloq_i.Taille();
const ReferenceAF & ref = ((ReferenceAF &) refinitial);
int reftaille = ref.Taille();
// on boucle sur les numéros de la référence
for (int ne =1; ne<= reftaille;ne++)
{// on regarde si le temps est actif ou pas
if (devient_actif)
// cas ou on veut le blocage mais qu'au temps précédent ce n'était pas valide
{ // récup de l'élément
SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
// que ce soit dans le cas d'un champ ou normal, on n'a pas besoin d'itérer sur les ddl du ddlLim
// car d'un part pour le champ, on a autant de dim_espace ddl que d'élément dans la référence
// et d'autre part dans le cas normal on a uniquement un seul dim_espace ddl -> vecteur
// !!!!!! pour l'instant on considère que c'est en 3D
#ifdef MISE_AU_POINT
if ((ParaGlob::Dimension() < 3) || (tabBloq_i.Taille() != 3))
{ cout << "\n erreur, pour l'instant les conditions de type TANGENTE_CL ne sont operationnelles "
<< " que pour la dimension 3 !! ";
cout << "\n reference concernee: "; ref.Affiche();
cout << "\n condition limite concernee: ";tabBloq_i.Affiche();
tempsCL.Arret_du_comptage();
Sortie(1);
};
#endif
int tabBloqitaille = tabBloq_i.Taille(); // normalement = 3 ici
Tableau <Ddl> t_ddl(tabBloqitaille); // les valeurs du vecteur qui permet le calcul de la tangence
for (int nd=1;nd<=tabBloqitaille;nd++)
{Ddl ddl = tabBloq_i.ElemLim(nd);
// choix entre valeur simple et valeur qui varie
if(tabBloq_i.Nom_courbe(nd) != "")
{ // cas d'une courbe de charge, récup de la courbe
Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd));
// on change la valeur du ddl
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // pour l'instant ce n'est pas implanté
// en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la
// position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à
// l'élément qui updaterait sa position (qui peut être différente pour chaque élément)
// $$$ à faire s'il y a une demande, pour l'instant on attend $$$$
cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant"
<< " ce cas n'est pas implante, donc le demander !!! "
<< "\n LesCondLim::MiseAJour_tdt(.... ";
tempsCL.Arret_du_comptage();
Sortie(1);
}
else
{ // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd);
};
t_ddl(nd) = ddl;
}
else if (tabBloq_i.NomF_charge(nd) != "")
{ // cas d'une fonction nD de charge, récup
Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd));
// on change la valeur du ddl
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // pour l'instant ce n'est pas implanté
// en fait, il faudrait une valeur sauvegardée, or le plus simple serait d'utiliser la
// position actuelle de la tangente sur l'élément, donc il faudrait donner l'incrément à
// l'élément qui updaterait sa position (qui peut être différente pour chaque élément)
// $$$ à faire s'il y a une demande, pour l'instant on attend $$$$
cout << "\n *** blocage relatif pour l'evolution d'une tangente aux elements, pour l'instant"
<< " ce cas n'est pas implante, donc le demander !!! "
<< "\n LesCondLim::MiseAJour_tdt(.... ";
tempsCL.Arret_du_comptage();
Sortie(1);
}
else
{// pour l'instant on limite l'utilisation des fonctions aux seules grandeurs globales
if (pt_fctnD->NbVariable_locale() != 0)
{cout << "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements, pour l'instant"
<< " seule une dependance a des variables globales est possible !!! "
<< "\n LesCondLim::MiseAJour_tdt(.... ";
tempsCL.Arret_du_comptage();
Sortie(1);
};
Tableau <double> & tab_ret = pt_fctnD->Valeur_pour_variables_globales();
#ifdef MISE_AU_POINT
if (tab_ret.Taille() != 1)
{cout << "\n*** Erreur : la fonction nD retourne un vecteur et non un scalaire comme escompte "
<< "\n *** blocage via une fonction nD pour l'evolution d'une tangente aux elements"
<< "\n LesCondLim::MiseAJour_tdt(.... ";
tempsCL.Arret_du_comptage();
Sortie(1);
};
#endif
// mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd);
};
t_ddl(nd) = ddl;
}
else // cas d'un ddl à valeur fixe
{ // cas d'un ddl à valeur fixe
t_ddl(nd) = ddl;
};
};
// on renseigne l'élément
Coordonnee3 vpla(t_ddl(1).Valeur(),t_ddl(2).Valeur(),t_ddl(3).Valeur());
elsfe.DefCondLim(tabBloq_i.TypeDeCL(),vpla, ref.NumeroFA(ne) );
}
else if (devient_inactif)
// on relache le blocage si nécessaire, pour cela on regarde donc s'il y a changement de statut
{ // récup de l'élément
SfeMembT & elsfe = (SfeMembT&) lesMail->Element_LesMaille(ref.Nbmaille(),ref.NumeroElem(ne));
// on renseigne l'élément
Coordonnee3 vpla; // initalisé à 0 par défaut, ne sert pas ici
elsfe.DefCondLim(RIEN_TYPE_CL,vpla, ref.NumeroFA(ne) );
};
// sinon on ne fait rien
}; //-- fin de la boucle sur ne
}//-- fin du test sur devient_actif ou devient_inactif
}//-- fin du cas ref d'encastrement ou de symétrie
else // cas d'une référence de noeud
{const ReferenceNE & ref = ((ReferenceNE &) refinitial);
int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// incrementation en fonction de la valeur de blocage et du coef
{Ddl ddl = tabBloq_i.ElemLim(nd);
// concernant le temps, soit le ddlLim est actif ou il change de statut: actif à non actif
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
// cas de deplacements imposes en entraine on change les Ui en Xi
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
bool a_considerer = tous_les_blocages;
if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux
{if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;}
Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier
if (a_considerer)
{ if ( noe.En_service(ddlenu) )
{ // on regarde si le temps est actif ou pas
if (!actif_pour_le_temps)
// cas du temps non actif, on relache le blocage si nécessaire
// on regarde donc s'il y a changement de statut
{if (tabBloq_i.Etat_validation() && (noe.Ddl_fixe(ddlenu)))
{ch_statut = true;
Retire_cl(nd,tabBloq_i,ddlenu,noe,cas);
}
} //-- fin du test ou le temps n'est pas actif
else
// cas du temps actif
// on regarde s'il y a changement de statut
{if (!(tabBloq_i.Etat_validation())&& (!(noe.Ddl_fixe(ddlenu))))
{ // on change le statut que si c'est une variable, les données n'influencent pas les raideurs et seconds membres
if (noe.UneVariable(ddlenu))
ch_statut = true;
// Mise_cl(nd,tabBloq_i,ddlenu,noe,cas);
};
// gestion des surcharges de blocage
// au premier passage on met tous les ddl en libre s'ils sont actifs
if (noe.Ddl_fixe(ddlenu))
Retire_cl(nd,tabBloq_i,ddlenu,noe,cas);
}//-- fin du test si le temps est actif
}//-- fin du test si le ddl du noeud est une variable et est en service
}//-- fin du test si le noeud est à considérer ou pas
}//-- fin de la boucle sur tabBloq_i: indice nd
}//-- fin de la boucle nn
}//-- fin du cas des noeuds
} // fin du if (!(tabBloq_i.Pas_a_prendre_en_compte(temps)))
}//-- fin de la boucle sur tabBloq
// ---- second passage ----
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
// on ne continue que si c'est une référence de noeud
if (ref.Indic() == 1)
{ int reftaille = ref.Taille();
// cas particulier des mouvements solides
if (tabBloq_i.Mouvement_Solide())
{MiseAjour_tdt_second_passage_mvtSolide(mult_gene,lesMail,deltat,cas
,lesCourbes1D,lesFonctionsnD,coef,tabBloq_i,ref,temps,en_ddl);
}
else
// cas différent des mouvements solides
{for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// incrementation en fonction de la valeur de blocage et du coef
{Ddl ddl = tabBloq_i.ElemLim(nd);
// pour le ddlLim, si le temps est inférieur au temps actif
// ou si d'une part le temps n'est pas actif et qu'au pas précédent
// il n'était pas également actif on ne fait rien
if (tabBloq_i.Pas_a_prendre_en_compte(temps)) break;
// maintenant soit le ddlLim est actif ou il change de statut: actif à non actif
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
////--debug
//if (noe.Num_noeud()==197)
// {cout << "\n debug1: LesCondLim::MiseAJour_tdt(..";
// noe.Affiche();cout << endl;
// };
////--fin debug
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
// cas de deplacements imposes en entraine on change les Ui en Xi
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
bool a_considerer = tous_les_blocages;
if (! a_considerer) // cas ou on ne veut que certain blocage, a_bloque est faux
{if (Meme_famille(en_ddl,ddl.Id_nom())) a_considerer = true;}
Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier
if (a_considerer)
{ // on regarde si les temps dépendent d'une fct nD
// si oui on modifie les bornes du ddl
if (tabBloq_i.Temps_depend_nD())
LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
bool actif_pour_le_temps = tabBloq_i.Temps_actif(temps); // pour simplifier
bool une_variable = noe.UneVariable(ddlenu); // pour simplifier
// cas des variables: si le ddl du noeud est en service on continue sinon on ne fait rien
// ou cas d'une donnée et le temps actif
if ( ( une_variable && noe.En_service(ddlenu))
||(!une_variable && actif_pour_le_temps) )
{ // on regarde si le temps est actif ou pas, seul le cas actif est ici considérer
if (actif_pour_le_temps)
// gestion des surcharges de blocage
// au second passage on fixe les ddl actifs
{Mise_cl(nd,tabBloq_i,ddlenu,noe,cas);
// on choisit entre ddl à valeur fixe ou avec une courbe de charge
// coef intègre le multiplicateur global: mult_gene
if ((tabBloq_i.Nom_courbe(nd) != "")&&(tabBloq_i.NomF_charge(nd) == ""))
{ // cas d'une courbe de charge, récup de la courbe
Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd));
// on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle
// car au paravant il pouvait être non nul
// ici changement et non ajout , prise en compte de la relativité du blocage
double val_final = 0.;
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat
ddl.Valeur() = ((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat)))
* tabBloq_i.Echelle_courbe(nd);
val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu);
}
else
{ // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
ddl.Valeur() = (pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd);
val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu);
};
noe.Change_val_tdt(ddlenu,val_final); // mise à jour
}
else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) == ""))
{ // cas d'une fonction nD de charge, récup
Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd));
// on commence par récupérer les conteneurs des grandeurs à fournir
List_io <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 du ddl"
<< Nom_ddl(ddlenu)
<< "\n LesCondLim::MiseAJour_tdt(.... ";
tempsCL.Arret_du_comptage();
Sortie(1);
};
#endif
// on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle
// car au paravant il pouvait être non nul
// ici changement et non ajout , prise en compte de la relativité du blocage
double val_final = 0.;
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // pour l'instant a priori ce n'est pas possible car le temps
// est une variable globale que l'on ne peut pas modifier pour les fonctions nD
// il faut donc utiliser conjointement une courbe1D pour le temps et la fonction nD pour le reste
cout << "\n *** blocage relatif avec uniquement une fonction nD: ce n'est pas possible"
<< " pour avoir un blocage relatif il faut utiliser conjointement une courbe de charge "
<< " pour le temps et une fonction nD pour le reste !!!!"
<< "\n LesCondLim::MiseAJour_tdt(.... ";
tempsCL.Arret_du_comptage();
Sortie(1);
}
else
{ // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
ddl.Valeur() = tab_ret(1) * tabBloq_i.Echelle_courbe(nd);
val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu);
};
noe.Change_val_tdt(ddlenu,val_final); // mise à jour
}
else if ((tabBloq_i.NomF_charge(nd) != "")&&(tabBloq_i.Nom_courbe(nd) != ""))
{ // cas d'une fonction nD de charge, récup
Fonction_nD * pt_fctnD = lesFonctionsnD->Trouve(tabBloq_i.NomF_charge(nd));
// on commence par récupérer les conteneurs des grandeurs à fournir
List_io <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 du ddl"
<< Nom_ddl(ddlenu)
<< "\n LesCondLim::MiseAJour_tdt(.... ";
tempsCL.Arret_du_comptage();
Sortie(1);
};
#endif
// idem pour la courbe 1D
Courbe1D * pt_courbe = lesCourbes1D->Trouve(tabBloq_i.Nom_courbe(nd));
// on change la valeur du ddl du noeud, même si la valeur à bloquer est nulle
// car au paravant il pouvait être non nul
// ici changement et non ajout , prise en compte de la relativité du blocage
double val_final = 0.;
if (tabBloq_i.BlocageRelatif()) // cas d'une modif relativement au temps précédent
{ // mise à jour de la valeur de l'incrément du ddl (et non ce sa valeur) sur deltat
ddl.Valeur() = tab_ret(1) *
(((pt_courbe->Valeur(temps)) - (pt_courbe->Valeur(temps-deltat)))
* tabBloq_i.Echelle_courbe(nd)
);
val_final = mult_gene * ddl.Valeur() + noe.Valeur_t(ddlenu);
}
else
{ // mise à jour de la valeur du ddl en absolu, c-a-d relativement à t=0
ddl.Valeur() = tab_ret(1) *
(pt_courbe->Valeur(temps)) * tabBloq_i.Echelle_courbe(nd);
val_final = mult_gene * ddl.Valeur() + noe.Valeur_0(ddlenu);
};
noe.Change_val_tdt(ddlenu,val_final); // mise à jour
}
else
{ // cas d'un ddl à valeur fixe
// du au fait de l'initialisation d'un incrément à l'autre dans les algos globaux on change
double val_final=noe.Valeur_t(ddlenu); // récup de la valeur à t
val_final += coef * ddl.Valeur(); // mise en place du delta
noe.Change_val_tdt(ddlenu,val_final);
};
}; //-- fin du test si le temps est actif
}; //-- fin du test si le ddl du noeud est en service
}; //-- fin du test si le noeud est à considérer ou pas
}; //-- fin de la boucle sur tabBloq_i
}; //-- fin de la boucle sur nn
}; //-- fin du else du if (tabBloq_i.Mouvement_Solide())
}; //-- fin du du test : if (ref.Indic() == 1)
};//-- fin de la boucle sur tabBloq
// vérif qu'il n'y a pas de surcharge de blocage
Verif_surcharge_blocage(lesMail,lesRef,temps,cas);
tempsCL.Arret_du_comptage(); // temps cpu
};
// validation des conditions de blocages, pour l'incrément.
// concernant l'activité des ddlLim, elle est enregistrée en fonction du temps
// idem pour les conditions linéaires
void LesCondLim::Validation_blocage (LesReferences* lesRef,const double& temps)
{
// tout d'abord les conditions de blocage
int tabBloqTaille =tabBloq.Taille();
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (ref.Indic() == 1) // ok que si c'est une ref de noeud
{ int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
for (int nd=1;nd<= tabBloqitaille;nd++)
// validation de l'activité du ddlLim
tabBloq_i.Validation(temps);
};
};
};
// maintenant les conditions linéaires
int tabTaille = tab_iocondiline.Taille();
////----- debug
//cout << "\n LesCondLim::Validation_blocage: avant validation \n temps = " << temps << "\n";
//cout << tab_iocondiline;
////--- fin debug
for (int icondli=1;icondli<= tabTaille; icondli++)
tab_iocondiline(icondli).Validation(temps);
////----- debug
//cout << "\n LesCondLim::Validation_blocage: après validation \n";
//cout << tab_iocondiline;
////--- fin debug
};
// test s'il y a changement de statut pour le temps indiqué par rapport à la situation actuelle ou pas
// n'effectue aucune autre opération
// si en_ddl est différent de NU_DDL on test le changement de statut uniquement pour le ddl en_ddl
bool LesCondLim::Changement_statut(const LesMaillages * lesMail,const LesReferences* lesRef
,LesFonctions_nD* lesFonctionsnD
,const double& temps,const Enum_ddl en_ddl)
// *************** a mettre en conformité avec miseà jour tdt ***************$
{ cout << "\n methode pas operationnelle, a mettre a jour !!!!"
<< "\n LesCondLim::Changement_statut(....";
Sortie(1);
// préparation
bool tous_les_blocages = true;
if (en_ddl != NU_DDL) tous_les_blocages = false;
bool ch_statut = false; // valeur de retour
int tabBloqTaille =tabBloq.Taille();
// on parcours le tableau de ddl bloques
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
for (int nd=1;nd<= tabBloqitaille;nd++)
// incrementation en fonction de la valeur de blocage et du coef
{Ddl ddl = tabBloq_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// on regarde si les temps dépendent d'une fct nD
// si oui on modifie les bornes du ddl
if (tabBloq_i.Temps_depend_nD())
LesCondLim::Mise_a_jour_t_minmax_ddlLim(noe,tabBloq_i,lesFonctionsnD);
Enum_ddl ddlenu= ddl.Id_nom(); // pour simplifier
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
// cas de deplacements imposes en entraine on change les Ui en Xi
ddl.Change_nom(UxyzXi(ddlenu));
bool a_bloquer = tous_les_blocages;
if (! a_bloquer) // cas ou on ne veut que certain blocage, a_bloque est faux
{if (Meme_famille(en_ddl,ddlenu)) a_bloquer = true;}
if (a_bloquer)
{ if (!(tabBloq_i.Temps_actif(temps)))
// cas de la courbe non active pour le temps
{ // si le ddl du noeud est en service on continue sinon on ne fait rien
if ( noe.En_service(ddlenu) )
// on regarde s'il y a changement de statut et que c'est une variable
{if ((noe.Ddl_fixe(ddlenu)) && (noe.UneVariable(ddlenu)))
ch_statut = true;
} //-- fin du test si le ddl du noeud est en service
} //-- fin du test ou le temps n'est pas actif
else
// cas du temps actif
{ if (ddl.Valeur() != 0)
{// si le ddl du noeud est en service on continue sinon on ne fait rien
if ( noe.En_service(ddlenu) )
// on regarde s'il y a changement de statut et que c'est une variable
{if ( (!(noe.Ddl_fixe(ddlenu))) && (noe.UneVariable(ddlenu)))
ch_statut = true;
} //-- fin du test si le ddl du noeud est en service
} //-- fin du test si la valeur a bloquer est différente de 0
} //-- fin du test si le temps est actif
}
}
}
}
return ch_statut;
};
// récupération des tableaux d'indices généraux des variables ddl bloqués
// cas : donne le type d'association de ddl que l'on veut
// =0 -> pas d'association
// =1 -> association de Xi avec Vi avec Gammai
// t_assemb: donne pour chaque type d'association, le numéro d'assemblage correspondant au different ddl
// de l'association
// cas=1 -> numéro d'assemblage de X1 puis V1 puis GAMMA1
// : en sortie une liste de Gene_asso, correspondant à tous les ddl bloqués et les
// les ddl associés
list <LesCondLim::Gene_asso> LesCondLim::Tableau_indice
(const LesMaillages * lesMail,const Tableau <Nb_assemb> & t_assemb
,const LesReferences* lesRef,const double& temps,int cas)
{ // def de la liste de retour
list <LesCondLim::Gene_asso> li_ret;
// préparation
int tabBloqTaille =tabBloq.Taille();
// on parcours le tableau de ddl bloques
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (ref.Indic() == 1) // ok pour les noeuds uniquement
{int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// incrementation en fonction de la valeur de blocage
{Ddl ddl = tabBloq_i.ElemLim(nd);
const Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
// cas de deplacements imposes en entraine on change les Ui en Xi
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
// si le blocage est relatif à une donnée et non à une variable arrêt
if (!(noe.UneVariable(ddl.Id_nom()))) break;
// si le ddl concerne la direction 3 et que l'on est en axi, arrêt
// car le ddl 3 n'est pas utilisé en blocage en axi
Enum_ddl en_ddl = ddl.Id_nom(); // le type principal de l'élément Gene_asso
if (ParaGlob::AxiSymetrie() && FoncDim(en_ddl))
{Enum_ddl prem_ddl = PremierDdlFamille(en_ddl);
// pour l'instant on ne traite que X, U, V et Gamma
bool fin_traitement = false; // init
switch (prem_ddl)
{ case X1: if (en_ddl == X3)fin_traitement = true;
break;
case V1: if (en_ddl == V3)fin_traitement = true;
break;
case GAMMA1:if (en_ddl == GAMMA3)fin_traitement = true;
break;
default:
cout << "\n *** erreur pour l'instant en axi, seules les cas "
<< " Xi, Vi, GAMMAi sont pris en compte pour les CL selon dir 3 "
<< " \n LesCondLim::Tableau_indice(... "<< endl;
break;
};
if (fin_traitement) break;
};
// on regarde si le ddl fait partie de la liste à scruter, si l'on est
// dans le cas d'une combinaison, sinon c'est ok
bool choix = true; // vrai a priori, c'est à dire le cas = 0
// qui convient que dans le cas = 0, sinon:
if (cas!= 0)
{ if (Dans_combinaison(cas,en_ddl))
{choix = true;}
else
{choix = false;} // cas d'une combinaison , et d'un ddl qui ni appartiend pas
};
if (choix)
{ // on test que si le temps est actif
// ici les tmin et tmax du ddl ne sont pas modifiés, on considère que ce sont
// ceux qui ont été mise à jour à la précédente mise à jour
if ((tabBloq_i.Temps_actif(temps)))
{ switch (cas)
{ case 0 : // cas pas d'association
{ // def du tableau de position pour l'élément Gene_asso
Tableau <int> pointe(1); // dimension pour Xi,Vi,GAMMAi
// recup de la position du ddl
pointe(1) = noe.Pointeur_assemblage(en_ddl,t_assemb(1).n);
// ajout dans la liste
Gene_asso aa(en_ddl,pointe);
li_ret.push_back(aa);
break;
}
case 1 : // cas de l'association X V GAMMA
{ // def du tableau de position pour l'élément Gene_asso
Tableau <int> pointe(3); // dimension pour Xi,Vi,GAMMAi
// récup des ddl secondaire et du ddl principal bloqué
Tableau <Enum_ddl> t_enu = MemeCombinaison(cas,en_ddl);
pointe(1) = noe.Pointeur_assemblage(t_enu(1),t_assemb(1).n);
pointe(2) = noe.Pointeur_assemblage(t_enu(2),t_assemb(2).n);
pointe(3) = noe.Pointeur_assemblage(t_enu(3),t_assemb(3).n);
// ajout dans la liste
Gene_asso aa(en_ddl,pointe);
li_ret.push_back(aa);
////// --debug
//cout << "\n debug LesCondlim::Tableau_indice("
// << "\n li_ret.size= "<< li_ret.size() << endl;
////// -- fin debug
break;
}
}; //-- fin du switch (cas)
}; //-- fin du if ((tabBloq_i.Temps_actif(temps)))
}; //-- fin du if (choix)
}; //-- fin du for (int nd=idebut;nd<= ifinfin ;nd++)
}; //-- fin du for (int nn =1; nn<= reftaille;nn++)
}; //-- fin du if (ref.Indic() == 1)
}; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
//// --debug
//cout << "\n debug LesCondlim::Tableau_indice("
// << "\n li_ret.size= "<< li_ret.size() ;
//list <LesCondLim::Gene_asso>::iterator ie,iefin=li_ret.end();; // def d'un iterator adoc
//int ih=1; // indice
//for(ie=li_ret.begin(),ih=1;ie!=iefin;ie++,ih++)
// // comme les valeurs des X V Gamma vont être écrasé par le calcul global, on utilise
// // des conteneurs intermédiaires
// {//trois cas
// LesCondLim::Gene_asso & s = (*ie); // pour simplifier
// int ix=s.pointe(1); // début des Xi
// int iv=s.pointe(2); // début des Vi
// int ig=s.pointe(3); // début des gammai
// cout << "\n ix= " << ix << ", iv= "<< iv << ", ig= "<< ig;
// };
//cout << endl;
//// -- fin debug
// retour de la liste
return li_ret;
};
// mise en place des conditions limites sur les matrices et/ou second membres
// cas : indique un type d'association de ddl
// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès
// lors que l'un a été fixé par l'utilisateur
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
// mais sans sauvegarde (correspond par exemple à une partie de vecglob)
void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef,
Mat_abstraite & matglob,Vecteur& vecglob
,const Nb_assemb& nb_casAssemb,int cas,Vecteur* vec2)
{
2023-05-03 17:23:49 +02:00
#ifdef UTILISATION_MPI
// cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées
if (ParaGlob::Monde()->rank() != 0)
return ;
#endif
tempsCL.Mise_en_route_du_comptage(); // temps cpu
int tabBloqTaille =tabBloq.Taille();
int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
Tableau <Enum_ddl> tmc; // tableau de travail
// on parcours le tableau de ddl bloques
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (ref.Indic() == 1) // ok pour les noeuds uniquement
{int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// mise en place de la condition limite
{ Ddl ddl = tabBloq_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
// on continue uniquement si le ddl du tableau de blocage est en service
// et si pour le noeud c'est une variable
if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
{ // récup des enu_ddl équivalent au groupe
tmc = MemeCombinaison(cas,ddl.Id_nom());
int tailletmc = tmc.Taille();
for (int itc=1;itc <= tailletmc;itc++)
{// on boucle sur tous les ddl a imposer
// calcul du pointeur correspondant au ddl cherche
int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
// cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
if ((pt != -1) && (noe.En_service(tmc(itc))))
{// ce que l'on veut c'est une variation nulle des ddl imposee
// -> valeur imposee = 0
// cas de la matrice, et modif du second membre si la valeur imposee
// est differente de zero (ce qui n'est pas le cas ici !)
condlim(nb_casAss).Val_imposee_Mat(matglob,vecglob,pt,0.,vec2);
// cas du second membre et sauvegarde des reactions
condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2);
};
}; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
}; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
}; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
}; //-- fin de for (int nn =1; nn<= reftaille;nn++)
}; //-- fin de if (ref.Indic() == 1)
}; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
// affichage éventuelle de la matrice de raideur et du second membre
if (ParaGlob::NiveauImpression() >= 10)
{ string entete = " affichage de la matrice apres conditions limites des ddl initialement bloques ";
matglob.Affichage_ecran(entete);
entete = " affichage du second membre apres conditions limites des ddl initialement bloques ";
vecglob.Affichage_ecran(entete);
};
tempsCL.Arret_du_comptage(); // temps cpu
};
// mise en place des conditions limites sur le second membres
// nb_casAssemb : le cas d'assemblage
// cas : indique un type d'association de ddl
// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un
// a été fixé par l'utilisateur
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
// mais sans sauvegarde (correspond par exemple à une partie de vecglob)
2023-05-03 17:23:49 +02:00
void LesCondLim::ImposeConLimtdt(LesMaillages * lesMail,LesReferences* lesRef
,Vecteur& vecglob,const Nb_assemb& nb_casAssemb
,int cas,Vecteur* vec2)
{
2023-05-03 17:23:49 +02:00
#ifdef UTILISATION_MPI
// cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées
if (ParaGlob::Monde()->rank() != 0)
return ;
#endif
tempsCL.Mise_en_route_du_comptage(); // temps cpu
int tabBloqTaille =tabBloq.Taille();
int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
Tableau <Enum_ddl> tmc; // tableau de travail
// on parcours le tableau de ddl bloques
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (ref.Indic() == 1) // ok pour les noeuds uniquement
{int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// mise en place de la condition limite
{ Ddl ddl = tabBloq_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
// on continue uniquement si le ddl du tableau de blocage est en service
// et si pour le noeud c'est une variable
if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
{ // récup des enu_ddl équivalent au groupe
tmc = MemeCombinaison(cas,ddl.Id_nom());
int tailletmc = tmc.Taille();
for (int itc=1;itc <= tailletmc;itc++)
{// on boucle sur tous les ddl a imposer
// calcul du pointeur correspondant au ddl cherche
int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
// cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
if ((pt != -1) && (noe.En_service(tmc(itc))))
{// ce que l'on veut c'est une variation nulle des ddl imposee
// -> valeur imposee = 0
// cas du second membre et sauvegarde des reactions
condlim(nb_casAss).Val_imposee_Sm(vecglob,pt,0.,vec2);
};
}; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
}; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
}; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
}; //-- fin de for (int nn =1; nn<= reftaille;nn++)
}; //-- fin de if (ref.Indic() == 1)
}; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
// affichage éventuelle du second membre
if (ParaGlob::NiveauImpression() >= 10)
{ string entete = " affichage du second membre apres conditions limites des ddl initialement bloques ";
vecglob.Affichage_ecran(entete);
};
tempsCL.Arret_du_comptage(); // temps cpu
};
// mise en place des conditions limites sur deux matrices
// utilisé par exemple pour le flambement
// la première matrice est initialisée avec des 1 sur la diagonale
// la seconde avec des 0 sur la diagonale
// cas : indique un type d'association de ddl
// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un
// a été fixé par l'utilisateur
void LesCondLim::ImpConLimtdt2Mat(LesMaillages * lesMail,LesReferences* lesRef,
Mat_abstraite & matglob,Mat_abstraite & matgeom
,const Nb_assemb& nb_casAssemb,int cas)
{
2023-05-03 17:23:49 +02:00
#ifdef UTILISATION_MPI
// cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées
if (ParaGlob::Monde()->rank() != 0)
return ;
#endif
tempsCL.Mise_en_route_du_comptage(); // temps cpu
int tabBloqTaille =tabBloq.Taille();
int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
Tableau <Enum_ddl> tmc; // tableau de travail
// on parcours le tableau de ddl bloques
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (ref.Indic() == 1) // ok pour les noeuds uniquement
{int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// mise en place de la condition limite
{ Ddl ddl = tabBloq_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
// on continue uniquement si le ddl du tableau de blocage est en service
// et si pour le noeud c'est une variable
if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
{ // récup des enu_ddl équivalent au groupe
tmc = MemeCombinaison(cas,ddl.Id_nom());
int tailletmc = tmc.Taille();
for (int itc=1;itc <= tailletmc;itc++)
{// on boucle sur tous les ddl a imposer
// calcul du pointeur correspondant au ddl cherche
int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
// cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
if ((pt != -1) && (noe.En_service(tmc(itc))))
{// ici on ne fait que modifier les matrices -> un 1 sur la diagonale
// et 0 sur le reste de la ligne et colonne correspondantes
condlim(nb_casAss).Val_imposSimple_Mat(matglob,pt,1.);
condlim(nb_casAss).Val_imposSimple_Mat(matgeom,pt,0.);
};
}; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
}; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
}; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
}; //-- fin de for (int nn =1; nn<= reftaille;nn++)
}; //-- fin de if (ref.Indic() == 1)
}; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
// affichage éventuelle des deux matrices de raideur
if (ParaGlob::NiveauImpression() >= 10)
{ string entete = " affichage de la premiere matrice de raideur apres conditions limites (matglob) ";
entete += " des ddl initialement bloques";
matglob.Affichage_ecran(entete);
entete = " affichage de la seconde matrice de raideur apres conditions limites (matgeom) ";
entete += " des ddl initialement bloques";
matgeom.Affichage_ecran(entete);
};
tempsCL.Arret_du_comptage(); // temps cpu
};
// récupération des reactions initiales, avant les rotations dues aux conditions linéaires
// il s'agit des réactions dues aux ddl bloqués et dues aux conditions linéaires
// et calcul des torseurs de réaction
void LesCondLim::ReacAvantCHrepere(Vecteur& residu,LesMaillages * lesMail,
LesReferences* lesRef,const Nb_assemb& nb_casAssemb,int cas)
{
2023-05-03 17:23:49 +02:00
#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 ;
#endif
int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
Tableau <Enum_ddl> tmc; // tableau de travail
// on cree une liste de stockage intermediaire
list <ReactStoc> lili;
list <int> indice_tabBloq; // tableau de travail, qui sert pour le calcul des torseurs de réaction
ReactStoc elem; // element courant de stockage des réactions
//----------- cas des ddl bloqués -----------------
// on parcours le tableau de ddl bloques
int tabBloqTaille =tabBloq.Taille();
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (!((ref.Indic() == 4) && // le cas des conditions de tangence sur
(tabBloq_i.TypeDeCL()==TANGENTE_CL )) // les arrêtes n'est pas à prendre en compte
&& (ref.Indic() == 1)) // s'applique uniquement au cas des ref de noeuds
{int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// récupération de la condition limite
{ Ddl ddl = tabBloq_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
// on continue uniquement si le ddl du tableau de blocage est en service
// et si pour le noeud c'est une variable
if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
{ // récup des enu_ddl équivalent au groupe
tmc = MemeCombinaison(cas,ddl.Id_nom());
int tailletmc = tmc.Taille();
for (int itc=1;itc <= tailletmc;itc++)
{// on boucle sur tous les ddl a imposer
// calcul du pointeur correspondant au ddl cherche
int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
// cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
if ((pt != -1) && (noe.En_service(tmc(itc))))
{ // maintenant on peut récupérer la réaction
elem.ddl = ddl;
elem.ddl.Valeur() = residu(pt);
elem.numMail = ref.Nbmaille();
elem.numNoeud = ref.Numero(nn);
elem.casAss = nb_casAss;
lili.push_back(elem); // sauvegarde de la réaction
indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq
};
}; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
}; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
}; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
}; //-- fin de for (int nn =1; nn<= reftaille;nn++)
}; //-- fin de if (!((ref.Indic() == 4) && (tabBloq_i.TypeDeCL()==TANGENTE_CL) ) )
}; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
//----------- cas des conditions linéaires -----------------
// on cree une liste de stockage intermediaire
list <ReactStoc> lili_CLin;List_io <DeuxEntiers> indice_dans_tab_iocondiline;
// on a besoin d'enregistrer une seule fois chaque réaction, or le mode de fabrication des CLL
// fait que cela conduit à des redondances. Pour les repérer, on va utiliser un conteneur de drapeau
// de manière à limiter la taille de ce conteneur on utilise une map, c'est moins rapide en acces
// qu'un tableau, mais c'est mieux qu'une liste et c'est plus petit qu'un tableau, car a priori
// il y a moins beaucoup moins de ddl bloqué par les CLL que de ddl total du pb
map < int , bool, std::less <int> > reac_deja_stocke;
// on parcours le tableau des CLL
// on boucle sur le tableau de conditions limites linéaires enregistré
int tabTaille = tab_CLinApplique.Taille();
for (int i=1;i<= tabTaille; i++)
{int sous_taille = tab_CLinApplique(i).Taille();
for (int j=1; j<= sous_taille; j++)
{ Condilineaire& condi = tab_CLinApplique(i)(j);
// on met à jour les pointeurs d'assemblage pour bien localiser les infos dans SM et K
// ce sera refait dans l'assemblage...
condi.ConditionPourPointeursAssemblage(nb_casAssemb);
// on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
if (condi.Iddl() > -1)
{ // chaque ddl qui appartient à une CLL et qui est associé
// à un coefficient non nulle conduit à une condition limite
const Vecteur& Vectval = condi.Val();
const Tableau<int>& pt = condi.Pt_t();
const Tableau<Enum_ddl>& t_enu = condi.Tab_Enum();
const Tableau < Noeud *>& t_noeud = condi.TabNoeud();
// on boucle sur les noeuds puis sur les ddl de la CLL
int taille = pt.Taille();
int nb_noeud = t_noeud.Taille();int itab=1;
int nbddlfamille = taille / nb_noeud;
for (int i_noe=1;i_noe <= nb_noeud;i_noe++)
for (int i_fa =1; i_fa<= nbddlfamille; i_fa++,itab++)
{ // on ne stocke que si la réaction n'a pas déjà été stockée
if ((reac_deja_stocke.find(pt(itab))==reac_deja_stocke.end())
&& (Vectval(itab) != 0.) ) // et que le coef est non nul
{ // on définit la réaction
elem.ddl.Change_nom(t_enu(itab));
elem.ddl.Valeur() = residu(pt(itab));
elem.numMail = t_noeud(i_noe)->Num_Mail();
elem.numNoeud = t_noeud(i_noe)->Num_noeud();
// elem.casAss = condi.CasAssemb().n;
elem.casAss = nb_casAssemb.n;
lili_CLin.push_back(elem); // on sauvegarde la réaction
// sauvegarde de l'indice dans tab_iocondiline car le premier indice "i"
// de tab_CLinApplique est celui correspondant à la condition tab_iocondiline(i)
// le second indice permet de retrouver la ref
indice_dans_tab_iocondiline.push_back(DeuxEntiers(i,i_noe));
// on renseigne la map
reac_deja_stocke[pt(itab)] = true;
};
};
};
};
};
//----------- fin du cas des conditions linéaires -----------------
//--débug ---
//cout << "\n " << indice_dans_tab_iocondiline << endl;
//--débug---
// ----- on initialise le tableau des torseurs de réaction
int tabtorsTaille = tab_torseurReac.Taille();
for (int i=1;i<= tabtorsTaille;i++)
if (tab_torseurReac(i).existe_torseur_reac)
tab_torseurReac(i).Zero_init_torseur();
int dima = ParaGlob::Dimension();
if(ParaGlob::AxiSymetrie())
// cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
// dimension-1 coordonnées donc on décrémente
dima--;
// --- enregistrement des réactions pour ddl bloqué et calcul des torseurs
{ // on encapsule
list <ReactStoc>::iterator i; // def d'un iterator adoc
reaction.Change_taille((int)lili.size());
// map_reaction.erase(map_reaction.begin(),map_reaction.end());
int j;
list <int>::iterator i_taBloq=indice_tabBloq.begin();
for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++,i_taBloq++)
{ reaction(j) = *i;
// map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)]
// .push_back(&(reaction(j)));
// transfert des informations aux noeuds
ReactStoc& reac = reaction(j); // pour simplifier
// récup du noeud j du maillage i
Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud);
Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction
// dans le cas où la réaction n'existe pas on l'ajoute
// a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas
// ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité
{ if (!noe.Existe_ici(enu_reac))
// { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE);
{ Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE);
noe.PlusDdl(reac_ddl);
}
else
// sinon il faut le bloquer car la réaction est imposée
{ noe.Change_fixe(enu_reac,true);};
// mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
if (ttRG(*i_taBloq) != 0) // si = 0 c'est que le ddl n'est pas un déplacement classique
CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac);
};
// mise à jour de la réaction
noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt
};
// on va maintenant exporter les composantes du tenseur vers des grandeurs globales
int taille_tors_bloqu = ttRG_noms_ref.Taille();
int taille_tors_bloquplus1 = taille_tors_bloqu +1;
// cas d'un blocage de ddl
{int il = 1;
for (int ia=1;ia<taille_tors_bloquplus1;ia++,il++)
{ TorseurReac& torseur= tab_torseurReac(ia); // tableau des torseurs de réaction
// 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);
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'exportation de composantes de torseur !! "
<< " la variable globale "<< (nom_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
Sortie(1);
};
#endif
// on l'affecte:
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic);
};
// 2) le moment
for (int ic= 1; ic < dimaPlus1; ic++)
{string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'exportation de composantes de torseur !! "
<< " la variable globale "<< (nom_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
Sortie(1);
};
#endif
// on l'affecte:
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic);
};
};
};
}; // fin encapsulation
// --- enregistrement des réactions pour les CLL et calcul également des torseurs associés
// il s'agit des réactions définies précédemment (-- cas des conditions linéaires --)
{ // on encapsule
list <ReactStoc>::iterator i; // def d'un iterator adoc
List_io <DeuxEntiers>::iterator iti = indice_dans_tab_iocondiline.begin();
reaction_CLin.Change_taille((int)lili_CLin.size());
int j;
for (i=lili_CLin.begin(),j=1 ; i != lili_CLin.end(); i++,j++,iti++)
{ reaction_CLin(j) = *i;
// transfert des informations aux noeuds
ReactStoc& reac = reaction_CLin(j); // pour simplifier
// récup du noeud j du maillage i
Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud);
Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction
// dans le cas où la réaction n'existe pas on l'ajoute
// a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas
// ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité
{ if (!noe.Existe_ici(enu_reac))
// { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE);
{ Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE);
noe.PlusDdl(reac_ddl);
}
else
// sinon il faut le bloquer car la réaction est imposée
{ noe.Change_fixe(enu_reac,true);};
// mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
CalculTorseurReaction(tab_torseurReac(ttRGCLL((*iti).un)((*iti).deux)),noe,reac);
};
// mise à jour de la réaction
noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt
};
// exportation en grandeurs globales: cas d'un blocage venant d'une CLL
int taille_tors_bloqu = ttRG_noms_ref.Taille();
int taille_tors_bloquplus1 = taille_tors_bloqu +1;
int taille_torsP1 = tab_torseurReac.Taille() + 1;
{int il = 1; //ttRGCLL_noms_ref.begin();
for (int ia=taille_tors_bloquplus1;ia<taille_torsP1;ia++,il++)
{ TorseurReac& torseur= tab_torseurReac(ia); // tableau des torseurs de réaction
// 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);
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'exportation de composantes de torseur !! "
<< " la variable globale "<< (nom_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
Sortie(1);
};
#endif
// on l'affecte:
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic);
};
// 2) le moment
for (int ic= 1; ic < dimaPlus1; ic++)
{string nom_ref="tors_"+ttRGCLL_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'exportation de composantes de torseur !! "
<< " la variable globale "<< (nom_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
Sortie(1);
};
#endif
// on l'affecte:
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic);
};
};
};
}; // fin encapsulation
};
// calcul des reactions et stockage des valeurs
// ceci dans le cas ou il n'y a pas de conditions lineaires appliquee
// on se sert des valeurs sauvegardees lors de la mise en place des CL bloquees
// cas : indique un type d'association de ddl
// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un
// a été fixé par l'utilisateur
void LesCondLim::CalculReaction(LesMaillages * lesMail,LesReferences* lesRef
,const Nb_assemb& nb_casAssemb,int cas)
{
2023-05-03 17:23:49 +02:00
#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 ;
#endif
int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
Tableau <Enum_ddl> tmc; // tableau de travail
// on cree une liste de stockage intermediaire
list <ReactStoc> lili;
list <int> indice_tabBloq; // tableau de travail
ReactStoc elem; // l'element courant
// on parcours le tableau de ddl bloques
int tabBloqTaille =tabBloq.Taille();
for (int i=1;i<= tabBloqTaille;i++)
{ DdlLim& tabBloq_i = tabBloq(i);
// recup de la reference correspondant au mot cle
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabBloq_i.NomRef(),tabBloq_i.NomMaillage()));
if (ref.Indic() == 1) // ok pour les noeuds uniquement
{int reftaille = ref.Taille();
for (int nn =1; nn<= reftaille;nn++)
{int tabBloqitaille = tabBloq_i.Taille();
// dans le cas d'un champ, pour chaque ddl on a un noeud associé, il ne faut donc pas itérer
// sur les noeuds, pour cela on modifie les borne de la boucle pour ne faire qu'un seul bon passage
int idebut=1; int ifinfin = tabBloqitaille;// début normale
if (tabBloq_i.Champ()) {idebut = nn; ifinfin = nn;};
for (int nd=idebut;nd<= ifinfin ;nd++)
// calcul de la reaction
{ Ddl ddl = tabBloq_i.ElemLim(nd);
Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
// cas de deplacements imposes en coordonnees entrainees on change les Ui en Xi
// if (noe.Existe_ici(X1) && (strchr(ddl.Nom(),'U') != NULL))
if (noe.Existe_ici(X1) && (PremierDdlFamille(ddl.Id_nom())==UX))
ddl.Change_nom(UxyzXi(ddl.Id_nom()));
// on continue uniquement si le ddl du tableau de blocage est en service
// et si pour le noeud c'est une variable
if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
{ // récup des enu_ddl équivalent au groupe
tmc = MemeCombinaison(cas,ddl.Id_nom());
int tailletmc = tmc.Taille();
for (int itc=1;itc <= tailletmc;itc++)
{// on boucle sur tous les ddl a imposer
// calcul du pointeur correspondant au ddl cherche
int pt = noe.Pointeur_assemblage(tmc(itc),nb_casAss);
// cas ou le ddl fait partie du cas d'assemblage et qu'il est actif
if ((pt != -1) && (noe.En_service(tmc(itc))))
{ elem.ddl = ddl;
elem.ddl.Valeur() = condlim(nb_casAss).ValReact(pt);
elem.numMail = ref.Nbmaille();
elem.numNoeud = ref.Numero(nn);
elem.casAss = nb_casAss;
lili.push_back(elem);
indice_tabBloq.push_back(i); // sauvegarde de l'indice dans tabBloq
};
}; //-- fin de for (int itc=1;itc <= tailletmc;itc++)
}; //-- fin de if ((ddl.Service()) && (noe.UneVariable(ddl.Id_nom())))
}; //-- fin de for (int nd=idebut;nd<= ifinfin ;nd++)
}; //-- fin de for (int nn =1; nn<= reftaille;nn++)
}; //-- fin de if (ref.Indic() == 1)
}; //-- fin de for (int i=1;i<= tabBloqTaille;i++)
// on initialise le tableau des torseurs de réaction
int tabtorsTaille = tab_torseurReac.Taille();
for (int i=1;i<= tabtorsTaille;i++)
if (tab_torseurReac(i).existe_torseur_reac)
tab_torseurReac(i).Zero_init_torseur();
// enregistrement
list <ReactStoc>::iterator i,ilfin = lili.end(); // def d'un iterator adoc
reaction.Change_taille((int)lili.size());
// map_reaction.erase(map_reaction.begin(),map_reaction.end());
int j;
list <int>::iterator i_taBloq=indice_tabBloq.begin();
for (i=lili.begin(),j=1 ; i != ilfin; i++,j++,i_taBloq++)
{reaction(j) = *i;
// map_reaction["mail"+ChangeEntierSTring((*i).numMail)+"noeud"+ChangeEntierSTring((*i).numNoeud)]
// .push_back(&(reaction(j)));
// transfert des informations aux noeuds
ReactStoc& reac = reaction(j); // pour simplifier
// récup du noeud j du maillage i
Noeud& noe = lesMail->Noeud_LesMaille(reac.numMail,reac.numNoeud);
Enum_ddl enu_reac = Vers_enum_reac(reac.ddl.Id_nom()); // le ddl de réaction
// dans le cas où la réaction n'existe pas on l'ajoute
// a priori on traite à chaque fois car c'est l'algorithme globale qui détermine si un ddl est actif ou pas
// ainsi, pour ne pas ajouter des réactions pour des ddl HS, c'est ici que l'on peut réellement voir l'activité
{ if (!noe.Existe_ici(enu_reac))
// { Ddl reac_ddl(enu_reac,0.0,HS_LISIBLE_FIXE);
{ Ddl reac_ddl(enu_reac,0.0,LISIBLE_FIXE);
noe.PlusDdl(reac_ddl);
}
else
// sinon il faut le bloquer car la réaction est imposée
{ noe.Change_fixe(enu_reac,true);};
// mise à jour et calcul éventuel du torseur de réaction: uniquement pour les ddl X1, X2, X3
CalculTorseurReaction(tab_torseurReac(ttRG(*i_taBloq)),noe,reac);
};
// mise à jour de la réaction
noe.Change_val_tdt(enu_reac,reac.ddl.Valeur()); // t=tdt
};
// on va maintenant exporter les composantes du tenseur vers des grandeurs globales
int taille_tors_bloqu = ttRG_noms_ref.Taille();
int taille_tors_bloquplus1 = taille_tors_bloqu +1;
int dima = ParaGlob::Dimension();
if(ParaGlob::AxiSymetrie())
// cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
// dimension-1 coordonnées donc on décrémente
dima--;
// cas d'un blocage de ddl
{int il = 1;
for (int ia=1;ia<taille_tors_bloquplus1;ia++,il++)
{TorseurReac& torseur= tab_torseurReac(ia); // tableau des torseurs de réaction
// 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);
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'exportation de composantes de torseur !! "
<< " la variable globale "<< (nom_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
Sortie(1);
};
#endif
// on l'affecte:
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.resultante(ic);
};
// 2) le moment
for (int ic= 1; ic < dimaPlus1; ic++)
{string nom_ref="tors_"+ttRG_noms_ref(il)+"_Mo_"+ChangeEntierSTring(ic);
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(nom_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'exportation de composantes de torseur !! "
<< " la variable globale "<< (nom_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesCondLim::ReacAvantCHrepere(..."<<flush;
Sortie(1);
};
#endif
// on l'affecte:
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
Grandeur_Ddl_etendu& tyTQ= *((Grandeur_Ddl_etendu*) (gr_quelc->Grandeur_pointee())); // pour simplifier
tyTQ.ConteneurDdl_etendu()->Valeur() = torseur.moment(ic);
};
};
};
};
// récupération des reactions= residu et stockage des valeurs
// NB: après changement de repère, il n'y a plus que des ddl bloqués
// cas : indique un type d'association de ddl
// = 0 -> pas d'association, seules les ddl fournis par l'utilisateur sont considéré
// = 1 -> association de Xi Vi Gammai, qui sont pris en compte dès lors que l'un
// a été fixé par l'utilisateur
void LesCondLim::ReacApresCHrepere(Vecteur& residu,LesMaillages * lesMail,
LesReferences* ,const Nb_assemb& nb_casAssemb,int )
{
2023-05-03 17:23:49 +02:00
#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 ;
#endif
int nb_casAss = nb_casAssemb.n; // recup du numéro du cas d'assemblage
Tableau <Enum_ddl> tmc; // tableau de travail
// on cree une liste de stockage intermediaire
list <ReactStoc> lili;
list <int> indice_tabBloq; // tableau de travail
ReactStoc elem; // l'element courant
//----------- cas des ddl bloqués -----------------
// l'indice des ddl bloqués reste inchangé après chgt de repère on utilise donc les
// réactions avant rotation par simplicité
// a priori ce sont exactement les mêmes conditions qui existent avant et après chgt de repère
// sauf la valeur de la réaction
int nb_reac = reaction.Taille();
for (int i=1; i<= nb_reac; i++)
if (reaction(i).casAss == nb_casAss) // si ce n'est pas le bon cas d'assemblage on ne fait rien
{ elem = reaction(i);
Noeud & noe=lesMail->Noeud_LesMaille(elem.numMail,elem.numNoeud);
elem.ddl.Valeur() = residu(noe.Position_ddl(elem.ddl.Id_nom(),nb_casAss) );
lili.push_back(elem);
};
// ------- cas des CLL --------------
// contrairement aux cas des ddl boqués ici on ne peut pas utiliser reaction_CLin
// car il y a une seule réaction dans le nouveau repère alors qu'il y en avait autant que de ddl
// dans la CLL, dans le repère initial, donc on reparcours le tableau des CLL
// on parcours le tableau des CLL
// on boucle sur le tableau de conditions limites linéaires enregistré
// et pour chaque element on impose une condition lineaire
int tabTaille = tab_CLinApplique.Taille();
for (int i=1;i<= tabTaille; i++)
{int sous_taille = tab_CLinApplique(i).Taille();
for (int j=1; j<= sous_taille; j++)
{ Condilineaire& condi = tab_CLinApplique(i)(j);
// on n'intervient que si la condition est exploitable c-a-d Iddl() > -1
if (condi.Iddl() > -1)
{ if (condi.CasAssemb() == nb_casAssemb)
{ // la condition limite concerne uniquement un ddl pour chaque CLL
// il s'agit du premier ddl, pour le premier noeud
// on définit la réaction
elem.ddl.Change_nom(condi.Tab_Enum()(1));
elem.ddl.Valeur() = residu(condi.Pt_t()(1));
elem.numMail = condi.TabNoeud()(1)->Num_Mail();
elem.numNoeud = condi.TabNoeud()(1)->Num_noeud();
elem.casAss = condi.CasAssemb().n;
lili.push_back(elem); // on sauvegarde la réaction
};
};
};
};
// enregistrement
list <ReactStoc>::iterator i; // def d'un iterator adoc
reactionApresCHrepere.Change_taille((int)lili.size());
int j;
for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++)
{reactionApresCHrepere(j) = *i;};
};
// affichage sur la sortie sort des reactions
void LesCondLim::Affiche_reaction(ofstream& sort,const LesMaillages * lesMail) const
2023-05-03 17:23:49 +02:00
{
#ifdef UTILISATION_MPI
// cas d'un calcul //, seule le CPU 0 est concerné
if (ParaGlob::Monde()->rank() != 0)
return ;
#endif
// l'entete
sort << "\n==========================================================================";
sort << "\n sortie des efforts generes par l\'exterieur sur les noeuds ";
sort << "\n==========================================================================\n";
sort << "\n\n 1) les reactions individuelles \n ";
// on balaie le tableau de reaction et on constitue une liste intermédiaire, pour éviter
// de sortir des doublons
int reactionTaille = reaction.Taille();
List_io <ReactStoc> li_inter;
// Tableau <ReactStoc> reaction; // les reactions pour les ddl bloqués
for (int i= 1; i<= reactionTaille;i++)
li_inter.push_back(reaction(i));
li_inter.sort(); // on organise la liste
li_inter.unique(); // on supprime les doublons
// *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non
// le contraire
List_io <ReactStoc>::iterator il,ilfin=li_inter.end();
for (il= li_inter.begin(); il != ilfin;il++)
{ sort << "\ncas assemb " << (*il).casAss
<< " maillage " << (*il).numMail <<", noeud " <<(*il).numNoeud
<< ", ddl = " << (*il).ddl.Nom() << ", valeur = " << (-(*il).ddl.Valeur()) ;
};
// on s'occupe maintenant des torseurs de réactions globales si éventuellement il en existe
sort << "\n\n\n==========================================================================";
sort << "\n 2) les torseurs globaux ";
sort << "\n==========================================================================\n";
// au niveau des références, il est possible d'avoir une référence qui sert pour plusieurs conditions limites
// aussi on va globaliser les torseurs de réaction en sortie
int dima = ParaGlob::Dimension();
if(ParaGlob::AxiSymetrie())
// cas d'élément axisymétrique, dans ce cas on ne prend en compte que les
// dimension-1 coordonnées donc on décrémente
dima--;
int ttail = tab_torseurReac.Taille();
for (int i=1;i<= ttail;i++)
{ TorseurReac& torseurReac = tab_torseurReac(i); // pour simplifier
if (torseurReac.existe_torseur_reac)
{// tout d'abord l'affichage de l'entête
if (torseurReac.bloque_ou_CLL)
// cas où le torseur provient d'une condition ddl bloquée
{DdlLim& tabBloq_i = tabBloq(*(ttorBloq(i).begin())); // pour simplifier (on ne prend que le
// premier des bloqués), tous les autres ont le même nom de maillage et de ref
sort << "\n";
if (tabBloq_i.NomMaillage() != NULL)
sort << " nom_maillage " << *(tabBloq_i.NomMaillage());
sort << " nom_ref " << tabBloq_i.NomRef()
<< "\n F= ";
}
else
// cas où le torseur provient d'une condition CLL
{I_O_Condilineaire& iocondiline_i = tab_iocondiline((*(ttorCLL(i).begin())).un); // pour simplifier
sort << "\n";
if (iocondiline_i.NomMaillage() != NULL)
// cas où on considère les noms de maillage
{ int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier
if (num_ref == 1)
{// cas d'une référence principale de CLL
const string& nom_maillage = *(iocondiline_i.NomMaillage());
sort << " nom_maillage " << nom_maillage
<< " nom_ref " << iocondiline_i.NomRef() << "_CLL ";
}
else
{// cas d'une référence associé
// on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris
// la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1
// qui correspond à la référence principale
//debug
//cout << "\n (*(ttorCLL(i).begin())).deux= " << (*(ttorCLL(i).begin())).deux << endl ;
//fin debug
const string& nom_maillage = iocondiline_i.NomMaillageAssociees()((*(ttorCLL(i).begin())).deux - 1);
sort << " nom_maillage " << nom_maillage
<< " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)
<< "_CLL ";
}
}
else
{// cas où on ne considère pas les noms de maillage
int num_ref = (*(ttorCLL(i).begin())).deux; // pour simplifier
if (num_ref == 1)
// cas d'une référence principale de CLL
{ sort << " nom_ref " << iocondiline_i.NomRef() << "_CLL "; }
else
// cas d'une référence associé
// on fait (*(ttorCLL(i).begin())).deux - 1) car ttorCLL contient l'ensemble des refs, y compris
// la ref principale, et ReferenceAssociees() ne ramène que les ref associés, donc il faut retirer 1
// qui correspond à la référence principale
{ sort << " nom_ref " << iocondiline_i.ReferenceAssociees()((*(ttorCLL(i).begin())).deux - 1)
<< "_CLL ";
};
};
sort << "\n F= ";
};
// et maintenant l'affichage des infos
torseurReac.resultante.Affiche(sort,ParaGlob::NbdigdoCA());
switch (dima)
{case 1: break; // pas de moment en dimension 1
case 2: sort << "\n M=" << setprecision(ParaGlob::NbdigdoCA())
<< torseurReac.moment(1); // la première composante est le moment
break;
case 3: sort << "\n M=";
torseurReac.moment.Affiche(sort,ParaGlob::NbdigdoCA());
break;
};
};
};
// sortie des réactions dues aux conditions linéaires
sort << "\n\n\n==========================================================================";
sort << "\n 3) les reactions dues aux conditions lineaires ";
sort << "\n==========================================================================\n";
// on balaie le tableau de reaction_CLin
// *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non le contraire
// non, j'ai l'impression qu'il ne faut pas ici changer de signe ??? à voir par la suite en fonction des résultats
// si finalement ??
int reaction_CLinTaille = reaction_CLin.Taille();
for (int i= 1; i<= reaction_CLinTaille;i++)
{ sort << "\ncas assemb " << reaction_CLin(i).casAss
<< " maillage " << reaction_CLin(i).numMail <<", noeud " <<reaction_CLin(i).numNoeud
<< ", ddl = " << reaction_CLin(i).ddl.Nom() << ", valeur = " << (-reaction_CLin(i).ddl.Valeur()) ;
// << ", ddl = " << reaction_CLin(i).ddl.Nom() << ", valeur = " << (reaction_CLin(i).ddl.Valeur()) ;
};
// l'entete
sort << "\n==========================================================================";
sort << "\n 4) sortie sous forme de force des efforts de l\'exterieur sur les noeuds ";
sort << "\n==========================================================================";
sort << "\n les reactions sont ordonnees et sous forme de vecteurs avec 3 composantes \n ";
// on balaie le tableau de reaction
// *** on change de signe à la réaction car on veut l'extérieur sur les noeuds et non
// le contraire nb_maillage
{Tableau <list <DeuxEntiers > > tab_indi(nb_maillage); // un tableau de travail
for (int i= 1; i<= reactionTaille;i++) // on remplit le tableau d'adressage indirecte
tab_indi(reaction(i).numMail).push_back(DeuxEntiers(i,reaction(i).numNoeud));
// on trie et on ordonne
for (int i=1;i<=nb_maillage;i++)
{ list <DeuxEntiers >& indica = (tab_indi(i)); // pour simplifier
indica.sort(); // ordonne en fonction du numéro de noeud
list <DeuxEntiers >::iterator ili,ilifin=indica.end();
// --- tout d'abord on sort une ref sur la liste des noeuds en réaction au cas ou
sort << "\n # pour information la ref des noeuds concernes\n ";
sort << "\n # nom_mail= "<<lesMail->NomMaillage(i)
<<"\n# N_list_noe_en_react ";
int compteur=0; int total_force=0;
for (ili=indica.begin();ili != ilifin;ili++)
// là on suit la progression des numéros de noeuds
{ ReactStoc& rea = reaction((*ili).un);
int num_noeud = (*ili).deux; // le noeud considéré
bool sortie_valide=false; // la sortie est validée ou non
while (num_noeud == (*ili).deux)
{switch (rea.ddl.Id_nom()) // on regarde les ddl
{ case X1 : sortie_valide=true;break;
case X2 : sortie_valide=true;break;
case X3 : sortie_valide=true;break;
default: break;
};
ili++;
};
// arrivée ici il y a une incrémentation de trop, on revient en arrière
ili--;
if (sortie_valide)
{ total_force++;
sort << num_noeud << " ";compteur++;
if (compteur > 20) {sort << "\n"; compteur=0;};
};
};
// --- maintenant on sort les forces
sort << "\n\n # --- les (" <<total_force<<") forces \n";
for (ili=indica.begin();ili != ilifin;ili++)
// là on suit la progression des numéros de noeuds
{
ReactStoc& rea = reaction((*ili).un);
int num_noeud = (*ili).deux; // le noeud considéré
Coordonnee3 force; // la force initialisée à 0.
bool sortie_valide=false; // la sortie est validée ou non
while (num_noeud == (*ili).deux)
{switch (rea.ddl.Id_nom()) // on regarde les ddl
{ case X1 : force(1)=rea.ddl.Valeur();sortie_valide=true;break;
case X2 : force(2)=rea.ddl.Valeur();sortie_valide=true;break;
case X3 : force(3)=rea.ddl.Valeur();sortie_valide=true;break;
default: break;
};
ili++;
if (ili != ilifin)
rea = reaction((*ili).un);
};
// arrivée ici il y a une incrémentation de trop, on revient en arrière
ili--;
if (sortie_valide)
{ sort << num_noeud << " " ;
force.Affiche(sort,ParaGlob::NbdigdoCA());
sort <<"\n";
};
};
};
};
};
// mise en place de condition externes lineaires
// expression de la raideur et du second membre dans un nouveau repere
// ramène si oui ou non, il y a eu un changement effectué
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
// mais sans sauvegarde (correspond par exemple à une partie de vecglob)
bool LesCondLim::CoLinCHrepere_ext(Mat_abstraite & matglob,Vecteur& vecglob
,const Tableau <Condilineaire>& tab,const Nb_assemb& nb_casAssemb,Vecteur* vec2)
{
2023-05-03 17:23:49 +02:00
#ifdef UTILISATION_MPI
// cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées
if (ParaGlob::Monde()->rank() != 0)
return false ;
#endif
tempsCLL.Mise_en_route_du_comptage(); // temps cpu
// on boucle sur le tableau et pour chaque element on impose une condition lineaire
int tabTaille = tab.Taille();
bool modification = false; // init du retour
for (int i=1;i<= tabTaille; i++)
{Condilineaire& condi = tab(i);
// calcul des pointeurs d'assemblage
condi.ConditionPourPointeursAssemblage(nb_casAssemb);
// application de la condition
condlim(nb_casAssemb.n).CondlineaireCHRepere
( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2);
modification=true;
};
// affichage éventuelle de la matrice de raideur et du second membre
if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0))
{ string entete = " affichage de la matrice apres changement de repere du aux conditions limites externes (ex contact)";
matglob.Affichage_ecran(entete);
entete = " affichage du second membre apres changement de repere du aux conditions limites externes (ex contact) ";
vecglob.Affichage_ecran(entete);
};
tempsCLL.Arret_du_comptage(); // temps cpu
// retour du fait qu'il y a eu ou non une modification faite
return modification;
};
// mise en place de condition externe lineaires en une opération
// retour de la raideur et du second membre sans changement de repere
// ramène si oui ou non, il y a eu un changement effectué
// vec2 : est un second vecteur éventuel (si != NULL) sur lequel on impose les mêmes CL que vecglob
// mais sans sauvegarde (correspond par exemple à une partie de vecglob)
bool LesCondLim::CoLinUneOpe_ext(Mat_abstraite & matglob,Vecteur& vecglob
,const Tableau <Condilineaire>& tab
,const Nb_assemb& nb_casAssemb,Vecteur* vec2)
{
2023-05-03 17:23:49 +02:00
#ifdef UTILISATION_MPI
// cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées
if (ParaGlob::Monde()->rank() != 0)
return false;
#endif
tempsCLL.Mise_en_route_du_comptage(); // temps cpu
// on boucle sur le tableau et pour chaque element on impose une condition lineaire
int tabTaille = tab.Taille();
bool modification = false; // init du retour
for (int i=1;i<= tabTaille; i++)
{Condilineaire& condi = tab(i);
// calcul des pointeurs d'assemblage
condi.ConditionPourPointeursAssemblage(nb_casAssemb);
// application d'une condition linéaire seule, avec en retour, la situation de la condition linéaire
// imposée, ramené dans le repère initial
condlim(nb_casAssemb.n).CondiLineaireImposeComplet
( matglob,vecglob,tab(i).Pt_t(),tab(i).Val(),tab(i).Beta(),vec2);
modification=true;
};
// affichage éventuelle de la matrice de raideur et du second membre
if ((ParaGlob::NiveauImpression() >= 10) && (tabTaille != 0))
{ string entete = " affichage de la matrice apres application CLL externes (ex contact) ";
matglob.Affichage_ecran(entete);
entete = " affichage du second membre apres apres application CLL externes (ex contact) ";
vecglob.Affichage_ecran(entete);
};
tempsCLL.Arret_du_comptage(); // temps cpu
// retour du fait qu'il y a eu ou non une modification faite
return modification;
};
//initialisation, mise a zero des sauvegarde
void LesCondLim::InitSauve(const Nb_assemb& nb_casAssemb)
{ condlim(nb_casAssemb.n).EffaceSauvegarde(); // blocages : second membre et matrice,
condlim(nb_casAssemb.n).EffaceCoLin(); // conditions lineaires
// puis les torseurs de réactions
int taille = tab_torseurReac.Taille();
for (int i=1; i<= taille; i++)
if (tab_torseurReac(i).existe_torseur_reac)
tab_torseurReac(i).Zero_init_torseur();
};
//----- lecture écriture dans base info -----
// le cas d'assemblage n'est pas sauvegardé, car ce n'est pas une variable
// qui appartient réellement à la classe
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void LesCondLim::Lecture_base_info(ifstream& ent,const int cas,LesReferences& ,LesCourbes1D&
,LesFonctions_nD& lesFonctionsnD)
{ // les conditions linéaires qui varies par exemples dues au contact sont stockées
// autre part, dans LesContacts par exemple
string toto;
switch (cas)
{ case 1:
{ cout << "== lecture des conditions limites \n";
// lecture du type et vérification
string nomtype;
ent >> nomtype;
if (nomtype != "****LesCondLim")
Sortie(1);
// lecture des différents tableaux
ent >> toto >> tabBloq >> toto >> tabInit
>> toto >> tab_iocondiline >> toto >> reaction >> toto >> reaction_CLin;
// dimensionnement du tableau des torseurs résultants
LesCondLim::DimensionneTorseurs();
break;
}
case 2:
{// on lit les grandeurs relatives aux réactions
ent >> toto;
reaction.Entree(ent);
ent >> toto;
reaction_CLin.Entree(ent);
// lectue des temps cpu de l'algo:
ent >> toto >> tempsCL;
ent >> toto >> tempsCLL;
break;
}
default:
{ cout << "\n **** erreur !! cas non prevu: cas = " << cas
<< "\n LesCondLim::Lecture_base_info(...";
Sortie(1);
}
};
// on met à jour le tableau map_reaction
// map_reaction.erase(map_reaction.begin(),map_reaction.end());
// int tail_reaction=reaction.Taille();
// for (int j=1; j<=tail_reaction; j++)
// { map_reaction["mail"+ChangeEntierSTring(reaction(j).numMail)
// +"noeud"+ChangeEntierSTring(reaction(j).numNoeud)].push_back(&(reaction(j)));
// };
};
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LesCondLim::Ecriture_base_info(ofstream& sort,const int cas)
{ // les conditions linéaires qui varies par exemples dues au contact sont stockées
// autre part, dans LesContacts par exemple
switch (cas)
{ case 1:
{// écriture du type
sort << "\n ****LesCondLim \n";
// écriture des différents tableaux
sort << " blocage " << tabBloq;
sort << " initialisation " << tabInit;
sort << " CLL_en_entree " << tab_iocondiline;
sort << " reactions " << reaction;
sort << " reac_CLineaire " << reaction_CLin << " ";
break;
}
case 2:
{// on sort les grandeurs relatives aux réactions
// en fait les réactions sont également sauvé aux noeuds mais peut-être que ce sera utile
// d'avoir ici le type réaction stocké ?? donc on laisse
sort << " reac_ddl_bloque ";
reaction.Sortir(sort);
sort << " reac_CLineaire ";
reaction_CLin.Sortir(sort); sort << " ";
// écriture des temps cpu de l'algo:
sort << "\n tps_cpu_CL " << tempsCL;
sort << "\n tps_cpu_CLL " << tempsCLL;
break;
}
default:
{ cout << "\n **** erreur !! cas non prevu: cas = " << cas
<< "\n LesCondLim::Ecriture_base_info(...";
Sortie(1);
}
};
};