Herezh_dev/Maillage/Maillage.cc
Gérard Rio 568dba18c7 version 7.029: (par rapport à la 7.028)
- modification du calcul des normales sur les facettes et sur les frontières, à l'initialisaion et lors des mises à jour
 - optimisation sur la l'ajout de grandeurs quelconque aux noeuds:
   . les anciennes versions étaient fonctionnelles  mais introduisait un stockage important. Avec  la nouvelle version,  on  économise 500M0 sur 2 Go !!
2024-04-24 10:34:35 +02:00

3206 lines
140 KiB
C++
Executable file

// FICHIER : Maillage.cp
// CLASSE : Maillage
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "Maillage.h"
# include <iostream>
using namespace std; //introduces namespace std
#include <stdlib.h>
#include "Sortie.h"
#include <stdio.h>
#include <vector>
#include "List_io.h"
#include "CharUtil.h"
//#ifndef SYSTEM_MAC_OS_X_unix
// #include "Frontier.h"
//#endif
#include "ConstMath.h"
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "MvtSolide.h"
#include "TypeQuelconqueParticulier.h"
// CONSTRUCTEURS :
// pour tous les constructeurs: map < string, int , std::less <string> >* lisNomMail,
// est un tableau associatif nom <=> numéro de maillage, qui est utilisé par
// les maillages, mais mis à jour par chaque maillage.
// nom_maill : est facultatif, s'il est différent de ".", il est pris en compte comme nom de maillage
// Constructeur par defaut
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail,int nmail,int dim
,const string& nom_maill):
listeNomMail(lisNomMail),nomDuMaillage(),idmail(nmail),dimension(dim)
,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front(),indice(),indice_NFr()
, list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element()
,ddl_representatifs_des_physiques(),types_de_problemes()
, ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
,detruire_les_noeuds_et_elements(true)
{ if (nom_maill == ".")
{// tout d'abord on donne un nom par défaut au maillage
nomDuMaillage = "pas_de_nom";
while (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
{ // on cherche un nom quelconque qui n'est pas déjà utilisé
nomDuMaillage += '_';
};
}
else // le paramètre de nom de maillage est valide
{ nomDuMaillage = nom_maill;
};
// maintenant on associe le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
};
// Constructeur fonction d'une dimension, du nombre de noeuds
// du nombre d'elements, et d'un numero d'identification (le nb de maillage)
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail
,int dim,int n_noeud,int n_elt,int nmail,const string& nom_maill):
// Constructeur utile quand la dimension, le nombre de noeuds
// et le nombre d'elements du maillage sont connus
listeNomMail(lisNomMail),tab_noeud(n_noeud),tab_element(n_elt),listFrontiere(),tab_noeud_front()
,indice(),indice_NFr(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element()
,ddl_representatifs_des_physiques(),types_de_problemes()
, ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
,detruire_les_noeuds_et_elements(true)
{if (nmail <=0)
{ cout << "\nErreur : numero de maillage invalide !\n";
cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n";
Sortie(1);
};
idmail = nmail;
// traitement du nom de maillage
if (nom_maill ==".")
{// on donne un nom par défaut au maillage
nomDuMaillage = "pas_de_nom";
while (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
{ // on cherche un nom quelconque qui n'est pas déjà utilisé
nomDuMaillage += '_';
};
}
else // le paramètre de nom de maillage est valide
{ nomDuMaillage = nom_maill;
};
// maintenant on associe le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
if ( (dim<1) || (dim>3) )
{ cout << "\nErreur : dimension invalide !\n";
cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n";
Sortie(1);
};
if ( n_noeud<=0 )
{ cout << "\nErreur : nombre de noeuds non valide !\n";
cout << "MAILLAGE::MAILLAGE(int ,int ,int ,int) \n";
Sortie(1);
};
if ( n_elt<=0 )
{ cout << "\nErreur : nombre d'elements invalide !\n";
cout << "MAILLAGE::MAILLAGE(int ,int ,int,int ) \n";
Sortie(1);
};
dimension=dim;
};
// Constructeur fonction de la plupart des informations (qui peuvent être vide
// mais doivent être cohérentes)
// *** 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éé
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail
,int dim,list <Noeud* >& li_noeud, list <Element* > li_element
,int nmail,const string& nom_maill ):
listeNomMail(lisNomMail),tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front()
,indice(),indice_NFr(),list_refIn(),list_refOut(),lesRefin(NULL),mitoyen_de_chaque_element()
,ddl_representatifs_des_physiques(),types_de_problemes()
, ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
,detruire_les_noeuds_et_elements(true)
{ if (ParaGlob::NiveauImpression() >= 5)
cout << " \n creation du maillage: " << nom_maill << endl;
if (nmail <=0)
{ cout << "\nErreur2 : numero de maillage invalide !\n";
cout << "MAILLAGE::MAILLAGE( ) \n";
Sortie(1);
};
// si le numéro de maillage est déjà utilisé, on signale que la place est prise
for (std::map< string, int , std::less <string> >::iterator it=listeNomMail.begin();
it!=listeNomMail.end(); ++it)
{ if ((it->second) == nmail)
{ cout << "\n *** erreur: le numero de maillage "<<nmail
<< " est deja utilise pour le maillage " << (it->first)
<< "\n constructeur: Maillage::Maillage (..."<< flush;
Sortie(1);
};
};
// sinon c'est ok
idmail = nmail;
// traitement du nom de maillage
if (nom_maill ==".")
{// on donne un nom par défaut au maillage
nomDuMaillage = "pas_de_nom";
while (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
{ // on cherche un nom quelconque qui n'est pas déjà utilisé
nomDuMaillage += '_';
};
}
else // le paramètre de nom de maillage est valide
{ nomDuMaillage = nom_maill;
};
// maintenant on associe le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
if ( (dim<1) || (dim>3) )
{ cout << "\nErreur2 : dimension invalide !\n";
cout << "MAILLAGE::MAILLAGE(... \n";
Sortie(1);
};
dimension=dim;
// récupération des noeuds
int nbN = li_noeud.size();
list <Noeud* >::iterator il,ilfin=li_noeud.end();
Change_nb_noeud(nbN);
// tab_noeud.Change_taille(nbN,NULL);
// on vérifie que la numérotation est correcte pour les noeuds
// c'est-à-dire que tous les numéros peuvent être rangés à suivre
bool numerotation_correcte = true;
for (il=li_noeud.begin();il!=ilfin;il++)
{int nb = (*il)->Num_noeud();
if (nb<1 || nb > nbN)
{numerotation_correcte=false;
break;
};
};
if (numerotation_correcte)
{// on peut y aller sans vérif
for (il=li_noeud.begin();il!=ilfin;il++)
tab_noeud((*il)->Num_noeud()) = *il;
}
else
// on est obligé de changer la numérotation des noeuds
{int nb=1;
for (il=li_noeud.begin();il!=ilfin;il++,nb++)
{tab_noeud(nb) = *il;int nbinit=(*il)->Num_noeud();
(*il)->Change_num_noeud(nb);
if (ParaGlob::NiveauImpression() > 0)
{cout << "\n warning : le numero initial du noeud " << nbinit << " est remplace par "
<< " le numero d'ordre attribue automatiquement par herezh " << nb
<< "\n seul ce dernier sera utilise par la suite ! " << endl;
if (ParaGlob::NiveauImpression() > 5)
cout << "\n Maillage::Maillage (map < string, int ,.... " << endl;
};
};
};
// récupération des éléments
int nbE = li_element.size();
list <Element* >::iterator ile,ilefin=li_element.end();
Change_nb_element(nbE);
// on vérifie que la numérotation est correcte pour les éléments (comme pour les noeuds)
// c'est-à-dire que tous les numéros peuvent être rangés à suivre
numerotation_correcte = true;
for (ile=li_element.begin();ile!=ilefin;ile++)
{int nb = (*ile)->Num_elt();
if (nb<1 || nb > nbE)
{numerotation_correcte=false;
break;
};
};
if (numerotation_correcte)
{// on peut y aller sans vérif
for (ile=li_element.begin();ile!=ilefin;ile++)
tab_element((*ile)->Num_elt()) = *ile;
}
else
// on est obligé de changer la numérotation des éléments
{int nb=1;
for (ile=li_element.begin();ile!=ilefin;ile++,nb++)
{tab_element(nb) = *ile;int nbinit=(*ile)->Num_elt();
(*ile)->Change_num_elt(nb);
if (ParaGlob::NiveauImpression() > 0)
{cout << "\n warning : le numero initial de l'element " << nbinit << " est remplace par "
<< " le numero d'ordre attribue automatiquement par herezh " << nb
<< "\n seul ce dernier sera utilise par la suite ! " << endl;
if (ParaGlob::NiveauImpression() > 5)
cout << "\n Maillage::Maillage (map < string, int ,.... " << endl;
};
};
};
// on modifie le numéro de maillage pour les noeuds et éléments
int NBN_P1 = tab_noeud.Taille()+1;
for (int nn=1;nn < NBN_P1;nn++)
tab_noeud(nn)->Change_num_Mail(idmail);
int NBE_P1 = tab_element.Taille()+1;
for (int ne=1;ne < NBE_P1;ne++)
tab_element(ne)->Change_num_maillage(idmail);
if (ParaGlob::NiveauImpression() >= 5)
cout << " \n fin creation du maillage: " << nom_maill << endl;
};
// Constructeur de copie, cependant ici il n'y a pas de création de noeud ni d'élément
// c'est seulement une création de nouveaux conteneurs de pointeurs
// d'autre part le numéro de maillage et le nom de maillage n'est pas valide, il faut
// ensuite les définir
Maillage::Maillage (const Maillage& mail):
listeNomMail(mail.listeNomMail),idmail(mail.idmail),nomDuMaillage(mail.nomDuMaillage),dimension(mail.dimension)
,tab_noeud(mail.tab_noeud),tab_element(mail.tab_element)
,listFrontiere(mail.listFrontiere),tab_noeud_front(mail.tab_noeud_front)
,indice(),indice_NFr(),list_refIn(),list_refOut(),lesRefin(NULL)
,mitoyen_de_chaque_element(mail.mitoyen_de_chaque_element)
,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques)
,types_de_problemes(mail.types_de_problemes)
, ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
,detruire_les_noeuds_et_elements(true)
{ // tout d'abord on donne un nom par défaut au maillage
nomDuMaillage = "pas_de_nom";
while (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
{ // on cherche un nom quelconque qui n'est pas déjà utilisé
nomDuMaillage += '_';
};
// maintenant on associe le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
};
// Constructeur de copie, avec création de nouveaux noeuds et éléments identiques à ceux passées
// en argument, nmail: donne le numéro du nouveau maillage créée, qui est donc a priori différent
// de celui de mail, idem pour le nom du maillage
// les frontières ne sont pas transmises ni calculées ! ni les normales,
// ni les infos concernant les intégrales (qui sont propres aux maillages existants)
Maillage::Maillage (map < string, int , std::less <string> > & lisNomMail
,int nmail, const string& nomDu,const Maillage& mail):
listeNomMail(lisNomMail),idmail(nmail),nomDuMaillage(nomDu),dimension(mail.dimension)
,tab_noeud(),tab_element(),listFrontiere(),tab_noeud_front()
,indice(),indice_NFr(),list_refIn(),list_refOut(),lesRefin(NULL)
,mitoyen_de_chaque_element()
,ddl_representatifs_des_physiques(mail.ddl_representatifs_des_physiques)
,types_de_problemes(mail.types_de_problemes)
, ind_elem(),tab_sens_element() // tableaux internes utilisés par Orientation_elements_mitoyens_recursif
,detruire_les_noeuds_et_elements(true)
{ // on vérifie que le nom de maillage fourni n'existe pas
if (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
{ cout << "\n erreur, le nom de maillage demande existe deja : " << nomDuMaillage
<< "\n Maillage::Maillage (.....";
Sortie(1);
};
// on vérifie que le numéro de maillage proposé est valide
if (idmail <=0)
{ cout << "\nErreur : numero de maillage invalide ! = "<< idmail <<"\n";
cout << "MAILLAGE::MAILLAGE(.... \n";
Sortie(1);
};
// maintenant on associe le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
// on s'occupe tout d'abord des noeuds
int nbn = mail.tab_noeud.Taille();
Change_nb_noeud(nbn);
for (int ino=1;ino<= nbn;ino++)
{ tab_noeud(ino) = new Noeud(*(mail.tab_noeud(ino)));
tab_noeud(ino)->Change_num_Mail(nmail);
};
// maintenant les éléments
int nbe = mail.tab_element.Taille();
Change_nb_element(nbe);
for (int ie=1;ie<=nbe;ie++)
{ tab_element(ie) = mail.tab_element(ie)->Nevez_copie();
//debug
//tab_element(ie)->Affiche(1); cout << endl;
//fin debug
// on réaffecte les noeuds du maillage
Tableau<Noeud *>& ttab = tab_element(ie)->Tab_noeud();
int ttabtaille=ttab.Taille();
for (int ine=1;ine<=ttabtaille;ine++)
ttab(ine)=tab_noeud(ttab(ine)->Num_noeud());
// on change le numéro de maillage
tab_element(ie)->Change_num_maillage(idmail);
};
// dans le cas où mail.mitoyen_de_chaque_element n'est pas vide,
// on construit le nouveau
if (mail.mitoyen_de_chaque_element.Taille() != 0)
Calcul_tous_les_front_et_leurs_mitoyens();
};
Maillage::~Maillage()
// Destructeur
{ if ( detruire_les_noeuds_et_elements) // cas normal
{ for (int i=1;i<= tab_noeud.Taille();i++)
delete tab_noeud(i);
for (int i=1;i<= tab_element.Taille();i++)
delete tab_element(i);
};
// pas de destruction de tab_noeud_front car ce sont des noeuds de tab_noeud, ils sont déjà détruit
};
void // lecture d'un maillage et def des references s'y rapportant
Maillage::LectureMaillage(UtilLecture * entreePrinc,LesReferences& lesRef)
{ if (ParaGlob::NiveauImpression() >= 5) cout << " debut de lecture de maillage " << endl;
if (ParaGlob::NiveauImpression() >= 6) cout << " lecture du nom de maillage " << endl;
// cas où il y a un nom de maillage
if (strstr(entreePrinc->tablcar,"nom_maillage")!=NULL)
{
// // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant
// listeNomMail.erase(listeNomMail.find(nomDuMaillage));
// modif le 14 avril 2015
// non c'est une mauvaise idée, il faut au contraire arrêter le programme et dire qu'il y a
// deux fois le même nom, par contre si le nom de maillage c'est "pas_de_nom" il faut le supprimer
if ((nomDuMaillage == "pas_de_nom") && (listeNomMail.find(nomDuMaillage) != listeNomMail.end()))
listeNomMail.erase(listeNomMail.find(nomDuMaillage));
string toto;
*(entreePrinc->entree) >> toto >> nomDuMaillage;
if (listeNomMail.find(nomDuMaillage) != listeNomMail.end())
{cout << "\n erreur *** plusieurs maillages ont le meme nom : "<< nomDuMaillage
<< " \n revoir les noms de maillage !! " << endl;
Sortie(1);
};
// maintenant on associe le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
// ensuite lecture de l'entête des noeuds
entreePrinc->NouvelleDonnee();
if (strstr(entreePrinc->tablcar,"noeuds")==NULL)
{ cout << " *** erreur dans la lecture des noeuds "
<< " \n LectureMaillage(... " << endl;
entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
}
else
// on définit un nom apriori uniquement dans le cas d'un seul maillage
// sinon c'est une erreur
{ if (idmail ==1)
{ // on commence par mettre à jour listeNomMail en supprimant le doublet nom <=> numéro existant
listeNomMail.erase(listeNomMail.find(nomDuMaillage));
nomDuMaillage = "premier_maillage";
// maintenant on associe le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
}
else
{ cout << "\n Erreur dans la lecture du maillage " << idmail <<" ****** ";
cout << "\n il n'y a pas de nom de maillage alors que c'est obligatoire !! "
<< " \n LectureMaillage(... " << endl;
entreePrinc->MessageBuffer("** lecture de l'entete des noeuds **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
};
};
//------------- lecture des noeuds -------------
// lecture du nombre de noeud
if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des noeuds " << endl;
entreePrinc->NouvelleDonnee();
if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre de noeud " << endl ;
int nbNoeud; // nombre de noeud
*(entreePrinc->entree) >> nbNoeud; // lecture dans le flot memoire
if (ParaGlob::NiveauImpression() >= 8) cout << nbNoeud << endl ;
Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud
#ifdef ETUDIANT_LIMITATION
if (nbNoeud > nb_maxi_noeud)
{ cout << "\n nombre maxi de noeud autorisé atteind " << nb_maxi_noeud;
Sortie(1);
};
#endif
// lecture des noeuds
Noeud * ptr;
for (int i=1; i<= nbNoeud; i++)
{ entreePrinc->NouvelleDonnee();
ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage
if (ParaGlob::NiveauImpression() == 10) cout << "n:" << i << " " << flush ;
// lecture du noeud
ptr->Lecture(entreePrinc);
Affectation_noeud(*ptr);
};
// -------------- lecture des references se rapportant aux noeuds ---------
entreePrinc->NouvelleDonnee();
if (strstr(entreePrinc->tablcar,"elements")==NULL)
// cas où les références sont mises aprés les noeuds, dans ce cas c'est
// des références de noeud
{ if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references de noeuds " << endl;
lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds
lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
lesRef.Lecture(*entreePrinc);
};
// ------------ lecture des elements -----------
// lecture du nombre d'element
int nbElement=0; // nombre d'element null par défaut
if (strstr(entreePrinc->tablcar,"elements")!=NULL) // cas avec element
{ if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des elements du maillage " << endl ;
entreePrinc->NouvelleDonnee();
if (ParaGlob::NiveauImpression() >= 8) cout << " lecture du nombre d'element " << endl ;
*(entreePrinc->entree) >> nbElement;
if (ParaGlob::NiveauImpression() >= 8) cout << nbElement << endl ;
#ifdef ETUDIANT_LIMITATION
if (nbElement > nb_maxi_element)
{ cout << "\n nombre maxi d'element autorise atteind " << nb_maxi_element;
Sortie(1);
};
#endif
// dimensionnement dynamique du tableau d'elements
Change_nb_element(nbElement);
// Lecture des elements
Element * ptr;
for (int i=1; i<= nbElement; i++)
{ // lecture geometrie et interpolation
entreePrinc->NouvelleDonnee();
if (ParaGlob::NiveauImpression() == 10) cout << "e:" << i << " " << flush ;
// def des énumérations de travail
int num_elt = i; // numéro interne de l'élément
int num_elt_lue; // numéro lue
Enum_geom id_geom; Enum_interpol id_interpol;EnumElemTypeProblem id_typeProb;
// cas d'info annexe
string str_precision(""); // stockage info annexe de choix, initié à rien par défaut
// lectures des infos pour le choix d'un élément
Lecture_info_1element(entreePrinc,num_elt_lue,id_geom,id_interpol,id_typeProb,str_precision);
if (num_elt_lue != num_elt)
{ if (ParaGlob::NiveauImpression() > 0)
{cout << "\n warning : le numero de l'element lue " << num_elt_lue << " est different du numero "
<< " d'ordre attribue automatiquement par herezh " << num_elt
<< "\n seul ce dernier sera utilise pour les resultats ! " << endl;
};
};
// ======== choix de l'element =====================================
// et affectation du pointeur d'element en fonction de id_geom et id_interpol
// le numero d'element : num_elt, est affecte a l'element pointe par ptr
ptr = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision);
if (ptr == NULL)
{ // l'operation a echouee
cout << "\n Erreur dans le choix d'element ****** ";
cout << "\n l\'element : " << Nom_interpol(id_interpol)
<< " " << Nom_geom(id_geom)
<< " n\'est pas present dans le programme ! " << endl;
entreePrinc->MessageBuffer("** lecture d'un element **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
};
// lecture des infos particulieres a l'element
Tableau<Noeud*> * pt = & tab_noeud;
ptr->LectureDonneesParticulieres(entreePrinc,pt);
Affectation_element(*ptr);
// si c'est le premier élément du premier maillage on regarde s'il s'agit
// d'un élément axisymétrique et on adapte l'espace de travail en conséquence
if ((i==1) && (idmail==1))
{ if (TestEnum_geom_axisymetrique(id_geom))
ParaGlob::Change_en_AxiSymetrie();
}
else
{// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent
if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie()))
{cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail
<< " nom= " << nomDuMaillage;
if (ParaGlob::AxiSymetrie())
cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)"
<< " et l'element lu est axisymetrique !! ";
else
cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)"
<< " et l'element lu n'est pas axisymetrique !! ";
cout << endl;
Sortie (1);
};
};
}
}
else
{ if (ParaGlob::NiveauImpression() >= 6)
cout << " cas de la lecture d'un maillage SANS elements " << endl; // cas sans element
};
// -------------- lecture des references se rapportant aux elements ---------
// ou aux arête ou aux faces et meme eventuellement à des noeuds
if (ParaGlob::NiveauImpression() >= 6) cout << " lecture des references apres les elements " << endl ;
entreePrinc->NouvelleDonnee();
lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
lesRef.Indic("rien_actuellement"); // indic que les prochaines references seront
// a déterminer en fonction du nom de la référence
lesRef.Lecture(*entreePrinc);
// -------------- ajout de références globales ---------------------
// ---- création de la référence de tous les éléments si elle n'existe pas déjà
string etout("E_tout");
if (!lesRef.Existe(etout,idmail) && (nbElement != 0))
{ // on construit le tableau des numéros des éléments
Tableau <int> tabE(nbElement); for (int i=1;i<=nbElement;i++) tabE(i)=i;
ReferenceNE* retout = new ReferenceNE(tabE,idmail,2,etout);// construction de la référence
lesRef.Ajout_reference(retout); // ajout de la ref, qui est maintenant géré par lesRef
};
// ---- dans tous les cas on ajoute la référence de tous les noeuds dans le cas où elle n'existe pas
string ntout("N_tout");
if (!lesRef.Existe(ntout,idmail))
{ // on construit le tableau des numéros de noeuds
Tableau <int> tabN(nbNoeud); for (int i=1;i<=nbNoeud;i++) tabN(i)=i;
ReferenceNE* rtout = new ReferenceNE(tabN,idmail,1,ntout);// construction de la référence
lesRef.Ajout_reference(rtout); // ajout de la ref, qui est maintenant géré par lesRef
};
if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture de maillage " << endl;
// ----- on s'occupe maintenant de définir les types de pb gérés ------
Mise_a_jour_type_pb_type_associe_ddl();
};
// lecture et application des opérations d'affinages sur le maillage: ex:déplacement solide
void Maillage::LectureEtApplicationAffinage(UtilLecture * entreePrinc,LesReferences& lesRef)
{
if (ParaGlob::NiveauImpression() >= 5) cout << " lecture affinage maillage " << endl;
while ( (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL)
|| (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL)
|| (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL)
|| (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL)
|| (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL)
|| (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL)
|| (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL)
|| (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL)
)
{
// -------------- lecture éventuelle et application de mouvements rigides ------------------
Lecture_des_mouvements_solides(entreePrinc);
// --------------- suppression éventuelle des noeuds, non référencés par les éléments ------
LectureEtSuppressionNoeudNonReferencer(entreePrinc,lesRef);
// --------------- création éventuelle d'une référence sur les noeuds, non référencés par les éléments ------
LectureEtCreationRefNoeudNonReferencer(entreePrinc,lesRef);
// --------------- éventuellement collapse de noeuds proches ------------------------
LectureEtCollapse_noeuds_proches(entreePrinc,&lesRef);
// --------------- éventuellement collapse d'éléments supperposés -------------------
LectureEtCollapse_element_superpose(entreePrinc,&lesRef);
// -------------- éventuellement suppression d'elements à 2 noeuds, de distances très proches
LectureEtSup_Elem_noeudsConfondu(entreePrinc,&lesRef);
//---------------- création automatique des références globales de frontière si demandé ----------
CreationRefFrontiere(entreePrinc,lesRef);
//----- debug
//{ // on écrit la connection de l'élément 55
// Element* el = tab_element(55);
// const Tableau<Noeud *>& tabi = el->Tab_noeud_const();
// cout << "\n *** connection de l'element 55: avant renumerotation ";
// for (int i=1;i<=tabi.Taille();i++) cout << " "<<tabi(i)->Num_noeud();
// cout << " Maillage::LectureMaillage () " << endl;
//}
//---fin debug
// --------------- renumérotation éventuelle des noeuds ------------------------------------
LectureEtRenumerotation(entreePrinc,lesRef);
////----- debug
//{ // on écrit la connection de l'élément 55
// Element* el = tab_element(55);
// const Tableau<Noeud *>& tabi = el->Tab_noeud_const();
// cout << "\n *** connection de l'element 55: après renumerotation ";
// for (int i=1;i<=tabi.Taille();i++) cout << " "<<tabi(i)->Num_noeud();
// cout << " Maillage::LectureMaillage () " << endl;
// Sortie(1);
//}
////---fin debug
};
// ----------------- vérification que toutes les références de noeuds, d'éléments, d'arêtes et de faces sont valides
// c-a-d se réfèrent à des éléments existants
VerifReference(lesRef);
if (ParaGlob::NiveauImpression() >= 5) cout << " fin lecture affinage maillage " << endl;
};
// affichage et definition interactive des commandes
// cas = 1: interactif complet
// cas = 2: entrée uniquement de noms de fichier
// cas = 3: entrée uniquement de l'affinage
void Maillage::Info_commande_Maillages(UtilLecture * entreePrinc,LesReferences& lesRef, int cas)
{ ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier
string rep="o";
if (cas == 2)
{ cout << "\n# voulez-vous inclure un fichier ou continuer sur un exemple (rep o ou ? ou f) ? ";
rep = lect_return_defaut(false,"f");
};
if (((rep == "o") || (rep == "O") ||(rep == "0")) && (cas != 3))
{ cout << "\n non du fichier .her (sans l'extension .her) a inclure ? ";
rep = lect_chaine();
sort << "\n\n # -- def maillage ";
sort << "\n < " << (rep+".her") ;
cout << "\n un fichier .lis a inclure ? (o ou n (defaut)) ";
rep = lect_return_defaut(false,"n");
if (rep == "o")
{ cout << "\n non du fichier .lis (sans l'extension .lis) a inclure ? ";
rep = lect_chaine();
sort << "\n < " << (rep+".lis") ;
};
}
else if ((rep == "?") && (cas != 3))
{ // sinon on continue sur un exemple de maillage
sort << "\n # -- defintion du nom du maillage (facultatif pour le premier maillage "
<< "\n # -- qui s'appel par defaut : premier_maillage)"
<< "\n"
<< "\n nom_maillage plaque_troue # exemple de nom de maillage"
<< "\n noeuds ------------ # definition des noeuds";
//------------- definition des noeuds -------------
int dimen = ParaGlob::Dimension();
#ifdef SYSTEM_MAC_OS_CARBON
int nbNoeud = pow(3,dimen); // nombre de noeud de l'exemple
#else
int nbNoeud = ((int)pow((float)3,(int)dimen)); // nombre de noeud de l'exemple
#endif
sort << "\n "<< nbNoeud << " NOEUDS # definition du nombre de noeud"
<< "\n \n"
<< "\n#---------------------------------------------------------------"
<< "\n#|NO DU| X | Y | Z |"
<< "\n#|NOEUD| | | |"
<< "\n#---------------------------------------------------------------";
Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud
// définition d'une grille générique de noeuds qui permettra de définir les éléments générique
Tableau <Coordonnee*> tab_coo(nbNoeud);
switch (dimen)
{ case 1:
{ for (int i=1;i<=3;i++) tab_coo(i) = new Coordonnee((double) i); break;}
case 2:
{ int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++,l++)
tab_coo(l) = new Coordonnee((double) i,(double) j); break;}
case 3:
{ int l=1; for (int i=1;i<=3;i++) for (int j=1;j<=3;j++) for (int k=1;k<=3;k++,l++)
tab_coo(l) = new Coordonnee((double) i,(double) j,(double) k); break;}
};
// def des noeuds
Noeud * ptr;
for (int i=1; i<= nbNoeud; i++)
{ ptr = new Noeud(i,dimension,1); // et attribution du numero de maillage
// def du noeud
ptr->Info_commande_Noeud(entreePrinc,*tab_coo(i),i);
Affectation_noeud(*ptr);
};
// -------------- def d'exemples de references se rapportant aux noeuds ---------
sort << "\n# --- reference de noeuds ce trouvant apres la definition des noeuds ---"
<< "\n# ( il est possible aussi de definir des references de noeud apres "
<< "\n# la definition des elements) "
<< "\n# NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres \n";
lesRef.Indic("noeud"); // indic que les prochaines references seront pour les noeuds
lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
lesRef.Info_commande_lesRef(nbNoeud,0,entreePrinc,1); // def d'exemple des divers refs de noeuds
// ------------ def d'exemple d'elements -----------
int nbElement = 0; // nombre d'element
bool choix_valide=false;
// affichage des types d'élément actuellement disponible selon la dimension
// creation d'un tableau d'éléments
Tableau <Element *> tab_el = Element::Info_commande_Element(entreePrinc);
int nbele = tab_el.Taille();
Tableau <bool> chooi(nbele,false); // tableau de travail
cout << "\n Donner le type d'element que vous souhaitez utiliser: ? ";
string rep;int num;
while (!choix_valide)
{
try
{ // affichage des éléments possibles
// on balaie le tableau des elements enregistre
int undeux=0;
cout << "\n (0) fin \n";
for (int i=1;i<=nbele;i++)
{ cout << " (" << i << ") " << tab_el(i)->Geometrie() <<" "<< tab_el(i)->Interpolation()
<<" ";
undeux++;
if (undeux==2) {cout << "\n";undeux=0;}
};
rep = lect_return_defaut(false,"0");
if (rep == "fin_prog") Sortie(1);
num = ChangeEntier(rep);
choix_valide=false;
if (num == 0)
{ choix_valide=true;}
else // sinon
{ if ((num > 0)&&(num<=nbele))
{if (chooi(num))
cout << "\n type d'element deja choisit, recommencer";
else
chooi(num) = true;
}
else { cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
}
}
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
{ cout << "\n Erreur on attendait un entier entre 0 et "<< nbele <<" !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper fin_prog pour arreter le programme";
choix_valide=false;
}
} //-- fin du while
// on definit le maillage d'essai
// 1- def du nombre d'élément
int ielmax=0;
for (int ie=1;ie<=nbele;ie++)
if (chooi(ie)) ielmax++;
Change_nb_element(ielmax);
// 2- remplissage du tableau d'élément
int iel=1;
for (int ie=1;ie<=nbele;ie++)
if (chooi(ie))
{tab_element(iel)=tab_el(ie);
tab_element(iel)->Change_num_elt(iel);
tab_el(ie)=NULL;
iel++;
}
// on affiche les éléments
sort << "\n # les elements \n"
<< "\n elements ----------";
sort << "\n " << ielmax << " ELEMENTS";
sort << "\n #----------------------------------------------------------------------";
sort << "\n #| NO | | |";
sort << "\n #|ELTS | type element | Noeuds |";
sort << "\n #----------------------------------------------------------------------";
string ord= "commande";
Tableau<Noeud*> * pt = & tab_noeud;
for (int i=1;i<=ielmax;i++)
tab_element(i)->Info_com_Element(entreePrinc,ord,pt);
sort << "\n \n" ;
// -------------- def des references se rapportant aux elements ---------
// ou aux arête ou aux faces et meme eventuellement à des noeuds
sort << "\n# --- reference ce trouvant apres la definition des elements ---"
<< "\n# NB: !! une reference de noeud doit commencer par N suivi d'une chaine de caracteres "
<< "\n# une reference d'element commence par E suivi d'une chaine de caracteres "
<< "\n# une reference de face commence par F et une reference d'arrete commence par A \n";
lesRef.NbMaille(idmail); // indic le numéro de maillage aux références
lesRef.Info_commande_lesRef(nbNoeud,ielmax,entreePrinc,2); // def d'exemple des divers refs de noeuds
// effacement des éléments qui ne servent plus
for (int i=1;i<=ielmax;i++)
if (tab_el(i) != NULL) delete tab_el(i);
}; // fin de l'exemple de maillage
// ---------- définition des affinages éventuelles ----------
// while ( (strstr(entreePrinc->tablcar,"def_mouvement_solide_initiaux_")!=NULL)
// || (strstr(entreePrinc->tablcar,"suppression_noeud_non_references_")!=NULL)
// || (strstr(entreePrinc->tablcar,"creation_ref_noeud_non_references_")!=NULL)
// || (strstr(entreePrinc->tablcar,"fusion_noeuds_proches_")!=NULL)
// || (strstr(entreePrinc->tablcar,"fusion_elements_superposes_")!=NULL)
// || (strstr(entreePrinc->tablcar,"suppression_elements_2noeuds_tres_proches_")!=NULL)
// || (strstr(entreePrinc->tablcar,"def_auto_ref_frontiere_")!=NULL)
// || (strstr(entreePrinc->tablcar,"renumerotation_des_noeuds_")!=NULL)
//On va proposer un menu
while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
{
try
{
cout
<< "\n (0 ou f defaut) (fin) "
<< "\n (1) mouvement solide "
<< "\n (2) suppression des noeuds non reference "
<< "\n (3) collapse de noeuds proches "
<< "\n (4) collapse d'elements superposes "
<< "\n (5) creation de references frontieres "
<< "\n (6) renumerotation "
<< "\n (7) creation d'une ref sur les noeuds non references "
<< "\n (8) suppression des petits elements a 2 ou 3 noeuds 2D "
<< "\n (9 ou ? ) informations "
<< "\n ";
rep = lect_return_defaut(false,"f");
if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie directe
break;
int num = ChangeEntier(rep);
if (Minuscules(rep) == "?")
num = 9;
bool choix_valide=false;
if ((num >= 0)&&(num<=9))
{ choix_valide=true; }
else { cout << "\n Erreur on attendait un entier entre 0 et 9 !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour arreter le programme";
choix_valide=false;
}
switch (num)
{ case 0: // sortie
{ break;} // normalement cela a déjà été filtré avant
case 1: // mouvement solide
{ MvtSolide mvt; // un mouvement par défaut
sort << "\n\n def_mouvement_solide_initiaux_ \n";
mvt.Info_commande_MvtSolide(sort);
break;}
case 2: // suppression des noeuds non reference
{ sort << "\n suppression_noeud_non_references_ ";
break;}
case 3: // collapse de noeuds proches
{ sort << "\n fusion_noeuds_proches_ ";
cout << "\n donner la distance en dessous de laquelle on fusionne (un reel) ? ";
double rayon=0.;
rayon = lect_double(); cout << " valeur lue "<< rayon;
sort << rayon << " ";
break;}
case 4: // collapse d'elements superposes
{ sort << "\n fusion_elements_superposes_ ";
break;}
case 5: // creation de references frontieres
{ sort << "\n def_auto_ref_frontiere_ ";
break;}
case 6: // creation de references frontieres
{ sort << "\n renumerotation_des_noeuds_ ";
break;}
case 7: // creation d'une ref sur les noeuds non reference
{ sort << "\n creation_ref_noeud_non_references_ ";
break;}
case 8: // suppression des petits elements a 2 ou 3 noeuds 2D
{ sort << "\n suppression_elements_2noeuds_tres_proches_ ";
cout << "\n donner la distance entre deux noeuds de l'element en dessous de laquelle on supprime (un reel) ? ";
double rayon=0.;
rayon = lect_double(); cout << " valeur lue "<< rayon;
sort << rayon << " ";
break;}
case 9: // informations
{ cout << "\n en dehors de la signification intuitive des differents ordres"
<< " pour des informations plus precise il est preferable de se rapporter a la documentation "
<< " d'Herezh++, car c'est differents ordres recouvrent des procedures difficiles a "
<< " decrire en quelques lignes. ";
break;}
default:
cout << "\n le cas "<<rep<<" n'est pas encore traite !!, mais cela devrait ce faire sans tarder ";
};
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
{ cout << "\n Erreur on attendait un des mots clés proposés !!, "
<< "\n redonnez une bonne valeur"
<< "\n ou taper f ou 0 pour sortir ";
};
}; //-- fin du while
};
// Affiche l'ensemble des donnees du maillage
void Maillage::Affiche () const
{cout << "\n\t\t*** DONNEES DU MAILLAGE ***\n\n";
cout << "\n nom du maillage : " << nomDuMaillage << " , ";
cout << "Dimension : " << dimension << "\n";
// les types de problèmes associés
// {list <EnumElemTypeProblem>::const_iterator il,ilfin=types_de_problemes.end();
// cout <<"\n types_de_problemes: " << types_de_problemes.size() ;
// for (il=types_de_problemes.begin();il != ilfin;il++)
// NomElemTypeProblem(*il);
// };
{int tail = types_de_problemes.Taille();
cout <<"\n types_de_problemes: " << tail ;
for (int i=1;i<=tail;i++)
cout << " "<< NomElemTypeProblem(types_de_problemes(i));
};
// // les ddl associés
// {list <Enum_ddl>::const_iterator il,ilfin=ddl_representatifs_des_physiques.end();
// cout <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size();
// for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++)
// Nom_ddl(*il);
// };
{int tail = ddl_representatifs_des_physiques.Taille();
cout <<"\n type_de_ddl_associes: " << tail;
for (int i=1;i<=tail;i++)
cout << " "<< Nom_ddl(ddl_representatifs_des_physiques(i));
};
// cout << "Nombre de degres de liberte : " << Nombre_ddl() << "\n";
cout << "Nombre de noeuds : " << Nombre_noeud() << "\n";
cout << "Nombre d'elements : " << Nombre_element() << "\n\n";
for (int i=1;i<=Nombre_noeud();i++)
// boucle sur les noeuds
{
cout << "\nNoeud " << i << " :\n";
tab_noeud(i)->Affiche();
};
cout << "\n";
for (int i=1;i<=Nombre_element();i++)
// boucle sur les elements
{
cout << "\nElement " << i << " :\n";
tab_element(i)->Affiche(ParaGlob::NiveauImpression());
};
cout << "\n";
// renseignement concernant les frontières
int nbmaxiElement = (int) listFrontiere.size();
cout << "nombre d'element frontiere : " << nbmaxiElement;
cout << "liste : \n";
LaLIST <Front>::const_iterator ip;int ne;
for (ne=1,ip = listFrontiere.begin();ip != listFrontiere.end(); ip++,ne++)
{ // écriture de l'élément courant
cout << ne << " " ; // le numéro
const ElemGeomC0 & geom = (*ip).Eleme()->ElementGeometrique();
cout << Nom_geom(geom.TypeGeometrie()) << " " ; // la géométrie
cout << Nom_interpol(geom.TypeInterpolation()) << " " ; // l'interpolation
// les noeuds
Tableau <Noeud *> tabnoeud = (*ip).Eleme()->TabNoeud();
int taille = tabnoeud.Taille();
for (int ine = 1; ine<=taille; ine++)
cout << tabnoeud(ine)->Num_noeud() << " ";
cout << "\n";
};
// la liste des noeuds de la frontières, on ne sort que les numéros
cout << " \n liste des numeros de noeud de la frontiere";
int taal = tab_noeud_front.Taille();
for (int i=1;i<= taal;i++)
cout << tab_noeud_front(i)->Num_noeud() << " ";
cout << "\n";
};
/*void
Maillage::Affiche (char* nom_fichier)
// Affiche les donnees du maillage dans le fichier nom_fichier
// au format du fichier d'entree ".her"
{
FILE* fichier;
// ouverture du fichier nom_fichier
if ( (fichier=fopen(nom_fichier,"w"))==NULL )
{
cout << "ERREUR D'OUVERTURE DU FICHIER :";
cout << nom_fichier << "\n";
Sortie(1);
};
fprintf(fichier,"\n nom_maillage ",nomDuMaillage.c_str());
fprintf(fichier,"\n\nnoeuds --------\n\n");
fprintf(fichier,"\t\t%d NOEUDS\n\n",Nombre_noeud());
// affichage des noeuds :
switch (dimension)
{
case 1 : // cas unidimensionnel
for (int i=1;i<=Nombre_noeud();i++)
{
fprintf(fichier,"\t%d\t%lf\n",Noeud_mail(i).Num_noeud(),
Noeud_mail(i).Coord0()(1));
};
break;
case 2 : // cas bidimensionnel
for (int i=1;i<=Nombre_noeud();i++)
{
fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud());
fprintf(fichier,"%lf\t%lf\n",Noeud_mail(i).Coord0()(1),
Noeud_mail(i).Coord0()(2));
};
break;
case 3 : // cas tridimensionnel
for (int i=1;i<=Nombre_noeud();i++)
{
fprintf(fichier,"\t%d\t\t",Noeud_mail(i).Num_noeud());
fprintf(fichier,"%lf\t%lf\t%lf\n",Noeud_mail(i).Coord0()(1),
Noeud_mail(i).Coord0()(2),Noeud_mail(i).Coord0()(3));
};
break;
default :
cout << "Erreur de dimension\n";
cout << "MAILLAGE::AFFICHE(char* ) \n";
Sortie(1);
};
fprintf(fichier,"\n\nelements --------\n\n");
fprintf(fichier,"\t\t%d ELEMENTS\n\n",Nombre_element());
// affichage des elements
for (int i=1;i<=Nombre_element();i++)
{
fprintf(fichier,"\t%d\t",Element_mail(i).Num_elt());
fprintf(fichier,"%s\t%s\t\t",Element_mail(i).Geometrie(),
Element_mail(i).Interpolation());
for (int j=1;j<=Element_mail(i).Nombre_noeud();j++)
fprintf(fichier,"%d\t",Element_mail(i).Num_noeud(j));
fprintf(fichier,"\n");
};
fprintf(fichier,"\n\n");
};
*/
Maillage&
Maillage::operator= (Maillage& mail)
// Surcharge de l'operateur = : realise l'egalite entre deux maillages
// cependant le numéro de maillage et le nom de maillage n'est pas valide, il faut
// ensuite les définir
{ dimension=mail.dimension;
//nomDuMaillage = mail.nomDuMaillage;
tab_noeud=mail.tab_noeud;
tab_element=mail.tab_element;
listFrontiere=mail.listFrontiere;
tab_noeud_front = mail.tab_noeud_front;
ddl_representatifs_des_physiques = mail.ddl_representatifs_des_physiques;
types_de_problemes = mail.types_de_problemes;
return (*this);
};
// test si toutes les informations des maillages sont completes
// = true -> complet
// = false -> incomplet
bool Maillage::Complet()
{ bool res = true;
int tab_noeudTaille = tab_noeud.Taille();
for ( int i=1; i<= tab_noeudTaille;i++)
{ // res = res && tab_noeud(i)->TestComplet();
if(!(tab_noeud(i)->TestComplet()))
{ cout << " \n pb au niveau du test du noeud " << tab_noeud(i)->Num_noeud();
res = false;
};
};
int tab_elemTaille = tab_element.Taille();
for ( int i=1; i<= tab_elemTaille;i++)
{//res = res && tab_element(i)->TestComplet();
if(!(tab_element(i)->TestComplet()))
{cout << "\n pb au niveau du test de l'element " << tab_element(i)->Num_elt();
res = false;
};
};
// les parties frontières ne sont pas obligatoires
return res;
};
// ramene la demi largeur de bande en ddl et la largeur de bande
void Maillage::Largeur_Bande(int& demi, int& total,const Nb_assemb& casAss)
{ demi = 0;
int nb_ass = casAss.n;
int tab_elemTaille = tab_element.Taille();
for (int ne=1;ne<=tab_elemTaille;ne++)
{int tab_eleNbNoeud = tab_element(ne)->Nombre_noeud();
for (int noe=1; noe<= tab_eleNbNoeud;noe++)
// bug, voic remarque qui suit for ( int no=noe+1; no<=tab_eleNbNoeud;no++)
// l'idée est bonne de commencer à noe+1, mais en fait lorsque l'on a un seul noeud, cela conduit
// a avoir une largeur de bande nulle, donc il faut commencer à noe, et dans ce cas c'est ok
// mais pour les éléments avec plus d'un noeud, on a une boucle supp
for ( int no=noe; no<=tab_eleNbNoeud;no++)
{ Noeud & nne = tab_element(ne)->Noeud_elt(noe);
Noeud & nno = tab_element(ne)->Noeud_elt(no);
int di;
if (nne.PosiAssemb(nb_ass) >= nno.PosiAssemb(nb_ass))
di = nne.PosiAssemb(nb_ass) - nno.PosiAssemb(nb_ass)
+ nne.NB_ddl_actif_casAssemb(nb_ass);
else
di = nno.PosiAssemb(nb_ass) - nne.PosiAssemb(nb_ass)
+ nno.NB_ddl_actif_casAssemb(nb_ass);
if ( di > demi) demi = di;
};
};
total = demi * 2 -1;
demi = demi;
};
// test pour savoir si tous les coordonnées des noeuds d'un maillage sont imposé
// ramène 1 si tout est fixé, 0 sinon
int Maillage::Tous_Xi_fixes(const Nb_assemb& casAss) const
{ int retour = 1;
int nb_ass = casAss.n;
// on va parcourir les noeuds
int tab_noeud_taille= tab_noeud.Taille();
int dim = ParaGlob::Dimension();
switch(dim)
{case 3:
{for (int i=1;i<=tab_noeud_taille;i++)
{ Noeud& noe = *tab_noeud(i); // pour simplifier
if (!( noe.Ddl_fixe(X3) && noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1)))
{retour=0; break;};
};
break;
}
case 2:
{for (int i=1;i<=tab_noeud_taille;i++)
{ Noeud& noe = *tab_noeud(i); // pour simplifier
if (!( noe.Ddl_fixe(X2) && noe.Ddl_fixe(X1)))
{retour=0; break;};
};
break;
}
case 1:
{for (int i=1;i<=tab_noeud_taille;i++)
{ Noeud& noe = *tab_noeud(i); // pour simplifier
if (!( noe.Ddl_fixe(X1)))
{retour=0; break;};
};
break;
}
};
// --- idem mais plus long a priori car contient un switch
// for (int i=1;i<=tab_noeud_taille;i++)
// { Noeud& noe = *tab_noeud(i); // pour simplifier
// switch(dim)
// {case 3: if (!(noe.Ddl_fixe(X3))) {retour=0; break;};
// case 2: if (!(noe.Ddl_fixe(X2))) {retour=0; break;};
// case 1: if (!(noe.Ddl_fixe(X1))) {retour=0; break;};
// };
// if (!retour) break;
// };
return retour;
};
// création pour chaque noeud de la liste des éléments qui contiennent le noeud
void Maillage::Calcul_indice()
{ // création du tableau indice : pour chaque noeud on regarde quel élément contiend ce noeud
/// les 3/ sont pour la version vector qui marche bien aussi
/// vector <vector <Element*> > indice(tab_noeud.Taille());
int tab_noeud_taille= tab_noeud.Taille();
indice.Change_taille(tab_noeud_taille);
// au cas où le tableau existait auparavant on initialise les éléments du tableau
for (int i=1;i<= tab_noeud_taille;i++)
indice(i).clear();
// maintenant on passe en revue les éléments
int tabelTaille = tab_element.Taille();
// indice(i) contiend les numéros d'élément contenant le noeud i
for (int i22 = 1; i22 <= tabelTaille; i22++)
{ Element * elem1 = tab_element(i22); // recup de l'element
// récup de son tableau de noeud
Tableau<Noeud *>& tabn = elem1->Tab_noeud();
int tabntaille = tabn.Taille();
for (int ij=1;ij<= tabntaille;ij++)
{// on balaie ses noeuds
/// indice[(tabn(ij)->Num_noeud())-1].push_back(elem1);
indice((tabn(ij)->Num_noeud())).push_back(elem1);
};
};
// on supprime les doublons
for (int i=1;i<=tab_noeud_taille;i++)
{ list<Element*>& intertab = indice(i); // pour allèger l'écriture
intertab.sort(); // on ordonne
intertab.unique(); // on supprime les doublons
/*//-- debug
//{cout << "\n noeud " << i << " taille indice(i) " << intertab.size() ;
// list<Element*>::iterator ina,infin;
// infin = intertab.end();
// for (ina = intertab.begin();ina!=infin;ina++)
// {Element * elem2 = *ina; // recup de l'element
// cout << " element " << elem2->Num_elt() << " ";
// };
// cout << "\n";
// };
//-- debug
//{cout << "\n debug ** Maillage::Calcul_indice() ";
// int numnoeud = 104;
// list<Element*>& intertab = indice(numnoeud);
// list<Element*>::iterator ina,infin;
// infin = intertab.end();
// for (ina = intertab.begin();ina!=infin;ina++)
// {Element * elem2 = *ina; // recup de l'element
// cout << " element-- " << elem2->Num_elt() << " ";
// };
// cout << "\n"<<endl ;
//};
//--fin debug*/
};
};
// création pour chaque noeud de la liste des éléments frontières qui contiennent le noeud
void Maillage::Calcul_indice_NFr()
{ // le tableau indice_NFr (indice des noeuds frontières) va permettre une recherche plus rapide
// on le construit:
int tab_noeud_taille= tab_noeud.Taille();
indice_NFr.Change_taille(tab_noeud_taille);
// au cas où le tableau existait auparavant on initialise les éléments du tableau
for (int i=1;i<= tab_noeud_taille;i++)
indice_NFr(i).clear();
// indice_NFr contiend les front succeptible d'avoir des frontières géométriques communes
LaLIST <Front>::iterator iF;
LaLIST <Front>::iterator iFfin = listFrontiere.end();
for (iF = listFrontiere.begin();iF!=iFfin; iF++)
{ Front* fro = &(*iF);
ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière
// récup de son tableau de noeud
Tableau<Noeud *>& tabn = efem1->TabNoeud();
int tabntaille = tabn.Taille();
for (int ij=1;ij<= tabntaille;ij++)
// on balaie ses noeuds
indice_NFr((tabn(ij)->Num_noeud())).push_back(fro);
};
// on supprime les doublons
for (int i=1;i<=tab_noeud_taille;i++)
{ List_io <Front*>& intertab = indice_NFr(i); // pour allèger l'écriture
intertab.sort(); // on ordonne
intertab.unique(); // on supprime les doublons
};
};
// calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement
// a priori le calcul s'effectue par une moyenne des normales des éléments qui
// entourent le noeud.
// init -> calcul des normales à t=0
// et ajout conteneur aux noeuds des normales à t = 0 et t
// init par défaut des valeurs à t == celle à t=0
void Maillage::InitNormaleAuxNoeuds()
{ // on va parcourir les noeuds et on n'intervient que si le noeud
// appartient à un élément 1D et/ou 2D
int nbNoeud = tab_noeud.Taille();
int borne_max_nbNoeud = nbNoeud+1;
Coordonnee coor_inter; // coordonnée de travail
Coordonnee premiere_normale;// idem
{
Grandeur_coordonnee grandCoordonnee_0(ParaGlob::Dimension()); // un type courant
TypeQuelconque typQ4_0(NN_SURF_t0,EPS11,grandCoordonnee_0);
Grandeur_coordonnee grandCoordonnee_t(ParaGlob::Dimension()); // un type courant
TypeQuelconque typQ4_t(NN_SURF_t,EPS11,grandCoordonnee_t);
// on commence par ajouter les conteneurs
// on fait un conteneur particulier pour tous les noeuds, donc 2 boucles
// car cela permet d'optimiser l'utilisation de la méthode AjoutUnTypeQuelconque de Noeud
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{// on regarde si le conteneur de la normale existe au noeud et création éventuelle
Noeud & noe = *tab_noeud(ine); // pour simplifier
if (!noe.Existe_ici(NN_SURF_t0))
noe.AjoutUnTypeQuelconque(typQ4_0);
};
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{// on regarde si le conteneur de la normale existe au noeud et création éventuelle
Noeud & noe = *tab_noeud(ine); // pour simplifier
if (!noe.Existe_ici(NN_SURF_t))
noe.AjoutUnTypeQuelconque(typQ4_t);
};
// maintenant on s'occupe du contenu
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on récupère le conteneur de la normale
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t0);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
normale.Zero(); // init
// calcul éventuel du tableau Indice
this->Indice();
List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud
List_io < Element*>::iterator il,ilfin = li_elem.end();
// on balaie les éléments
int nb_normale=0; // le nombre de normales trouvées
for (il = li_elem.begin(); il != ilfin; il++)
{Element& elem = *(*il);
Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie());
// if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
{int cas = elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter);
if (cas == 0)
{cout << "\n *** erreur, le calcul de la normale n'est pas possible "
<< " pour le noeud "<<tab_noeud(ine)->Num_noeud()
<< " du maillage " << tab_noeud(ine)->Num_Mail()
<< " par rapport a l'element "<< elem.Num_elt()
<< " du maillage " << elem.Num_maillage()
<< "\n Maillage::MiseAjourNormaleAuxNoeuds() ";
Sortie(1);
}
else if (cas == 2)
{// le calcul n'est pas licite, mais ce n'est pas une erreur
// simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
}
else // sinon c'est ok
{// on peut avoir des directions très proches mais de sens inverse ... ce qui va
// conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire
// s'il est négatif on utilise l'inverse de la normale
// donc en définitif on gardera globalement la direction précédente
if ((normale * coor_inter) > 0.)
{normale += coor_inter;}
else
{normale -= coor_inter;};
nb_normale++;
};
};
};
if (nb_normale != 0)
{normale /= nb_normale;
// enfin on normalise la normale
////------ debug
//if (normale.Norme() == 0.)
// {
// for (il = li_elem.begin(); il != ilfin; il++)
// {Element& elem = *(*il);
// Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie());
// // if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
// if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
// {elem.CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter);
// if (coor_inter.Dimension() == 0)
// {cout << "\n *** erreur, le calcul de la normale n'est pas possible "
// << " pour le noeud "<<tab_noeud(ine)->Num_noeud()
// << " du maillage " << tab_noeud(ine)->Num_Mail()
// << " par rapport a l'element "<< elem.Num_elt()
// << " du maillage " << elem.Num_maillage()
// << "\n Maillage::MiseAjourNormaleAuxNoeuds() ";
// Sortie(1);
// }
// else // sinon c'est ok
// {normale += coor_inter;
// nb_normale++;
// };
// };
// };
//
// }
//
//// end debug
normale.Normer();
// ce qui fini la mise à jour de la normale au noeud
};
};
}
// on fait de même pour les éléments frontières minimals
// calcul éventuel du tableau indice_NFr
this->Indice_NFr();
int dima = ParaGlob::Dimension();
{Grandeur_coordonnee grandCoordonnee_0(ParaGlob::Dimension()); // un type courant
TypeQuelconque typQ4_0(N_FRONT_t0,EPS11,grandCoordonnee_0);
Grandeur_coordonnee grandCoordonnee_t(ParaGlob::Dimension()); // un type courant
TypeQuelconque typQ4_t(N_FRONT_t,EPS11,grandCoordonnee_t);
// à t=0
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on regarde si le conteneur de la normale à un noeud frontière existe au noeud et création éventuelle
if (!noe.Existe_ici(N_FRONT_t0))
noe.AjoutUnTypeQuelconque(typQ4_0);
};
// on fait la même chose à t ce qui évitera de tester à la mise à jour
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on regarde si le conteneur de la normale à un noeud frontière existe au noeud et création éventuelle
if (!noe.Existe_ici(N_FRONT_t))
noe.AjoutUnTypeQuelconque(typQ4_t);
};
// on s'occupe du contenu
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on récupère le conteneur au noeud
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(N_FRONT_t0);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
normale.Zero(); // init
// si on est en dimension 1, la normale est directement déterminé
if (dima == 1)
{normale(1) = 1.;
}
else
{// ici dima > 1, les éléments ont une métrique car ils sont différents des éléments points
List_io <Front*>& li_elem = indice_NFr(ine);// la liste des Front qui contiennent le noeud
List_io <Front*>::iterator il,ilfin = li_elem.end();
// on balaie les éléments
int nb_normale=0; // le nombre de normales trouvées
for (il = li_elem.begin(); il != ilfin; il++)
{Front& elem = *(*il);
Enum_type_geom enutygeom = elem.Eleme_const()->Type_geom_front();
int cas = elem.Eleme()->CalculNormale_noeud(TEMPS_0,*tab_noeud(ine),coor_inter);
// //------ debug
// if ((noe.Num_noeud() == 6) && (noe.Num_Mail()==2))
// { cout << "\n debug Maillage::InitNormaleAuxNoeuds():"
// << " noe "<< noe.Num_noeud() << " N= "; coor_inter.Affiche();
// };
// // ----- end debug
if (cas == 0)
{cout << "\n *** erreur, le calcul de la normale n'est pas possible "
<< " pour le noeud "<<tab_noeud(ine)->Num_noeud()
<< " du maillage " << tab_noeud(ine)->Num_Mail()
<< " par rapport a l'element de frontiere ";
elem.Affiche(1);
cout << "\n Maillage::InitNormaleAuxNoeuds() ";
Sortie(1);
}
else if (cas == 2)
{// le calcul n'est pas licite, mais ce n'est pas une erreur
// simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
}
else // sinon c'est ok
{// on peut avoir des directions très proches mais de sens inverse ... ce qui va
// conduire à une somme nulle,
double intens_normale = normale.Norme(); // l'intensité actuelle
Coordonnee inter_co = normale + coor_inter;
// if ((intens_normale > ConstMath::unpeupetit) && (inter_co.Norme() < ConstMath::petit))
// // normalement ne devrait pas arriver
// {
//
// }
//pour éviter cela, on pourrait regarder le produit scalaire
// s'il est négatif on utilise l'inverse de la normale
// donc en définitif on gardera globalement la direction précédente
if ((intens_normale > ConstMath::unpeupetit) && (inter_co.Norme() < ConstMath::petit))
{normale -= coor_inter;} // cas où la somme s'annulle
else // sinon cas normale
// if ((normale * coor_inter) > 0.)
{normale += coor_inter;}
// {normale += coor_inter; }// ici cela me semble plus juste: on ne doit pas avoir de pb d'inversion de normale
nb_normale++;
};
};
if (nb_normale != 0)
{normale /= nb_normale;
// enfin on normalise la normale
normale.Normer();
// ce qui fini la mise à jour de la normale au noeud
// //------ debug
// if ((noe.Num_noeud() == 6) && (noe.Num_Mail()==2))
// { cout << "\n debug Maillage::InitNormaleAuxNoeuds():"
// << " noe "<< noe.Num_noeud() << " N= "; normale.Affiche();
// };
// // ----- end debug
};
};
};
}
#ifdef MISE_AU_POINT
// on vérifie que tous les noeuds des frontières possèdent une normales
{LaLIST <Front>::iterator il,ilfin = listFrontiere.end();
for (il = listFrontiere.begin(); il != ilfin; il++)
{ Front& elem = (*il); // pour simplifier
ElFrontiere* elfro = elem.Eleme();
Tableau <Noeud *>& tabNFront = elfro->TabNoeud();
int nbnoefront_et1 = 1+tabNFront.Taille();
for (int inoe = 1; inoe<nbnoefront_et1; inoe++)
{Noeud & noe = *tabNFront(inoe); // pour simplifier
// on récupère le conteneur au noeud après création éventuelle
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(N_FRONT_t0);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
if(Dabs(normale.Norme()) == 0.)
// cela veut qu'aucune normale n'est disponible, c'est bizarre
{ cout << "\n *** attention le noeud "<<noe.Num_noeud()
<< " du maillage " << noe.Num_Mail()
<< " n'a pas de normale moyenne definie a t0";
};
////------ debug
//if ((noe.Num_noeud() == 139) && (noe.Num_Mail()==2))
// { cout << "\n debug Maillage::InitNormaleAuxNoeuds():"
// << " noe "<< noe.Num_noeud() << " N à t = "; normale_t.Affiche();
// };
//// ----- end debug
};
};
};
#endif
// on initialise à t par défaut
{LaLIST <Front>::iterator il,ilfin = listFrontiere.end();
for (il = listFrontiere.begin(); il != ilfin; il++)
{ Front& elem = (*il); // pour simplifier
ElFrontiere* elfro = elem.Eleme();
Tableau <Noeud *>& tabNFront = elfro->TabNoeud();
int nbnoefront_et1 = 1+tabNFront.Taille();
for (int inoe = 1; inoe<nbnoefront_et1; inoe++)
{Noeud & noe = *tabNFront(inoe); // pour simplifier
// on récupère le conteneur au noeud après création éventuelle
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(N_FRONT_t0);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
// on récupère le conteneur au noeud après création éventuelle
TypeQuelconque& tiq_t = noe.ModifGrandeur_quelconque(N_FRONT_t);
Grandeur_coordonnee& gr_t= *((Grandeur_coordonnee*) (tiq_t.Grandeur_pointee()));
Coordonnee& normale_t = *gr_t.ConteneurCoordonnee();
normale_t = normale;
};
};
};
};
// calcule des normales aux noeuds: dans le cas d'éléments 1D ou 2D uniquement
// a priori le calcul s'effectue par une moyenne des normales des éléments qui
// entourent le noeud.
// mise à jour -> mise à jour des normales à t
void Maillage::MiseAjourNormaleAuxNoeuds()
{ // on va parcourir les noeuds et on n'intervient que si le noeud
// appartient à un élément 1D et/ou 2D
int nbNoeud = tab_noeud.Taille();
int borne_max_nbNoeud = nbNoeud+1;
Coordonnee coor_inter; // coordonnée de travail
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on récupère la normale au noeud
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
normale.Zero(); // init
// calcul éventuel du tableau Indice
this->Indice();
int dima = ParaGlob::Dimension();
// si on est en dimension 1, la normale est directement déterminé
if (dima == 1)
{normale(1) = 1.;
}
else
{// ici dima > 1, les éléments ont une métrique car ils sont différents des éléments points
List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud
List_io < Element*>::iterator il,ilfin = li_elem.end();
// on balaie les éléments
int nb_normale=0; // le nombre de normales trouvées
for (il = li_elem.begin(); il != ilfin; il++)
{Element& elem = *(*il);
Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie());
// if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
{int cas = elem.CalculNormale_noeud(TEMPS_t,*tab_noeud(ine),coor_inter);
if (cas == 0)
{cout << "\n *** erreur, le calcul de la normale n'est pas possible "
<< " pour le noeud "<<tab_noeud(ine)->Num_noeud()
<< " du maillage " << tab_noeud(ine)->Num_Mail()
<< " par rapport a l'element "<< elem.Num_elt()
<< " du maillage " << elem.Num_maillage()
<< "\n Maillage::MiseAjourNormaleAuxNoeuds() ";
Sortie(1);
}
else if (cas == 2)
{// le calcul n'est pas licite, mais ce n'est pas une erreur
// simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
}
else // sinon c'est ok
{// on peut avoir des directions très proches mais de sens inverse ... ce qui va
// conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire
// s'il est négatif on utilise l'inverse de la normale
// donc en définitif on gardera globalement la direction précédente
if ((normale * coor_inter) > 0.)
{normale += coor_inter;}
else
{normale -= coor_inter;};
// {normale += coor_inter;
nb_normale++;
};
};
};
if (nb_normale != 0)
{normale /= nb_normale;
// enfin on normalise la normale
normale.Normer();
};
};
// ce qui fini la mise à jour de la normale au noeud
};
// on fait de même pour les éléments frontières minimals
// calcul éventuel du tableau indice_NFr
this->Indice_NFr();
int dima = ParaGlob::Dimension();
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on récupère la normale au noeud
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(N_FRONT_t);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
normale.Zero(); // init
// si on est en dimension 1, la normale est directement déterminé
if (dima == 1)
{normale(1) = 1.;
}
else
{// ici dima > 1, les éléments ont une métrique car ils sont différents des éléments points
List_io <Front*>& li_elem = indice_NFr(ine);// la liste des Front qui contiennent le noeud
List_io <Front*>::iterator il,ilfin = li_elem.end();
// on balaie les éléments
int nb_normale=0; // le nombre de normales trouvées
for (il = li_elem.begin(); il != ilfin; il++)
{Front& elem = *(*il);
Enum_type_geom enutygeom = elem.Eleme_const()->Type_geom_front();
int cas = elem.Eleme()->CalculNormale_noeud(TEMPS_t,*tab_noeud(ine),coor_inter);
if (cas == 0)
{cout << "\n *** erreur, le calcul de la normale n'est pas possible "
<< " pour le noeud "<<tab_noeud(ine)->Num_noeud()
<< " du maillage " << tab_noeud(ine)->Num_Mail()
<< " par rapport a l'element de frontiere ";
elem.Affiche(1);
cout << "\n Maillage::InitNormaleAuxNoeuds() ";
Sortie(1);
}
else if (cas == 2)
{// le calcul n'est pas licite, mais ce n'est pas une erreur
// simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
}
else // sinon c'est ok
{// on peut avoir des directions très proches mais de sens inverse ... ce qui va
// conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire
// s'il est négatif on utilise l'inverse de la normale
// donc en définitif on gardera globalement la direction précédente
if ((normale * coor_inter) > 0.)
{normale += coor_inter;}
else
{normale -= coor_inter;};
nb_normale++;
};
};
if (nb_normale != 0)
{normale /= nb_normale;
// enfin on normalise la normale
normale.Normer();
};
};
// ce qui fini la mise à jour de la normale au noeud
};
#ifdef MISE_AU_POINT
// on vérifie que tous les noeuds des frontières possèdent une normales
{LaLIST <Front>::iterator il,ilfin = listFrontiere.end();
for (il = listFrontiere.begin(); il != ilfin; il++)
{ Front& elem = (*il); // pour simplifier
ElFrontiere* elfro = elem.Eleme();
Tableau <Noeud *>& tabNFront = elfro->TabNoeud();
int nbnoefront_et1 = 1+tabNFront.Taille();
for (int inoe = 1; inoe<nbnoefront_et1; inoe++)
{Noeud & noe = *tabNFront(inoe); // pour simplifier
// on récupère le conteneur au noeud après création éventuelle
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(N_FRONT_t);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
if(Dabs(normale.Norme()) == 0.)
// cela veut qu'aucune normale n'est disponible, c'est bizarre
{ cout << "\n *** attention le noeud "<<noe.Num_noeud()
<< " du maillage " << noe.Num_Mail()
<< " n'a pas de normale moyenne definie a t ";
};
};
};
};
#endif
};
// mise à jour -> mise à jour des normales à t
// mais ici, on calcule les normales à tdt, et on transfert à t
// cette méthode est utile si on veut utiliser des normales à t pour une valeur
// particulière (transitoire) de la géométrie à tdt
// cf: l'algo non dyna par exempel
void Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T()
{ // on va parcourir les noeuds et on n'intervient que si le noeud
// appartient à un élément 1D et/ou 2D
int nbNoeud = tab_noeud.Taille();
int borne_max_nbNoeud = nbNoeud+1;
Coordonnee coor_inter; // coordonnée de travail
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on récupère la normale au noeud
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(NN_SURF_t);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
normale.Zero(); // init
// calcul éventuel du tableau Indice
this->Indice();
List_io < Element*>& li_elem = indice(ine);// la liste des éléments qui contiennent le noeud
List_io < Element*>::iterator il,ilfin = li_elem.end();
// on balaie les éléments
int nb_normale=0; // le nombre de normales trouvées
for (il = li_elem.begin(); il != ilfin; il++)
{Element& elem = *(*il);
Enum_type_geom enutygeom = Type_geom_generique(elem.Id_geometrie());
// if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
if (enutygeom == SURFACE) // pour l'intant on ne traite que les surfaces
{// ici contrairement à la méthode: MiseAjourNormaleAuxNoeuds
// on demande à l'élément de calculer la normale avec la géométrie à tdt
int cas = elem.CalculNormale_noeud(TEMPS_tdt,*tab_noeud(ine),coor_inter);
if (cas == 0)
{cout << "\n *** erreur, le calcul de la normale n'est pas possible "
<< " pour le noeud "<<tab_noeud(ine)->Num_noeud()
<< " du maillage " << tab_noeud(ine)->Num_Mail()
<< " par rapport a l'element "<< elem.Num_elt()
<< " du maillage " << elem.Num_maillage()
<< "\n Maillage::MiseAjourNormaleAuxNoeuds_de_tdt_vers_T() ";
Sortie(1);
}
else if (cas == 2)
{// le calcul n'est pas licite, mais ce n'est pas une erreur
// simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
}
else // sinon c'est ok
{// on peut avoir des directions très proches mais de sens inverse ... ce qui va
// conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire
// s'il est négatif on utilise l'inverse de la normale
// donc en définitif on gardera globalement la direction précédente
if ((normale * coor_inter) > 0.)
{normale += coor_inter;}
else
{normale -= coor_inter;};
// {normale += coor_inter;
nb_normale++;
};
};
};
if (nb_normale != 0)
{normale /= nb_normale;
// enfin on normalise la normale
normale.Normer();
};
// ce qui fini la mise à jour de la normale au noeud
};
// on fait de même pour les éléments frontières minimals
// calcul éventuel du tableau indice_NFr
this->Indice_NFr();
int dima = ParaGlob::Dimension();
for (int ine =1; ine < borne_max_nbNoeud;ine++ )
{Noeud & noe = *tab_noeud(ine); // pour simplifier
// on récupère la normale au noeud
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(N_FRONT_t);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
normale.Zero(); // init
// si on est en dimension 1, la normale est directement déterminé
if (dima == 1)
{normale(1) = 1.;
}
else
{// ici dima > 1, les éléments ont une métrique car ils sont différents des éléments points
// la norme est nulle, on continue
List_io <Front*>& li_elem = indice_NFr(ine);// la liste des Front qui contiennent le noeud
List_io <Front*>::iterator il,ilfin = li_elem.end();
// on balaie les éléments
int nb_normale=0; // le nombre de normales trouvées
for (il = li_elem.begin(); il != ilfin; il++)
{Front& elem = *(*il);
Enum_type_geom enutygeom = elem.Eleme_const()->Type_geom_front();
// ici contrairement à la méthode: MiseAjourNormaleAuxNoeuds
// on demande à l'élément de calculer la normale avec la géométrie à tdt
int cas = elem.Eleme()->CalculNormale_noeud(TEMPS_tdt,*tab_noeud(ine),coor_inter);
if (cas == 0)
{cout << "\n *** erreur, le calcul de la normale n'est pas possible "
<< " pour le noeud "<<tab_noeud(ine)->Num_noeud()
<< " du maillage " << tab_noeud(ine)->Num_Mail()
<< " par rapport a l'element de frontiere ";
elem.Affiche(1);
cout << "\n Maillage::InitNormaleAuxNoeuds() ";
Sortie(1);
}
else if (cas == 2)
{// le calcul n'est pas licite, mais ce n'est pas une erreur
// simplement, l'élément n'est pas rusé pour ce noeud, on ne fait rien
}
else // sinon c'est ok
{// on peut avoir des directions très proches mais de sens inverse ... ce qui va
// conduire à une somme nulle, pour éviter cela, on regarde le produit scalaire
// s'il est négatif on utilise l'inverse de la normale
// donc en définitif on gardera globalement la direction précédente
if ((normale * coor_inter) > 0.)
{normale += coor_inter;}
else
{normale -= coor_inter;};
nb_normale++;
};
};
if (nb_normale != 0)
{normale /= nb_normale;
// enfin on normalise la normale
normale.Normer();
};
};
// ce qui fini la mise à jour de la normale au noeud
};
#ifdef MISE_AU_POINT
// on vérifie que tous les noeuds des frontières possèdent une normales
{LaLIST <Front>::iterator il,ilfin = listFrontiere.end();
for (il = listFrontiere.begin(); il != ilfin; il++)
{ Front& elem = (*il); // pour simplifier
ElFrontiere* elfro = elem.Eleme();
Tableau <Noeud *>& tabNFront = elfro->TabNoeud();
int nbnoefront_et1 = 1+tabNFront.Taille();
for (int inoe = 1; inoe<nbnoefront_et1; inoe++)
{Noeud & noe = *tabNFront(inoe); // pour simplifier
// on récupère le conteneur au noeud après création éventuelle
TypeQuelconque& tiq = noe.ModifGrandeur_quelconque(N_FRONT_t);
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tiq.Grandeur_pointee()));
Coordonnee& normale = *gr.ConteneurCoordonnee();
if(Dabs(normale.Norme()) == 0.)
// cela veut qu'aucune normale n'est disponible, c'est bizarre
{ cout << "\n *** attention le noeud "<<noe.Num_noeud()
<< " du maillage " << noe.Num_Mail()
<< " n'a pas de normale moyenne definie a t";
};
};
};
};
#endif
};
// creation des elements frontiere
// il s'agit ici des frontière minimales permettant de représenter toute la frontière
// Ainsi:
// en 1D on retrouve:
// - des points uniquement
// en 2D on retrouve :
// - des segments dans le cas d'une surface (les noeuds sont exclus car intégrés aux lignes)
// - points et segment pour les lignes
// en 2D axi, on retrouve :
// - des segments dans le cas d'une surface (les noeuds sont exclus car intégrés aux lignes)
// - points et segment pour les lignes
// en 3D, on retrouve
// - des faces pour les éléments volumique (noeuds et lignes sont exclus)
// - une face et des lignes pour les éléments 2D (pas de noeuds)
void Maillage::CreeElemFront()
{
// 0- on supprime la liste existante
listFrontiere.erase(listFrontiere.begin(),listFrontiere.end());
// 1- tout d'abord on crée les éléments frontière dans chaque élément
int tabelTaille = tab_element.Taille();
// on boucle sur les elements
for (int i2 = 1; i2 <= tabelTaille; i2++)
// création des éléments frontières (on force)
tab_element(i2)->Frontiere(true);
// 2- maintenant on va créé des tableaux permettant d'accélérer l'algorithme final
// pour chaque noeud on regarde quel élément contiend ce noeud
Calcul_indice();
int tab_noeud_taille= tab_noeud.Taille();
// indice contiend les numéros d'élément succeptible d'avoir des frontières
// communes
// 3- maintenant on va de nouveau boucler sur les éléments en regardant
// pour chaque frontière si elle est effectivement recevable c-a-d si
// il n'y a pas deux frontières identiques
Front lili; // un element de référence de frontière courant
// for (int i1 = 1; i1 <= tabelTaille-1; ++i1)
for (int i1 = 1; i1 <= tabelTaille; i1++)
{Element * elem1 = tab_element(i1); // recup de l'element
const Tableau <ElFrontiere*>& tab1 = elem1->Frontiere(); // et de ses frontières
int tab1Taille = tab1.Taille(); // frontières
//-- debug
//cout << "\n elem1 " << elem1->Num_elt() << " ";
//--fin debug
// on boucle sur les frontière, qui doivent être repérée par un pointeur non nulle
for (int j1=1;j1<= tab1Taille;j1++)
// on essaie de voir si l'élément j1 est recevable, c-a-d pointeur non nulle
// sinon cela veut dire que la frontière a été supprimer car en double
{ElFrontiere * elfr = tab1(j1); // pour simplifier
// on ne continu que si le pointeur est non nul
if (elfr != NULL)
{
bool res = false;
// si deux éléments frontières sont identiques alors tous leurs noeuds
// sont identiques. En particulier le premier noeud de *elfr est commum
// avec tous les éléments succeptibles de contenir un élément frontière
// identique. On va donc utiliser la liste indice qui contiend cette liste
int numnoeud = (elfr->TabNoeud())(1)->Num_noeud();
/// vector<Element*>::iterator ina,infin;
/// vector<Element*>& intertab = indice[numnoeud-1]; // pour allèger l'écriture
list<Element*>::iterator ina,infin;
list<Element*>& intertab = indice(numnoeud); // pour allèger l'écriture
infin = intertab.end();
// on balaie les élément succeptibles d'avoir des frontières communes
for (ina = intertab.begin();ina!=infin;ina++)
{Element * elem2 = *ina; // recup de l'element
//-- debug
//cout << " intertab.size() = " << intertab.size();
//cout << ", elem2 " << elem2->Num_elt() << " ";
//--fin debug
// on ne fait la recherche que pour les éléments différents de elem1
bool res_ina = false; // init d'un indicateur interne à la boucle j2 qui suit,
if (elem2 != elem1)
{
//------- debug
//cout << "\n debug ** Maillage::CreeElemFront() ";
//elem2->Affiche(); cout << endl;
//---- fin debug
const Tableau <ElFrontiere*>& tab2 = elem2->Frontiere(); // et des éléments
int tab2Taille = tab2.Taille(); // frontières
for (int j2=1;j2<= tab2Taille;++j2)
{ // dans le cas où l'élément frontière existe, c'est-à-dire
// qu'il n'a pas été supprimé par un précédent passage
// on le compare
ElFrontiere* tab2j2 = tab2(j2); // pour simplifier
if (tab2j2 != NULL)
{ElFrontiere* p = tab2j2->Oppose(); // variable transitoire
if ((*elfr) == (*p))
// on a trouve un element qui annule
{ res = res_ina = true;// on met l'indicateur
// suppression de l'élément dans la liste
elem2->SupprimeFront(tab2j2);
};
delete p; // suppression de l'element p transitoire
}
// si il y a eu suppression de l'élément frontière on sort de la boucle
if (res_ina) break; // on sort de la boucle si pas élément de frontière
};
// si l'on a détecté une égalité on arête également cette boucle
// après avoir supprimé l'élément frontière
// non, car on pourrait avoir une frontière qui soit commune à plus de 2 éléments
// pour l'instant ce n'est pas le cas, mais par exemple des arrêtes pour les volumes ??
// if (res)
// { elem1->SupprimeFront(elfr);
// elfr=NULL;
// break;
// }
};
};
// en sortie on sauvegarde uniquement si c'est un élément frontière
if (!res)
{// lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1;
int num_dans_le_type = elem1->Num_de_frontiere_dans_le_type(j1);
listFrontiere.push_back(Front(*elfr,elem1,num_dans_le_type));
}
else // sinon la frontière est commune avec au moins une autre, on l'a supprime
{ elem1->SupprimeFront(elfr);
};
}; // fin du test if (elfr != NULL)
}; // fin de la boucle sur les frontières de elem1
}// fin de la boucle externe des éléments
/* // cas du dernier élément, ses éléments frontières non nuls sont forcément bons
non finalement, cela semble poser des pb sur le dernier élément vu que l'on a mis une procédure d'accélération
pour le calcul des frontières donc on met en stand by pour l'instant, si pas de pb qui apparaissent on supprime
{ Element * elem1 = tab_element(tabelTaille); // recup de l'element
const Tableau <ElFrontiere*>& tab1 = elem1->Frontiere(); // et des éléments
int tab1Taille = tab1.Taille(); // frontières
for (int j1=1;j1<= tab1Taille;++j1)
// on essaie de voir si l'élément j1 est recevable
{ ElFrontiere * elfr = tab1(j1); // pour simplifier
if (elfr != NULL)
{//lili.Eleme() =elfr; lili.numMail = idmail; lili.ptEl = elem1;
listFrontiere.push_back(Front(elfr,elem1));
}
}
}
*/
//Sortie(1);
// effacement du contenu du tableau indice
indice.Libere ();
//// ---- debug -----
// vérification que l'on a bien les frontières bien connectées
// cout << " \n debug: Maillage::CreeElemFront()";
//{ LaLIST <Front>::iterator iF;
// LaLIST <Front>::iterator iFfin = listFrontiere.end();
// cout << "\n liste des frontières: \n ";
// for (iF = listFrontiere.begin();iF!=iFfin; iF++)
// { Front* elfront = &(*iF);
// Enum_type_geom type_front; // va être modifier par Num_frontiere
// cout << " frontière: " << elfront->Num_frontiere() << " " << elfront->Eleme()->Type_geom_front()
// << " de l'element " << elfront->PtEI()->Num_elt() << " du maillage "
// << elfront->PtEI()->Num_maillage() << " \n ";
// };
//};
// // vérif particulière (a commenter !)
//{ LaLIST <Front>::iterator iF;
// LaLIST <Front>::iterator iFfin = listFrontiere.end();
// int nbf = 1;
// for (iF = listFrontiere.begin();iF!=iFfin; iF++)
// { Front* fro = &(*iF);
// ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière
// // récup de son tableau de noeud
// Tableau<Noeud *>& tabn = efem1->TabNoeud();
// int tabntaille = tabn.Taille();
// if (fro->PtEI()->Id_geometrie() == HEXAEDRE)
// {cout << "nbf= " << nbf << ", ele= " << fro->PtEI()->Num_elt() << " : ";
// for (int ij=1;ij<= tabntaille;ij++)
// // on balaie ses noeuds
// cout << tabn(ij)->Num_noeud() << " ";
// cout << endl ;
// nbf++;
// };
// };
//
//}
//
//// ---- fin debug -----
// definition des elements frontières mitoyens aux elements de frontiere
MitoyenFront();
// ==== définition du tableau des noeuds frontières =====
// 1) on définit un tableau de numéro de noeuds qui sont utilisés
Tableau <int> t_noe(tab_noeud_taille,0); // tous les éléments sont nul
// 2) on balaie les éléments frontières
LaLIST <Front>::iterator li,li_end=listFrontiere.end();
for (li=listFrontiere.begin();li!=li_end;li++)
{ Tableau <Noeud *> & tt = (*li).Eleme()->TabNoeud();
int tt_taille=tt.Taille();
for (int i=1;i<=tt_taille;i++)
(t_noe(tt(i)->Num_noeud()))++;
};
// 3) on récupère le nombre de noeud frontière
int nb_n_f=0;
for (int ii=1;ii<= tab_noeud_taille;ii++)
if (t_noe(ii)!=0) nb_n_f++;
// 4) def du tableau final
tab_noeud_front.Change_taille(nb_n_f);
nb_n_f=0; // on se ressert du numéro
for (int ii=1;ii<= tab_noeud_taille;ii++)
{if (t_noe(ii)!=0) {nb_n_f++;tab_noeud_front(nb_n_f)=tab_noeud(ii);};};
// dans le cas où les éléments frontières sont des lignes, on les ordonnes
// de manière à former une ligne continue
// OrdonancementDesLigne();
};
// création forcée en 3D de toutes les frontières lignes (non traités par CreeElemFront())
// qui appartiennent à la frontière globales, ceci uniquement pour les éléments volumiques
// - Ces frontières ne sont pas intégrées dans la liste de frontière minimale
// - une même ligne peut appartenir à plusieurs éléments finis, elle n'est donc pas ici
// définit de manière unique (contrairement aux frontières minimales)
void Maillage::CreeListFrontiere_ligne_3D()
{ // on n'intervient qu'en 3D
if ((ParaGlob::Dimension() == 3) && !(ParaGlob::AxiSymetrie()))
{ // au cas où ... si la liste des frontières est vide on crée les frontières
if (listFrontiere.size() == 0)
CreeElemFront();
// maintenant on efface la liste existante de front segment au cas où
listFrontiere_ligne_3D.erase(listFrontiere_ligne_3D.begin(),listFrontiere_ligne_3D.end());
// on crée les éléments frontière segment pour chaque élément de la frontière minimale
LaLIST <Front>::iterator il,ilfin = listFrontiere.end();
for (il = listFrontiere.begin(); il != ilfin; il++)
{ // on vérifie que c'est un élément volumique
Enum_type_geom enutygeom = Type_geom_generique((*il).PtEI()->Id_geometrie());
if (enutygeom == VOLUME)
{// on construit et on récupère les frontières segments,
// récup de l'élément géométrique
ElemGeomC0& el = (*il).PtEI()->ElementGeometrique();
int tail_ar = el.NbSe(); // nombre potentiel d'arêtes
for (int ifront = 1; ifront <= tail_ar; ifront++)
{ElFrontiere* const elfr = (*il).PtEI()->Frontiere_lineique(ifront,true);
// ajout après création, de la frontière front
// dans front il y a une création d'un ElFrontiere qui est == à *elfr
// mais c'est un élément frontière autonome (indépendant de celui de l'élément)
listFrontiere_ligne_3D.push_back(Front(*elfr,(*il).PtEI(),ifront));
};
};
};
};
};
// change le nom et le numéro du maillage
void Maillage::ChangeNomNumeroMaillage(const string & nom,int num)
{ // on vérifie que le nom de maillage fourni n'existe pas
if (listeNomMail.find(nom) != listeNomMail.end())
{ cout << "\n erreur, le nom de maillage demande existe deja : " << nom
<< "\n Maillage::ChangeNomNumeroMaillage(.....";
Sortie(1);
};
// on met à jour listeNomMail en supprimant le doublet nom <=> numéro existant
listeNomMail.erase(listeNomMail.find(nomDuMaillage));
nomDuMaillage = nom; // on enregistre le nouveau nom
// on vérifie que le numéro de maillage proposé est valide
if (num <=0)
{ cout << "\nErreur : numero de maillage invalide ! = "<< num <<"\n";
cout << "Maillage::ChangeNomNumeroMaillage(.... \n";
Sortie(1);
};
idmail=num; // on enregistre le nouveau numéro
// maintenant on peut associer le nom au numéro dans la map
listeNomMail[nomDuMaillage]=idmail;
};
// ramène le numéro du noeud le plus proche du point donné à t=0
int Maillage::Noeud_le_plus_proche_0(const Coordonnee& M)
{ // tout d'abord si le maillage n'a pas de noeud on ramène 0
int tail_mail = tab_noeud.Taille();
if (tail_mail == 0) return 0;
// sinon initialisation de la recherche
int num_rech = 1; // choix du premier noeud
// distance avec le noeud
double dist = (tab_noeud(1)->Coord0() - M).Norme();
// on boucle sur les noeuds
for (int i=2;i<=tail_mail;i++)
{ double dista = (tab_noeud(i)->Coord0() - M).Norme();
if (dista <= dist)
{ dist = dista; num_rech = i;};
};
// retour
return num_rech;
};
// ramène le numéro du noeud le plus proche du point donné à t=t
int Maillage::Noeud_le_plus_proche_t(const Coordonnee& M)
{ // tout d'abord si le maillage n'a pas de noeud on ramène 0
int tail_mail = tab_noeud.Taille();
if (tail_mail == 0) return 0;
// sinon initialisation de la recherche
int num_rech = 1; // choix du premier noeud
// distance avec le noeud
double dist = (tab_noeud(1)->Coord1() - M).Norme();
// on boucle sur les noeuds
for (int i=2;i<=tail_mail;i++)
{ double dista = (tab_noeud(i)->Coord1() - M).Norme();
if (dista <= dist)
{ dist = dista; num_rech = i;};
};
// retour
return num_rech;
};
// ramène le numéro du noeud le plus proche du point donné à t=tdt
int Maillage::Noeud_le_plus_proche_tdt(const Coordonnee& M)
{ // tout d'abord si le maillage n'a pas de noeud on ramène 0
int tail_mail = tab_noeud.Taille();
if (tail_mail == 0) return 0;
// sinon initialisation de la recherche
int num_rech = 1; // choix du premier noeud
// distance avec le noeud
double dist = (tab_noeud(1)->Coord2() - M).Norme();
// on boucle sur les noeuds
for (int i=2;i<=tail_mail;i++)
{ double dista = (tab_noeud(i)->Coord2() - M).Norme();
if (dista <= dist)
{ dist = dista; num_rech = i;};
};
// retour
return num_rech;
};
// ramène le numéro de l'élément qui contiend un point donné et le numéro du point
// d'intégration le plus proche pour les ddl de la liste, (ddl spécifique à l'élément c'est-a-dire
// hors des ddl des noeuds de l'éléments)
// si pas de numéro d'élément ramène un numéro d'élément nulle
// si les numéros de point d'intégration ne sont pas identique pour l'ensemble
// des ddl, pb !!, le numéro du pt integ de retour est alors négatif
// enu_temps: dit si les coordonnées du point M sont à 0 ou t ou tdt
Maillage::NBelemEtptInteg Maillage::Element_le_plus_proche
(Enum_dure enu_temps,const List_io <Ddl_enum_etendu>& list_enu
,const Coordonnee& M)
{ Maillage::NBelemEtptInteg ret;
// tout d'abord si le maillage n'a pas d'élément on ramène 0
int tail_mail = tab_element.Taille();ret.nbElem=0;ret.nbPtInteg=0;
if (tail_mail == 0) { return ret;}
// sinon initialisation de la recherche
// on boucle sur les éléments pour trouver celui qui contiend M
// M peut également être sur la surface de l'élément ce qui est ok également
for (int i=1;i<=tail_mail;i++)
{ bool trouve = false;
switch (enu_temps)
{ case TEMPS_0 : if(tab_element(i)->Interne_0(M)) trouve = true; break;
case TEMPS_t : if(tab_element(i)->Interne_t(M)) trouve = true; break;
case TEMPS_tdt : if(tab_element(i)->Interne_tdt(M)) trouve = true; break;
};
if(trouve)
{// on a trouvé un élément on recherche le point le plus près ou est exprimé la grandeur
ret.nbElem = i;
List_io <Ddl_enum_etendu>::const_iterator ii,iide= list_enu.begin();
List_io <Ddl_enum_etendu>::const_iterator iifin= list_enu.end();
ret.nbPtInteg = tab_element(i)->PointLePlusPres(enu_temps,(*iide).Enum(),M);
// on vérifie que tous les ddl sont disponibles au pt d'integ
for (ii = iide;ii != iifin; ii++)
if (!(tab_element(i)->Existe_pt_integ (ret.nbPtInteg,(*ii).Enum())))
{ ret.nbPtInteg = -1; return ret;}
// retour normal
return ret;
/* ancienne vérif, pas bonne
// on vérifie que tous les ddl sont de la même famille sinon erreur
for (ii = iide;ii != iifin; ii++)
if (!Meme_famille((*ii).Enum(),(*iide).Enum()))
{ ret.nbPtInteg = -1; return ret;}
// retour normal
return ret;
*/
};
};
// retour dans le cas où l'on n'a pas trouvé d'élément
ret.nbElem = 0;
ret.nbPtInteg = 0;
return ret;
};
// ramène le numéro de l'élément dont le centre de gravité à t = enu_temps est le plus proche d'un point donné
// Le point peut être n'importe où, en particulier à l'extérieur de la matière
// si pb retour de null
const Element* Maillage::Centre_de_Gravite_Element_le_plus_proche(Enum_dure enu_temps,const Coordonnee& M)
{ Element * el_retour=NULL;
double distance = ConstMath::tresgrand;
int nbelem = tab_element.Taille();
Coordonnee G(ParaGlob::Dimension());
// on balaie les éléments
for (int ine = 1; ine <= nbelem; ine++)
{// on commence par calculer le centre de gravité
G.Zero();
Tableau <Noeud *> taN = tab_element(ine)->Tab_noeud();
int nbn = taN.Taille();
switch (enu_temps)
{ case TEMPS_0:
for (int inn = 1;inn<=nbn;inn++)
{Noeud* noe = taN(inn);
G += noe->Coord0();
};
break;
case TEMPS_t:
for (int inn = 1;inn<=nbn;inn++)
{Noeud* noe = taN(inn);
G += noe->Coord1();
};
break;
case TEMPS_tdt:
for (int inn = 1;inn<=nbn;inn++)
{Noeud* noe = taN(inn);
G += noe->Coord2();
};
break;
};
G /= nbn;
double new_distance = (M-G).Norme();
if (new_distance < distance)
{el_retour = tab_element(ine);
distance = new_distance;
};
};
// retour de l'élément
return el_retour;
};
// ramène le maximum de variation de coordonnée entre t et tdt de tous les noeuds du maillage
double Maillage::Max_var_dep_t_a_tdt() const
{ int nbn = tab_noeud.Taille(); double ret=0.;
for (int i=1;i<=nbn;i++) ret=MaX(tab_noeud(i)->Max_var_coor_t_a_tdt(),ret);
return ret;
};
// ramène le minimum de la distance entre deux noeuds de l'ensemble des éléments
double Maillage::Min_dist2Noeud_des_elements(Enum_dure temps) const
{ double retour=ConstMath::tresgrand; // init
// on balaie les éléments
int taille_elem = tab_element.Taille();
for (int i=1; i<=taille_elem;i++)
{ const Tableau<Noeud *>& tab_N_el = tab_element(i)->Tab_noeud();
int nbn_loc = tab_N_el.Taille();
switch (temps)
{ case TEMPS_0 :
{ for (int in = 1;in<=nbn_loc;in++)
{const Coordonnee& Ci = tab_N_el(in)->Coord0();
for (int jn = in+1;jn<=nbn_loc;jn++)
{const Coordonnee& Cj = tab_N_el(jn)->Coord0();
retour = MiN(retour,(Ci-Cj).Max_val_abs());
};
};
break;
}
case TEMPS_t :
{ for (int in = 1;in<=nbn_loc;in++)
{const Coordonnee& Ci = tab_N_el(in)->Coord1();
for (int jn = in+1;jn<=nbn_loc;jn++)
{const Coordonnee& Cj = tab_N_el(jn)->Coord1();
retour = MiN(retour,(Ci-Cj).Max_val_abs());
};
};
break;
}
case TEMPS_tdt :
{ for (int in = 1;in<=nbn_loc;in++)
{const Coordonnee& Ci = tab_N_el(in)->Coord2();
for (int jn = in+1;jn<=nbn_loc;jn++)
{const Coordonnee& Cj = tab_N_el(jn)->Coord2();
retour = MiN(retour,(Ci-Cj).Max_val_abs());
};
};
break;
}
default :
cout << "\nErreur : valeur incorrecte du type Enum_dure !\n";
cout << "Maillage::Min_dist2Noeud_des_elements(... \n";
Sortie(1);
};
};
return retour;
};
//----- lecture écriture de base info -----
// lecture base info
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void Maillage::Lecture_base_info(ifstream& entr,const int cas)
{switch (cas)
{ case 1 : // ------- on récupère tout -------------------------
{// l'id et le nom du maillage et la dimension
int dime; string toto; int idmail_n; string nomDuMaillage_n;
entr >> toto >> idmail_n >> nomDuMaillage_n >> toto >> dime ;
// les types de problèmes associés
// { types_de_problemes.clear(); int nb=0; // init
// entr >> toto >> nb ; string type;
// for (int i=1;i<=nb;i++)
// {entr >> type;types_de_problemes.push_back(Id_nom_ElemTypeProblem(type));};
// };
{ int nb=0; // init
entr >> toto >> nb ; string type;
types_de_problemes.Change_taille(nb);
for (int i=1;i<=nb;i++)
{entr >> type;types_de_problemes(i)=(Id_nom_ElemTypeProblem(type));};
};
// les ddl associés
// { ddl_representatifs_des_physiques.clear(); int nb=0; // init
// entr >> toto >> nb ; string ddl;
// for (int i=1;i<=nb;i++)
// {entr >> ddl;ddl_representatifs_des_physiques.push_back(Id_nom_ddl(ddl));};
// };
{ int nb=0; // init
entr >> toto >> nb ; string type;
ddl_representatifs_des_physiques.Change_taille(nb);
for (int i=1;i<=nb;i++)
{entr >> type;ddl_representatifs_des_physiques(i)=(Id_nom_ddl(type));};
};
// si le nom de maillage lu est différent de celui existant,
// on supprime le doublet dans la map de gestion et on met à jour
if (nomDuMaillage != nomDuMaillage_n)
{ listeNomMail.erase(listeNomMail.find(nomDuMaillage));
nomDuMaillage = nomDuMaillage_n;
listeNomMail[nomDuMaillage] = idmail_n;
idmail = idmail_n;
}
else
{ // sinon on vérifie quand même que le numéro n'a pas changé
if (idmail != idmail_n)
{ listeNomMail[nomDuMaillage] = idmail_n;
idmail = idmail_n;
};
};
if (dime != dimension)
cout << "\nErreur : valeur de la dimension non coherente avec "
<< " l'espace de travail!\n"
<< "Maillage::Lecture_base_info(ofstream& sort,int cas)"
<< endl;
cout << " === lecture du maillage " << nomDuMaillage << " nb " << idmail << "\n" ;
//------------- lecture des noeuds -------------
cout << " lecture des noeuds " ;
// le nombre de noeud
int nbNoeud = tab_noeud.Taille();
entr >> nbNoeud >> toto;
// normalement ici on ne doit pas avoir déjà de noeud
Change_nb_noeud(nbNoeud); // dimensionnement dynamique du tableau de noeud
// lecture des noeuds
Noeud * ptr;
for (int i=1; i<= nbNoeud; i++)
{ ptr = new Noeud(i,dimension,idmail); // et attribution du numero de maillage
ptr->Lecture_base_info(entr,cas);
Affectation_noeud(*ptr);
};
// ------------ les elements finis -----------
cout << ", lecture des elements \n" ;
entr >> toto;
// lecture du nombre d'element
int nbElement;
entr >> toto >> nbElement;
// dimensionnement dynamique du tableau d'elements
Change_nb_element(nbElement);
// Lecture des elements
Element * pte;
#ifndef UTILISATION_MPI
// cas d'un calcul uni-CPU
for (int i=1; i<= nbElement; i++)
#else
// cas d'un calcul //
// on récupère la distribution d'éléments concernant le cpu en cours
const list <int > list_elem_cpu = ParaGlob::param->const_List_element_CPU_en_cours(idmail);
// le nombre d'élément spécifiquement pour le CPU
int nbElement_cpu = list_elem_cpu.size();
int inter; // le nombre stocké sur le .BI
entr >> toto >> inter;
// on vérifie que c'est le bon
if (inter != nbElement_cpu)
{ cout << "\nErreur : le nombre d'element a lire: " << nbElement_cpu
<< " est different de celui stocke sur le .BI: " << inter
<< "\n cas d'un calcul parallele avec lecture initiale du .BI, cpu nb:"
<< ParaGlob::Monde()->rank() << " !! "
<< "\n Maillage::Lecture_base_info(ofstream& sort,int cas)"
<< endl;
Sortie (1);
};
// lecture des éléments
// on balaie les éléments nécessaires
list <int >::const_iterator il,ilfin=list_elem_cpu.end();
for (il = list_elem_cpu.begin();il != ilfin;il++)
{int i = (*il);
#endif
{ // lecture geometrie et interpolation
Enum_geom id_geom; Enum_interpol id_interpol;
EnumElemTypeProblem id_typeProb;string str_precision;
int num_elt; // donnee dont on ne se sert pas
entr >> toto >> num_elt >> id_geom >> id_interpol >> id_typeProb;
// on regarde le prochain caractère sans changer le flot
/////int cr=entr.peek();
//--- début du remplacement du peek
char car = Picococar(entr); // = flot.peek();
// on recupère l'entier correspondant au caractère
int cr = int(car);
//--- fin du remplacement du peek
// on regarde s'il y a une chaine discriminante
if (cr == int('_')) entr >> str_precision;
// ======== choix de l'element =====================================
// et affectation du pointeur d'element en fonction de id_geom et id_interpol
// le numero d'element : num_elt, est affecte a l'element pointe par ptr
pte = Element::Choix_element(idmail,num_elt,id_geom,id_interpol,id_typeProb,str_precision);
if (pte == NULL)
{ // l'operation a echouee
cout << "\n Erreur dans le choix d'element ****** ";
cout << "\n l\'element : " << Nom_interpol(id_interpol)
<< " " << Nom_geom(id_geom)
<< " n\'est pas present dans le programme ! "
<< "\n Maillage::Lecture_base_info(..." << endl;
Sortie (1);
};
// lecture des infos particulieres a l'element
Tableau<Noeud*> * pt = & tab_noeud;
pte->Lecture_base_info(entr,pt,cas);
Affectation_element(*pte);
// si c'est le premier élément du premier maillage on regarde s'il s'agit
// d'un élément axisymétrique et on adapte l'espace de travail en conséquence
if ((i==1) && (idmail==1))
{ if (TestEnum_geom_axisymetrique(id_geom))
ParaGlob::Change_en_AxiSymetrie();
}
else
{// dans le cas des autres éléments on vérifie qu'ils ne sont pas incohérent
if (TestEnum_geom_axisymetrique(id_geom) != (ParaGlob::AxiSymetrie()))
{cout << "\n **** erreur en definition de l'element " << num_elt <<" du maillage " << idmail
<< " nom= " << nomDuMaillage;
if (ParaGlob::AxiSymetrie())
cout << "\n incoherence : l'espace de travail n'est pas axisymetrique (definit par les precedents elements)"
<< " et l'element lu est axisymetrique !! ";
else
cout << "\n incoherence : l'espace de travail est axisymetrique (definit par les precedents elements)"
<< " et l'element lu n'est pas axisymetrique !! ";
cout << endl;
Sortie (1);
};
};
}
#ifdef UTILISATION_MPI
// fin cas d'un calcul //
};
#endif
// ------------ les elements frontières -----------
// il sont créé par ailleurs si il y en a besoin
break;
}
case 2 : // ----------- lecture uniquement de se qui varie --------------------
{// le nom du maillage pour vérification
// cout << "\n debug **** Maillage::Lecture_base_info\n"
// << "\n entr.rdstate() " << entr.rdstate() << flush;
//entr.clear();
string inter,nomDuMail;
entr >> inter >> nomDuMail ;
//string truc; entr >> truc;
// cout << "\n debug **** Maillage::Lecture_base_info\n"
// << " inter=" << inter << " nomDuMaillage= " << nomDuMail
// << " titi= "<< titi << " titi1= "<< titi1
// << "\n entr.rdstate() " << entr.rdstate() << flush;
if (nomDuMail != nomDuMaillage)
{ cout << "\nErreur : le nom du maillage lu (" << nomDuMail << ") n'est pas identique avec celui en cours ("
<< nomDuMaillage << ") !! "
<< "\n Maillage::Lecture_base_info(ofstream& sort,int cas)"
<< endl;
Sortie (1);
};
//------------- les noeuds -------------
// le tableau doit être déjà dimensionné
int nbNoeud = tab_noeud.Taille();
for (int i=1; i<=nbNoeud;i++)
tab_noeud(i)->Lecture_base_info(entr,cas);
// ------------ les elements finis -----------
int nbElement = tab_element.Taille();
Tableau<Noeud*> * pt = & tab_noeud;
int nb;string toto;
#ifndef UTILISATION_MPI
// cas d'un calcul uni-CPU
for (int j=1;j<=nbElement;j++)
#else
// cas d'un calcul //
// on récupère la distribution d'éléments concernant le cpu en cours
const list <int > list_elem_cpu = ParaGlob::param->const_List_element_CPU_en_cours(idmail);
// le nombre d'élément spécifiquement pour le CPU
int nbElement_cpu = list_elem_cpu.size();
int intera; // le nombre stocké sur le .BI
entr >> toto >> intera;
// on vérifie que c'est le bon
if (intera != nbElement_cpu)
{ cout << "\nErreur : le nombre d'element a lire: " << nbElement_cpu
<< " est different de celui stocke sur le .BI: " << inter
<< "\n cas d'un calcul parallele avec lecture courante du .BI, cpu nb:"
<< ParaGlob::Monde()->rank() << " !! "
<< "\n Maillage::Lecture_base_info(ofstream& sort,int cas)"
<< endl;
Sortie (1);
};
// lecture des éléments
// on balaie les éléments nécessaires
list <int >::const_iterator il,ilfin=list_elem_cpu.end();
for (il = list_elem_cpu.begin();il != ilfin;il++)
{int j = (*il);
#endif
{entr >> toto >> nb; // le numéro de l'élément
tab_element(j)->Lecture_base_info(entr,pt,cas);
};
#ifdef UTILISATION_MPI
// fin cas d'un calcul //
};
#endif
// ------------ les elements frontières -----------
// il sont créé par ailleurs si il y en a besoin
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de lecture !\n";
cout << "Maillage::Lecture_base_info(ofstream& sort,int cas)"
<< " cas= " << cas << endl;
Sortie(1);
};
};
};
// écriture base info
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Maillage::Ecriture_base_info(ofstream& sort,const int cas)
{switch (cas)
{ case 1 : // ------- on sauvegarde tout -------------------------
{// l'id et le nom du maillage et la dimension
sort << "\n num= " << idmail <<" "<< nomDuMaillage <<" "
<< "dim= " << dimension;
// les types de problèmes associés
// {list <EnumElemTypeProblem>::iterator il,ilfin=types_de_problemes.end();
// sort <<"\n types_de_problemes: " << types_de_problemes.size() ;
// for (il=types_de_problemes.begin();il != ilfin;il++)
// sort << NomElemTypeProblem(*il);
// };
{int tail = types_de_problemes.Taille();
sort <<"\n types_de_problemes: " << tail ;
for (int i=1;i<=tail;i++)
sort << " "<< NomElemTypeProblem(types_de_problemes(i));
};
// les ddl associés
// {list <Enum_ddl>::iterator il,ilfin=ddl_representatifs_des_physiques.end();
// sort <<"\n type_de_ddl_associes: " << ddl_representatifs_des_physiques.size();
// for (il=ddl_representatifs_des_physiques.begin();il != ilfin;il++)
// Nom_ddl(*il);
// };
{int tail = ddl_representatifs_des_physiques.Taille();
sort <<"\n type_de_ddl_associes: " << tail;
for (int i=1;i<=tail;i++)
sort << " "<< Nom_ddl(ddl_representatifs_des_physiques(i));
};
sort <<"\n";
//------------- les noeuds -------------
// le nombre de noeud
int nbNoeud = tab_noeud.Taille();
sort << nbNoeud << " noeuds \n";
// sorti des noeuds
for (int i=1; i<=nbNoeud;i++)
tab_noeud(i)->Ecriture_base_info(sort,cas);
// ------------ les elements finis -----------
sort << "\n --les_elements-- ";
// le nombre d'élément total
int nbElement = tab_element.Taille();
sort <<"\n nombre_total_element " << nbElement ;
// écriture des éléments
#ifndef UTILISATION_MPI
// cas d'un calcul uni-CPU
for (int j=1;j<=nbElement;j++)
#else
// cas d'un calcul //
// on récupère la distribution d'éléments concernant le cpu en cours
const list <int > list_elem_cpu = ParaGlob::param->const_List_element_CPU_en_cours(idmail);
// le nombre d'élément spécifiquement pour le CPU
int nbElement_cpu = list_elem_cpu.size();
sort <<"\n nombre_element_CPU " << nbElement_cpu ;
// écriture des éléments
// on balaie les éléments nécessaires
list <int >::const_iterator il,ilfin=list_elem_cpu.end();
for (il = list_elem_cpu.begin();il != ilfin;il++)
{int j = (*il);
#endif
{ // tout d'abord les données de différentiation
// numéro geometrie et interpolation
sort << "\n\n element: " << tab_element(j)->Num_elt() << " "
<< tab_element(j)->Id_geometrie() << " "
<< tab_element(j)->Interpolation() << " "
<< tab_element(j)->TypeProblem() << " "
<< tab_element(j)->Infos_annexe() << "\n";
// puis les données de l'élément
tab_element(j)->Ecriture_base_info(sort,cas);
};
#ifdef UTILISATION_MPI
// fin cas d'un calcul //
};
#endif
sort << "\n ";
// ------------ les elements frontières -----------
// ne sont pas sauvegardé car reconstruit à la demande
break;
}
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
{// le nom du maillage pour vérification en lecture
sort << "\nnomDuMail= " << nomDuMaillage << "\n";
//------------- les noeuds -------------
int nbNoeud = tab_noeud.Taille();
// sorti des noeuds
for (int i=1; i<=nbNoeud;i++)
tab_noeud(i)->Ecriture_base_info(sort,cas);
// ------------ les elements finis -----------
int nbElement = tab_element.Taille();
#ifndef UTILISATION_MPI
// cas d'un calcul uni-CPU
for (int j=1;j<=nbElement;j++)
#else
// cas d'un calcul //
// on récupère la distribution d'éléments concernant le cpu en cours
const list <int > list_elem_cpu = ParaGlob::param->const_List_element_CPU_en_cours(idmail);
// le nombre d'élément spécifiquement pour le CPU
int nbElement_cpu = list_elem_cpu.size();
sort <<"\n nombre_element_CPU " << nbElement_cpu ;
// écriture des éléments
// on balaie les éléments nécessaires
list <int >::const_iterator il,ilfin=list_elem_cpu.end();
for (il = list_elem_cpu.begin();il != ilfin;il++)
{int j = (*il);
#endif
{sort << "\n\n element_nb: " << tab_element(j)->Num_elt() << " ";
tab_element(j)->Ecriture_base_info(sort,cas);
};
#ifdef UTILISATION_MPI
// fin cas d'un calcul //
};
#endif
// ------------ les elements frontières -----------
// ne sont pas sauvegardé car reconstruit à la demande
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
cout << "Maillage::Ecriture_base_info(ofstream& sort,int cas)"
<< " cas= " << cas << endl;
Sortie(1);
};
};
};
// ------ informations utiles par exemples pour la visualisation
// retourne les dimensions minis et maxi suivant les axes du repère
// absolu du maillage (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> Maillage::Taille_boiteMail()
{ // définition du tableau de retour
Tableau <Vecteur> tabret(2);
// cas particulier de maillage vide
int nbNoeud = tab_noeud.Taille();
if (nbNoeud == 0)
return tabret;
// sinon le cas normal
tabret(1).Change_taille(dimension);
tabret(2).Change_taille(dimension);
// on balaie tous les coordonnées des noeuds pour déterminer les tailles
// maxi et mini
// dans une première étape on regarde s'il existe les coordonnées à t=0
// t et t+dt, ceci à partir du premier noeud qui sert de test
// on cherche les extrémas
for (int i=1; i<=nbNoeud;i++)
{ Coordonnee a0=tab_noeud(i)->Coord0();
for (int k=1;k<= dimension;k++)
{ if (tabret(1)(k) > a0(k))
tabret(1)(k) = a0(k);
if (tabret(2)(k) < a0(k))
tabret(2)(k) = a0(k);
}
// dans le cas de coordonnées à t idem
if (tab_noeud(i)->ExisteCoord1())
{Coordonnee aat=tab_noeud(i)->Coord1();
for (int k=1;k<= dimension;k++)
{ if (tabret(1)(k) > aat(k))
tabret(1)(k) = aat(k);
if (tabret(2)(k) < aat(k))
tabret(2)(k) = aat(k);
}
};
// dans le cas de coordonnées à t+dt idem
if (tab_noeud(i)->ExisteCoord2())
{Coordonnee aatdt=tab_noeud(i)->Coord2();
for (int k=1;k<= dimension;k++)
{ if (tabret(1)(k) > aatdt(k))
tabret(1)(k) = aatdt(k);
if (tabret(2)(k) < aatdt(k))
tabret(2)(k) = aatdt(k);
}
};
}
return tabret;
};
//========================== fonction protegee =============================
// definition des elements frontières mitoyens aux elements de frontiere
// à la fin du programme tous les éléments mitoyens sont stocké dant les éléments front
// la manip est de créer des éléments frontières aux éléments frontières existant
// ensuite deux éléments sont mitoyens s'il ont la même frontière
// à la fin du programme tous les frontières des éléments frontières sont supprimé
void Maillage::MitoyenFront()
{ // le tableau indice_NFr (indice des noeuds frontières) va permettre une recherche plus rapide
Calcul_indice_NFr();
// // on le construit:
// int tab_noeud_taille= tab_noeud.Taille();
// Tableau <List_io <Front*> > indice_NFr(tab_noeud_taille);
// // indice_NFr contiend les front succeptible d'avoir des frontières géométriques communes
// LaLIST <Front>::iterator iF;
// LaLIST <Front>::iterator iFfin = listFrontiere.end();
// for (iF = listFrontiere.begin();iF!=iFfin; iF++)
// { Front* fro = &(*iF);
// ElFrontiere * efem1 = fro->Eleme(); // recup de l'element géométrique qui a créé la frontière
// // récup de son tableau de noeud
// Tableau<Noeud *>& tabn = efem1->TabNoeud();
// int tabntaille = tabn.Taille();
// for (int ij=1;ij<= tabntaille;ij++)
// // on balaie ses noeuds
// indice_NFr((tabn(ij)->Num_noeud())).push_back(fro);
// };
// // on supprime les doublons
// for (int i=1;i<=tab_noeud_taille;i++)
// { List_io <Front*>& intertab = indice_NFr(i); // pour allèger l'écriture
// intertab.sort(); // on ordonne
// intertab.unique(); // on supprime les doublons
// };
//-- debug
// cout << "\n maillage " << idmail << "\n";
// for (int ii=1;ii<= tab_noeud.Taille();ii++)
// {cout << "\n noeud " << ii << "\n";
// list<Front*>::iterator ina,infin;
// list<Front*>& intertab = indice_NFr(ii); // pour allèger l'écriture
// infin = intertab.end();
// for (ina = intertab.begin();ina!=infin;ina++)
// {Front* elem2 = (*ina); // recup de l'element
// elem2->Affiche();
// };
// };
// cout << endl;
// // Sortie(1);
//--fin debug
// on determine les elements front mitoyens a chaque element frontiere, s'ils existent
LaLIST <Front>::iterator iE,jE,iiE;
LaLIST <Front*> inters; // stockage intermediaire
LaLIST <Front>::iterator iEfin = listFrontiere.end();
for ( iE = listFrontiere.begin(); iE !=iEfin; iE++)
// pour chaque element on recherche d'autre element ayant des frontieres communes
{ // création d'élément frontières secondaires des frontières primaires
Tableau <ElFrontiere*> tabi = (*iE).Eleme()->Frontiere(); // frontieres géométriques de iE
// pour le débug cout << "\n on cherche un mitoyen a "; (*iE).Affiche();
int tabitaille = tabi.Taille();
for (int i=1;i<= tabitaille;i++)
{ ElFrontiere* elfr = tabi(i);
// pour le débug cout << " frontiere : " << i ;
// si deux éléments frontières sont identiques alors tous leurs noeuds
// sont identiques. En particulier le premier noeud de *elfr est commum
// avec tous les éléments succeptibles de contenir un élément frontière
// identique. On va donc utiliser le vector indice_NFr qui contiend cette liste
int numnoeud = (elfr->TabNoeud())(1)->Num_noeud();
list<Front*>::iterator ina,infin;
list<Front*>& intertab = indice_NFr(numnoeud); // pour allèger l'écriture
infin = intertab.end();
// on balaie les élément succeptibles d'avoir des frontières communes
for (ina = intertab.begin();ina!=infin;ina++)
{Front* elem2 = (*ina); // recup de l'element frontière
// on ne fait la recherche que pour les éléments différent de *iE
if (*elem2!=*iE)
{Tableau <ElFrontiere*> tabj = elem2->Eleme()->Frontiere(); // frontieres de ina
int tabjtaille = tabj.Taille();
for (int j=1;j<= tabjtaille;j++)
{ // ElFrontiere * tabjjOppose=(tabj(j)->Oppose()); // element transitoire
if ((*elfr) == *(tabj(j))) // ||
// (*(tabi(i)) == *tabjjOppose) )
// iE et ina ont une frontiere commune, sont donc mitoyen
{ //Front pj = &(*(*ina));
inters.push_back(&(*elem2));
//-- debug
//{Tableau <Noeud *>& toto = elfr->TabNoeud(); cout << "\n premiere frontiere NB: "<< i << ": ";
//for (int ii=1;ii<=toto.Taille();ii++) cout <<toto(ii)->Num_noeud() << " ";}
//{Tableau <Noeud *>& toto = (tabj(j))->TabNoeud(); cout << "\n frontiere mitoyenne NB: "<< j << ": ";
//for (int ii=1;ii<=toto.Taille();ii++) cout <<toto(ii)->Num_noeud() << " "; }
//cout << "\n ";
//if ((j1==3)&&(j2==6))
// cout << "on y est ";
//--fin debug
// pour le débug
// cout << "\n on a trouve une frontiere commune ";
// elem2->Affiche();
// cout << " frontiere commune: noeuds: ";
// Tableau <Noeud *> tabno = (tabj(j))->TabNoeud();
// int nb = tabno.Taille();
// for (int ijk=1;ijk<=nb; ijk++)
// cout << tabno(ijk)->Num_noeud() << " ";
// fin pour le débug
};
// delete tabjjOppose; // suppression de l'element transitoire
};
};
};
};
// fin de la recherche concernant elfr
// on supprime les doublons
inters.sort(); // on ordonne
inters.unique(); // on supprime les doublons
// creation d'un tableau a la place de la liste
Tableau <Front*> tabb((int) inters.size());
LaLIST <Front*>::iterator ip; int i2;
LaLIST <Front*>::iterator ipfin=inters.end();
LaLIST <Front*>::iterator ipdebut=inters.begin();
for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++)
tabb(i2) = &(*(*ip));
// def des elements mitoyen
(*iE).DefMitoyen(tabb);
// -- débug --- affichage
//if (inters.size() > 6)
// {cout << "\n nb frontière > 6 ";
// (*iE).Affiche();
// cout << endl;
// };
// -- fin débug --- affichage
// on vide la liste
inters.erase(ipdebut,ipfin);
};
// -- débug --- affichage
// for ( iE = listFrontiere.begin(); iE !=iEfin; iE++)
// (*iE).Affiche();
// -- fin débug --- affichage
//effacement de tous les éléments frontières secondaires des éléments frontières
// primaires
LaLIST <Front>::iterator iEE;
for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++)
(*iEE).Eleme()->EffaceFrontiere();
// -- débug --- affichage
// for ( iE = listFrontiere.begin(); iE !=iEfin; iE++)
// { Tableau <Front*>& tabi = (*iE).TabMitoyen();
// int tabitaille = tabi.Taille();
// for (int i=1;i<= tabitaille;i++)
// { Front* elfr = tabi(i);
// cout << "\n";
// elfr->Affiche();
// }
// };
//// -- fin débug --- affichage
//
};
// dans le cas où les éléments frontières sont des lignes, on les ordonnes
// de manière à former une ligne continue
void Maillage::OrdonancementDesLigne()
{// on définit une liste intermédiaire
LaLIST <Front> interlist;
// on commence par le premier élément de la liste et de proche en proche on
// rempli la liste
// on passe en revue les éléments frontières
// LaLIST <Front>::iterator iEE;
// for ( iEE = listFrontiere.begin(); iEE !=iEfin; iEE++)
// (*iEE).elem->EffaceFrontiere();
};
// definition d'un stockage contenant tous les Front associés à toutes les frontières de tous les éléments
// puis définition des elements mitoyens à ces Front : deux éléments Front sont mitoyens
// s'ils correspondent à des Element différents, et si les frontières associées possèdent les mêmes noeuds
// toutes ces informations sont stockées dans : mitoyen_de_chaque_element (cf. sa description)
void Maillage::Calcul_tous_les_front_et_leurs_mitoyens()
{ // on crée les éléments frontières dans chaque élément
int tabelTaille = tab_element.Taille();
mitoyen_de_chaque_element.Change_taille(tabelTaille); // dimensionnement
// on boucle sur les elements
for (int i2 = 1; i2 <= tabelTaille; i2++)
{ // création des éléments frontières
Element * elem1 = tab_element(i2);
elem1->Frontiere(true);
// puis on crée tous les éléments Front, qui sont alors stockés dans mitoyen_de_chaque_element(i2)
// par contre pour l'instant on n'a pas les mitoyens de calculés
const Tableau <ElFrontiere*>& tab1 = elem1->Frontiere(); // et de ses frontières
Tableau <Front> & tab_front = mitoyen_de_chaque_element(i2); // pour simplifier
int tab1Taille = tab1.Taille(); // nb de frontières
tab_front.Change_taille(tab1Taille); // dimensionne mitoyen_de_chaque_element(i2)
for (int j=1;j<=tab1Taille;j++)
tab_front(j) = Front(*tab1(j),elem1,j);
//cout << "\n les front";
//for (int j=1;j<=tab1Taille;j++)
// tab_front(j).Affiche();
};
// on crée des tableaux permettant d'accélérer l'algorithme final
// pour chaque noeud on note quel élément contiend ce noeud
// "indice" contiend les numéros d'élément succeptible d'avoir des frontières communes
Calcul_indice();
// on va boucler sur les éléments en regardant
// pour chaque frontière si il y a d'autres frontières mitoyennes c-a-d si
// il y a d'autres frontières identiques
for (int i1 = 1; i1 <= tabelTaille; i1++)
{Tableau <Front> & tab_front = mitoyen_de_chaque_element(i1); // pour simplifier
int tab1Taille = tab_front.Taille(); // nb de frontières (qui sont déjà stockées)
for (int j1=1;j1<= tab1Taille;j1++) // on boucle sur les frontière de l'élément principale (nb=i1)
// on essaie de voir si l'élément j1 est recevable
{const ElFrontiere * elfr = tab_front(j1).Eleme_const(); // récup de la frontière
// si deux éléments frontières sont identiques alors tous leurs noeuds
// sont identiques. En particulier le premier noeud de *elfr est commum
// avec tous les éléments succeptibles de contenir un élément frontière
// identique. On va donc utiliser la liste indice qui contiend cette liste
int numnoeud = (elfr->TabNoeud_const())(1)->Num_noeud();
list<Element*>::iterator ina,infin;
list<Element*>& intertab = indice(numnoeud); // pour allèger l'écriture
infin = intertab.end();
LaLIST <Front*> inters; // stockage intermediaire
// on balaie les élément succeptibles d'avoir des frontières communes
for (ina = intertab.begin();ina!=infin;ina++)
{Element * elem2 = *ina; // recup de l'element
// on ne fait la recherche que pour les éléments différents de elem1
int num_elem2 = elem2->Num_elt();
if (num_elem2 != i1)
{// récup des éléments front correspondant à elem2
Tableau <Front>& tab_fro = mitoyen_de_chaque_element(num_elem2);
int tab_fro_taille = tab_fro.Taille();
for (int j2=1;j2<=tab_fro_taille;j2++)
{ // on compare
if ((*tab_fro(j2).Eleme_const()) == (*elfr))
{// on récupère le Front de l'élément elem2, pour la frontière j2
Front* front_j2 = &tab_fro(j2);
inters.push_back(front_j2);
//--debug
//tab_front(j1).Affiche();
//front_j2->Affiche();
//--fin_debug
};
};
};
};
// on supprime les doublons
inters.sort(); // on ordonne
inters.unique(); // on supprime les doublons
// creation d'un tableau a la place de la liste
Tableau <Front*> tabb((int) inters.size());
LaLIST <Front*>::iterator ip; int i2;
LaLIST <Front*>::iterator ipfin=inters.end();
LaLIST <Front*>::iterator ipdebut=inters.begin();
for (i2=1,ip = ipdebut;ip != ipfin; ip++,i2++)
tabb(i2) = &(*(*ip));
// def des elements mitoyen, stocké dans mitoyen_de_chaque_element(i1)
tab_front(j1).DefMitoyen(tabb);
}; // fin de la boucle sur les frontières de elem1
};// fin de la boucle externe des éléments
//--debug
//for (int i=1;i<=mitoyen_de_chaque_element.Taille();i++)
// {cout <<"\n\n **** element: "<<i<<" frontiere: ";
// Tableau <Front>& tab_f = mitoyen_de_chaque_element(i);
// for (int j=1;j<=tab_f.Taille();j++)
// tab_f(j).Affiche();
// }
//--fin debug
// effacement du contenu du tableau indice
indice.Libere ();
};
// lectures des infos pour le choix d'un élément
void Maillage::Lecture_info_1element(UtilLecture * entreePrinc,int& num_elt,Enum_geom& id_geom
,Enum_interpol& id_interpol,EnumElemTypeProblem& id_typeProb
,string& str_precision)
{ // mise en place des valeurs par défaut
str_precision = "";
id_typeProb = MECA_SOLIDE_DEFORMABLE; // type par défaut
// lecture des champs qui doivent être toujours présents
*(entreePrinc->entree) >> num_elt >> id_geom >> id_interpol;
// cas d'info annexe ou du type de problème
// on regarde le prochain caractère sans changer le flot
/// int cr=(entreePrinc->entree)->peek(); ne marche pas !!!
//--- début du remplacement du peek
char car = Picococar(*(entreePrinc->entree)); // = flot.peek();
// on recupère l'entier correspondant au caractère
int cr = int(car);
//--- fin du remplacement du peek
// si c'est un chiffre c'est fini pour le choix de l'élément
int zero = int('0'); int neuf = int('9');
// if ((cr >= int('0'))&&(cr <= int('9'))) return;
if ((cr >= zero)&&(cr <= neuf)) return;
// maintenant on a deux cas, soit des infos annexes ou soit
// la définition du type de pb suivi ou non d'infos annexes
if (cr == int('_'))
// cas où on a des infos annexes de choix
{ *(entreePrinc->entree) >> str_precision;
// ensuite il ne doit y avoir que des numéros donc fin
return;
}
// ou on regarde s'il y a définition du type de problème
// qui doit commencer par une lettre
else if ( ((cr >= int('a'))&&(cr<=int('z'))) ||
((cr >= int('A'))&&(cr<=int('Z'))) )
{ *(entreePrinc->entree) >> id_typeProb;
// on regarde s'il y a des infos annexes après le type de problem
if (cr == int('_'))
// cas où on a des infos annexes de choix
{ *(entreePrinc->entree) >> str_precision;
// ensuite il ne doit y avoir que des numéros donc fin
return;
}
};
// sinon c'est le cas qui ne doit pas arriver mais pour éviter des warnings
return;
};
// affectation d'un noeud au maillage c-a-d au tableau de pointeur de noeud,
// a condition que la place ne soit pas déjà occupée sinon on change le numéro
// de noeud et on augmente le tableau
void Maillage::Affectation_noeud(Noeud& noeud)
{ int nbn = noeud.Num_noeud();
if (tab_noeud(nbn) == NULL)
{tab_noeud(nbn)=&noeud;}
else
// on augmente la place
{int tail_tab_noeud = tab_noeud.Taille()+1;
tab_noeud.Change_taille(tail_tab_noeud);
noeud.Change_num_noeud(tail_tab_noeud);
tab_noeud(tail_tab_noeud)=&noeud;
if (ParaGlob::NiveauImpression() > 0)
{cout << "\n warning : le numero initial du noeud " << nbn << " est remplace par "
<< " le numero d'ordre attribue automatiquement par herezh " << tail_tab_noeud
<< "\n seul ce dernier sera utilise par la suite ! " << endl;
if (ParaGlob::NiveauImpression() > 5)
cout << "\n Maillage::Affectation_noeud (Noeud& noeud) " << endl;
};
};
};
// affectation d'un element au maillage c-a-d au tableau de pointeur d'element,
// a condition que la place ne soit pas déjà occupée sinon on change le numéro
// de l'élément et on augmente le tableau
void Maillage::Affectation_element(Element& element)
{ int nbe = element.Num_elt();
if (tab_element(nbe) == NULL)
{tab_element(nbe)=&element;}
else
// on augmente la place
{int tail_tab_element = tab_element.Taille()+1;
tab_element.Change_taille(tail_tab_element);
element.Change_num_elt(tail_tab_element);
tab_element(tail_tab_element)=&element;
if (ParaGlob::NiveauImpression() > 0)
{cout << "\n warning : le numero initial de l'element " << nbe << " est remplace par "
<< " le numero d'ordre attribue automatiquement par herezh " << tail_tab_element
<< "\n seul ce dernier sera utilise par la suite ! " << endl;
if (ParaGlob::NiveauImpression() > 5)
cout << "\n Maillage::Affectation_element (Element& element) " << endl;
};
};
// on met à jour éventuellement les types de problèmes gérés
EnumElemTypeProblem enu = element.Id_TypeProblem();
if (!types_de_problemes.Contient(enu))
{int tail = types_de_problemes.Taille();
types_de_problemes.Change_taille(tail+1);
types_de_problemes(tail+1) = enu;
ddl_representatifs_des_physiques.Change_taille(tail+1);
switch (enu)
{case MECA_SOLIDE_DEFORMABLE :
ddl_representatifs_des_physiques(tail+1)=X1;break;
case THERMIQUE :
ddl_representatifs_des_physiques(tail+1)=TEMP;break;
default :
cout << "\n***Erreur : pour l'instant le type de probleme: "<<NomElemTypeProblem(enu)
<< "n'est pas pris en compte !\n";
cout << "\n Maillage::Affectation_element(... \n";
Sortie(1);
};
};
//
//
//
// if (find(types_de_problemes.begin(),types_de_problemes.end(),enu) == types_de_problemes.end())
// {
// types_de_problemes.push_back(enu);
// types_de_problemes.sort(); types_de_problemes.unique();
// switch (enu)
// {case MECA_SOLIDE_DEFORMABLE :
// ddl_representatifs_des_physiques.push_back(X1);break;
// case THERMIQUE :
// ddl_representatifs_des_physiques.push_back(TEMP);break;
// default :
// cout << "\n***Erreur : pour l'instant le type de probleme: "<<NomElemTypeProblem(enu)
// << "n'est pas pris en compte !\n";
// cout << "\n Maillage::Affectation_element(... \n";
// Sortie(1);
// };
// };
};
// Modifie le nombre de noeuds du maillage (N.B.: Fait appel
// a la methode Change_taille de la classe Tableau<Noeud>)
// les éléments supplémentaires ont un pointeur mis à Null
void Maillage::Change_nb_noeud (int nouveau_nb)
{ int vieille_taille = tab_noeud.Taille();
tab_noeud.Change_taille(nouveau_nb);
for (int i=vieille_taille+1;i<=nouveau_nb;i++)
tab_noeud(i)=NULL;
};
// Modifie le nombre d'elements du maillage (N.B.: Fait appel
// a la methode Change_taille de la classe Tableau<Element>)
// les éléments supplémentaires ont un pointeur mis à Null
void Maillage::Change_nb_element (int nouveau_nb)
{ int vieille_taille = tab_element.Taille();
tab_element.Change_taille(nouveau_nb);
for (int i=vieille_taille+1;i<=nouveau_nb;i++)
tab_element(i)=NULL;
};