3168 lines
138 KiB
C++
Executable file
3168 lines
138 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
|
|
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))
|
|
{ Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant
|
|
TypeQuelconque typQ4(NN_SURF_t0,EPS11,grandCoordonnee);
|
|
noe.AjoutUnTypeQuelconque(typQ4);
|
|
};
|
|
// on fait la même chose à t ce qui évitera de tester à la mise à jour
|
|
if (!noe.Existe_ici(NN_SURF_t))
|
|
{ Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant
|
|
TypeQuelconque typQ4(NN_SURF_t,EPS11,grandCoordonnee);
|
|
noe.AjoutUnTypeQuelconque(typQ4);
|
|
};
|
|
// et on le récupère après création éventuelle
|
|
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();
|
|
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))
|
|
{ Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant
|
|
TypeQuelconque typQ4(N_FRONT_t0,EPS11,grandCoordonnee);
|
|
noe.AjoutUnTypeQuelconque(typQ4);
|
|
};
|
|
// on fait la même chose à t ce qui évitera de tester à la mise à jour
|
|
if (!noe.Existe_ici(N_FRONT_t))
|
|
{ Grandeur_coordonnee grandCoordonnee(ParaGlob::Dimension()); // un type courant
|
|
TypeQuelconque typQ4(N_FRONT_t,EPS11,grandCoordonnee);
|
|
noe.AjoutUnTypeQuelconque(typQ4);
|
|
};
|
|
|
|
// 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();
|
|
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
|
|
// {
|
|
//
|
|
// }
|
|
normale += coor_inter; // ici cela me semble plus juste: on ne doit pas avoir de pb d'inversion de normale
|
|
|
|
|
|
|
|
// //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
|
|
// //------ 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
|
|
{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
|
|
{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 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 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;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|