Herezh_dev/herezh_pp/Maillage/LesMaillages2.cc

2938 lines
149 KiB
C++
Executable file

// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "LesMaillages.h"
#include "ElemMeca.h"
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "MathUtil.h"
#include "ConstMath.h"
#include "CharUtil.h"
#include "TypeQuelconqueParticulier.h"
#ifndef SYSTEM_MAC_OS_X_unix
#include "Frontier.h"
#endif
// --------- calcul dynamique ---------
// ajout des ddl de vitesse pour tous les maillages
// pour tous les noeuds qui ont un ddl de déplacement
// val_fixe indique si l'on veut des ddl libres ou pas
void LesMaillages::Plus_Les_ddl_Vitesse(Enum_boolddl val_fixe)
{ // recup de la dimension
int dimen = ParaGlob::Dimension();
// recup de la position de VI-1
int posi = Id_nom_ddl("V1") -1;
// création du tableau de ddl de travail
Tableau <Ddl> ta(dimen);
for (int ii=1; ii<= dimen; ii++)
{//ta(ii) = Enum_ddl(ii+posi); // ERREUR D'AFFECTATION, À VOIRE EN DEBUG OU IL VA
ta(ii) = Ddl (Enum_ddl(ii+posi),0.,val_fixe); // bonne version
};
// dans le cas où le calcul est axisymétrique
// le dernier ddl en z est mis en HSLIBRE, car on ne le prend pas en compte dans le calcul
// axisymétrique
if (ParaGlob::AxiSymetrie())
ta(3) = Ddl (Enum_ddl(3+posi),0.,HSLIBRE); // bonne version;
// maintenant on passe en revu les noeuds
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
// on regarde si le déplacement existe
if (noo->Existe_ici(X1))
noo->PlusTabDdl(ta);
}
};
};
// ajout des ddl d'accélération pour tous les maillages
// pour tous les noeuds qui ont un ddl de déplacement
// val_fixe indique si l'on veut des ddl libres ou pas
void LesMaillages::Plus_Les_ddl_Acceleration(Enum_boolddl val_fixe)
{ // recup de la dimension
int dimen = ParaGlob::Dimension();
// recup de la position de GAMMA1-1
int posi = Id_nom_ddl("GAMMA1") -1;
// création du tableau de ddl de travail
Tableau <Ddl> ta(dimen);
for (int ii=1; ii<= dimen; ii++)
ta(ii) = Ddl (Enum_ddl(ii+posi),0.,val_fixe); // bonne version
// dans le cas où le calcul est axisymétrique
// le dernier ddl en z est mis en HSLIBRE, car on ne le prend pas en compte dans le calcul
// axisymétrique
if (ParaGlob::AxiSymetrie())
ta(3) = Ddl (Enum_ddl(3+posi),0.,HSLIBRE); // bonne version;
// maintenant on passe en revu les noeuds
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
// on regarde si le déplacement existe
if (noo->Existe_ici(X1))
noo->PlusTabDdl(ta);
}
}
};
// calcul de la longueur d'arrête d'élément minimal
// divisé par la célérité dans le matériau
double LesMaillages::Longueur_arrete_mini_sur_c(Enum_dure temps)
{ double dist_ret = ConstMath::tresgrand; // def de la distance de retour
// on balaie les maillages et les éléments
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbelementmax = tabMaillage(i1)->Nombre_element();
for (int i2 = 1; i2 <= nbelementmax; i2++)
{ Element & elem = Element_LesMaille(i1,i2);
if (elem.Id_TypeProblem() == MECA_SOLIDE_DEFORMABLE)
{ double dist = ((ElemMeca&) elem).Long_arrete_mini_sur_c(temps);
dist_ret = MiN(dist_ret,dist);
}
}
}
return dist_ret;
};
// initialisation éventuelle du bulk viscosity
void LesMaillages::Init_bulk_viscosity(int choix,const DeuxDoubles & coef)
{ // on renseigne la classe générique d'éléments mécanique si besoin
// choix peut-être égale à 0, 1 ou 2
if (choix)
{ ElemMeca::ActiveBulkViscosity(choix); // activation du bulk viscosity
ElemMeca::ChangeCoefsBulkViscosity(coef); // passage des coeffs
}
};
// -- encore plus générique
// changement de toutes les conditions données (service, variable, fixage ..)
// selon le tableau de ddl passé en paramètre
// par contre les valeurs de ta ne sont pas utilisé donc les valeurs actuelles restent inchangé
void LesMaillages::ChangeToutesLesConditions(const Tableau<Ddl>& ta)
{ // création d'une liste qui contiendra tous les ddl à passer aux noeuds
list <Ddl> liddl;
// on boucle sur le tableau
int taTaille = ta.Taille();
for (int ita=1;ita<=taTaille;ita++)
{ Ddl& taa=ta(ita);Enum_boolddl enub=taa.Retour_Fixe();
Tableau<Enum_ddl> tenu = TableauTypeDdl(taa.Id_nom()); // récup du tableau d'enum
int tenuTaille = tenu.Taille();
for (int i=1;i<=tenuTaille;i++) liddl.push_back(Ddl(tenu(i),0.,enub));
};
// création du tableau de travail que l'on passera aux noeuds
Tableau<Ddl> tddl(liddl.size());
list<Ddl>::iterator il,ifin=liddl.end();int iii=1;
for (il=liddl.begin();il!=ifin;il++,iii++) tddl(iii)=(*il);
// maintenant on passe en revue les noeuds
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
noo->ChangeToutesLesConditions(tddl);
}
}
};
// changement de statu des ddl d'une combinaison, en fonction du statut
// de enuta dans chaque noeud, les ddl de la combinaison, prennent le même statut que celui
// de enuta dans chaque noeud.
// cas est la combinaison,
void LesMaillages::ChangeStatut(int cas,Enum_ddl enuta)
{// on passe en revue les noeuds
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
noo->ChangeStatut(cas,enuta);
}
}
};
// changement de statu des ddl d'une combinaison dans chaque noeud, en fonction
// de enubold, les ddl de la combinaison, prennent le même statut que enubold
// cas est la combinaison,
void LesMaillages::ChangeStatut(int cas,Enum_boolddl enubold)
{// on passe en revue les noeuds
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
noo->ChangeStatut(cas,enubold);
}
}
};
//change le statut de tous les ddl liés à la physique en cours
//par exemple: met à libre ou bloque les ddl liés à la physique en cours
void LesMaillages::Libere_Ddl_representatifs_des_physiques(Enum_boolddl enubold)
{ // ddl_representatifs_des_physiques représentent tous les ddl de la physique
if (ddl_representatifs_des_physiques.size()) // on ne continue que si c'est diff de 0
{list <Enum_ddl >::iterator il,ilfin= ddl_representatifs_des_physiques.end();
list <Enum_ddl >::iterator ildebut = ddl_representatifs_des_physiques.begin();
// on fait un premier balayage, car il s'agit des "types" de ddl mais pas de la liste
// qui elle dépend de la dimension éventuellement
int nbddl = 0; // init
for (il = ildebut;il != ilfin; il++)
nbddl += TableauTypeDdl(*il).Taille();
// on définit un tableau "ta" pour appeler les noeuds
// qui contient tous les ddl (et pas seulement les types)
Ddl enu((*ildebut),0.0,enubold); // def du premier ddl
Tableau<Ddl> ta(nbddl,enu); int ita=1;
for (il = ildebut;il != ilfin; il++)
{Tableau<Enum_ddl> tddl = TableauTypeDdl(*il);
int ndPlus1 = tddl.Taille() + 1;
for (int i=1;i< ndPlus1;i++,ita++)
ta(ita).Change_nom(tddl(i));
};
// on passe en revue les noeuds
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
// on change les conditions données par ta
noo->ChangeToutesLesConditions(ta);
};
};
};
};
//----- lecture écriture base info -----
// lecture base info
// 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 LesMaillages::Lecture_base_info(ifstream& ent,const int cas)
{ string toto;
// cout << "\n debug **** LesMaillages::Lecture_base_info\n"
// << "\n entr.rdstate() " << ent.rdstate() << flush;
// lecture du nombre de maillage total
ent >> toto >> nbMaillageTotal;
// cout << "\n debug **** LesMaillages::Lecture_base_info\n"
// << " toto= "<< toto << nbMaillageTotal
// << "\n entr.rdstate() " << ent.rdstate() << flush;
switch (cas)
{ case 1 : // ------- on récupère tout -------------------------
{for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ // tout d'abord création du maillage
tabMaillage(i1) = new Maillage (mapNomMail,i1,paraGlob->Dimension());
// puis lecture
tabMaillage(i1)->Lecture_base_info(ent,cas);
};
// on s'occupe de mettre à jour les types de pb et les ddl types associés
Mise_a_jour_type_pb_type_associe_ddl();
break;
}
case 2 : // ----------- on ne récupère que ce qui varie
{ for (int i1 = 1; i1<= nbMaillageTotal; i1++)
tabMaillage(i1)->Lecture_base_info(ent,cas);
// ----- cas des grandeurs intégrés éventuelles-----
// utile pour pouvoir post-traiter et également pour le cumul sur le temps
ent >> toto;
if (toto != "int_vol_mail")
{ cout << "\nErreur : en lecture de l'entete de l'integration de volume eventuelle"
<< " on attendait le mot cle int_vol_mail et on a lu "<< toto <<" !\n";
cout << "LesMaillages::Lecture_base_info(....)" << flush;
Sortie(1);
};
int integ_vol_typeQuel_taille = 0;
ent >> integ_vol_typeQuel_taille;
// on boucle sur les grandeurs à lire
// si la grandeur existe déjà, elle est mise à jour, sinon elle est crée
// mais dans ce cas elle ne changera plus pendant le calcul
for (int i=1;i<= integ_vol_typeQuel_taille;i++)
{ // on lit l'entête d'un type quelconque
// -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes
TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE);
TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE);
// lecture de l'entête et récup d'enu
// on utilise: avec création, car il peut s'agir d'une intégrale qui n'est plus active
// du coup le tableau existant ne contient pas cette intégrale
EnuTypeQuelParticulier enu_t =
pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
int indice_t = integ_vol_typeQuel_t.Contient(pour_lire_t);
if (indice_t)
{// là il suffit de lire la grandeur associée
ent >> (*integ_vol_typeQuel_t(indice_t).Grandeur_pointee());
};
// normalement le cas a tdt est identique
EnuTypeQuelParticulier enu =
pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
// là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur
// le test se fait uniquement sur le TypeQuelconque_enum_etendu
// qui est supposé suffisant comme signature
int indice = integ_vol_typeQuel.Contient(pour_lire);
if (indice)
{// là il suffit de lire la grandeur associée
ent >> (*integ_vol_typeQuel(indice).Grandeur_pointee());
};
if (!indice)
{ // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur
// figée, dont la valeur ne changera pas pendant le calcul
// création d'une grandeur associée et lecture des information sur le flot
TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent);
// création du type quelconque
TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t);
delete grandeur_t; // car il ne sert plus à rien
TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent);
// création du type quelconque
TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur);
delete grandeur; // car il ne sert plus à rien
// maintenant on va mettre à jour le stockage interne
// ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue
// à l'initialisation du .info
indice_t = integ_vol_typeQuel_t.Taille()+1;
indice = integ_vol_typeQuel.Taille()+1;
integ_vol_typeQuel_t.Change_taille(indice_t);
integ_vol_typeQuel.Change_taille(indice);
integ_vol_typeQuel(indice) = typQ;
integ_vol_typeQuel_t(indice_t) = typQ_t;
ref_integ_vol.Change_taille(indice);// normalement c'est le même qu'indice_t
// par défaut on met la ref à NULL, ce qui veut dire que la grandeur est
// figé, car aucun domaine d'intégration n'a été définit
ref_integ_vol(indice) = NULL;
};
// on va créer ou mettre à jour une grandeur globale associée
{TypeQuelconque& TQ_t = integ_vol_typeQuel_t(indice); // pour simplifier
// cas des grandeurs à t: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee();
const string* nom_de_ref = g_TG_t->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_typeQuel_t(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t));
};
};
// idem pour la grandeur courante
{TypeQuelconque& TQ = integ_vol_typeQuel(indice); // pour simplifier
// cas des grandeurs à tdt: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_typeQuel(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
// la valeur passée en paramétre est celle de t !!
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG));
};
};
}; // boucle sur les grandeurs lues
// maintenant les intégrales de volume et en temps
ent >> toto;
if (toto != "int_vol_temps_mail")
{ cout << "\nErreur : en lecture de l'entete de l'integration de volume et en temps eventuelle"
<< " on attendait le mot cle int_vol_temps_mail et on a lu "<< toto <<" !\n";
cout << "LesMaillages::Lecture_base_info(....)" << flush;
Sortie(1);
};
int integ_vol_t_typeQuel_taille = 0;
ent >> integ_vol_t_typeQuel_taille;
// on boucle sur les grandeurs à lire
// si la grandeur existe déjà, elle est mise à jour, sinon elle est crée
// mais dans ce cas elle ne changera plus pendant le calcul
for (int i=1;i<= integ_vol_t_typeQuel_taille;i++)
{ // on lit l'entête d'un type quelconque
// -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes
TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE);
TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE);
// lecture de l'entête et récup d'enu
// on utilise: avec création, car il peut s'agire d'une intégrale qui n'est plus active
// du coup le tableau exitant ne contient pas cette intégrale
EnuTypeQuelParticulier enu_t =
pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
// là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur
// le test se fait uniquement sur le TypeQuelconque_enum_etendu
// qui est supposé suffisant comme signature
int indice_t = integ_vol_t_typeQuel_t.Contient(pour_lire_t);
if (indice_t)
{// là il suffit de lire la grandeur associée
ent >> (*integ_vol_t_typeQuel_t(indice_t).Grandeur_pointee());
};
// idem à t
EnuTypeQuelParticulier enu =
pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
int indice = integ_vol_t_typeQuel.Contient(pour_lire);
if (indice)
{// là il suffit de lire la grandeur associée
ent >> (*integ_vol_t_typeQuel(indice).Grandeur_pointee());
};
if (!indice)
{ // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur
// figée, dont la valeur ne changera pas pendant le calcul
// création d'une grandeur associée et lecture des information sur le flot
TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent);
// création du type quelconque
TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t);
delete grandeur_t; // car il ne sert plus à rien
TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent);
// création du type quelconque
TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur);
delete grandeur; // car il ne sert plus à rien
// maintenant on va mettre à jour le stockage interne
// ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue
// à l'initialisation du .info
indice = integ_vol_t_typeQuel_t.Taille()+1;
integ_vol_t_typeQuel_t.Change_taille(indice);
integ_vol_t_typeQuel.Change_taille(indice);
integ_vol_t_typeQuel(indice) = typQ;
integ_vol_t_typeQuel_t(indice) = typQ_t;
ref_integ_vol_t.Change_taille(indice);
// par défaut on met la ref à NULL, ce qui veut dire que la grandeur est
// figé, car aucun domaine d'intégration n'a été définit
ref_integ_vol_t(indice) = NULL;
};
// on va créer ou mettre à jour une grandeur globale associée
{TypeQuelconque& TQ_t = integ_vol_t_typeQuel_t(indice); // pour simplifier
TypeQuelconque& TQ = integ_vol_t_typeQuel(indice); // pour simplifier
// transfert des intégrales finalisées
// on considère que les grandeurs à tdt doivent être initialisées à celles de t
(TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee()));
// cas des grandeurs à t: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee();
const string* nom_de_ref = g_TG_t->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_t_typeQuel_t(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t));
};
};
// cas des grandeurs à tdt
// integ_vol_t_typeQuel(i) = integ_vol_t_typeQuel_t(i);
// on va créer ou mettre à jour une grandeur globale associée
{TypeQuelconque& TQ = integ_vol_t_typeQuel(indice); // pour simplifier
// cas des grandeurs à tdt: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&integ_vol_t_typeQuel(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG));
};
};
}; // boucle sur les grandeurs lues
// déjà fait
// integ_vol_t_typeQuel = integ_vol_t_typeQuel_t; // init
// ----- cas des statistiques éventuelles-----
// utile pour pouvoir post-traiter et également pour le cumul sur le temps
ent >> toto;
if (toto != "statistique_mail")
{ cout << "\nErreur : en lecture de l'entete de statistique eventuelle"
<< " on attendait le mot cle statistique_mail et on a lu "<< toto <<" !\n";
cout << "LesMaillages::Lecture_base_info(....)" << flush;
Sortie(1);
};
int statistique_typeQuel_taille = 0;
ent >> statistique_typeQuel_taille;
// on boucle sur les grandeurs à lire
// si la grandeur existe déjà, elle est mise à jour, sinon elle est crée
// mais dans ce cas elle ne changera plus pendant le calcul
for (int i=1;i<= statistique_typeQuel_taille;i++)
{ // on lit l'entête d'un type quelconque
// -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes
TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE);
TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE);
// lecture de l'entête et récup d'enu
// on utilise: avec création, car il peut s'agir d'une statistique qui n'est plus active
// du coup le tableau existant ne contient pas cette statistique
EnuTypeQuelParticulier enu_t =
pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
int indice_t = statistique_typeQuel_t.Contient(pour_lire_t);
if (indice_t)
{// là il suffit de lire la grandeur associée
ent >> (*statistique_typeQuel_t(indice_t).Grandeur_pointee());
};
// normalement le cas a tdt est identique
EnuTypeQuelParticulier enu =
pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
// là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur
// le test se fait uniquement sur le TypeQuelconque_enum_etendu
// qui est supposé suffisant comme signature
int indice = statistique_typeQuel.Contient(pour_lire);
if (indice)
{// là il suffit de lire la grandeur associée
ent >> (*statistique_typeQuel(indice).Grandeur_pointee());
};
if (!indice)
{ // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur
// figée, dont la valeur ne changera pas pendant le calcul
// création d'une grandeur associée et lecture des information sur le flot
TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent);
// création du type quelconque
TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t);
delete grandeur_t; // car il ne sert plus à rien
TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent);
// création du type quelconque
TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur);
delete grandeur; // car il ne sert plus à rien
// maintenant on va mettre à jour le stockage interne
// ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue
// à l'initialisation du .info
indice_t = statistique_typeQuel_t.Taille()+1;
indice = statistique_typeQuel.Taille()+1;
statistique_typeQuel_t.Change_taille(indice_t);
statistique_typeQuel.Change_taille(indice);
statistique_typeQuel(indice) = typQ;
statistique_typeQuel_t(indice_t) = typQ_t;
ref_statistique.Change_taille(indice);// normalement c'est le même qu'indice_t
// par défaut on met la ref à NULL, ce qui veut dire que la grandeur est
// figé, car aucune ref de statistique n'a été définie
ref_statistique(indice) = NULL;
};
// on va créer ou mettre à jour une grandeur globale associée
{TypeQuelconque& TQ_t = statistique_typeQuel_t(indice); // pour simplifier
// cas des grandeurs à t: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee();
const string* nom_de_ref = g_TG_t->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans statistique !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&statistique_typeQuel_t(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t));
};
};
// idem pour la grandeur courante
{TypeQuelconque& TQ = statistique_typeQuel(indice); // pour simplifier
// cas des grandeurs à tdt: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans statistique !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&statistique_typeQuel(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
// la valeur passée en paramétre est celle de t !!
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG));
};
};
}; // boucle sur les grandeurs lues
// maintenant les statistiques avec cumul en temps
ent >> toto;
if (toto != "statistique_temps_mail")
{ cout << "\nErreur : en lecture de l'entete de la statistique avec cumul en temps eventuelle"
<< " on attendait le mot cle statistique_temps_mail et on a lu "<< toto <<" !\n";
cout << "LesMaillages::Lecture_base_info(....)" << flush;
Sortie(1);
};
int statistique_t_typeQuel_taille = 0;
ent >> statistique_t_typeQuel_taille;
// on boucle sur les grandeurs à lire
// si la grandeur existe déjà, elle est mise à jour, sinon elle est crée
// mais dans ce cas elle ne changera plus pendant le calcul
for (int i=1;i<= statistique_t_typeQuel_taille;i++)
{ // on lit l'entête d'un type quelconque
// -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes
TypeQuelconque pour_lire_t(RIEN_TYPEQUELCONQUE);
TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE);
// lecture de l'entête et récup d'enu
// on utilise: avec création, car il peut s'agir d'une statistique qui n'est plus active
// du coup le tableau exitant ne contient pas cette statistique
EnuTypeQuelParticulier enu_t =
pour_lire_t.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
// là on regarde dans le tableau existant, pour voir s'il existe déjà le bon conteneur
// le test se fait uniquement sur le TypeQuelconque_enum_etendu
// qui est supposé suffisant comme signature
int indice_t = statistique_t_typeQuel_t.Contient(pour_lire_t);
if (indice_t)
{// là il suffit de lire la grandeur associée
ent >> (*statistique_t_typeQuel_t(indice_t).Grandeur_pointee());
};
// idem à t
EnuTypeQuelParticulier enu =
pour_lire.Lecture_un_avec_creation_TypeQuelconque_enum_etendu(ent);
int indice = statistique_t_typeQuel.Contient(pour_lire);
if (indice)
{// là il suffit de lire la grandeur associée
ent >> (*statistique_t_typeQuel(indice).Grandeur_pointee());
};
if (!indice)
{ // sinon c'est plus compliqué car cela signifie qu'il va s'agir d'une grandeur
// figée, dont la valeur ne changera pas pendant le calcul
// création d'une grandeur associée et lecture des information sur le flot
TypeQuelconque::Grandeur* grandeur_t =NevezGrandeurParticuliereEnLecture(enu_t,ent);
// création du type quelconque
TypeQuelconque typQ_t(pour_lire_t.EnuTypeQuelconque(),pour_lire_t.Enum(),*grandeur_t);
delete grandeur_t; // car il ne sert plus à rien
TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent);
// création du type quelconque
TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur);
delete grandeur; // car il ne sert plus à rien
// maintenant on va mettre à jour le stockage interne
// ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue
// à l'initialisation du .info
indice = statistique_t_typeQuel_t.Taille()+1;
statistique_t_typeQuel_t.Change_taille(indice);
statistique_t_typeQuel.Change_taille(indice);
statistique_t_typeQuel(indice) = typQ;
statistique_t_typeQuel_t(indice) = typQ_t;
ref_statistique_t.Change_taille(indice);
// par défaut on met la ref à NULL, ce qui veut dire que la grandeur est
// figé, car aucune ref de noeuds n'a été définie
ref_statistique_t(indice) = NULL;
};
// on va créer ou mettre à jour une grandeur globale associée
{TypeQuelconque& TQ_t = statistique_t_typeQuel_t(indice); // pour simplifier
TypeQuelconque& TQ = statistique_t_typeQuel(indice); // pour simplifier
// transfert des statistiques finalisées
// on considère que les grandeurs à tdt doivent être initialisées à celles de t
(TQ_t.Grandeur_pointee())->Affectation_numerique(*(TQ.Grandeur_pointee()));
// cas des grandeurs à t: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee();
const string* nom_de_ref = g_TG_t->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&statistique_t_typeQuel_t(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG_t));
};
};
// on va créer ou mettre à jour une grandeur globale associée
{TypeQuelconque& TQ = statistique_t_typeQuel(indice); // pour simplifier
// cas des grandeurs à tdt: on alimente les grandeurs globales
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans statistique avec cuml en temps !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Lecture_base_info(..."<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur éventuel
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
if (pointe == NULL)
// la grandeur n'existe pas on la définie
ParaGlob::param->Ajout_grandeur_consultable(&statistique_t_typeQuel(indice),*nom_de_ref);
else // sinon on affecte
{TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
(gr_quelc->Grandeur_pointee())->Affectation_numerique(*(g_TG));
};
};
}; // boucle sur les grandeurs lues
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
cout << "LesMaillages::Lecture_base_info(....)"
<< " cas= " << cas << flush;
Sortie(1);
};
};
};
// écriture base info
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void LesMaillages::Ecriture_base_info(ofstream& sort,const int cas)
{ sort << "\n ****les_maillages:_nombre= " << nbMaillageTotal ;
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
tabMaillage(i1)->Ecriture_base_info(sort,cas);
switch (cas)
{ case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
{ // ----- cas des grandeurs intégrés éventuelles-----
// utile pour pouvoir post-traiter et également pour le cumul sur le temps
// 1) les intégrales de volume
sort << "\n\n int_vol_mail ";
int integ_vol_typeQuel_taille = integ_vol_typeQuel.Taille();
if (integ_vol_typeQuel_taille == 0)
sort << 0; else sort << integ_vol_typeQuel_taille;
sort << " ";
for (int i=1;i<= integ_vol_typeQuel_taille;i++)
// il faut que l'on sauvegarde à t et tdt sinon au restart les grandeurs à tdt n'existe pas
sort << "\n" << integ_vol_typeQuel_t(i) << " "<<integ_vol_typeQuel(i);
// 2) les intégrales de volume et de temps
sort << "\n int_vol_temps_mail ";
int integ_vol_t_typeQuel_taille = integ_vol_t_typeQuel.Taille();
if (integ_vol_t_typeQuel_taille == 0) sort << 0; else sort <<integ_vol_t_typeQuel_taille;
sort << " ";
for (int i=1;i<= integ_vol_t_typeQuel_taille;i++)
sort << "\n" << integ_vol_t_typeQuel_t(i)<< " "<<integ_vol_t_typeQuel(i);
// ----- cas des grandeurs statistique éventuelles-----
// utile pour pouvoir post-traiter et également pour le cumul sur le temps
// 1) les statistiques sur des ref de noeuds
sort << "\n\n statistique_mail ";
int statistique_typeQuel_taille = statistique_typeQuel.Taille();
if (statistique_typeQuel_taille == 0)
sort << 0; else sort << statistique_typeQuel_taille;
sort << " ";
for (int i=1;i<= statistique_typeQuel_taille;i++)
// il faut que l'on sauvegarde à t et tdt sinon au restart les grandeurs à tdt n'existe pas
sort << "\n" << statistique_typeQuel_t(i) << " "<<statistique_typeQuel(i);
// 2) les statistiques avec cumul sur le temps
sort << "\n statistique_temps_mail ";
int statistique_t_typeQuel_taille = statistique_t_typeQuel.Taille();
if (statistique_t_typeQuel_taille == 0) sort << 0; else sort <<statistique_t_typeQuel_taille;
sort << " ";
for (int i=1;i<= statistique_t_typeQuel_taille;i++)
sort << "\n" << statistique_t_typeQuel_t(i)<< " "<<statistique_t_typeQuel(i);;
}
};
};
// sortie du schemaXML: en fonction de enu
void LesMaillages::SchemaXML_LesMaillages(ofstream& sort,const Enum_IO_XML enu) const
{ switch (enu)
{case XML_TYPE_GLOBAUX:
{ // cas des classes de base
DeuxEntiers toto;
toto.SchemaXML_DeuxEntiers(sort,enu);
Maillage::SchemaXML_Maillages(sort,enu) ;
break;
}
case XML_IO_POINT_INFO:
{// cas de def de LesMaillages
sort << "\n <xs:element name=\"LesMaillages\" >"
<< "\n <xs:complexType>"
<< "\n <xs:annotation>"
<< "\n <xs:documentation> une suite de maillages </xs:documentation>"
<< "\n </xs:annotation>"
<< "\n <xs:sequence>"
<< "\n <xs:element name=\"Maillage\" type=\"Maillage\" "
<< "\n minOccurs=\"1\" maxOccurs=\"unbounded\" />"
<< "\n </xs:sequence>"
<< "\n </xs:complexType>"
<< "\n </xs:element>";
// def de Maillage
// SchemaXML_Maillage(sort,niveau);
break;
}
};
};
// ------ informations utiles par exemples pour la visualisation
// retourne les dimensions minis et maxi suivant les axes du repère
// absolu du maillage numéro nbmail (en faite le calcul est fondé
// uniquement sur la position des noeuds du maillage
// le premier vecteur contient les minimums
// le deuxième vecteur contient les maximums
Tableau <Vecteur> LesMaillages::Taille_boite(int nbmail)
{
#ifdef MISE_AU_POINT
// vérification que le numéro de maillage est correcte
if (( nbmail <= 0) || (nbmail > nbMaillageTotal))
{ cout << "\n erreur, le numéro de maillage demandé est érroné,"
<< " nbmail = " << nbmail
<< " \n LesMaillages::Taille_boite(int nbmail) " ;
Sortie(1);
}
#endif
return tabMaillage(nbmail)->Taille_boiteMail();
};
// dans le cas ou aucun numéro de maillage n'est fournis
// c'est l'encombrement de tous les maillages qui est fourni
Tableau <Vecteur> LesMaillages::Taille_boite()
{ if (nbMaillageTotal == 0)
// cas particulier ou aucun maillage n'est définit
{ Tableau <Vecteur> toto(2);
return toto;
}
// l'objectif est de balayer tous les maillages
// tout d'abord initialisation du tableau de retour sur le premier
// maillage
Tableau <Vecteur> tabsortie = tabMaillage(1)->Taille_boiteMail();
for (int i1 = 2; i1<= nbMaillageTotal; i1++)
{ // récupération du tableau calculé
Tableau <Vecteur> tabinter = tabMaillage(i1)->Taille_boiteMail();
// différent tests
int dima = tabsortie(1).Taille();
for (int it=1;it<=dima;it++)
{ if (tabsortie(1)(it) > tabinter(1)(it))
tabsortie(1)(it) = tabinter(1)(it);
if (tabsortie(2)(it) < tabinter(2)(it))
tabsortie(2)(it) = tabinter(2)(it);
}
}
// retour
return tabsortie;
};
// mise à jour des boites d'encombrements des éléments, qui contiennent des éléments frontières
// et des éléments frontières eux-même
void LesMaillages::Mise_a_jour_boite_encombrement_elem_front(Enum_dure temps)
{for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ // tout d'abord les boites des éléments: on passe en revue tous les éléments
int nbelmax = Nombre_element(i1);
for (int jel = 1; jel <= nbelmax; jel++)
{ // récup de l'élément
Element& elem = tabMaillage(i1)->Element_mail(jel);
// on regarde si l'élément contient des éléments frontières
if (elem.Existe_frontiere())
elem.Boite_encombre_element(temps);
};
// maintenant on s'occupe des frontières
LaLIST <Front>* lisfrontmail = listFrontiere(i1); // pour simplifier
LaLIST <Front>::iterator il,ilfin=lisfrontmail->end();
for (il=lisfrontmail->begin();il != ilfin; il++)
(*il).Boite_encombrement_frontiere(temps);
};
};
// crée et ramene pour tous les maillages, la liste des éléments qui contiennent chaque noeud
// mis à jour lorsque lors de la création des frontières
const Tableau < const Tableau <List_io < Element* > > *>& LesMaillages::Indice()
{ tous_indices.Change_taille(nbMaillageTotal);
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ tous_indices(i1)= &(tabMaillage(i1)->Maillage::Indice());};
return tous_indices;
};
// -----------------------------------------------------
// | utilitaires de manipulation de maillage |--
// -----------------------------------------------------
// création de maillage quadratiques incomplets à partir de maillages linéaires.
// En fait il y création de maillages identiques aux maillages déjà existants, les éléments qui sont de types
// linéaires sont remplacés par des éléments quadratiques incomplets correspondants.
// Il y a création de références correspondantes
void LesMaillages::CreeMaillagesQuadratiques_a_partir_des_lineaires(LesReferences* lesRef)
{ // création de la liste qui sert pour repérer les maillages créés
list <DeuxEntiers> tab_lin_vers_comp;
// tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter
int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets
for (int im=1;im<=nbMaillageTotal;im++)
if (tabMaillage(im)->Contient_lineaire())
{ nb_final_maillage++;
tab_lin_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage));
};
// dans le cas où des maillages linéaires existent, création de nouveaux maillages
nbMaillageTotal = nb_final_maillage;
// on vérifie et augmente éventuellement la taille du nombre de maillage
while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// maintenant on passe en revue les maillages candidats
list<DeuxEntiers>::iterator il,ifin= tab_lin_vers_comp.end();
for (il=tab_lin_vers_comp.begin();il!=ifin;il++)
{ // on commence par créé le futur maillage quadratique à l'identique du maillage linéaire
// original, il y a ici création de nouveau noeud et élément
// on utilise un nouveau nom de maillage construit a partir de l'ancien
string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez";
while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un));
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { if(ref1->Nbmaille() == (*il).un)
// on a trouvé une référence à considérer
{ // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille((*il).deux);
list_inter_ref.push_back(ref_nv);
// on intègre la référence dans lesRéférences
// lesRef->Ajout_reference(ref_nv);
}
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques
// complets. Les références sont également transformés en cohérence.
tabMaillage((*il).deux)->Transfo_lin_quadraIncomp(*lesRef);
}
};
// création de maillage quadratiques complets à la place des maillages incomplet
// les éléments qui sont de types quadratiques incomplets sont remplacés par des éléments
// quadratiques complets correspondants.
// Il y a création de références correspondantes
void LesMaillages::CreeMaillagesQuadratiquesComplets_a_partir_des_incomplets(LesReferences* lesRef)
{ // création de la liste qui sert pour repérer les maillages complets créés
list <DeuxEntiers> tab_quadra_inc_vers_comp;
// tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter
int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets
for (int im=1;im<=nbMaillageTotal;im++)
if (tabMaillage(im)->Contient_quadratique_incomplet())
{ nb_final_maillage++;
tab_quadra_inc_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage));
}
// dans le cas où des maillages de quadratiques incomplet existent, création de nouveaux maillages
nbMaillageTotal = nb_final_maillage;
while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// maintenant on passe en revue les maillages candidats
list<DeuxEntiers>::iterator il,ifin= tab_quadra_inc_vers_comp.end();
for (il=tab_quadra_inc_vers_comp.begin();il!=ifin;il++)
{ // on commence par créé le futur maillage complet à l'identique du maillage incomplet
// original, il y a ici création de nouveau noeud et élément
// on utilise un nouveau nom de maillage construit a partir de l'ancien
string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez";
while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un));
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { if(ref1->Nbmaille() == (*il).un)
// on a trouvé une référence à considérer
{ // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille((*il).deux);
list_inter_ref.push_back(ref_nv);
// on intègre la référence dans lesRéférences
// lesRef->Ajout_reference(ref_nv);
}
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques
// complets. Les références sont également transformés en cohérence.
tabMaillage((*il).deux)->Transfo_quadraIncomp_quadraComp(*lesRef);
}
};
// Affiche les donnees des maillages dans des fichiers dont le nom est construit à partir du nom de
// chaque maillage au format ".her" et ".lis"
// le paramètre optionnel indique le numéro du maillage à afficher, s'il vaut -1, on affiche tous les maillages
void LesMaillages::Affiche_maillage_dans_her_lis(Enum_dure temps,LesReferences &lesRef,int imail)
{ if (imail == -1)
{// cas de l'affichage de tous les maillages, on passe en revue les différents maillages
for (int im=1;im<=nbMaillageTotal;im++)
tabMaillage(im)->Affiche_dans_her_lis(lesRef,temps);
}
else
{// cas de l'affichage d'un maillage particulier
if ((imail < 1)||(imail > nbMaillageTotal))
{ cout << "\n erreur dans l'affichage d'un maillage en format .her et .lis"
<< "\n le numero propose: " << imail << " de maillage n'existe pas !! "
<< "\n LesMaillages::Affiche_maillage_dans_her_lis(LesReferences &lesRef,int imail)";
Sortie(1);
}
tabMaillage(imail)->Affiche_dans_her_lis(lesRef,temps);
}
};
// relocalisation des points milieux des arrêtes des éléments quadratiques
void LesMaillages::RelocPtMilieuMailleQuadra()
{ // on passe en revue les différents maillages
for (int im=1;im<=nbMaillageTotal;im++)
tabMaillage(im)->RelocPtMilieuMailleQuadra();
};
// création et ajout d'un nouveau maillage en fonction d'un nom et d'une liste
// d'éléments et de noeuds
// *** il n'y a pas de création de nouveaux noeuds et de nouveaux éléments,
// ce sont les éléments et noeuds passés en paramètres qui sont ceux du maillage créé
// >> ramène le numéro du nouveau maillage
int LesMaillages::Creation_nouveau_maillage
(list <Noeud*>& li_noeud,list <Element*>& list_elem,const string& nom_maillage)
{ if (ParaGlob::NiveauImpression() >= 4)
cout << " debut de l'ajout d'un nouveau maillage " << flush;
// recherche d'un numéro du maillage
nbMaillageTotal++;
if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
int nbElem= list_elem.size();
tabMaillage(nbMaillageTotal) = new Maillage (mapNomMail,paraGlob->Dimension()
,li_noeud,list_elem
,nbMaillageTotal,nom_maillage);
// indique le nb de maillage pour l'enregistrement des prochaines references
lesRef->NbMaille(nbMaillageTotal);
if (ParaGlob::NiveauImpression() >= 4)
cout << " fin de l'ajout d'un nouveau maillage " << flush;
// retour du numéro de maillage
return nbMaillageTotal;
};
// suppression d'un maillage existant
// par défaut, tous les noeuds et éléments du maillage sont supprimés
// si sans_conservation_noeuds_elements est false: les noeuds et les éléments ne sont pas supprimés
// mais ils ne sont plus référencés dans ce maillage !
void LesMaillages::Suppression_maillage( const string& nom_maillage,const bool sans_conservation_noeuds_elements)
{ // on commence par récupérer le numéro du maillage
int num_mail = NumMaillage(nom_maillage);
if (num_mail != 0 ) // sinon il n'y a rien n'a supprimer
{ if (ParaGlob::NiveauImpression() >= 4)
cout << " delet of the mesh " << nom_maillage << flush ;
// on supprime le maillage
// Dans le cas particulier où l'on veut garder les noeuds et éléments, on l'indique au maillage
// avant sa suppression
if(!sans_conservation_noeuds_elements)
tabMaillage(num_mail)->Preparation_destruction_avec_conservation_noeuds_elements();
delete tabMaillage(num_mail);
// 1) il faut également supprimer les références qui sont relative au maillage que l'on vient de supprimer
// on commence par stocker la liste des ref à supprimer, on ne les supprime pas à la volée
// de manière à ne pas modifier les bornes de l'algo de parcours
// 2) il faut changer de numéro de maillage, toutes les ref qui sont pour les maillages après le maillage supprimé
bool avec_diminution_num_maillage = true;
lesRef->Supprime_tour_lesRef_un_maillage(num_mail,avec_diminution_num_maillage);
// la map des noms
mapNomMail.erase(nom_maillage);
// -- maintenant il faut que l'on gère tous les tableaux internes qui sont relatifs aux maillages
// on retasse les tableaux
nbMaillageTotal--;
// le tableau de maillage
for (int i = num_mail;i<= nbMaillageTotal;i++)
{tabMaillage(i) = tabMaillage(i+1);
tabMaillage(i)->Change_numero_maillage(i); // changement du numéro de maillage
};
tabMaillage(nbMaillageTotal+1)=NULL;
// les frontières si elles ont été construite
if (listFrontiere.Taille() != 0)
{for (int i = num_mail;i<= nbMaillageTotal;i++)
{tabMaillage(i) = tabMaillage(i+1);
listFrontiere(i) = listFrontiere(i+1);
tt_noeud_front(i) = tt_noeud_front(i+1);
};
listFrontiere.Change_taille(nbMaillageTotal);
tt_noeud_front.Change_taille(nbMaillageTotal);
};
// le nombre de domaine esclave
if (num_mail <= domEsclave )
// il faut diminuer le nombre d'esclave
domEsclave--;
};
};
// création de maillage par extrusion
// Il y a création de références correspondantes
void LesMaillages::CreeMaillageExtrusion2D3D(LesReferences* lesRef)
{ // création de la liste qui sert pour repérer les maillages complets créés
list <DeuxEntiers> tab_quadra_inc_vers_comp;
// tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter
int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets
for (int im=1;im<=nbMaillageTotal;im++)
if (tabMaillage(im)->Contient_quadratique_incomplet())
{ nb_final_maillage++;
tab_quadra_inc_vers_comp.push_back(DeuxEntiers(im,nb_final_maillage));
}
// dans le cas où des maillages de quadratiques incomplet existent, création de nouveaux maillages
nbMaillageTotal = nb_final_maillage;
while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// maintenant on passe en revue les maillages candidats
list<DeuxEntiers>::iterator il,ifin= tab_quadra_inc_vers_comp.end();
for (il=tab_quadra_inc_vers_comp.begin();il!=ifin;il++)
{ // on commence par créé le futur maillage complet à l'identique du maillage incomplet
// original, il y a ici création de nouveau noeud et élément
// on utilise un nouveau nom de maillage construit a partir de l'ancien
string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez";
while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un));
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { if(ref1->Nbmaille() == (*il).un)
// on a trouvé une référence à considérer
{ // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille((*il).deux);
list_inter_ref.push_back(ref_nv);
// on intègre la référence dans lesRéférences
// lesRef->Ajout_reference(ref_nv);
}
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// On transforme les éléments quadratiques incomplet du nouveau maillage en quadratiques
// complets. Les références sont également transformés en cohérence.
tabMaillage((*il).deux)->Transfo_quadraIncomp_quadraComp(*lesRef);
}
};
// définition interactive de listes de références
void LesMaillages::CreationInteractiveListesRef(LesReferences* lesRef)
{ // on récupère le nombre de maillage actuellement actif
int nb_maillages_actifs_initiaux = nbMaillageTotal;
cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n";
// on va boucler sur les maillages et définir des ref pour chaque maillages
for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++)
tabMaillage(imail)->CreationInteractiveListesRef(lesRef);
};
// modification de l'orientation d'éléments
void LesMaillages::Modif_orientation_element(int cas_orientation,LesReferences* lesRef)
{ // on récupère le nombre de maillage actuellement actif
int nb_maillages_actifs_initiaux = nbMaillageTotal;
cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n";
switch(cas_orientation)
{ case 1: case 2: case 3: // cas d'une orientation automatique des maillages:
{ // on vérifie et augmente éventuellement la taille du nombre de maillage
while (nbMaillageTotal > nbPortion)
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// on va boucler sur les maillages et définir de nouveaux maillages identiques
for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++)
{ // il y a ici création de nouveau noeud et élément
// on utilise un nouveau nom de maillage construit a partir de l'ancien
int imailnew = imail+nb_maillages_actifs_initiaux;
string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez";
while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail));
nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { if(ref1->Nbmaille() == imail)
// on a trouvé une référence à considérer
{ // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille(imailnew);
list_inter_ref.push_back(ref_nv);
};
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// on modifie l'orientation du nouveau maillage en fonction du cas
tabMaillage(imailnew)->Modif_orientation_element(cas_orientation,lesRef);
};
break;
}
case -1: // uniquement vérification
{ // on va boucler sur les maillages
for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++)
tabMaillage(imail)->Modif_orientation_element(cas_orientation,lesRef);
break;
}
default:
cout << "\n erreur le cas : " << cas_orientation
<< " n'est pas actuellement pris en compte"
<< "\n LesMaillages::Modif_orientation_element(...";
Sortie(1);
};
};
// Collapse des éléments supperposés, c-a-d identiques, dans le cas où il en existe
void LesMaillages::Collapse_element_supperpose(LesReferences* lesRef)
{ // on récupère le nombre de maillage actuellement actif
int nb_maillages_actifs_initiaux = nbMaillageTotal;
cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n";
// on vérifie et augmente éventuellement la taille du nombre de maillage
while (nbMaillageTotal > nbPortion)
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// on va boucler sur les maillages et définir de nouveaux maillages identiques
for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++)
{ // il y a ici création de nouveau noeud et élément
// on utilise un nouveau nom de maillage construit a partir de l'ancien
int imailnew = imail+nb_maillages_actifs_initiaux;
string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez";
while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail));
nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { if(ref1->Nbmaille() == imail)
// on a trouvé une référence à considérer
{ // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille(imailnew);
list_inter_ref.push_back(ref_nv);
};
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// on fusionne les noeuds
tabMaillage(imailnew)->Collapse_element_superpose(lesRef);
};
};
// collapse de noeuds très proche: appartenant à des éléments différents
// rayon : donne la distance maxi entre les noeuds qui doivent être collapsé
void LesMaillages::Collapse_noeuds_proches(double rayon, LesReferences* lesRef)
{ // on récupère le nombre de maillage actuellement actif
int nb_maillages_actifs_initiaux = nbMaillageTotal;
cout << "\n il y a " << nb_maillages_actifs_initiaux << " maillages a considerer \n";
// on vérifie et augmente éventuellement la taille du nombre de maillage
while (nbMaillageTotal > nbPortion)
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// on va boucler sur les maillages et définir de nouveaux maillages identiques
for (int imail = 1; imail <= nb_maillages_actifs_initiaux; imail++)
{ // il y a ici création de nouveau noeud et élément
// on utilise un nouveau nom de maillage construit a partir de l'ancien
int imailnew = imail+nb_maillages_actifs_initiaux;
string nvnom= tabMaillage(imail)->NomDuMaillage() + "_nevez";
while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
tabMaillage(imailnew)=new Maillage(mapNomMail,imailnew, nvnom,*tabMaillage(imail));
nbMaillageTotal++; // on signale qu'il y a un maillage supplémentaire
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { if(ref1->Nbmaille() == imail)
// on a trouvé une référence à considérer
{ // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille(imailnew);
list_inter_ref.push_back(ref_nv);
};
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// on fusionne les noeuds
tabMaillage(imailnew)->Collapse_noeuds_proches(rayon,lesRef);
};
};
// création d'un nouveau maillage issue de la fusion de maillages existants
// nom_mails_a_fusionner : la liste des maillages à fusionner
// new_mail : le nom du nouveau maillage à construire
// NB: si new_mail correspond à un maillage déjà existant, il y a fusion de ce maillage
// avec les autres, sans création d'un nouveau maillage
void LesMaillages::Fusion_maillages(List_io < string >& nom_mails_a_fusionner,const string& new_mail
,LesReferences* lesRef)
{ // on va commencer par créer un nouveau maillage
if (ParaGlob::NiveauImpression() >= 4)
cout << " debut d'une operation de fusion de maillage " << flush;
// on regarde s'il s'agit d'une fusion avec un maillage existant ou non:
Maillage* nevez_mail_ = NULL; // est renseigné dans le if suivant
bool creation_nouveau_maillage = false;
if (NumMaillage(new_mail) == 0)
{ // le retour est nulle: cas d'un nouveau maillage, on va créer un nouveau maillage
// recherche d'un numéro du maillage
nbMaillageTotal++;
if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// le premier maillage est vide
int dim = ParaGlob::Dimension();
tabMaillage(nbMaillageTotal) = new Maillage(mapNomMail,nbMaillageTotal,dim,new_mail);
nevez_mail_ = (tabMaillage(nbMaillageTotal)); // pour simplifier
creation_nouveau_maillage = true;
}
else
{ // il s'agit ici d'un maillage qui existe déjà
nevez_mail_ = (tabMaillage(NumMaillage(new_mail)));
};
// on récupère le maillage de base, qui intègrera les autres
Maillage& nevez_mail = *nevez_mail_;
// avant de faire l'opération de fusion, on va faire un traitement spécial pour les
// références automatiques E_tout, N_tout, F_tout, A_tout, P_tout, G_tout
{Tableau <string> tab_tout(6);
tab_tout(1) = "E_tout";tab_tout(2) = "N_tout"; tab_tout(3) = "F_tout";
tab_tout(4) = "A_tout";tab_tout(5) = "P_tout"; tab_tout(6) = "G_tout";
int idmail = NumMaillage(new_mail);
for (int i=1;i<= 6; i++)
{string& nreftout= tab_tout(i);
if (lesRef->Existe(nreftout,idmail))
{ const Reference& ref1 = lesRef->Trouve(nreftout,idmail); // récup de la ref
Reference* ref2 = ref1.Nevez_Ref_copie(); // on crée une ref identique
string nevez_nom=nreftout+"_1";int num=1; // on cherche un nom qui n'existe pas encore
while (lesRef->Existe(nevez_nom,idmail))
{nevez_nom += "_"+ChangeEntierSTring(num);num++;};
ref2->Change_nom(nevez_nom); // change le nom de la nouvelle ref
lesRef->Ajout_reference(ref2); // ajout de la ref
if (ParaGlob::NiveauImpression() > 0)
cout << "\n >>> attention la reference " << nreftout << " du maillage "
<< nevez_mail.NomDuMaillage() << " a un nouveau nom "<< nevez_nom;
};
};
};
// maintenant on va passer en revue tous les maillages à fusionner
List_io < string >::iterator il,ilfin=nom_mails_a_fusionner.end();
for (il = nom_mails_a_fusionner.begin();il != ilfin;il++)
{ // récup du numéro de maillage,
// et éventuellement on passe le maillage identique à new_mail
// debug
//cout << "\n maillage de la liste à fusionner " << (*il) << " newmail= "<<new_mail << flush;
// fin debug
if (*(il) != new_mail)
{ int num_mail_a_fusion = NumMaillage(*(il));
Maillage& mail_a_fusion = *(tabMaillage(num_mail_a_fusion));
// debug
//cout << "\n *il " << (*il) << " newmail= "<<new_mail
// << " num_mail_a_fusion= "<<num_mail_a_fusion << " NomDuMaillage() " << mail_a_fusion.NomDuMaillage() << flush;
// fin debug
// constitution de la liste de noeuds
Tableau<Noeud *>& tabN = mail_a_fusion.Tab_noeud();
int nbN = tabN.Taille();list <Noeud *> li_Noe;
for (int i=1;i<=nbN;i++)
li_Noe.push_back(tabN(i));
// constitution de la liste d'éléments
Tableau<Element *>& tabE = mail_a_fusion.Tab_element();
int nbE = tabE.Taille();list <Element *> li_Elem;
for (int i=1;i<=nbE;i++)
li_Elem.push_back(tabE(i));
// on récupère les références associées à ce maillage
list <const Reference*> lref; // la liste qui contiendra les ref recherchées
const Reference* ref1 = lesRef->Init_et_Premiere();
// on parcours la liste pour récupérer les ref appartenant au maillage
do { if(ref1->Nbmaille() == num_mail_a_fusion)
// on a trouvé une référence à considérer
{// si l'on est dans le cas de la fusion avec un maillage existant
// on regarde s'il y a déjà une ref avec le même nom dans le maillage
// si oui on change le nom de la ref à ajouter
string ajout="";int num=0;
if (!creation_nouveau_maillage)
{while (lesRef->Existe((ref1->Nom()+ajout),NumMaillage(new_mail)))
{num++;ajout = "_"+ChangeEntierSTring(num);
// debug
//cout << "\n (ref1->Nom()+ajout)" << (ref1->Nom()+ajout) << flush;
// fin debug
};
};
// on crée la référence à ajouter
Reference* ref2 = ref1->Nevez_Ref_copie(); // on crée une ref identique
ref2->Change_nom(ref1->Nom()+ajout);
lref.push_back(ref2);
// on averti que le nom de la référence a changé
if ((ParaGlob::NiveauImpression() > 0) && (ajout != ""))
cout << "\n >>> attention la reference "<<ref1->Nom()<<" du maillage "
<< mail_a_fusion.NomDuMaillage() << " a un nouveau nom "<< (ref1->Nom()+ajout);
// debug
//cout << "\n ref2= " << ref2->Nom() << " num maille "<< ref2->Nbmaille() << flush;
// fin debug
};
// debug
//cout << "\n " << ref1->Nom() << " num maille "<< ref1->Nbmaille() << flush;
// fin debug
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// appel de la méthode de fusion
nevez_mail.Ajout_elements_et_noeuds(li_Noe,li_Elem,&lref,lesRef);
};
};
if (ParaGlob::NiveauImpression() >= 4)
cout << "\n fin de l'operation de fusion de maillage " << flush;
};
// création d'un nouveau maillage issue d'un maillages existants et d'une ref d'éléments
// le nouveau maillage = les éléments de la ref
void LesMaillages::Cree_sous_maillage(int num_mail,LesReferences* lesRef, string nom_ref,const string& new_mail)
{ // on va commencer par créer un nouveau maillage
if (ParaGlob::NiveauImpression() >= 4)
cout << " debut d'une operation de creation de sous-maillage " << flush;
// on va créer un nouveau maillage
// recherche d'un numéro du maillage
nbMaillageTotal++;
if (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// le premier maillage est vide
int dim = ParaGlob::Dimension();
// si le nom du nouveau maillage existe déjà, on met nevez en suffixe
string nvnom(new_mail); // init
while (NumMaillage(nvnom))
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
// on commence par créé le futur maillage à l'identique du maillage contenant la ref
// originale, il y a ici création de nouveaux noeuds et éléments
// tabMaillage(nbMaillageTotal) = new Maillage(mapNomMail,nbMaillageTotal,dim,nvnom);
tabMaillage(nbMaillageTotal) = new Maillage (mapNomMail,nbMaillageTotal,nvnom,*tabMaillage(nbMaillageTotal-1));
Maillage* nevez_mail_ = (tabMaillage(nbMaillageTotal)); // pour simplifier
// pour simplifier
Maillage& nevez_mail = *nevez_mail_;
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille(nbMaillageTotal);
list_inter_ref.push_back(ref_nv);
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// puis, pour le nouveau maillage,
// on restreint le maillage aux seuls éléments de la référence passée en paramètre
// toutes les infos relatives à des éléments supprimés, sont également supprimés
nevez_mail.Restreint_sous_maillage(lesRef, nom_ref);
if (ParaGlob::NiveauImpression() >= 4)
cout << "\n fin de l'operation de creation de sous-maillage " << flush;
};
// création d'éléments SFE en fonction d'éléments classiques
void LesMaillages::CreationMaillageSFE() // on passe en revue les différents maillages
{ // création de la liste qui sert pour repérer les maillages créés
list <DeuxEntiers> tab_tri_vers_sfe;
// tout d'abord on parcours les différents maillages pour sélectionner ceux qui sont a traiter
int nb_final_maillage = nbMaillageTotal; // contiend le nombre final de maillage tenant compte des complets
for (int im=1;im<=nbMaillageTotal;im++)
if (tabMaillage(im)->OKPourTransSfe())
{ nb_final_maillage++;
tab_tri_vers_sfe.push_back(DeuxEntiers(im,nb_final_maillage));
};
// dans le cas où des maillages candidats existent, création de nouveaux maillages
nbMaillageTotal = nb_final_maillage;
// on vérifie et augmente éventuellement la taille du nombre de maillage
while (nbMaillageTotal > nbPortion) // il faut agrandir le tableau de maillage
{ nbPortion = nbPortion+nbEnreg;
tabMaillage.Change_taille(nbPortion);
};
// maintenant on passe en revue les maillages candidats
list<DeuxEntiers>::iterator il,ifin= tab_tri_vers_sfe.end();
for (il=tab_tri_vers_sfe.begin();il!=ifin;il++)
{ // on commence par créer le futur maillage SFE à l'identique du maillage triangulaire
// original, il y a ici création de nouveau noeud et élément
// on utilise un nouveau nom de maillage construit a partir de l'ancien
string nvnom= tabMaillage((*il).un)->NomDuMaillage() + "_nevez"; // init
while (NumMaillage(nvnom)) // si le maillage existe déjà , on rajoute un _nevez
// on utilise un nouveau nom de maillage construit a partir de l'ancien
nvnom += "_nevez";
tabMaillage((*il).deux)=new Maillage(mapNomMail,(*il).deux, nvnom,*tabMaillage((*il).un));
// création de références identiques aux cas du maillage initial
const Reference* ref1 = lesRef->Init_et_Premiere();
list <Reference * > list_inter_ref; // une liste intermédiaire de travail
// l'opération s'effectue en deux temps, car pendant que l'on parcours la liste
// des références existantes, on ne peut pas en ajouter sous peine de casser le mécanisme de parcours
// 1) donc premier temps on enregistre
do { if(ref1->Nbmaille() == (*il).un)
// on a trouvé une référence à considérer
{ // on crée une référence identique
Reference* ref_nv = ref1->Nevez_Ref_copie();
// on met à jour le numéro de maillage associé
ref_nv->Change_Nbmaille((*il).deux);
list_inter_ref.push_back(ref_nv);
};
ref1 = lesRef->Reference_suivante(); // la référence suivante
} while (ref1 != NULL);
// 2) deuxième temps on enregistre
list <Reference * >::iterator kl,klfin=list_inter_ref.end();
for (kl=list_inter_ref.begin();kl != klfin; kl++)
lesRef->Ajout_reference((*kl));
// On transforme les éléments triangulaire du nouveau maillage en SFE
// Les références sont conservées, car a priori identiques
tabMaillage((*il).deux)->CreationMaillageSFE();
}
};
// renumérotation des noeuds de tous les maillages en même temps, + prise en compte
// des conditions linéaires qui existent entre les noeuds
// attention, ne peut fonctionner que si les maillages ont des relations entre eux,
//sinon l'arbre de descendance ne sera pas complet !!
// ramène false si rien n'a changé, vrai sinon
// si le pointeur d'assemblage est non nulle, cela veut dire que l'on veut également une mise à jour
// globale des pointeurs d'assemblages (ce qui est différent de la méthode : MiseAJourPointeurAssemblage(
// qui agit maillage après maillage)
// si le pointeur d'assemblage est non nulle et le drapeau: sans_changement_num_noeud = true
// cela signifie que l'on désire uniquement une renumérotation de pointeur sans les noeuds
// ramène dans tous les cas les nouvelles largeurs en ddl
// nouvelles_largeur_en_ddl.un = la largeur totale
// nouvelles_largeur_en_ddl.deux = la demie largeur
// nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis
// uniquement (sans les CLL)
// ramène dans tous les cas les nouvelles largeurs en ddl
// nouvelles_largeur_en_ddl.un = la largeur totale résultante
// nouvelles_largeur_en_ddl.deux = la demie largeur totale résultante
// nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis
// uniquement (sans les CLL)
//
bool LesMaillages::Renumerotation(LesReferences& lesRef,const Tableau <Tableau <Condilineaire> >& tab_condCLL
,TroisEntiers& nouvelles_largeur_en_ddl
,const Nb_assemb* nb_casAssemb,bool sans_changement_num_noeud)
{ // pour effectuer la renumérotation il est nécessaire de créer un tableau global de tous les noeuds et
// de tous les éléments, de manière à pouvoir les gérer en même temps
// a1) on calcul les nombres maxi
int nb_noeud = 0; int nb_element = 0;
for (int imail=1;imail<=nbMaillageTotal;imail++)
{ nb_noeud += tabMaillage(imail)->Nombre_noeud();
nb_element += tabMaillage(imail)->Nombre_element();
};
// a2) on crée maintenant les éléments frontières car cela utilise les numéros des noeuds, qui vont être changé
// mais ce n'est pas toujours bien de recréer les frontières, car on peut avoir des grandeurs qui dépendent des frontières
// comme par exemple les éléments de contact: si on refait les frontières, il faut refaire les éléments de contact
// or la renumérotation n'a pas à changer les frontières en elles-mêmes
// donc on adopte une création conditionnelle
if ((listFrontiere.Taille() == 0) || (tt_noeud_front.Taille() == 0))
LesMaillages::CreeElemFront(); // on crée les éléments frontières
// b) on crée les tableaux
Tableau <Noeud *> t_noe(nb_noeud); // le tableau global de noeuds
Tableau <int > t_oldNumNoeud(nb_noeud); // tableau des anciens numéros de noeuds
Tableau<Element *> t_elem(nb_element); // le tableau global des éléments
// c) on rempli les tableaux en changeant les numéros des noeuds (pour avoir une seule numérotation)
// normalement cela n'influe pas sur les éléments car eux ils contiennent des tableaux de pointeur de noeuds
int numGlobNoeud=1; int numGlobEle = 1;
for (int imil=1;imil<=nbMaillageTotal;imil++)
{ int nbn = tabMaillage(imil)->Nombre_noeud();
Tableau<Noeud *>& tab_noeud = tabMaillage(imil)->Tab_noeud();
for (int inoe = 1; inoe <= nbn; inoe++,numGlobNoeud++)
{ t_noe(numGlobNoeud) = tab_noeud(inoe);
t_oldNumNoeud(numGlobNoeud) = tab_noeud(inoe)->Num_noeud();
t_noe(numGlobNoeud)->Change_num_noeud(numGlobNoeud);
};
int nb_ele = tabMaillage(imil)->Nombre_element();
Tableau<Element *>& tab_element = tabMaillage(imil)->Tab_element();
for (int iel = 1; iel <= nb_ele; iel++,numGlobEle++)
{ t_elem(numGlobEle) = tab_element(iel);
};
};
// avant tout changement on calcul la largeur initiale due aux conditions linéaires
// celle-ci n'est valide que dans le cas où tous les noeuds ont des numéros différents
// ce qui est le cas maintenant
int taille_tab_cll = tab_condCLL.Taille();
int largeur_initiale_CLL = 0; // init
for (int i = 1; i<= taille_tab_cll;i++)
{ Tableau <Condilineaire>& condCLL = tab_condCLL(i);
int taille = condCLL.Taille();
for (int j=1;j<= taille;j++)
largeur_initiale_CLL=MaX(largeur_initiale_CLL,condCLL(j).DiffMaxiNumeroNoeud());
};
if ((ParaGlob::NiveauImpression() > 4)
|| ((nb_casAssemb == NULL)&&(ParaGlob::NiveauImpression() > 0))
)
{ cout << "\n pour l'ensemble des conditions linaires: via une numerotation unique pour tous les maillages, "
<< " la 1/2 largeur de bande en noeud initiale est "
<< largeur_initiale_CLL << flush;
};
bool nouvelle_numerotation = false; // pour le contrôle de la fin
// on calcul le point de départ
Tableau < LaLIST_io <Noeud* > > t_voisin; // def du tableau des voisins des noeuds
list < list < Maillage::Noeud_degre > > lis_descent; // stockage des descendants
bool calcul_ok = false; // init par défaut
Noeud* noe_dep = Maillage::Point_de_depart(t_elem,t_noe,tt_noeud_front,t_voisin,lis_descent,tab_condCLL,calcul_ok);
if (calcul_ok) // on ne continue que si c'est ok
{// on appelle l'algorithme de Cuthill Mac Kee
Tableau <Noeud* > tab_N_final = Maillage::Cuthill_Mac_Kee(nb_noeud,noe_dep,t_voisin,lis_descent);
// --- maintenant on regarde l'évolution de la largeur de bande en noeud
// tout d'abord la largeur initiale
int largeur_initiale = Maillage::LargeurBandeEnNoeuds(t_elem);
// on change la numérotation
for (int ia=1;ia <= nb_noeud; ia++)
tab_N_final(ia)->Change_num_noeud(ia);
// nouvelle largeur de bande
int largeur_Cuthill = Maillage::LargeurBandeEnNoeuds(t_elem);
// idem pour les CLL
int largeur_Cuthill_CLL = 0; // init
for (int i = 1; i<= taille_tab_cll;i++)
{ Tableau <Condilineaire>& condCLL = tab_condCLL(i);
int taille = condCLL.Taille();
for (int j=1;j<= taille;j++)
largeur_Cuthill_CLL=MaX(largeur_Cuthill_CLL,condCLL(j).DiffMaxiNumeroNoeud());
};
// on change en numérotation inverse : Cuthill Mac Kee inverse
// car on pense qu'a priori c'est celle-là qui sera la meilleur
///// Tableau <Noeud* > tab_N_inverse(tab_N_final);
for (int ia=1;ia <= nb_noeud; ia++)
{tab_N_final(ia)->Change_num_noeud(1+nb_noeud-ia);
// avec les modifs que j'ai fait après la ligne qui suit ne sert plus ???
///// tab_N_inverse(1+nb_noeud-ia) = tab_N_final(ia);
};
int largeur_Cuthill_inverse = Maillage::LargeurBandeEnNoeuds(t_elem);
// idem pour les CLL
int largeur_Cuthill_inverse_CLL = 0; // init
for (int i = 1; i<= taille_tab_cll;i++)
{ Tableau <Condilineaire>& condCLL = tab_condCLL(i);
int taille = condCLL.Taille();
for (int j=1;j<= taille;j++)
largeur_Cuthill_inverse_CLL=MaX(largeur_Cuthill_inverse_CLL,condCLL(j).DiffMaxiNumeroNoeud());
};
if ((ParaGlob::NiveauImpression() > 3)
|| ((nb_casAssemb == NULL)&&(ParaGlob::NiveauImpression() > 0))
)
{ cout << "\n $$ Premiere etape: optimisation sur l'ensemble des maillages sous forme d'un seul groupe $$ ";
cout << "\n pour l'ensemble des maillages: 1/2 largeur de bande en noeud, initiale= " << largeur_initiale
<< "\n partie conditions lineaires initiales : " << largeur_initiale_CLL
<< " --> maxi des deux: " << MaX(largeur_initiale_CLL, largeur_initiale)
<< " \n apres l'algo de Cuthill Mac Kee= " << largeur_Cuthill
<< ", conditions lineaires : " << largeur_Cuthill_CLL
<< " --> maxi des deux: " << MaX(largeur_Cuthill_CLL, largeur_Cuthill)
<< " \n en Cuthill Mac Kee inverse= " << largeur_Cuthill_inverse
<< ", conditions lineaires : " << largeur_Cuthill_inverse_CLL
<< " --> maxi des deux: " << MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse)<< flush ;
};
// normalement le dernier est le meilleur, en tout cas il est meilleur que le cas 2
// ----- dernières opérations: on regarde si effectivement il faut appliquer la nouvelle
// ----- numérotation
int demi_largeur_totale=MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse);
if (MaX(largeur_initiale_CLL, largeur_initiale)
< MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse))
// if (largeur_initiale < largeur_Cuthill_inverse)
// bizarre, cela veut dire qu'il faut revenir à la forme initiale
{ for (int ia=1;ia <= nb_noeud; ia++)
t_noe(ia)->Change_num_noeud(t_oldNumNoeud(ia));
demi_largeur_totale = MaX(largeur_initiale_CLL, largeur_initiale);
}
else if (MaX(largeur_Cuthill_CLL, largeur_Cuthill)
< MaX(largeur_Cuthill_inverse_CLL, largeur_Cuthill_inverse) )
// else if (largeur_Cuthill < largeur_Cuthill_inverse )
// bizarre, cela veut dire qu'il faut revenir à la forme de Cuthill directe
{ nouvelle_numerotation = true;
// on met la numérotation définitive relativement au tableau directe
Tableau <int> num_courant(nbMaillageTotal); // tableau des numéros courant de noeud
// pour chaque maillage
for (int ia=1;ia <= nb_noeud; ia++)
// je ne comprend pas ce que j'ai fait. je modifie en faisant ce que je pense être bon ???
////modifié { Noeud* noe = tab_N_final(ia); // pour simplifier
////modifié int num = (num_courant(noe->Num_Mail())++);
////modifié noe->Change_num_noeud(num);
////modifié };
tab_N_final(ia)->Change_num_noeud(ia);
demi_largeur_totale = MaX(largeur_Cuthill_CLL, largeur_Cuthill);
}
else
// c'est le cas normale
{ nouvelle_numerotation=true;
// on met la numérotation définitive relativement au tableau inverse
// là je ne comprend pas ce que j'ai fait, car la numérotation inverse a déjà été faite donc il n'y a rien
// à faire, je comment donc la suite
//// Tableau <int> num_courant(nbMaillageTotal); // tableau des numéros courant de noeud
//// // pour chaque maillage
//// for (int ia=1;ia <= nb_noeud; ia++)
//// { Noeud* noe = tab_N_inverse(ia); // pour simplifier
//// int num = (num_courant(noe->Num_Mail())++);
//// noe->Change_num_noeud(num);
//// };
};
// on calcule si demandé, la largeur de bande en ddl qui résulte de la nouvelle numérotation
// avant de changer les numéros de noeuds
// et la mise à jour des pointeurs d'assemblages
Tableau <Noeud*> tab_N_final_final;// ne sert que pour le cas nb_casAssemb != NULL
if (nouvelle_numerotation && (nb_casAssemb != NULL))
{ // on garde en mémoire la numérotation des noeuds, dans l'ordre de tab_N_final
// car on ne connait pas exactement le cheminement précédent de ce qui est retenue au final
tab_N_final_final.Change_taille(nb_noeud);
for (int i=1;i<=nb_noeud;i++)
tab_N_final_final(tab_N_final(i)->Num_noeud()) = tab_N_final(i);
// on met à jour les pointeurs d'assemblage en suivant le nouvel ordre de noeud
MiseAJourPointeurAssemblage_interne(*nb_casAssemb,tab_N_final_final);
// on calcul la largeur finale
int demi = 0; int total = 0;
int cumule = 0;
// cas des CLL:
for (int i = 1; i<= taille_tab_cll;i++)
{ Tableau <Condilineaire>& condCLL = tab_condCLL(i);
int taille = condCLL.Taille();
for (int j=1;j<= taille;j++)
condCLL(j).Largeur_Bande(demi,total,*nb_casAssemb);
};
// on s'occupe des maillages
int demi_pour_mail=0; int total_pour_mail=0;
for (int imil=1;imil<=nbMaillageTotal;imil++)
{int demi_inter=0; int total_inter=0;
tabMaillage(imil)->Largeur_Bande(demi_inter,total_inter,*nb_casAssemb);
demi_pour_mail = MaX(demi_pour_mail,demi_inter);
total_pour_mail =MaX(total_pour_mail,total_inter);
};
// on garde les maxi
demi = MaX(demi,demi_pour_mail);
total =MaX(total,total_pour_mail);
// enregistrement
nouvelles_largeur_en_ddl.deux = demi;
nouvelles_largeur_en_ddl.un = total;
nouvelles_largeur_en_ddl.trois = demi_pour_mail;
if (ParaGlob::NiveauImpression() > 2)
cout << "\n $$$ ==>> opti. glob. numerot. $$$ "
<< " 1/2 larg. ddl ==> " << demi
<< " larg. totale ==> " << total;
//cout << "\n entrer une valeur pour continuer ";
//int toto; cin >> toto;
};
// dans le cas d'une nouvelle numérotation + dans le cas où on veut un changement
// de numérotation effectif dans les noeuds
// ->> introduction de la nouvelle numérotation dans les noeuds et mise à jour des reférences
if ((nouvelle_numerotation) && (!sans_changement_num_noeud))
// il faut donc redéfinir une numérotation pour chaque maillage. Celle-ci
// ne sera pas aussi optimum que dans le cas d'un seul maillage, mais elle devrait
// être meilleure
// -- un tableau d'indice qui donne le nouveau numéro en cours pour chaque maillage
{ Tableau<int> num_noeu_par_maillage(nbMaillageTotal,0);
// un nouveau tableau intermédiaire tel que le noeud t_noe_ordonnee(i), a le numéro i
Tableau <Noeud *> t_noe_ordonnee(nb_noeud); // le tableau global de noeuds
for (int ia=1;ia <= nb_noeud; ia++)
{ Noeud* noe = t_noe(ia); // pour simplifier
t_noe_ordonnee(noe->Num_noeud()) = noe;
};
// si nouvelle numérotation est vrai, on parcourt le tableau et on renumérote à la volée
// la méthode revient à compresser la numérotation pour chaque maillage de manière a
// rester dans les limites du nombre de noeud pour chaque maillage
for (int ia=1;ia <= nb_noeud; ia++)
{ Noeud* noe = t_noe_ordonnee(ia); // pour simplifier
int num_mail = noe->Num_Mail();
num_noeu_par_maillage(num_mail)++;
////--debug
//cout << "\n debug LesMaillages::Renumerotation( "
// << "\n num_noeu_par_maillage("<<num_mail<<")= "<< num_noeu_par_maillage(num_mail)<<flush;
////--- fin debug
noe->Change_num_noeud(num_noeu_par_maillage(num_mail));
};
// Maintenant on s'occupe des références et de la numérotation définitive
// si on a introduit une nouvelle numérotation
// -- on s'occupe des numéros de référence
// 1) on définit un tableau par maillage qui contient les nouveaux numéros
// t_nv_num(j)(i) est pour le maillage j, le nouveau numéro du noeud
// qui avait auparavant le numéro "i"
Tableau <Tableau <int> > t_nv_num(nbMaillageTotal); // nouveau num/ au ancien
for (int iml=1; iml<= nbMaillageTotal;iml++)
t_nv_num(iml).Change_taille(tabMaillage(iml)->Nombre_noeud()); // init
for (int ia=1;ia <= nb_noeud; ia++)
{ Noeud* noe = t_noe(ia); // pour simplifier, on utilise t_noe et non t_noe_ordonnee
// car ensuite on utilise t_oldNumNoeud qui suit le même ordre que t_noe
// //--debug
// cout << "\n debug LesMaillages::Renumerotation( "
// << "\n noe->Num_Mail()= "<<noe->Num_Mail() <<", ia= "<< ia
// << " noe->Num_noeud()= "<<noe->Num_noeud()
// << " t_oldNumNoeud(ia)= "<< t_oldNumNoeud(ia) << flush;
////--- fin debug
t_nv_num(noe->Num_Mail())(t_oldNumNoeud(ia))=noe->Num_noeud();
};
// 2) maintenant on change les références
for (int idmail=1;idmail<=nbMaillageTotal;idmail++)
lesRef.Mise_a_jour_ref_noeud(t_nv_num(idmail),idmail);
// --- on reconstruit les tableaux de pointeurs de noeuds dans chaque maillage
// a) on crée un tableau intermédiaire de tous les tableaux de noeuds
Tableau <Tableau <Noeud *> *> t_t_noeud(nbMaillageTotal);
for (int iml=1; iml<= nbMaillageTotal;iml++)
t_t_noeud(iml) = &(tabMaillage(iml)->Tab_noeud()); // init
// b) on le remplit
for (int ia=1;ia <= nb_noeud; ia++)
{ Noeud* noe = t_noe_ordonnee(ia); // pour simplifier
(*t_t_noeud(noe->Num_Mail()))(noe->Num_noeud()) = noe;
};
};
// affichage du résultat et éventuellement deuxième étape concernant le
// changement des pointeurs d'assemblage
if (nouvelle_numerotation)
{if (nb_casAssemb == NULL) // cas sans changement des pointeurs
// si on ne veut pas changer les pointeurs d'assemblage dans la foulée
// on met une information sur la largeur de bande nouvelle, en noeud,
// qui découle de la nouvelle numérotation (et non de l'assemblage)
{
int largeur_finale_CLL = 0; // init
for (int i = 1; i<= taille_tab_cll;i++)
{ Tableau <Condilineaire>& condCLL = tab_condCLL(i);
int taille = condCLL.Taille();
for (int j=1;j<= taille;j++)
largeur_finale_CLL=MaX(largeur_finale_CLL,condCLL(j).DiffMaxiNumeroNoeud());
};
if (ParaGlob::NiveauImpression() > 0)
{ cout << "\n pour l'ensemble des conditions linaires: la 1/2 largeur de bande en noeud, finale est "
<< largeur_finale_CLL << flush;
};
// non c'est débile, car on n'a pas fait de nouvelle numérotation en ddl, donc cela ne sert à rien de les imprimer
// et au niveau de la numérotation en noeud, c'est déja visualisé
/*
int demi = 0; int total = 0;
int cumule = 0;
// on est quand même obligé de considérer un cas d'assemblage, on prend le dernier
// par défaut
// on récupère le nombre actuel de cas d'assemblage
int nb_actuel = tab_nb_assemb;
#ifdef MISE_AU_POINT
if (nb_actuel == 0)
{cout << "\n erreur Renumerotation : pas de cas d'assemblage encore defini !! "
<< " la renumerotation n'est pas possible ....";
Sortie(1);
};
#endif
Nb_assemb nbAssemble(nb_actuel);
// cas des CLL:
for (int i = 1; i<= taille_tab_cll;i++)
{ Tableau <Condilineaire>& condCLL = tab_condCLL(i);
int taille = condCLL.Taille();
for (int j=1;j<= taille;j++)
condCLL(j).Largeur_Bande(demi,total,nbAssemble);
};
// on s'occupe des maillages
int demi_pour_mail=0; int total_pour_mail=0;
for (int imil=1;imil<=nbMaillageTotal;imil++)
{int demi_inter=0; int total_inter=0;
tabMaillage(imil)->Largeur_Bande(demi_inter,total_inter,nbAssemble);
demi_pour_mail = MaX(demi_pour_mail,demi_inter);
total_pour_mail =MaX(total_pour_mail,total_inter);
};
// on garde les maxi
demi = MaX(demi,demi_pour_mail);
total =MaX(total,total_pour_mail);
// enregistrement
nouvelles_largeur_en_ddl.deux = demi;
nouvelles_largeur_en_ddl.un = total;
nouvelles_largeur_en_ddl.trois = demi_pour_mail;
// affichage du résultat
if (ParaGlob::NiveauImpression() >= 3)
cout << "\n $$$ =>> opti. glob. numerot. $$$ "
<< " 1/2 larg. ddl => " << demi
<< " larg. totale => " << total
<< flush;
*/
}
else // sinon c'est le cas où on veut changer les pointeurs d'assemblage
{// deuxième partie pour les pointeurs d'assemblage:
// on doit mettre à jour le tableau t_i_n pour les pointeurs d'assemblage
// concernant uniquement les numéros de noeuds
// --> deux cas suivant que l'on ne veut pas enregistrer la nouvelle numérotation
// des noeuds ou non
if (sans_changement_num_noeud)
{ // mise à jour des numéros de noeud, on revient aux numéros initiaux
// on revient au numéro initiaux
for (int i=1;i<=nb_noeud;i++)
t_noe(i)->Change_num_noeud(t_oldNumNoeud(i));
// pour chaque noeud, tab_N_final(i) correspond au noeud qui avait le numéro i ancien
// et qui a maintenant le numéro tab_N_final(i)->Num_noeud()
// mise à jour de t_i_n
MiseAJourTableau_t_i_n(*nb_casAssemb,tab_N_final_final);
}
else
{MiseAJourTableau_t_i_n(*nb_casAssemb,tab_N_final_final);
};
};
}
else
{// on remet néanmoins l'ancienne numérotation, car elle a changé
int nbN = t_noe.Taille();
for (int i=1;i<=nbN;i++)
t_noe(i)->Change_num_noeud(t_oldNumNoeud(i));
if (ParaGlob::NiveauImpression() >= 3)
cout << "\n $$$ au final numerot. idem $$$ " << flush;
nouvelle_numerotation = false;
calcul_ok = true;
};
};
// retour
return (calcul_ok && nouvelle_numerotation);
};
// renumérotation des noeuds maillages par maillage,
// === sans prise en compte de conditions linéaires ===
// en sortie les maillages sont mis à jour si la nouvelle numérotation conduit à une largeur de bande
// plus faible que la largeur initiale: en noeuds
// ramène: false si rien n'a changé (à cause d'un pb ou parce que la renumérotation n'est pas meilleure)
// vrai sinon
bool LesMaillages::Renumerotation(LesReferences& lesRef)
{ // on crée les éléments frontières car cela utilise les numéros des noeuds, qui vont être changé
// mais ce n'est pas toujours bien de recréer les frontières, car on peut avoir des grandeurs
// qui dépendent des frontières
// comme par exemple les éléments de contact: si on refait les frontières,
// il faut refaire les éléments de contact
// or la renumérotation n'a pas à changer les frontières en elles-mêmes
// donc on adopte une création conditionnelle
if ((listFrontiere.Taille() == 0) || (tt_noeud_front.Taille() == 0))
LesMaillages::CreeElemFront(); // on crée les éléments frontières
// on passe en revue tous les maillages pour une renumérotation individuelle
bool calcul_ok = false; // init par défaut
Tableau <Tableau <Condilineaire> > condCLL; // un tableau vide pour l'appel
for (int imail=1;imail<=nbMaillageTotal;imail++)
{ if (ParaGlob::NiveauImpression() > 2)
cout << "\n ===>> traitement du maillage: " << tabMaillage(imail)->NomDuMaillage();
bool inter = tabMaillage(imail)->Renumerotation(lesRef,condCLL);
calcul_ok = calcul_ok || inter;
};
// retour
return calcul_ok ;
};
// indique aux éléments un niveau de précision de calcul désiré pour les prochains calculs
// precision = 0 : aucune précision demandée, precision >=0 : précision maximale demandée
void LesMaillages::Drapeau_preparation_calcul_precis(int precision)
{for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbelmax = Nombre_element(i1);
Maillage* maillage = tabMaillage(i1); // pour simplifier
for (int jel = 1; jel <= nbelmax; jel++)
{ maillage->Element_mail(jel).Drapeau_preparation_calcul_precis(precision);};
};
};
// on s'occupe de mettre à jour les types de pb et les ddl types associés
void LesMaillages::Mise_a_jour_type_pb_type_associe_ddl()
{ types_de_problemes.clear();
ddl_representatifs_des_physiques.clear();
for (int i = 1; i<= nbMaillageTotal; i++)
{
{//const list <EnumElemTypeProblem >& type_pb = (tabMaillage(i))->Types_de_problemes(); // pour simplifier
const Tableau <EnumElemTypeProblem >& type_pb = (tabMaillage(i))->Types_de_problemes(); // pour simplifier
// list <EnumElemTypeProblem>::const_iterator il,ilfin=type_pb.end();
// for (il=type_pb.begin();il != ilfin;il++)
int taill = type_pb.Taille();
for (int j=1;j<=taill;j++)
if (find(types_de_problemes.begin(),types_de_problemes.end(),type_pb(j)) == types_de_problemes.end())
types_de_problemes.push_back(type_pb(j));//(*il);
};
{//const list <Enum_ddl >& type_ddl = (tabMaillage(i))->Ddl_representatifs_des_physiques(); // pour simplifier
//list <Enum_ddl>::const_iterator il,ilfin=type_ddl.end();
//for (il=type_ddl.begin();il != ilfin;il++)
const Tableau <Enum_ddl >& type_ddl = (tabMaillage(i))->Ddl_representatifs_des_physiques(); // pour simplifier
int taill = type_ddl.Taille();
for (int j=1;j<=taill;j++)
if (find(ddl_representatifs_des_physiques.begin(),ddl_representatifs_des_physiques.end()
,type_ddl(j)) == ddl_representatifs_des_physiques.end())
ddl_representatifs_des_physiques.push_back(type_ddl(j));
};
};
types_de_problemes.sort(); types_de_problemes.unique();
ddl_representatifs_des_physiques.sort(); ddl_representatifs_des_physiques.unique();
};
// --- utilitaires pour calculs particuliers-------
// Tableau <TypeQuelconque> integ_vol_typeQuel, integ_vol_typeQuel_t;
// Tableau <const Reference*> ref_integ_vol; // les références associées
// // 2) intégration de volume et en temps: donc on commule le delta
// Tableau <TypeQuelconque> integ_vol_t_typeQuel, integ_vol_t_typeQuel_t;
// Tableau <const Reference*> ref_integ_vol_t; // les références associées
// LesReferences* lesRef; // references
// calcul des diverses intégrations: volume et volume + temps,
// alimentation des grandeurs globales associées
void LesMaillages::Integration()
{ // on passe en revue les références de volumes a intégrer
// Tableau <const Reference*> ref_integ_vol; // les références associées
// les références sont ordonnées par apparition dans le fichier .info
// des intégrales, ceci permet de repérer les bonnes grandeurs à cummuler
int taill = ref_integ_vol.Taille();
for (int rang_integ =1;rang_integ<= taill;rang_integ++)
if (ref_integ_vol(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas
// l'intégrale stockée reste fixe pendant le calcul
{ const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol(rang_integ));
// initialisation du conteneur relatif à chaque ref
TypeQuelconque& TQ = integ_vol_typeQuel(rang_integ); // pour simplifier
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
g_TG->InitParDefaut(); // on initialise le conteneur
// cumule des valeurs: on récupère les infos à partir des éléments concernés
int ref_Taille=ref->Taille();
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero de l'element dans le maillage
int nnn = ref->Nbmaille(); // le numero du maillage
// recup de l'element
Element * poi = & Element_LesMaille(nnn,nbb);
// demande a l'element des infos
const Tableau <TypeQuelconque>* tab_Q = poi->Integ_vol_typeQuel();
const Tableau <int>& index_integ = *(poi->Index_Integ_vol_typeQuel());
// la grandeur à cumuler c'est celle qui a le bon indexe
int indice = index_integ.Contient(rang_integ);
*(g_TG) += *((*tab_Q)(indice).Grandeur_pointee());
// -- les deux lignes d'avant sont a priori équivalentes aux lignes qui suivent
// int nb_integ = tab_Q->Taille(); // le nombre d'intégrale à considérer
// for (int iteg = 1;iteg <= nb_integ;iteg++)
// {if ((index_integ)(iteg)==rang_integ) // si l'index est négatif, on ne cumule pas
// // cela veut aussi dire que l'intégrale est figée
// // sinon si on a le bon index: on cumule l'intégrale
// {*(g_TG) += *((*tab_Q)(iteg).Grandeur_pointee());
// break;
// };
// };
};
// maintenant il s'agit d'alimenter les grandeurs globales
// on récupère le pointeur correspondant à la grandeur correspondant au nom
// de référence
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Integration()"<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " la variable globale "<< (*nom_de_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesMaillages::Integration()"<<flush;
Sortie(1);
};
#endif
// on l'affecte
//// --- debug
//cout << "\n debug LesMaillages::Integration() "
// << " \n valeur de l'integral: " << g_TG->Nom_ref()
// << " :: " << *(g_TG) << flush;
//
//// -- fin debug
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
*(gr_quelc->Grandeur_pointee()) = *(g_TG);
};
// même chose pour les intégrales en volume et en temps
int taill1 = ref_integ_vol_t.Taille();
for (int rang_integ =1;rang_integ<= taill1;rang_integ++)
if (ref_integ_vol_t(rang_integ) != NULL) // si null cela veut que l'on n'intègre pas
// l'intégrale stockée reste fixe pendant le calcul
{ const ReferenceNE * ref = ((ReferenceNE *) ref_integ_vol_t(rang_integ));
// initialisation du conteneur relatif à chaque ref
TypeQuelconque& TQ = integ_vol_t_typeQuel(rang_integ); // pour simplifier
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
g_TG->InitParDefaut(); // on initialise le conteneur
// cumule des valeurs: on récupère les infos à partir des éléments concernés
int ref_Taille=ref->Taille();
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero de l'element dans le maillage
int nnn = ref->Nbmaille(); // le numero du maillage
// recup de l'element
Element * poi = & Element_LesMaille(nnn,nbb);
// demande a l'element des infos
const Tableau <TypeQuelconque>* tab_Q = poi->Integ_vol_t_typeQuel();
const Tableau <int>& index_integ = *(poi->Index_Integ_vol_t_typeQuel());
// la grandeur à cumuler c'est celle qui a le bon indexe
int indice = index_integ.Contient(rang_integ);
*(g_TG) += *((*tab_Q)(indice).Grandeur_pointee());
// -- les deux lignes d'avant sont a priori équivalentes aux lignes qui suivent
// int nb_integ = tab_Q->Taille(); // le nombre d'intégrale à considérer
// for (int iteg = 1;iteg <= nb_integ;iteg++)
// {if ((index_integ)(iteg)==rang_integ)
// // sinon si on a le bon index: on cumule l'intégrale
// {*(g_TG) += *((*tab_Q)(iteg).Grandeur_pointee());
// break;
// };
// };
};
// maintenant il s'agit d'alimenter les grandeurs globales
// on récupère le pointeur correspondant à la grandeur correspondant au nom
// de référence
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::Integration()"<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans l'integration !! "
<< " la variable globale "<< (*nom_de_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesMaillages::Integration()"<<flush;
Sortie(1);
};
#endif
// on l'affecte
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
*(gr_quelc->Grandeur_pointee()) = *(g_TG);
};
};
// calcul des diverses statistiques sur des ref de noeuds et avec éventuellement
// cumul sur le temps
// alimentation des grandeurs globales associées
void LesMaillages::CalStatistique()
{ // on passe en revue les références de noeud des statistiques
{// Tableau <const Reference*> ref_statistique; // les références associées
int NB_ref = ref_statistique.Taille();
if (NB_ref)
{// on boucle sur les ref
for (int i_ref =1;i_ref<= NB_ref;i_ref++)
if (ref_statistique(i_ref) != NULL) // si null cela veut que l'on ne fait rien
// la statistique stockée reste fixe pendant le calcul
{ const ReferenceNE * ref = ((ReferenceNE *) ref_statistique(i_ref));
// initialisation du conteneur relatif à chaque ref
TypeQuelconque& TQ = statistique_typeQuel(i_ref); // pour simplifier
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
g_TG->InitParDefaut(); // on initialise le conteneur
int ref_Taille=ref->Taille();
int i_mail = ref->Nbmaille(); // le numero du maillage
Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier
Fonction_nD* fct = gr.Fct(); // récupération d'un pointeur de fonction nD
// différent choix
if (fct == NULL)
{ // cas d'un stockage pour ddl_etendu
Ddl_enum_etendu& ddl_enu_eten = pour_statistique_de_ddl(i_ref);// récup du ddl
// on veut : (1) la somme, (2) la moyenne, (3) le max, (4) le min, (5) le max des | | , (6) le min des | |
// tab_val(k) : la grandeur k
// tab_index(k) : k= 1 -> le numéro du noeud pour le max
// k= 2 -> le numéro du noeud pour le min
// k= 3 -> le numéro du noeud pour le max des | |
// k= 4 -> le numéro du noeud pour le min des | |
// t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k)
Vecteur& t10 = (gr.ConteneurVecteur());
t10(4)=t10(6)=ConstMath::tresgrand; // on met les mini très grand
// t10(i), i=7 à 10 --> correspond aux numéros de noeud, stockés en double au lieu de int
// == tab_index(k)
// ceci pour utiliser uniquement un seul conteneur global
double& tab_pour_MAXI_1 = t10(7);
double& tab_pour_MAXI_2 = t10(8);
double& tab_pour_MAXI_3 = t10(9);
double& tab_pour_MAXI_4 = t10(10);
// on regarde s'il s'agit d'un ddl pur ou étendu
if (ddl_enu_eten.Nom_vide())
// cas d'un ddl pur
{// récup de l'énumération
Enum_ddl enu = ddl_enu_eten.Enum();
// cumule des valeurs: on récupère les infos à partir des noeuds concernés
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage
// récupération du Noeud
Noeud& noe = Noeud_LesMaille(i_mail,nbb);
// récup de la valeur du ddl
double val_du_ddl = 0.; // init
if (noe.Existe_ici(enu))
{val_du_ddl = noe.Ddl_noeud_tdt(enu).Valeur();}
#ifdef MISE_AU_POINT
else
{if (ParaGlob::NiveauImpression() >= 4)
{if (ParaGlob::Francais())
{cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein()
<< " n'est pas disponible pour statistique, on met 0 a la place";}
else
{cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein()
<< " is not available for statistic, the value will be 0 ";};
};
};
#endif
// le calcul des grandeurs
t10(1) += val_du_ddl;
t10(2) += 1.; // on s'en sert ici comme compteur
int num_noeud = noe.Num_noeud();
if (t10(3) < val_du_ddl)
{ t10(3) = val_du_ddl;
tab_pour_MAXI_1 = num_noeud;
};
if (t10(4) > val_du_ddl)
{ t10(4) = val_du_ddl;
tab_pour_MAXI_2 = num_noeud;
};
if (Dabs(t10(5)) < Dabs(val_du_ddl))
{ t10(5) = val_du_ddl;
tab_pour_MAXI_3 = num_noeud;
};
if (Dabs(t10(6)) > Dabs(val_du_ddl))
{ t10(6) = val_du_ddl;
tab_pour_MAXI_4 = num_noeud;
};
};
// calcul de la moyenne
t10(2) = t10(1) / t10(2);
}
else // cas d'un ddl étendu
{// cumule des valeurs: on récupère les infos à partir des noeuds concernés
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage
// récupération du Noeud
Noeud& noe = Noeud_LesMaille(i_mail,nbb);
// récup de la valeur du ddl
double val_du_ddl = 0.; // init
// on examine tout d'abord le cas particulier des positions
bool trouver = false;
// on regarde d'abord s'il s'agit d'une info spécifique au contact
int posi = ddl_enu_eten.Position()-NbEnum_ddl();
switch (posi)
{ case 123: // "X1_t"
{ val_du_ddl = noe.Coord1()(1);trouver=true; break;}
case 124: // "X2_t"
{ val_du_ddl = noe.Coord1()(2);trouver=true; break;}
case 125: // X3_t
{ val_du_ddl = noe.Coord1()(3);trouver=true; break;}
case 126: // X1_t0
{ val_du_ddl = noe.Coord0()(1);trouver=true; break;}
case 127: // X2_t0
{ val_du_ddl = noe.Coord0()(2);trouver=true; break;}
case 128: // X3_t0
{ val_du_ddl = noe.Coord0()(3);trouver=true; break;}
default: ;// rien
};
// si ce n'était pas un cas particulier on continue la recherche
if (!trouver)
// on regarde si la grandeur existe
{if (noe.Existe_ici_ddlEtendu(ddl_enu_eten))
{val_du_ddl = noe.DdlEtendue(ddl_enu_eten).ConstValeur();}
#ifdef MISE_AU_POINT
else
{if (ParaGlob::NiveauImpression() >= 4)
{if (ParaGlob::Francais())
{cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein()
<< " n'est pas disponible pour statistique, on met 0 a la place";}
else
{cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein()
<< " is not available for statistic, the value will be 0 ";};
};
};
#endif
};
// le calcul des grandeurs
t10(1) += val_du_ddl;
t10(2) += 1.; // on s'en sert ici comme compteur
int num_noeud = noe.Num_noeud();
if (t10(3) < val_du_ddl)
{ t10(3) = val_du_ddl;
tab_pour_MAXI_1 = num_noeud;
};
if (t10(4) > val_du_ddl)
{ t10(4) = val_du_ddl;
tab_pour_MAXI_2 = num_noeud;
};
if (Dabs(t10(5)) < Dabs(val_du_ddl))
{ t10(5) = val_du_ddl;
tab_pour_MAXI_3 = num_noeud;
};
if (Dabs(t10(6)) > Dabs(val_du_ddl))
{ t10(6) = val_du_ddl;
tab_pour_MAXI_4 = num_noeud;
};
};
// calcul de la moyenne
t10(2) = t10(1) / t10(2);
}
////------- debug ---------
// cout << "\n debug statistique: ";
// cout << t10;
//
//
////------- fin debug --------
}
else // cas d'un stockage pour fonction nD
{ Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier
Fonction_nD* fct = gr.Fct(); // récupération de la fonction nD
// supposons que la fonction nD ramène n valeurs,
// pour chaque valeur on va avoir pour la valeur i :
// ((6*(i-1)+1) la somme, ((6*(i-1)+2) la moyenne, ((6*(i-1)+3) le max, ((6*(i-1)+4) le min,
// ((6*(i-1)+5) -> le numéro du noeud pour le max, ((6*(i-1)+6) -> le numéro du noeud pour le min,
// donc en tout cela donne 6*n valeurs
// ensuite on a:
// (6*n + 1) le max des | |, (6*n + 2) le min des | |,
// (6*n + 3) -> le numéro du noeud pour le max des | |
// (6*n + 4) -> le numéro du noeud pour le min des | |
// d'où un vecteur de taille (6*n + 4)
// on commence par récupérer les conteneurs des grandeurs à fournir
List_io <Ddl_enum_etendu>& li_enu_scal = fct->Li_enu_etendu_scalaire();
List_io <TypeQuelconque >& li_quelc = fct->Li_equi_Quel_evolue();
int nb_composante = fct->NbComposante();
// t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k)
Vecteur& t6 = (gr.ConteneurVecteur());
t6(4)=t6(6)=ConstMath::tresgrand; // on met les mini très grand
// cumule des valeurs: on récupère les infos à partir des noeuds concernés
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage
// récupération du Noeud
Noeud& noe = Noeud_LesMaille(i_mail,nbb);
// récupération d'une liste d'info
// le tableau de retour à la taille de li_enu_scal et contient
// les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud
// en fait ici on cumule les ddl pur "et" les ddl_étendue,
// li_quelc : est modifié par les valeurs contenues au noeud
Tableau <double> tab = noe.Valeur_multi_et_Tensorielle(li_enu_scal,li_quelc);
// récup des valeurs de la fonction
Tableau <double> & t_ret = fct->Valeur_FnD_Evoluee(&tab,&li_enu_scal,&li_quelc,NULL,NULL);
int num_noeud = noe.Num_noeud();
// le calcul des grandeurs sur chaque composante
double norme=0;
for (int i=1;i<= nb_composante;i++)
{ int decal = 6*(i-1);
double val_composante = t_ret(i);
t6(decal+1) += val_composante;
t6(decal+2) += 1.; // on s'en sert ici comme compteur
if (t6(decal+3) < val_composante)
{ t6(decal+3) = val_composante;
t6(decal+5) = num_noeud;
};
if (t6(decal+4) > val_composante)
{ t6(decal+4) = val_composante;
t6(decal+6) = num_noeud;
};
norme +=val_composante*val_composante;
};
// on traite la norme
int decal = 6*nb_composante;
norme = sqrt(norme);
if (t6(decal+1) < norme)
{ t6(decal+1) = norme;
t6(decal+3) = num_noeud;
};
if (t6(decal+2) > norme)
{ t6(decal+2) = norme;
t6(decal+4) = num_noeud;
};
};
// on calcule les moyennes
for (int i=1;i<= nb_composante;i++)
{ int decal = 6*(i-1);
t6(decal+2) = t6(decal+1)/t6(decal+2);
};
};
// maintenant il s'agit d'alimenter les grandeurs globales
// on récupère le pointeur correspondant à la grandeur correspondant au nom
// de référence
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans le transfert d'une statistique !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::CalStatistique()"<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans le transfert d'une statistique !! "
<< " la variable globale "<< (*nom_de_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesMaillages::CalStatistique()"<<flush;
Sortie(1);
};
#endif
// on l'affecte
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
*(gr_quelc->Grandeur_pointee()) = *(g_TG);
};
}; // fin de la boucle sur les ref
};
// idem pour l'accumulation en temps
{// Tableau <const Reference*> ref_statistique_t; // les références associées
int NB_ref = ref_statistique_t.Taille();
if (NB_ref)
{// on boucle sur les ref
for (int i_ref =1;i_ref<= NB_ref;i_ref++)
if (ref_statistique_t(i_ref) != NULL) // si null cela veut que l'on ne fait rien
// la statistique stockée reste fixe pendant le calcul
{ const ReferenceNE * ref = ((ReferenceNE *) ref_statistique_t(i_ref));
// initialisation du conteneur relatif à chaque ref
TypeQuelconque& TQ = statistique_t_typeQuel(i_ref); // pour simplifier
TypeQuelconque& TQ_t = statistique_t_typeQuel_t(i_ref); // le précédent
// le conteneur qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG = TQ.Grandeur_pointee();
g_TG->InitParDefaut(); // on initialise le conteneur
int ref_Taille=ref->Taille();
int i_mail = ref->Nbmaille(); // le numero du maillage
Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier
Fonction_nD* fct = gr.Fct(); // récupération d'un pointeur de fonction nD
// le conteneur à t qui contient le résultat globalisé
TypeQuelconque::Grandeur* g_TG_t = TQ_t.Grandeur_pointee();
Grandeur_Vecteur_Nommer& gr_t = *((Grandeur_Vecteur_Nommer*) g_TG_t);
// différent choix
if (fct == NULL)
{ // cas d'un stockage pour ddl_etendu
Ddl_enum_etendu& ddl_enu_eten = pour_statistique_t_de_ddl(i_ref);// récup du ddl
// on veut : (1) la somme, (2) la moyenne, (3) le max, (4) le min, (5) le max des | | , (6) le min des | |
// tab_val(k) : la grandeur k
// tab_index(k) : k= 1 -> le numéro du noeud pour le max
// k= 2 -> le numéro du noeud pour le min
// k= 3 -> le numéro du noeud pour le max des | |
// k= 4 -> le numéro du noeud pour le min des | |
// t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k)
Vecteur& t10 = (gr.ConteneurVecteur());
t10(4)=t10(6)=ConstMath::tresgrand; // on met les mini très grand
// t10(i), i=7 à 10 --> correspond aux numéros de noeud, stockés en double au lieu de int
// == tab_index(k)
// ceci pour utiliser uniquement un seul conteneur global
double& tab_pour_MAXI_1 = t10(7);
double& tab_pour_MAXI_2 = t10(8);
double& tab_pour_MAXI_3 = t10(9);
double& tab_pour_MAXI_4 = t10(10);
// on regarde s'il s'agit d'un ddl pur ou étendu
if (ddl_enu_eten.Nom_vide())
// cas d'un ddl pur
{// récup de l'énumération
Enum_ddl enu = ddl_enu_eten.Enum();
// cumule des valeurs: on récupère les infos à partir des noeuds concernés
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage
// récupération du Noeud
Noeud& noe = Noeud_LesMaille(i_mail,nbb);
// récup de la valeur du ddl
double val_du_ddl = 0.; // init
// on regarde si la grandeur existe
if (noe.Existe_ici(enu))
{val_du_ddl = noe.Ddl_noeud_tdt(enu).Valeur();}
#ifdef MISE_AU_POINT
else
{if (ParaGlob::NiveauImpression() >= 4)
{if (ParaGlob::Francais())
{cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein()
<< " n'est pas disponible pour statistique cumulee, on met 0 a la place";}
else
{cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein()
<< " is not available for statistic cumuled, the value will be 0 ";};
};
};
#endif
// le calcul des grandeurs
t10(1) += val_du_ddl;
t10(2) += 1.; // on s'en sert ici comme compteur
int num_noeud = noe.Num_noeud();
if (t10(3) < val_du_ddl)
{ t10(3) = val_du_ddl;
tab_pour_MAXI_1 = num_noeud;
};
if (t10(4) > val_du_ddl)
{ t10(4) = val_du_ddl;
tab_pour_MAXI_2 = num_noeud;
};
if (Dabs(t10(5)) < Dabs(val_du_ddl))
{ t10(5) = val_du_ddl;
tab_pour_MAXI_3 = num_noeud;
};
if (Dabs(t10(6)) > Dabs(val_du_ddl))
{ t10(6) = val_du_ddl;
tab_pour_MAXI_4 = num_noeud;
};
};
// calcul de la moyenne
t10(2) = t10(1) / t10(2);
// cumule sur le temps
Vecteur& t10_t = (gr_t.ConteneurVecteur());
t10(1) += t10_t(1); t10(2) += t10_t(2);
t10(3) += t10_t(3); t10(4) += t10_t(4);
t10(5) += t10_t(5); t10(6) += t10_t(6);
}
else // cas d'un ddl étendu
{// cumule des valeurs: on récupère les infos à partir des noeuds concernés
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage
// récupération du Noeud
Noeud& noe = Noeud_LesMaille(i_mail,nbb);
// récup de la valeur du ddl
double val_du_ddl = 0.; // init
// on examine tout d'abord le cas particulier des positions
bool trouver = false;
// on regarde d'abord s'il s'agit d'une info spécifique au contact
int posi = ddl_enu_eten.Position()-NbEnum_ddl();
switch (posi)
{ case 123: // "X1_t"
{ val_du_ddl = noe.Coord1()(1);trouver=true; break;}
case 124: // "X2_t"
{ val_du_ddl = noe.Coord1()(2);trouver=true; break;}
case 125: // X3_t
{ val_du_ddl = noe.Coord1()(3);trouver=true; break;}
case 126: // X1_t0
{ val_du_ddl = noe.Coord0()(1);trouver=true; break;}
case 127: // X2_t0
{ val_du_ddl = noe.Coord0()(2);trouver=true; break;}
case 128: // X3_t0
{ val_du_ddl = noe.Coord0()(3);trouver=true; break;}
default: ;// rien
};
// si ce n'était pas un cas particulier on continue la recherche
if (!trouver)
{if (noe.Existe_ici_ddlEtendu(ddl_enu_eten))
{val_du_ddl = noe.DdlEtendue(ddl_enu_eten).ConstValeur();}
#ifdef MISE_AU_POINT
else
{if (ParaGlob::NiveauImpression() >= 4)
{if (ParaGlob::Francais())
{cout << "\n attention la grandeur " << ddl_enu_eten.Nom_plein()
<< " n'est pas disponible pour statistique cumulee, on met 0 a la place";}
else
{cout << "\n Warning the quantity " << ddl_enu_eten.Nom_plein()
<< " is not available for statistic cumuled, the value will be 0 ";};
};
};
#endif
};
// le calcul des grandeurs
t10(1) += val_du_ddl;
t10(2) += 1.; // on s'en sert ici comme compteur
int num_noeud = noe.Num_noeud();
if (t10(3) < val_du_ddl)
{ t10(3) = val_du_ddl;
tab_pour_MAXI_1 = num_noeud;
};
if (t10(4) > val_du_ddl)
{ t10(4) = val_du_ddl;
tab_pour_MAXI_2 = num_noeud;
};
if (Dabs(t10(5)) < Dabs(val_du_ddl))
{ t10(5) = val_du_ddl;
tab_pour_MAXI_3 = num_noeud;
};
if (Dabs(t10(6)) > Dabs(val_du_ddl))
{ t10(6) = val_du_ddl;
tab_pour_MAXI_4 = num_noeud;
};
};
// calcul de la moyenne
t10(2) = t10(1) / t10(2);
// cumule sur le temps
Vecteur& t10_t = (gr_t.ConteneurVecteur());
t10(1) += t10_t(1); t10(2) += t10_t(2);
t10(3) += t10_t(3); t10(4) += t10_t(4);
t10(5) += t10_t(5); t10(6) += t10_t(6);
};
// ensuite on cumule sur le temps
////------- debug ---------
//cout << "\n debug statistique: ";
//cout << t10;
//
//
////------- fin debug --------
}
else // cas d'un stockage pour fonction nD
{ Grandeur_Vecteur_Nommer& gr = *((Grandeur_Vecteur_Nommer*) g_TG); // pour simplifier
Fonction_nD* fct = gr.Fct(); // récupération de la fonction nD
// supposons que la fonction nD ramène n valeurs,
// pour chaque valeur on va avoir pour la valeur i :
// ((6*(i-1)+1) la somme, ((6*(i-1)+2) la moyenne, ((6*(i-1)+3) le max, ((6*(i-1)+4) le min,
// ((6*(i-1)+5) -> le numéro du noeud pour le max, ((6*(i-1)+6) -> le numéro du noeud pour le min,
// donc en tout cela donne 6*n valeurs
// ensuite on a:
// (6*n + 1) le max des | |, (6*n + 2) le min des | |,
// (6*n + 3) -> le numéro du noeud pour le max des | |
// (6*n + 4) -> le numéro du noeud pour le min des | |
// d'où un vecteur de taille (6*n + 4)
// on commence par récupérer les conteneurs des grandeurs à fournir
List_io <Ddl_enum_etendu>& li_enu_scal = fct->Li_enu_etendu_scalaire();
List_io <TypeQuelconque >& li_quelc = fct->Li_equi_Quel_evolue();
int nb_composante = fct->NbComposante();
// t10(i), i=1 à 6 --> correspond aux 6 valeurs de statistique == tab_val(k)
Vecteur& t6 = (gr.ConteneurVecteur());
t6(4)=t6(6)=ConstMath::tresgrand; // on met les mini très grand
// cumule des valeurs: on récupère les infos à partir des noeuds concernés
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref->Numero(jj) ; // le numero du noeud dans le maillage
// récupération du Noeud
Noeud& noe = Noeud_LesMaille(i_mail,nbb);
// récupération d'une liste d'info
// le tableau de retour à la taille de li_enu_scal et contient
// les valeurs correspondantes aux Ddl_enum_etendu stockées au noeud
// en fait ici on cumule les ddl pur "et" les ddl_étendue,
// li_quelc : est modifié par les valeurs contenues au noeud
Tableau <double> tab = noe.Valeur_multi_et_Tensorielle(li_enu_scal,li_quelc);
// récup des valeurs de la fonction
Tableau <double> & t_ret = fct->Valeur_FnD_tab_scalaire(&tab);
int num_noeud = noe.Num_noeud();
// le calcul des grandeurs sur chaque composante
double norme=0;
for (int i=1;i<= nb_composante;i++)
{ int decal = 6*(i-1);
double val_composante = t_ret(i);
t6(decal+1) += val_composante;
t6(decal+2) += 1.; // on s'en sert ici comme compteur
if (t6(decal+3) < val_composante)
{ t6(decal+3) = val_composante;
t6(decal+5) = num_noeud;
};
if (t6(decal+4) > val_composante)
{ t6(decal+4) = val_composante;
t6(decal+6) = num_noeud;
};
norme +=val_composante*val_composante;
};
// on traite la norme
int decal = 6*nb_composante;
norme = sqrt(norme);
if (t6(decal+1) < norme)
{ t6(decal+1) = norme;
t6(decal+3) = num_noeud;
};
if (t6(decal+2) > norme)
{ t6(decal+2) = norme;
t6(decal+4) = num_noeud;
};
};
// on calcule les moyennes et on cumule dans le temps
// pour les composantes i
Vecteur& t6_t = (gr_t.ConteneurVecteur());
for (int i=1;i<= nb_composante;i++)
{ int decal = 6*(i-1);
t6(decal+2) = t6(decal+1)/t6(decal+2);
// le cumul dans le temps
t6(decal+1) += t6_t(decal+1);t6(decal+2) += t6_t(decal+2);
t6(decal+3) += t6_t(decal+3);t6(decal+4) += t6_t(decal+4);
};
// idem pour les normes
int decal = 6*nb_composante;
t6(decal+1) += t6_t(decal+1) ; t6(decal+2) += t6_t(decal+2);
};
// maintenant il s'agit d'alimenter les grandeurs globales
// on récupère le pointeur correspondant à la grandeur correspondant au nom
// de référence
const string* nom_de_ref = g_TG->Nom_ref();
#ifdef MISE_AU_POINT
if (nom_de_ref == NULL)
{ cout << "\n *** pb dans le transfert d'une statistique cumulee !! "
<< " nom_de_ref est nul, on ne peut pas continuer "
<< "\n LesMaillages::CalStatistique()"<<flush;
Sortie(1);
};
#endif
// récup du pointeur de conteneur
const void* pointe = (ParaGlob::param->GrandeurGlobal(*nom_de_ref));
#ifdef MISE_AU_POINT
if (pointe == NULL)
{ cout << "\n *** pb dans le transfert d'une statistique cumulee !! "
<< " la variable globale "<< (*nom_de_ref)
<< ", n'est pas disponible, on ne peut pas continuer "
<< "\n LesMaillages::CalStatistique()"<<flush;
Sortie(1);
};
#endif
// on l'affecte
TypeQuelconque* gr_quelc = (TypeQuelconque*) (pointe);
*(gr_quelc->Grandeur_pointee()) = *(g_TG);
};
}; // fin de la boucle sur les ref
};
};
// mise à jour des repères d'anisotropie
void LesMaillages::Mise_a_jour_repere_anisotropie
(DiversStockage* divers,LesFonctions_nD* lesFonctionsnD)
{ // l'idée est d'éviter de stocker les infos déjà présentes dans DiversStockage ...
// on reprend le caneva de la méthode LesMaillages::Completer
// par contre on considère que tous les dimensionnements sont corrects
// cas de la définition de repère d'anisotropie
int divers_TabRepAnisotrope_Taille=divers->TabRepAnisotrope().Taille();
for (int ii=1;ii<= divers_TabRepAnisotrope_Taille;ii++)
{ string nomRepAnisotrope = (divers->TabRepAnisotrope())(ii).NomRef(); // recup du nom de la ref
const BlocDdlLim<BlocGen_6_0>& div_TabRepAnisotrope = (divers->TabRepAnisotrope())(ii);
const Reference & refG = lesRef->Trouve(nomRepAnisotrope,div_TabRepAnisotrope.NomMaillage()); // recup de la reference
const ReferenceNE & ref = (ReferenceNE &) refG;
int ref_Taille=ref.Taille();
// creation d'un bloc general contenant des informations
// n= nombre de string, m nombre de double
BlocGen bloc(5,0) ; // par defaut
string nom_inter("repere_anisotropie_");
bloc.Change_nom(1,nom_inter); // le mot clé
// ensuite le type l'identificateur de repere
bloc.Change_nom(2,div_TabRepAnisotrope.Nom(2));
// ensuite le type de repere
bloc.Change_nom(3,div_TabRepAnisotrope.Nom(3));
// puis la méthode de définition du repère
bloc.Change_nom(4,div_TabRepAnisotrope.Nom(4));
// un string qui contient le nom de la fonction nD
bloc.Change_nom(5,div_TabRepAnisotrope.Nom(6));
// puis on alimente les éléments concernés par ces calculs
////--- debug
//cout << "\n -- debug LesMaillages::Completer( ";
//bloc.Affiche(); cout << endl;
////--- fin debug
for (int jj= 1; jj<= ref_Taille; jj++)
{int nbb = ref.Numero(jj) ; // le numero de l'element dans le maillage
int nnn = ref.Nbmaille(); // le numero du maillage
// recup de l'element
Element * poi = & Element_LesMaille(nnn,nbb);
// demande a l'element de se completer
poi->Mise_a_jour_repere_anisotropie(bloc,lesFonctionsnD);
};
};
};
// initialisation par défaut de tous les conteneurs aux noeuds
// de tous les maillages
// contenant li_restreinte_TQ et li_restreinte_ddl
// ces conteneurs sont supposés déjà existés
// typiquement si le conteneurs est un scalaire, on met 0
void LesMaillages::Init_par_defaut_conteneurs(List_io < TypeQuelconque >& li_restreinte_TQ
)
{List_io < TypeQuelconque >::iterator il,ilfin=li_restreinte_TQ.end();
for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
// on parcours la liste
for (il = li_restreinte_TQ.begin(); il != ilfin;il++)
{TypeQuelconque_enum_etendu enuTypeQuelconque = (*il).EnuTypeQuelconque();
TypeQuelconque& tyqN = noo->ModifGrandeur_quelconque(enuTypeQuelconque);
tyqN.Grandeur_pointee()->InitParDefaut();
};
}
}
};
// idem pour une seule grandeur
void LesMaillages::Init_par_defaut_conteneurs(TypeQuelconque_enum_etendu enuTypeQuelconque)
{for (int i1 = 1; i1<= nbMaillageTotal; i1++)
{ int nbnoeudmax = tabMaillage(i1)->Nombre_noeud();
for (int i2 = 1; i2 <= nbnoeudmax; i2++)
{ // recup du noeud
Noeud * noo = & Noeud_LesMaille(i1,i2);
TypeQuelconque& tyqN = noo->ModifGrandeur_quelconque(enuTypeQuelconque);
tyqN.Grandeur_pointee()->InitParDefaut();
};
};
};