1652 lines
76 KiB
C++
Executable file
1652 lines
76 KiB
C++
Executable file
// FICHIER : Element.cc
|
|
// CLASSE : Element
|
|
|
|
|
|
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
|
|
|
|
# include <iostream>
|
|
using namespace std; //introduces namespace std
|
|
|
|
|
|
#include "Element.h"
|
|
#include "ConstMath.h"
|
|
#include "Util.h"
|
|
#include "TypeQuelconqueParticulier.h"
|
|
|
|
//----------------------------------------------------------------
|
|
// def des donnees commune a tous les elements ( membre static)
|
|
//----------------------------------------------------------------
|
|
list <Element::NouvelleTypeElement> Element::listTypeElement;
|
|
// constantes générales qui permettent d'éviter d'utiliser des chiffres dans les classes
|
|
// dérivées ceci pour plus de lisibilité et de sureté
|
|
const double Element::epaisseur_defaut = -1. + sqrt(2.)/1000.; // épaisseur par défaut
|
|
const double Element::largeur_defaut = -1. + sqrt(2.)/1001.; // largeur par défaut
|
|
const double Element::section_defaut = -1. + sqrt(2.)/1002.; // section par défaut
|
|
const double Element::masse_volumique_defaut = -1. + sqrt(2.)/1003.; // masse_volumique par défaut
|
|
// variable de travail pour la fonction Choix_element
|
|
bool Element::premier_passage_Choix_element=true;
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// def des class internes et fonctions pour les classes internes
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
// constructeur par défaut
|
|
Element::NouvelleTypeElement::NouvelleTypeElement() :
|
|
id_geom(RIEN_GEOM),id_interpol(RIEN_INTERPOL)
|
|
,id_typeProblem(MECA_SOLIDE_DEFORMABLE),infos_annexes(""),el(NULL)
|
|
{};
|
|
// constructeur normal
|
|
Element::NouvelleTypeElement::NouvelleTypeElement(const Enum_geom id_g,const Enum_interpol id_in
|
|
, const EnumElemTypeProblem id_type
|
|
,ConstrucElement * eli ,string discri ) :
|
|
id_geom(id_g),id_interpol(id_in)
|
|
,id_typeProblem(id_type),infos_annexes(discri),el(eli)
|
|
{};
|
|
|
|
// constructeur de copie
|
|
Element::NouvelleTypeElement::NouvelleTypeElement(const NouvelleTypeElement& nvel) :
|
|
id_geom(nvel.id_geom),id_interpol(nvel.id_interpol)
|
|
,id_typeProblem(nvel.id_typeProblem),infos_annexes(nvel.infos_annexes),el(nvel.el)
|
|
{};
|
|
// opérateur d'assigment
|
|
Element::NouvelleTypeElement& Element::NouvelleTypeElement::operator= (const Element::NouvelleTypeElement& nvel)
|
|
{ id_geom=nvel.id_geom;id_interpol=nvel.id_interpol;
|
|
id_typeProblem=nvel.id_typeProblem;infos_annexes=nvel.infos_annexes;el=nvel.el;
|
|
return (*this);
|
|
};
|
|
// opérateur tests
|
|
bool Element::NouvelleTypeElement::operator == (const Element::NouvelleTypeElement& nvel)
|
|
{ if ( (id_geom==nvel.id_geom)&&(id_interpol==nvel.id_interpol)
|
|
&&(id_typeProblem==nvel.id_typeProblem)&&(infos_annexes==nvel.infos_annexes)
|
|
&&(el==nvel.el))
|
|
return true;
|
|
else return false;
|
|
};
|
|
bool Element::NouvelleTypeElement::operator != (const Element::NouvelleTypeElement& elt)
|
|
{ if (*this == elt) return true; else return false;
|
|
};
|
|
// retourne vraie si *this est le meme type d'élément que elt
|
|
bool Element::NouvelleTypeElement::MemeTypeElement(const Element::NouvelleTypeElement& nvel)
|
|
{ if ( (id_geom==nvel.id_geom)&&(id_interpol==nvel.id_interpol)
|
|
&&(id_typeProblem==nvel.id_typeProblem)&&(infos_annexes==nvel.infos_annexes))
|
|
return true;
|
|
else return false;
|
|
};
|
|
|
|
// surcharge de l'operateur d'ecriture pour les éléments de la classe signature
|
|
ostream & operator << ( ostream & sort,const Element::Signature & signature)
|
|
{ // sortie
|
|
sort << "element_finis_de_signature: " << NomElemTypeProblem(signature.id_problem)
|
|
<< " " << Nom_geom(signature.id_geom)
|
|
<< " " << Nom_interpol(signature.id_interpol)
|
|
<< " " << signature.infos_annexes;
|
|
return sort;
|
|
};
|
|
// surcharge de l'affectation
|
|
Element::Signature& Element::Signature::operator = ( const Element::Signature& a)
|
|
{ id_interpol = a.id_interpol;
|
|
id_geom = a.id_geom; id_problem = a.id_problem;
|
|
infos_annexes = a.infos_annexes;
|
|
return *this;
|
|
};
|
|
// surcharge de l'égalité
|
|
bool Element::Signature::operator == (const Element::Signature& a)
|
|
{ if ( (id_interpol==a.id_interpol)
|
|
&& (id_geom == a.id_geom) && (id_problem == a.id_problem)
|
|
&& (infos_annexes == a.infos_annexes))
|
|
return true;
|
|
else return false;
|
|
};
|
|
// surcharge de non égalité
|
|
bool Element::Signature::operator != (const Element::Signature& a)
|
|
{ return !(*this == a);};
|
|
|
|
//--------------------------------------------------------------
|
|
//-- les constructeurs --
|
|
//--------------------------------------------------------------
|
|
|
|
Element::Element (int num_maill,int num_id) :
|
|
|
|
// Constructeur utile quand le numero de maillage et d'identification de l'element est connu
|
|
tab_noeud(),residu(NULL),raideur(NULL),res_extA(NULL),raid_extA(NULL)
|
|
,res_extS(NULL),raid_extS(NULL),mat_masse(NULL)
|
|
,volume(0.),num_maillage(0),volumePlan(ParaGlob::Dimension())
|
|
,integ_vol_typeQuel(NULL),integ_vol_typeQuel_t(NULL),index_Integ_vol_typeQuel(NULL)
|
|
,integ_vol_t_typeQuel(NULL),integ_vol_t_typeQuel_t(NULL),index_Integ_vol_t_typeQuel(NULL)
|
|
,enu_integ_vol_TQ(NULL),enu_integ_vol_t_TQ(NULL)
|
|
,tabb(),ind_front_lin(0),ind_front_surf(0),posi_tab_front_lin(0)
|
|
,ind_front_point(0),posi_tab_front_point(0)
|
|
,boite_encombre(),prepa_niveau_precision(0)
|
|
,sens_numerotation(1)
|
|
{ num_maillage=num_maill; num_elt=num_id;
|
|
id_interpol=RIEN_INTERPOL;
|
|
id_geom=RIEN_GEOM;
|
|
id_problem = RIEN_PROBLEM;
|
|
infos_annexes = "";
|
|
};
|
|
|
|
Element::Element (int num_maill,int num_id,const Tableau<Noeud *>& tab):
|
|
// Constructeur utile quand le numero de maillage et de l'élément, et le tableau des noeuds
|
|
// de l'element sont connu
|
|
tab_noeud(tab),residu(NULL),raideur(NULL),res_extA(NULL),raid_extA(NULL)
|
|
,res_extS(NULL),raid_extS(NULL),mat_masse(NULL)
|
|
,volume(0.),volumePlan(ParaGlob::Dimension())
|
|
,integ_vol_typeQuel(NULL),integ_vol_typeQuel_t(NULL),index_Integ_vol_typeQuel(NULL)
|
|
,integ_vol_t_typeQuel(NULL),integ_vol_t_typeQuel_t(NULL),index_Integ_vol_t_typeQuel(NULL)
|
|
,enu_integ_vol_TQ(NULL),enu_integ_vol_t_TQ(NULL)
|
|
,tabb(),ind_front_lin(0),ind_front_surf(0),posi_tab_front_lin(0)
|
|
,ind_front_point(0),posi_tab_front_point(0)
|
|
,boite_encombre(),prepa_niveau_precision(0)
|
|
,sens_numerotation(1)
|
|
{ num_maillage=num_maill; num_elt=num_id;
|
|
id_interpol=RIEN_INTERPOL;
|
|
id_geom=RIEN_GEOM;
|
|
id_problem = RIEN_PROBLEM;
|
|
infos_annexes = "";
|
|
};
|
|
|
|
|
|
// Constructeur utile quand le numero du maillage et d'identification est connu,
|
|
// ainsi que la geometrie le type d'interpolation le problème traité de l'element
|
|
// et éventuellement un string d'information annexe
|
|
Element::Element (int num_maill,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,
|
|
EnumElemTypeProblem id_prob,string info):
|
|
num_maillage(num_maill),num_elt(num_id),id_interpol(id_interp_elt),id_geom(id_geom_elt)
|
|
,id_problem(id_prob),infos_annexes(info),tab_noeud()
|
|
,residu(NULL),raideur(NULL),res_extA(NULL),raid_extA(NULL)
|
|
,res_extS(NULL),raid_extS(NULL),mat_masse(NULL)
|
|
,volume(0.),volumePlan(ParaGlob::Dimension())
|
|
,integ_vol_typeQuel(NULL),integ_vol_typeQuel_t(NULL),index_Integ_vol_typeQuel(NULL)
|
|
,integ_vol_t_typeQuel(NULL),integ_vol_t_typeQuel_t(NULL),index_Integ_vol_t_typeQuel(NULL)
|
|
,enu_integ_vol_TQ(NULL),enu_integ_vol_t_TQ(NULL)
|
|
,tabb(),ind_front_lin(0),ind_front_surf(0),posi_tab_front_lin(0)
|
|
,ind_front_point(0),posi_tab_front_point(0)
|
|
,boite_encombre(),prepa_niveau_precision(0)
|
|
,sens_numerotation(1)
|
|
{ };
|
|
|
|
// Constructeur fonction d'un numéro de maillage, d'un numero et de deux noms (geometrie, interpolation)
|
|
//et le type de problème traité par l'element
|
|
Element::Element (int num_maill,int num_id,const string& nom_interpol,const string& nom_geom,
|
|
const string& nom_prob,string info):
|
|
num_maillage(num_maill),num_elt(num_id),infos_annexes(info),tab_noeud()
|
|
,residu(NULL),raideur(NULL),res_extA(NULL),raid_extA(NULL)
|
|
,res_extS(NULL),raid_extS(NULL),mat_masse(NULL)
|
|
,volume(0.),volumePlan(ParaGlob::Dimension())
|
|
,integ_vol_typeQuel(NULL),integ_vol_typeQuel_t(NULL),index_Integ_vol_typeQuel(NULL)
|
|
,integ_vol_t_typeQuel(NULL),integ_vol_t_typeQuel_t(NULL),index_Integ_vol_t_typeQuel(NULL)
|
|
,enu_integ_vol_TQ(NULL),enu_integ_vol_t_TQ(NULL)
|
|
,tabb(),ind_front_lin(0),ind_front_surf(0),posi_tab_front_lin(0)
|
|
,ind_front_point(0),posi_tab_front_point(0)
|
|
,boite_encombre(),prepa_niveau_precision(0)
|
|
,sens_numerotation(1)
|
|
{
|
|
id_interpol=Id_nom_interpol(nom_interpol);
|
|
id_geom=Id_nom_geom(nom_geom);
|
|
id_problem=Id_nom_ElemTypeProblem(nom_prob);
|
|
};
|
|
|
|
// Constructeur fonction d'un numéro de maillage, d'un numero, du tableau de connexite des noeuds et de
|
|
// trois identificateurs et un nom (geometrie, interpolation, type de probleme,
|
|
// particularité éventuelle),
|
|
// et du type de problème traité par l'element
|
|
Element::Element (int num_maill,int num_id,const Tableau<Noeud *>& tab,Enum_interpol id_interp_elt,
|
|
Enum_geom id_geom_elt,EnumElemTypeProblem id_prob,string info):
|
|
num_maillage(num_maill),num_elt(num_id),id_interpol(id_interp_elt),id_geom(id_geom_elt)
|
|
,id_problem(id_prob),infos_annexes(info),tab_noeud(tab)
|
|
,residu(NULL),raideur(NULL),res_extA(NULL),raid_extA(NULL)
|
|
,res_extS(NULL),raid_extS(NULL),mat_masse(NULL)
|
|
,volume(0.),volumePlan(ParaGlob::Dimension())
|
|
,integ_vol_typeQuel(NULL),integ_vol_typeQuel_t(NULL),index_Integ_vol_typeQuel(NULL)
|
|
,integ_vol_t_typeQuel(NULL),integ_vol_t_typeQuel_t(NULL),index_Integ_vol_t_typeQuel(NULL)
|
|
,enu_integ_vol_TQ(NULL),enu_integ_vol_t_TQ(NULL)
|
|
,tabb(),ind_front_lin(0),ind_front_surf(0),posi_tab_front_lin(0)
|
|
,ind_front_point(0),posi_tab_front_point(0)
|
|
,boite_encombre(),prepa_niveau_precision(0)
|
|
,sens_numerotation(1)
|
|
{
|
|
};
|
|
|
|
// Constructeur fonction d'un numéro de maillage, d'un numero, du tableau de connexite des noeuds, de
|
|
// quatre noms (geometrie, interpolation, type de probleme, particularité éventuelle),
|
|
// et du type de problème traité par l'element
|
|
Element::Element (int num_maill,int num_id,const Tableau<Noeud *>& tab,const string& nom_interpol,
|
|
const string& nom_geom,const string& nom_prob,string info):
|
|
num_maillage(num_maill),num_elt(num_id),infos_annexes(info),tab_noeud(tab)
|
|
,residu(NULL),raideur(NULL),res_extA(NULL),raid_extA(NULL)
|
|
,res_extS(NULL),raid_extS(NULL),mat_masse(NULL)
|
|
,volume(0.),volumePlan(ParaGlob::Dimension())
|
|
,integ_vol_typeQuel(NULL),integ_vol_typeQuel_t(NULL),index_Integ_vol_typeQuel(NULL)
|
|
,integ_vol_t_typeQuel(NULL),integ_vol_t_typeQuel_t(NULL),index_Integ_vol_t_typeQuel(NULL)
|
|
,enu_integ_vol_TQ(NULL),enu_integ_vol_t_TQ(NULL)
|
|
,tabb(),ind_front_lin(0),ind_front_surf(0),posi_tab_front_lin(0)
|
|
,ind_front_point(0),posi_tab_front_point(0)
|
|
,boite_encombre(),prepa_niveau_precision(0)
|
|
,sens_numerotation(1)
|
|
{
|
|
id_interpol=Id_nom_interpol(nom_interpol);
|
|
id_geom=Id_nom_geom(nom_geom);
|
|
id_problem=Id_nom_ElemTypeProblem(nom_prob);
|
|
};
|
|
|
|
// Constructeur de copie
|
|
Element::Element (const Element& elt):
|
|
num_maillage(elt.num_maillage),num_elt(elt.num_elt),id_interpol(elt.id_interpol)
|
|
,id_geom(elt.id_geom),id_problem(elt.id_problem),infos_annexes(elt.infos_annexes)
|
|
,tab_noeud(elt.tab_noeud)
|
|
,residu(NULL),raideur(NULL),res_extA(NULL),raid_extA(NULL)
|
|
,res_extS(NULL),raid_extS(NULL),mat_masse(NULL)
|
|
,volume(elt.volume),volumePlan(elt.volumePlan)
|
|
,integ_vol_typeQuel(NULL),integ_vol_typeQuel_t(NULL),index_Integ_vol_typeQuel(NULL)
|
|
,integ_vol_t_typeQuel(NULL),integ_vol_t_typeQuel_t(NULL),index_Integ_vol_t_typeQuel(NULL)
|
|
,enu_integ_vol_TQ(NULL),enu_integ_vol_t_TQ(NULL)
|
|
,tabb(),ind_front_lin(0),ind_front_surf(0),posi_tab_front_lin(0)
|
|
,ind_front_point(0),posi_tab_front_point(0)
|
|
,boite_encombre(elt.boite_encombre),prepa_niveau_precision(elt.prepa_niveau_precision)
|
|
,sens_numerotation(elt.sens_numerotation)
|
|
// on ne recopie pas les adresses pointees car celles-ci peuvent changer, donc il vaut mieux
|
|
// les reconstruire si besoin est
|
|
{if (elt.integ_vol_typeQuel != NULL)
|
|
{integ_vol_typeQuel = new Tableau <TypeQuelconque>(*(elt.integ_vol_typeQuel));};
|
|
if (elt.integ_vol_typeQuel_t != NULL)
|
|
{integ_vol_typeQuel_t = new Tableau <TypeQuelconque>(*(elt.integ_vol_typeQuel_t));};
|
|
if (elt.index_Integ_vol_typeQuel != NULL)
|
|
{index_Integ_vol_typeQuel = new Tableau <int> (*(elt.index_Integ_vol_typeQuel));}
|
|
if (elt.integ_vol_t_typeQuel != NULL)
|
|
{integ_vol_t_typeQuel = new Tableau <TypeQuelconque>(*(elt.integ_vol_t_typeQuel));};
|
|
if (elt.integ_vol_t_typeQuel_t != NULL)
|
|
{integ_vol_t_typeQuel_t = new Tableau <TypeQuelconque>(*(elt.integ_vol_t_typeQuel_t));};
|
|
if (elt.index_Integ_vol_t_typeQuel != NULL)
|
|
{index_Integ_vol_t_typeQuel = new Tableau <int> (*(elt.index_Integ_vol_t_typeQuel));}
|
|
if (elt.enu_integ_vol_TQ != NULL)
|
|
{enu_integ_vol_TQ = new Tableau <TypeQuelconque_enum_etendu>(*(elt.enu_integ_vol_TQ));};
|
|
if (elt.enu_integ_vol_t_TQ != NULL)
|
|
{enu_integ_vol_t_TQ = new Tableau <TypeQuelconque_enum_etendu> (*(elt.enu_integ_vol_t_TQ));}
|
|
};
|
|
|
|
Element::~Element()
|
|
// Destructeur
|
|
{ int dimtaille= tabb.Taille();
|
|
////---- debug
|
|
//if ((num_elt==1) && (num_maillage==1))
|
|
// cout << "\n debug Element::~Element () "<<endl;
|
|
////--- fin debug
|
|
|
|
for (int i=1;i<= dimtaille;i++)
|
|
if (tabb(i) != NULL) delete tabb(i);
|
|
|
|
// cas des intégrales de volumes
|
|
if (integ_vol_typeQuel != NULL)
|
|
{delete integ_vol_typeQuel;};
|
|
if (integ_vol_typeQuel_t != NULL)
|
|
{delete integ_vol_typeQuel_t;};
|
|
if (integ_vol_t_typeQuel != NULL)
|
|
{delete integ_vol_t_typeQuel;};
|
|
if (integ_vol_t_typeQuel_t != NULL)
|
|
{delete integ_vol_t_typeQuel_t;};
|
|
if (index_Integ_vol_typeQuel != NULL)
|
|
delete index_Integ_vol_typeQuel;
|
|
if (index_Integ_vol_t_typeQuel != NULL)
|
|
delete index_Integ_vol_t_typeQuel;
|
|
if (enu_integ_vol_TQ != NULL)
|
|
delete enu_integ_vol_TQ;
|
|
if (enu_integ_vol_t_TQ != NULL)
|
|
delete enu_integ_vol_t_TQ;
|
|
};
|
|
|
|
/*// lecture de l'entete de l'element, permet son identification parmi
|
|
// tous les elements derivants
|
|
void Element::LectureEnTete(UtilLecture * entreePrinc)
|
|
{ *(entreePrinc->entree) >> num_elt >> id_geom >> id_interpol; };*/
|
|
|
|
// test si l'element est complet
|
|
int Element::TestComplet()
|
|
{ int ret =1;
|
|
if (tab_noeud.Taille() == 0)
|
|
{ cout << " \n *** Warning le tableau de noeud est vide dans l element "
|
|
<< num_elt << '\n';
|
|
// ret = 0;
|
|
}
|
|
if (num_elt == -3)
|
|
{ cout << " \n l'element n a pas de numero d'identification \n ";
|
|
ret = 0;
|
|
};
|
|
if (id_geom == RIEN_GEOM)
|
|
{ cout << " \n la geometrie de l'element n est pas defini\n ";
|
|
ret = 0;
|
|
};
|
|
if (id_interpol == RIEN_INTERPOL)
|
|
{ cout << " \n l interpolation sur l'element n est pas defini\n ";
|
|
ret = 0;
|
|
};
|
|
if (id_problem == RIEN_PROBLEM)
|
|
{ cout << " \n le type de probleme de l'element n est pas defini\n ";
|
|
ret = 0;
|
|
};
|
|
return ret;
|
|
};
|
|
// Libere la place occupee par le residu et eventuellement la raideur
|
|
void Element::Libere ()
|
|
{ // if (residu != NULL) delete residu; // tous les résidus, raideurs et tableaux de
|
|
// if (raideur != NULL) delete raideur;// pointent sur des données static
|
|
};
|
|
|
|
// mise à jour éventuel de repère d'anisotropie
|
|
void Element::Mise_a_jour_repere_anisotropie(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD)
|
|
{ cout << "\n Erreur , methode actuellement non defini pour l'element \n";
|
|
cout << "\n Element::Mise_a_jour_repere_anisotropie(.. \n";
|
|
Sortie(1);
|
|
};
|
|
|
|
// test si this et l'élément passé en paramètre sont identiques uniquement concernant la signature, la géométrie
|
|
// et le maillage
|
|
// par contre il peut y avoir des différences au niveau de la loi, de la matière etc.
|
|
// ramène true s'il y a identité, false sinon
|
|
bool Element::Meme_signature_et_geometrie(const Element& elem)const
|
|
{ // on continue que si les deux éléments ont la même signature
|
|
if ((this->Signature_element() == elem.Signature_element())
|
|
&& (num_maillage == elem.Num_maillage()))
|
|
{ int ta = tab_noeud.Taille(); // nb de noeud de this
|
|
const Tableau<Noeud *>& tab_noeu_ext = elem.Tab_noeud_const(); // pour simplifier
|
|
switch (ta)
|
|
{ case 1 : // cas d'un élément point, on simplifie
|
|
if (tab_noeud(1) == tab_noeu_ext(1)) {return true;} else {return false;}
|
|
break;
|
|
case 2 : // cas d'un élément à 2 noeuds uniquement
|
|
{if (tab_noeud(1) == tab_noeu_ext(1))
|
|
{if (tab_noeud(2) == tab_noeu_ext(2)) {return true;} else {return false;}}
|
|
else if (tab_noeud(1) == tab_noeu_ext(2))
|
|
{if (tab_noeud(2) == tab_noeu_ext(1)) {return true;} else {return false;}}
|
|
else {return false;};
|
|
break;
|
|
}
|
|
default : // les autres cas
|
|
{// récup de l'élément géométrique
|
|
const ElemGeomC0 & elemgeom = this->ElementGeometrique();
|
|
const Tableau <int> & ind = elemgeom.Ind(); // récup du tableau des tranches
|
|
int nb_tranche = ind.Taille(); // le nombre d'intervalle de numéros de noeuds constituant la numérotation
|
|
// vérification que la taille de toutes les tranches est au moins supérieure à 1
|
|
#ifdef MISE_AU_POINT
|
|
if (nb_tranche == 0)
|
|
{cout << "\n *** erreur, pas de tranche de nb de noeud definie "
|
|
<< "\n Element::Meme_signature_et_geometrie(... " << endl;
|
|
Sortie(1);
|
|
};
|
|
for (int i1=1;i1<=nb_tranche;i1++)
|
|
if (ind(i1) < 1)
|
|
{cout << "\n *** erreur, une tranche de nb de noeud est nulle "
|
|
<< " tableau ind: " << ind
|
|
<< "\n Element::Meme_signature_et_geometrie(... " << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// on balaie chaque intervalle
|
|
int deb_intervalle = 0; int fin_intervalle = 0; // init
|
|
for (int iter =1;iter<= nb_tranche;iter++)
|
|
{ int tranche = ind(iter);
|
|
deb_intervalle = fin_intervalle+1; // mise à jour des bornes de l'intervalle de scrutation
|
|
fin_intervalle += tranche; // " "
|
|
// on commence par chercher un premier noeud identique dans l'intervalle
|
|
bool res = false;
|
|
int nd; // indice du cote this
|
|
Noeud * ptNoeud_a = tab_noeu_ext(deb_intervalle);
|
|
for (nd=deb_intervalle; nd<= fin_intervalle; nd++)
|
|
{if (tab_noeud(nd) == ptNoeud_a)
|
|
{ res = true; break; };
|
|
};
|
|
if (!res) // on arrête de suite si
|
|
{return false;}; // on n'a pas trouvé de premier noeud !!
|
|
// s'il n'y a qu'un seule noeud dans la tranche, on a finit cette tranche sinon on continue
|
|
if (tranche > 1)
|
|
{ // on regarde dans quel sens il faut tourner
|
|
int ndplus = nd + 1; if (ndplus > fin_intervalle) ndplus -= tranche;
|
|
int ndmoins = nd - 1; if (ndmoins < deb_intervalle) ndmoins += tranche;
|
|
if (tab_noeud(ndplus) == tab_noeu_ext(deb_intervalle+1))
|
|
{// on est dans le bon sens en augmentant, et c'est ok pour le 2ième noeud,
|
|
// continue que s'il y a plus de 2 noeuds dans la tranche
|
|
if (tranche > 2)
|
|
{ for (int i=1;i<= (tranche-2);i++)
|
|
{ ndplus++;
|
|
if (ndplus > fin_intervalle) ndplus -= tranche;
|
|
if (tab_noeud(ndplus) != tab_noeu_ext(deb_intervalle+i+1))
|
|
return false;
|
|
};
|
|
};
|
|
// sinon ok, on vient de balayer tous les noeuds, on continue
|
|
}
|
|
// le sens 1 ne marche pas , on regarde l'autre sens
|
|
else if (tab_noeud(ndmoins) == tab_noeu_ext(deb_intervalle+1))
|
|
{// le bon sens est finalement en diminuant
|
|
// continue que s'il y a plus de 2 noeuds dans la tranche
|
|
if (tranche > 2)
|
|
{ for (int i=1;i<= (tranche-2);i++)
|
|
{ ndmoins--;
|
|
if (ndmoins < deb_intervalle) ndmoins += tranche;
|
|
if (tab_noeud(ndmoins) != tab_noeu_ext(deb_intervalle+i+1))
|
|
return false;
|
|
};
|
|
};
|
|
// sinon ok, on vient de balayer tous les noeuds, on continue
|
|
}
|
|
else // sinon ne marche pas dans les deux sens
|
|
{ return false;};
|
|
};
|
|
}; // fin de la boucle sur les tranches
|
|
|
|
}; // fin du cas courant (default du switch)
|
|
}; // fin du switch sur le nombre de noeuds
|
|
}
|
|
else // le type est different et ou le numéro de maillage est différent
|
|
{return false;};
|
|
// si on arrive ici, cela veut dire que toutes les égalités sont bonnes pour un cas autre que
|
|
// point ou élément à 2 noeuds
|
|
return true;
|
|
};
|
|
|
|
|
|
//------- calcul d'erreur, remontée des contraintes -------------------
|
|
// calcul du résidu et de la matrice de raideur pour le calcul d'erreur
|
|
// pour l'instant uniquement virtuel, par la suite devra être virtuelle pure
|
|
//1) remontée aux contraintes
|
|
Element::Er_ResRaid Element::ContrainteAuNoeud_ResRaid()
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : ContrainteAuNoeud_ResRaid() \n";
|
|
Sortie(1);
|
|
return Element::Er_ResRaid();
|
|
};
|
|
// 2) remontée aux erreurs aux noeuds
|
|
Element::Er_ResRaid Element::ErreurAuNoeud_ResRaid()
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : ErreurAuNoeud_ResRaid() \n";
|
|
Sortie(1);
|
|
return Element::Er_ResRaid();
|
|
};
|
|
|
|
// suppression d'un élément frontière
|
|
void Element::SupprimeFront(ElFrontiere* elemFront)
|
|
{ // on commence par mettre à jour les répercussions de la
|
|
// suppression sur les classes dérivées
|
|
Prise_en_compte_des_consequences_suppression_une_frontiere(elemFront);
|
|
// puis suppression dans les tableaux gérés par Element
|
|
int taille = tabb.Taille();
|
|
for (int i=1; i<=taille; i++)
|
|
if (tabb(i) == elemFront)
|
|
{ delete tabb(i);
|
|
tabb(i) = NULL;
|
|
// puis gestion des indicateurs
|
|
if ((ind_front_point != 0) && (i>posi_tab_front_point))
|
|
// cas d'une frontière point
|
|
ind_front_point = 2;
|
|
else if ((ind_front_lin != 0) && (i> posi_tab_front_lin))
|
|
// cas d'une frontière linéique
|
|
ind_front_lin = 2;
|
|
else if (ind_front_surf != 0)
|
|
// cas d'une frontière surfacique
|
|
ind_front_surf = 2;
|
|
else
|
|
{ cout << "\n erreur l'élément frontière n'est pas correcte "
|
|
<< "\n Element::SupprimeFront(ElFrontiere* elemFront)";
|
|
Sortie(1);
|
|
}
|
|
break;
|
|
};
|
|
};
|
|
|
|
// suppression de tous les éléments frontières
|
|
void Element::SupprimeFront()
|
|
{ // on commence par mettre à jour les répercussions de la
|
|
// suppression sur les classes dérivées
|
|
Prise_en_compte_des_consequences_suppression_tous_frontieres();
|
|
// puis suppression dans les tableaux gérés par Element
|
|
int taille = tabb.Taille();
|
|
for (int i=1; i<=taille; i++)
|
|
{ delete tabb(i);
|
|
tabb(i) = NULL;
|
|
};
|
|
ind_front_surf = 0;
|
|
ind_front_lin = 0;
|
|
ind_front_point = 0;
|
|
};
|
|
|
|
// mise à jour de la boite d'encombrement de l'élément, suivant les axes I_a globales
|
|
// en retour coordonnées du point mini dans retour.Premier() et du point maxi dans .Second()
|
|
const DeuxCoordonnees& Element::Boite_encombre_element(Enum_dure temps)
|
|
{ int tab_taille= tab_noeud.Taille();
|
|
Coordonnee& encomb_min_e=boite_encombre.Premier();
|
|
Coordonnee& encomb_max_e=boite_encombre.Second();
|
|
switch (temps)
|
|
{ case TEMPS_0:
|
|
{encomb_min_e=tab_noeud(1)->Coord0();encomb_max_e=encomb_min_e; // init
|
|
for (int i=2;i<=tab_taille;i++) // balayage des autres noeuds
|
|
{ Coordonnee co=tab_noeud(i)->Coord0();
|
|
encomb_min_e.Modif_en_min(co); encomb_max_e.Modif_en_max(co);
|
|
};
|
|
break;
|
|
}
|
|
case TEMPS_t:
|
|
{encomb_min_e=tab_noeud(1)->Coord1();encomb_max_e=encomb_min_e; // init
|
|
for (int i=2;i<=tab_taille;i++) // balayage des autres noeuds
|
|
{ Coordonnee co=tab_noeud(i)->Coord1();
|
|
encomb_min_e.Modif_en_min(co); encomb_max_e.Modif_en_max(co);
|
|
};
|
|
break;
|
|
}
|
|
case TEMPS_tdt:
|
|
{encomb_min_e=tab_noeud(1)->Coord2();encomb_max_e=encomb_min_e; // init
|
|
for (int i=2;i<=tab_taille;i++) // balayage des autres noeuds
|
|
{ Coordonnee co=tab_noeud(i)->Coord2();
|
|
encomb_min_e.Modif_en_min(co); encomb_max_e.Modif_en_max(co);
|
|
};
|
|
break;
|
|
}
|
|
}; // fin du switch
|
|
// maintenant on tiend compte d'un facteur majorant pour incertitude
|
|
Coordonnee delta=(encomb_max_e- encomb_min_e)
|
|
* (ParaGlob::param->ParaAlgoControleActifs().Extra_boite_prelocalisation()-1.);
|
|
// ajout d'un extra dans toutes les directions
|
|
delta.Ajout_meme_valeur(ParaGlob::param->ParaAlgoControleActifs().Ajout_extra_boite_prelocalisation());
|
|
// mise à jour
|
|
encomb_min_e -= delta; encomb_max_e += delta;
|
|
// retour
|
|
return boite_encombre;
|
|
};
|
|
|
|
// test si le point passé en argument appartient à la boite d'encombrement de l'élément
|
|
// tous les points sont supposées avoir la même dimension
|
|
// si depass est différent de 0, les maxi et mini de la boite sont augmentés de "depass"
|
|
bool Element::In_boite_emcombrement_elem(const Coordonnee& M,double depass) const
|
|
{ // on va essayer de faire efficace, pour cela on test le minimum
|
|
const Coordonnee& co_min = boite_encombre.Premier(); // par commodité
|
|
const Coordonnee& co_max = boite_encombre.Second(); // par commodité
|
|
#ifdef MISE_AU_POINT
|
|
if ((M.Dimension() != ParaGlob::Dimension())|| (M.Dimension() != co_min.Dimension()))
|
|
{ cout << "\n *** pb de dimensions non coherente !! "
|
|
<< "\n Element::In_boite_emcombrement_elem(...";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
//debug
|
|
//cout << "\n M= " << M << " co_min= " << co_min << " co_max= " << co_max << endl;
|
|
//fin debug
|
|
if (depass == 0.)
|
|
{switch (ParaGlob::Dimension())
|
|
{ case 3: if ((M(3)<co_min(3)) || (M(3) > co_max(3))) return false;
|
|
case 2: if ((M(2)<co_min(2)) || (M(2) > co_max(2))) return false;
|
|
case 1: if ((M(1)<co_min(1)) || (M(1) > co_max(1))) return false;
|
|
};
|
|
}
|
|
else // cas ou il faut rajouter depass
|
|
{depass = Dabs(depass);
|
|
switch (ParaGlob::Dimension())
|
|
{ case 3: if ((M(3)<(co_min(3)-depass)) || (M(3) > (co_max(3)+depass))) return false;
|
|
case 2: if ((M(2)<(co_min(2)-depass)) || (M(2) > (co_max(2)+depass))) return false;
|
|
case 1: if ((M(1)<(co_min(1)-depass)) || (M(1) > (co_max(1)+depass))) return false;
|
|
};
|
|
};
|
|
|
|
// si on arrive ici c'est que le point est interne
|
|
return true;
|
|
};
|
|
|
|
void
|
|
Element::Affiche (int n) const
|
|
// Affiche les donnees liees a un element
|
|
{ // n indique un niveau d'impression
|
|
if((n < 1) || (n > 4))
|
|
{ cout << "\n il faut un chiffre entre 1 et 4 ! \n";
|
|
cout << " Element::Affiche (int n), n = " << n << '\n';
|
|
return; }
|
|
|
|
switch (n)
|
|
{ case 4 : // + la raideur et la matrice de masse si elle existe
|
|
{ if ( raideur == NULL )
|
|
{cout << "\n ** pas encore de raideur \n";}
|
|
else
|
|
{cout << "\t raideur : \n";
|
|
cout << "nombre de ligne : " << (*raideur).Nb_ligne() << " .\n";
|
|
cout << "nombre de colonne : " << (*raideur).Nb_colonne() << " .\n";
|
|
cout << "Composante(s) :\n ";
|
|
for (int i=1;i<= (*raideur).Nb_ligne();i++)
|
|
{ cout << "\t[ ";
|
|
for (int j=1; j<= (*raideur).Nb_colonne(); j++)
|
|
cout << (*raideur)(i,j) << " ";
|
|
cout << "]\n\n";
|
|
};
|
|
};
|
|
if ( mat_masse == NULL )
|
|
{cout << "\n ** pas de matrice masse \n";}
|
|
else
|
|
{cout << "\t matrice_masse : \n";
|
|
cout << "nombre de ligne : " << (*mat_masse).Nb_ligne() << " .\n";
|
|
cout << "nombre de colonne : " << (*mat_masse).Nb_colonne() << " .\n";
|
|
cout << "Composante(s) :\n ";
|
|
for (int i=1;i<= (*mat_masse).Nb_ligne();i++)
|
|
{ cout << "\t[ ";
|
|
for (int j=1; j<= (*mat_masse).Nb_colonne(); j++)
|
|
cout << (*mat_masse)(i,j) << " ";
|
|
cout << "]\n\n";
|
|
};
|
|
};
|
|
}
|
|
case 3 : // + le residu
|
|
{if ( residu == NULL )
|
|
{cout << "\n ** pas encore de residu \n";}
|
|
else
|
|
{cout << "\t residu : \n";
|
|
cout << "Taille du residu : " << (*residu).Taille() << " .\n";
|
|
cout << "Composante(s) :\n\t[ ";
|
|
for (int i=1;i<= (*residu).Taille();i++)
|
|
cout << (*residu)(i) << " ";
|
|
cout << "]\n\n";
|
|
};
|
|
}
|
|
case 2 : // + tableau de noeuds
|
|
{cout << "\tNoeuds de l'element : \n";
|
|
cout << "Taille du tableau : " << tab_noeud.Taille() << " .\n";
|
|
cout << "Composante(s) :\n\t[ ";
|
|
for (int i=1;i<=tab_noeud.Taille();i++)
|
|
cout << Num_noeud(i) << " ";
|
|
cout << "]\n\n";
|
|
}
|
|
case 1 : // donnees d'en-tete
|
|
{cout << "\tNumero d'identification de l'element : ";
|
|
if (num_elt > 1000000)
|
|
{ cout << " interne Hourglass \n"; }
|
|
else { cout << num_elt << "\n"; };
|
|
cout << "\tType de geometrie : " << Nom_geom(id_geom) << "\n";
|
|
cout << "\tType d'interpolation : " << Nom_interpol(id_interpol) << "\n";
|
|
cout << "\tType de problem : " << NomElemTypeProblem(id_problem) << "\n";
|
|
if (infos_annexes != "")
|
|
cout << "particularité: " << infos_annexes;
|
|
}
|
|
};
|
|
};
|
|
|
|
Element&
|
|
Element::operator= (Element& elt)
|
|
// Surcharge de l'operateur = : realise l'egalite de deux elements
|
|
{num_elt=elt.num_elt;
|
|
tab_noeud=elt.tab_noeud;
|
|
id_interpol=elt.id_interpol;
|
|
id_geom=elt.id_geom;
|
|
id_problem=elt.id_problem;
|
|
infos_annexes=elt.infos_annexes;
|
|
//*residu = *elt.residu; // tous les résidus, raideurs et tableaux de
|
|
//*raideur = *elt.raideur;// pointent sur des données static
|
|
volume = elt.volume;
|
|
volumePlan = elt.volumePlan;
|
|
// ---- cas des intégrales ----
|
|
if (elt.integ_vol_typeQuel != NULL)
|
|
{if (integ_vol_typeQuel == NULL)
|
|
{integ_vol_typeQuel = new Tableau <TypeQuelconque>(*(elt.integ_vol_typeQuel));}
|
|
else {(*integ_vol_typeQuel) = (*elt.integ_vol_typeQuel);};
|
|
}
|
|
else {if (integ_vol_typeQuel != NULL) delete integ_vol_typeQuel;};
|
|
|
|
if (elt.integ_vol_typeQuel_t != NULL)
|
|
{if (integ_vol_typeQuel_t == NULL)
|
|
{integ_vol_typeQuel_t = new Tableau <TypeQuelconque>(*(elt.integ_vol_typeQuel_t));}
|
|
else {(*integ_vol_typeQuel_t) = (*elt.integ_vol_typeQuel_t);};
|
|
}
|
|
else {if (integ_vol_typeQuel_t != NULL) delete integ_vol_typeQuel_t;};
|
|
|
|
if (elt.integ_vol_t_typeQuel != NULL)
|
|
{if (integ_vol_t_typeQuel == NULL)
|
|
{integ_vol_t_typeQuel = new Tableau <TypeQuelconque>(*(elt.integ_vol_t_typeQuel));}
|
|
else {(*integ_vol_t_typeQuel) = (*elt.integ_vol_t_typeQuel);};
|
|
}
|
|
else {if (integ_vol_t_typeQuel != NULL) delete integ_vol_t_typeQuel;};
|
|
|
|
if (elt.integ_vol_t_typeQuel_t != NULL)
|
|
{if (integ_vol_t_typeQuel_t == NULL)
|
|
{integ_vol_t_typeQuel_t = new Tableau <TypeQuelconque>(*(elt.integ_vol_t_typeQuel_t));}
|
|
else {(*integ_vol_t_typeQuel_t) = (*elt.integ_vol_t_typeQuel_t);};
|
|
}
|
|
else {if (integ_vol_t_typeQuel_t != NULL) delete integ_vol_t_typeQuel_t;};
|
|
|
|
if (elt.index_Integ_vol_typeQuel != NULL)
|
|
{if (index_Integ_vol_typeQuel == NULL)
|
|
{index_Integ_vol_typeQuel = new Tableau <int>(*(elt.index_Integ_vol_typeQuel));}
|
|
else {(*index_Integ_vol_typeQuel) = (*elt.index_Integ_vol_typeQuel);};
|
|
}
|
|
else {if (index_Integ_vol_typeQuel != NULL) delete index_Integ_vol_typeQuel;};
|
|
|
|
if (elt.index_Integ_vol_t_typeQuel != NULL)
|
|
{if (index_Integ_vol_t_typeQuel == NULL)
|
|
{index_Integ_vol_t_typeQuel = new Tableau <int>(*(elt.index_Integ_vol_t_typeQuel));}
|
|
else {(*index_Integ_vol_t_typeQuel) = (*elt.index_Integ_vol_t_typeQuel);};
|
|
}
|
|
else {if (index_Integ_vol_t_typeQuel != NULL) delete index_Integ_vol_t_typeQuel;};
|
|
|
|
if (elt.enu_integ_vol_TQ != NULL)
|
|
{if (enu_integ_vol_TQ == NULL)
|
|
{enu_integ_vol_TQ = new Tableau <TypeQuelconque_enum_etendu>(*(elt.enu_integ_vol_TQ));}
|
|
else {(*enu_integ_vol_TQ) = (*elt.enu_integ_vol_TQ);};
|
|
}
|
|
else {if (enu_integ_vol_TQ != NULL) delete enu_integ_vol_TQ;};
|
|
|
|
if (elt.enu_integ_vol_t_TQ != NULL)
|
|
{if (enu_integ_vol_t_TQ == NULL)
|
|
{enu_integ_vol_t_TQ = new Tableau <TypeQuelconque_enum_etendu>(*(elt.enu_integ_vol_t_TQ));}
|
|
else {(*enu_integ_vol_t_TQ) = (*elt.enu_integ_vol_t_TQ);};
|
|
}
|
|
else {if (enu_integ_vol_t_TQ != NULL) delete enu_integ_vol_t_TQ;};
|
|
|
|
//--------- fin intégrale
|
|
|
|
// tabb = elt.tabb; // non ça c'est une erreur car on fait une recopie de frontière et
|
|
// pas de création
|
|
int dim_tabb_new = elt.tabb.Taille();
|
|
// on commence par supprimer le tableau actuel, car les nouvelles frontières peuvent
|
|
// être complètement différentes des anciennes
|
|
Element::SupprimeFront();
|
|
// maintenant on affecte
|
|
tabb.Change_taille(dim_tabb_new);
|
|
for (int i=1;i<=dim_tabb_new;i++)
|
|
if (elt.tabb(i) != NULL)
|
|
tabb(i) = elt.tabb(i)->NevezElemFront();
|
|
// maintenant les indicateurs
|
|
ind_front_lin = elt.ind_front_lin;
|
|
ind_front_surf = elt.ind_front_surf;
|
|
ind_front_point = elt.ind_front_point;
|
|
posi_tab_front_lin = elt.posi_tab_front_lin;
|
|
posi_tab_front_point = elt.posi_tab_front_point;
|
|
boite_encombre = elt.boite_encombre;
|
|
prepa_niveau_precision = elt.prepa_niveau_precision;
|
|
sens_numerotation = elt.sens_numerotation;
|
|
|
|
return (*this);
|
|
};
|
|
|
|
// calcul d'une longueur géométrique mini représentative de l'élément
|
|
// cas = 1: correspond à la distance mini entre deux noeuds coins de l'élément
|
|
// cas = 2: dans le cas 1D -> distance mini entre noeuds extrèmes
|
|
// en 2D: quadrangle: racine carré de la surface; triangle: racine carré de 2*surface
|
|
// en 3D: hexa: racine cubique de vol; penta: racine cub de 2*vol, tétra: racine cub 6*vol
|
|
// cas = 3: 1D idem cas 2, 2D: distance mini noeud arrête opposée, 3D: distance mini noeud face opposé
|
|
double Element::LongueurGeometrique(int cas) const
|
|
{ double longueur=0.; // valeur de retour
|
|
switch (cas)
|
|
{ case 1:
|
|
{ int nbne = tab_noeud.Taille(); // récup du nombre de noeud
|
|
//cout << "\n nbne=" << nbne;
|
|
// tout d'abord l'objectif est de déterminer la distance minimum entre les différents noeuds
|
|
// initialisation de la distance entre les deux noeuds
|
|
double dist = ConstMath::tresgrand;
|
|
if (tab_noeud(1)->ExisteCoord1())
|
|
{// cas où les coordonnées à t sont définit
|
|
for (int i=1;i<= nbne;i++)
|
|
// on itère sur les noeuds restants
|
|
for (int j=i+1;j<= nbne;j++)
|
|
{ double dist_new = (tab_noeud(i)->Coord1() - tab_noeud(j)->Coord1()).Norme();
|
|
//cout << " dist_new= " << dist_new;
|
|
if (dist_new < dist) dist = dist_new;
|
|
}
|
|
}
|
|
else
|
|
{// cas où seules les coordonnées à 0 sont définit
|
|
for (int i=1;i<= nbne;i++)
|
|
// on itère sur les noeuds restants
|
|
for (int j=i+1;j<= nbne;j++)
|
|
{ double dist_new = (tab_noeud(i)->Coord0() - tab_noeud(j)->Coord0()).Norme();
|
|
if (dist_new < dist) dist = dist_new;
|
|
}
|
|
}
|
|
// traitement d'une erreur éventuelle
|
|
if (dist <= ConstMath::petit)
|
|
{ cout << "\n **** ERREUR une longueur d'arrête de l'element est nulle"
|
|
<< "\n Element::LongueurGeometrique(int cas)"
|
|
<< "\n element: "; this->Affiche(1);
|
|
#ifdef MISE_AU_POINT
|
|
cout << "\n *** version mise au point: on continue neanmoins avec une longueur "
|
|
<< " arbitrairement tres petite (" <<ConstMath::petit <<") ";
|
|
#else
|
|
Sortie(1);
|
|
#endif
|
|
}
|
|
longueur=dist; //enregistrement
|
|
break;
|
|
}
|
|
default :
|
|
cout << "\nErreur : cas:" << cas <<" non encore traite !\n"
|
|
<< "Element::LongueurGeometrique(int cas) ) \n";
|
|
Sortie(1);
|
|
}
|
|
//cout << " longueur= "<< longueur << endl;
|
|
return longueur;
|
|
};
|
|
|
|
// calcul le volume entre l'élément (=surface2D) et les plans de ref: yz, xz, xy, dans cet ordre
|
|
// valable uniquement pour les éléments 2D dans un espace 3D, ramène une dim nulle sinon
|
|
// le calcul est approché, il est effectué à partir d'une triangulation de la surface de l'élément
|
|
const Coordonnee & Element::VolumePlan()
|
|
{ // petite vérif au début
|
|
if (!((ParaGlob::Dimension()==3)&&(Type_geom_generique(id_geom)==SURFACE)))
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (ParaGlob::NiveauImpression() > 4)
|
|
{cout << "\n **** attention "
|
|
<< " ( elem "<<num_elt<<" du maillage "<< num_maillage <<") ";
|
|
if (ParaGlob::Dimension()!=3) cout << " dim " << ParaGlob::Dimension();
|
|
if (Type_geom_generique(id_geom)!=SURFACE)
|
|
cout << " geometrie " << Nom_type_geom(Type_geom_generique(id_geom));
|
|
cout << " pas de calcul definit de volume entre surface et plans de ref ";
|
|
|
|
// cout << "\n **** attention, soit la geometrie n'est pas une surface, soit la dimension n'est pas 3 !!!! "
|
|
// << "\n ( elem "<<num_elt<<" du maillage "<< num_maillage <<") "
|
|
// << "\n **** le calcul du volume entre la surface et les plans de reference n'est pas definit dans ce cas " ;
|
|
if (ParaGlob::NiveauImpression() > 8)
|
|
cout << " Coordonnee & Element::VolumePlan() ";
|
|
// cout << endl;
|
|
};
|
|
#endif
|
|
volumePlan.Change_dim(0);
|
|
return volumePlan;
|
|
};
|
|
// --- maintenant on est dans le cas d'un élément 2D et le calcul est en 3D
|
|
// on récupère l'élément géométrique
|
|
ElemGeomC0& elgeo = this->ElementGeometrique();
|
|
// on récupère la triangulation
|
|
const Tableau<Tableau<Tableau<int> > >& triaLinGlob = elgeo.Trian_lin();
|
|
// comme on a un élément surface, il n'y a qu'une face pour l'élément, on simplifie
|
|
const Tableau<Tableau<int> > & triaLin = triaLinGlob(1);
|
|
// on boucle sur les triangles
|
|
int nbtriang = triaLin.Taille();
|
|
volumePlan.Zero();
|
|
for (int i=1;i<=nbtriang;i++)
|
|
{ const Tableau<int> & tabNG = triaLin(i); // pour simplifier
|
|
const Coordonnee& A = tab_noeud(tabNG(1))->Coord2();
|
|
const Coordonnee& B = tab_noeud(tabNG(2))->Coord2();
|
|
const Coordonnee& C = tab_noeud(tabNG(3))->Coord2();
|
|
Coordonnee AB(B-A); Coordonnee AC(C-A);
|
|
Coordonnee G=1./3.*(A+B+C); // coordonnées du centre de gravité
|
|
Coordonnee so=0.5*Util::ProdVec_coor(AB,AC);
|
|
so(1) *=G(1);so(2) *=G(2);so(3) *=G(3);
|
|
volumePlan += so;
|
|
};
|
|
// retour
|
|
return volumePlan;
|
|
};
|
|
|
|
// vérification de l'existence d'un point d'intégration correspondant à un ddl
|
|
bool Element::Existe_pt_integ (int nbptinteg, Enum_ddl enu) const
|
|
{ // récup de l'élement géométrique de l'élément
|
|
const ElemGeomC0& elemgeo = this->ElementGeometrie(enu);
|
|
// vérif du numéro de pt d'integ
|
|
if ((nbptinteg <= 0) || (nbptinteg > elemgeo.Nbi()))
|
|
return false;
|
|
else
|
|
return true;
|
|
};
|
|
|
|
// avec la méthode Frontiere() on obtient un tableau de frontières tabb(i) , qui peut contenir des points, lignes ou surfaces
|
|
// la méthode qun peu redondante, mais pratique, qui ramène le numéro local "n" de frontière dans le type en fonction du numéro global "i"
|
|
// d'une manière générale supposons que tabb contient des lignes, points et surfaces, alors:
|
|
// si tabb(i) est une surface, Num_de_frontiere_dans_le_type(i) donnera le numéro de la surface
|
|
// si tabb(i) est une ligne, Num_de_frontiere_dans_le_type(i) donnera le numéro de la ligne
|
|
// si tabb(i) est un point, Num_de_frontiere_dans_le_type(i) donnera le numéro du point
|
|
int Element::Num_de_frontiere_dans_le_type(int i) const
|
|
{ // on supprime les cas hors du tableau tabb
|
|
if (i<1) return 0;
|
|
int tailletab = tabb.Taille();
|
|
if (i>tailletab) return 0;
|
|
// cas normal
|
|
if (i <= posi_tab_front_lin)
|
|
// cela veut dire que i est une surface car les premières frontières sont les surfaces, de plus i est directement le numéro de surface
|
|
{ return i;}
|
|
else if (i <= posi_tab_front_point)
|
|
// cela veut dire que i est une ligne car les frontières après les surfaces sont les lignes
|
|
{ return (i-posi_tab_front_lin); }
|
|
else
|
|
// cela veut dire que i est un point car les frontières après les lignes sont des points
|
|
{ return (i-posi_tab_front_point);};
|
|
};
|
|
|
|
// ramene le numero de la frontière passée en argument si elle existe actuellement au niveau de l'élément
|
|
// sinon ramène 0
|
|
// ramene également type_front: qui indique le type de frontière: POINT_G, LIGNE ou SURFACE
|
|
// c'est une méthode très longue, a utiliser avec précaution
|
|
int Element::Num_frontiere(const ElFrontiere& fronti, Enum_type_geom& type_front)
|
|
{ int num=0; type_front = RIEN_TYPE_GEOM; // initialisation du retour
|
|
// on commence par balayer toutes les frontières pour trouver le numéro global
|
|
int tail_tab=tabb.Taille();
|
|
for (int i=1;i<=tail_tab;i++)
|
|
if (fronti == (*tabb(i))) {num = i; break;}
|
|
// si num est diff de 0 c'est ok, on recherche le type de frontière
|
|
if (num != 0)
|
|
{ // les frontières sont rangées selon: surface, ligne, point
|
|
// s'il n'y a pas de point: ind_front_point = 0, dans ce cas posi_tab_front_point = 0 par défaut et ne veut rien dire
|
|
// idem pour les lignes et les surfaces
|
|
// suivant le type de frontière on retire la position initiale de ce type dans le tableau
|
|
if ((num > posi_tab_front_point)&&(ind_front_point!=0)) {type_front = POINT_G;num -= posi_tab_front_point;}
|
|
else if ((num > posi_tab_front_lin)&&(ind_front_lin!=0)) {type_front = LIGNE;num -= posi_tab_front_lin;}
|
|
// si ce n'est ni un point ni une ligne, vue que ça doit-être quelque chose ça ne peut être qu'une surface
|
|
else {type_front = SURFACE;}; // et num a directement la bonne valeur que ce sont d'abord les faces qui sont stockées
|
|
}
|
|
// retour des infos
|
|
return num;
|
|
};
|
|
|
|
// ========== calcul des seconds membres suivant les chargements =======
|
|
// cas d'un chargement surfacique, sur les frontières des éléments
|
|
// force indique la force surfacique appliquée
|
|
// numface indique le numéro de la face chargée
|
|
// retourne le second membre résultant
|
|
// ici la définition est celle par défaut qui concerne tous les éléments
|
|
// qui ne possède pas de surface externe, type biellette etc
|
|
// -> version explicite à t
|
|
Vecteur Element::SM_charge_surfacique_E_t(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_surfacique_E_t(const "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> version explicite à tdt
|
|
Vecteur Element::SM_charge_surfacique_E_tdt(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_surfacique_E_tdt(const "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// cas d'un chargement surfacique, sur les frontières des éléments
|
|
// force indique la force surfacique appliquée
|
|
// numface indique le numéro de la face chargée
|
|
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de
|
|
// surface externe -> message d'erreur d'où le virtuel et non virtuel pur
|
|
// ici la définition est celle par défaut qui concerne tous les éléments
|
|
// -> implicit
|
|
// pa : permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
Element::ResRaid Element::SMR_charge_surfacique_I(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SMR_charge_surfacique_I( "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
// cas d'un chargement de type pression, sur les frontières des éléments
|
|
// pression indique la pression appliquée
|
|
// numface indique le numéro de la face chargée
|
|
// retourne le second membre résultant
|
|
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de
|
|
// surface externe -> message d'erreur d'où le virtuel et non virtuel pur
|
|
// -> cas d'un calcul explicite à t
|
|
Vecteur Element::SM_charge_pression_E_t(double ,Fonction_nD* ,int ,const ParaAlgoControle &)
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_pression_E_t( "
|
|
<< "double pression,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> cas d'un calcul explicite à tdt
|
|
Vecteur Element::SM_charge_pression_E_tdt(double ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_pression_E_tdt( "
|
|
<< "double pression,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
|
|
// -> implicite,
|
|
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
// retourne le second membre et la matrice de raideur correspondant
|
|
Element::ResRaid Element::SMR_charge_pression_I(double ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SMR_charge_pression_I( "
|
|
<< "double pression,int numFace) \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
|
|
// cas d'un chargement de type pression unidirectionnelle, sur les frontières des éléments
|
|
// presUniDir indique le vecteur appliquée
|
|
// numface indique le numéro de la face chargée
|
|
// retourne le second membre résultant
|
|
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de
|
|
// surface externe -> message d'erreur d'où le virtuel et non virtuel pur
|
|
// -> cas d'un calcul explicite à t
|
|
Vecteur Element::SM_charge_presUniDir_E_t(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_presUniDir_E_t( "
|
|
<< "const Coordonnee& presUniDir,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> cas d'un calcul explicite à tdt
|
|
Vecteur Element::SM_charge_presUniDir_E_tdt(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_presUniDir_E_tdt( "
|
|
<< "const Coordonnee& presUniDir,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> implicite,
|
|
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
// retourne le second membre et la matrice de raideur correspondant
|
|
Element::ResRaid Element::SMR_charge_presUniDir_I(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SMR_charge_presUniDir_I( "
|
|
<< "const Coordonnee& presUniDir,int numFace) \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
// cas d'un chargement lineique, sur les aretes frontières des éléments
|
|
// force indique la force lineique appliquée
|
|
// numarete indique le numéro de l'arete chargée
|
|
// retourne le second membre résultant
|
|
// ici la définition est celle par défaut qui concerne tous les éléments
|
|
// qui ne possède pas d'arete externe, type point !
|
|
// -> explicite à t
|
|
Vecteur Element::SM_charge_lineique_E_t(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_lineique_E_t(const "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> explicite à tdt
|
|
Vecteur Element::SM_charge_lineique_E_tdt(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_lineique_E_tdt(const "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
|
|
// -> implicite,
|
|
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
// retourne le second membre et la matrice de raideur correspondant
|
|
Element::ResRaid Element::SMR_charge_lineique_I(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SMR_charge_lineique__I(bool "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
// cas d'un chargement lineique suiveuse, sur les aretes frontières des éléments 2D (uniquement)
|
|
// force indique la force lineique appliquée
|
|
// numarete indique le numéro de l'arete chargée
|
|
// retourne le second membre résultant
|
|
// ici la définition est celle par défaut qui concerne tous les éléments
|
|
// qui ne possède pas d'arete externe, type point ! ou 3D pour lesquels la fonction n'est pas implantée
|
|
// -> explicite à t
|
|
Vecteur Element::SM_charge_lineique_Suiv_E_t(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_lineique_Suiv_E_t(const "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> explicite à tdt
|
|
Vecteur Element::SM_charge_lineique_Suiv_E_tdt(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_lineique_Suiv_E_tdt(const "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
|
|
// -> implicite,
|
|
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
// retourne le second membre et la matrice de raideur correspondant
|
|
Element::ResRaid Element::SMR_charge_lineique_Suiv_I(const Coordonnee& ,Fonction_nD* ,int ,const ParaAlgoControle &)
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SMR_charge_lineique_Suiv_I(bool "
|
|
<< "Coordonnee& force,int numFace) \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
// cas d'un chargement volumique,
|
|
// force indique la force volumique appliquée
|
|
// retourne le second membre résultant
|
|
// -> explicite à t
|
|
Vecteur Element::SM_charge_volumique_E_t(const Coordonnee& ,Fonction_nD* ,const ParaAlgoControle & ,bool )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_volumique_E_t(const "
|
|
<< "Coordonnee& force) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> explicite à tdt
|
|
Vecteur Element::SM_charge_volumique_E_tdt(const Coordonnee& ,Fonction_nD* ,const ParaAlgoControle & ,bool )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SM_charge_volumique_E_tdt(const "
|
|
<< "Coordonnee& force) \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
|
|
// -> implicite,
|
|
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
// retourne le second membre et la matrice de raideur correspondant
|
|
Element::ResRaid Element::SMR_charge_volumique_I(const Coordonnee& ,Fonction_nD* ,const ParaAlgoControle & ,bool )
|
|
{ cout << "\n Erreur , fonction non défini pour l'élément \n";
|
|
cout << "\n méthode : SMR_charge_volumique_I(bool "
|
|
<< "Coordonnee& force) \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
|
|
|
|
// cas d'un chargement surfacique hydrostatique,
|
|
// poidvol: indique le poids volumique du liquide
|
|
// M_liquide : un point de la surface libre
|
|
// dir_normal_liquide : direction normale à la surface libre
|
|
// sans_limitation : indique s'il y a une limitation du calcul pour les seuls positions négatives
|
|
// retourne le second membre résultant
|
|
// -> explicite à t
|
|
Vecteur Element::SM_charge_hydrostatique_E_t(const Coordonnee& ,const double& ,int
|
|
,const Coordonnee& ,const ParaAlgoControle & , bool)
|
|
{ cout << "\n Erreur , fonction non defini pour l'element \n";
|
|
cout << "\n methode : SM_charge_hydrostatique_E_t(... \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> explicite à tdt
|
|
Vecteur Element::SM_charge_hydrostatique_E_tdt(const Coordonnee& ,const double& ,int
|
|
,const Coordonnee& ,const ParaAlgoControle & ,bool )
|
|
{ cout << "\n Erreur , fonction non defini pour l'element \n";
|
|
cout << "\n methode : SM_charge_hydrostatique_E_tdt(... \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> implicite,
|
|
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
// retourne le second membre et la matrice de raideur correspondant
|
|
Element::ResRaid Element::SMR_charge_hydrostatique_I(const Coordonnee& ,const double& ,int
|
|
,const Coordonnee& ,const ParaAlgoControle & ,bool)
|
|
{ cout << "\n Erreur , fonction non defini pour l'element \n";
|
|
cout << "\n methode : SMR_charge_hydrostatique_I(... \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
|
|
// cas d'un chargement surfacique hydro-dynamique,
|
|
// Il y a trois forces: une suivant la direction de la vitesse: de type traînée aerodynamique
|
|
// Fn = poids_volu * fn(V) * S * (normale*u) * u, u étant le vecteur directeur de V (donc unitaire)
|
|
// une suivant la direction normale à la vitesse de type portance
|
|
// Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire, normal à V, et dans le plan n et V
|
|
// une suivant la vitesse tangente de type frottement visqueux
|
|
// T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
|
|
// coef_mul: est un coefficient multiplicateur global (de tout)
|
|
// retourne le second membre résultant
|
|
// -> explicite à t
|
|
Vecteur Element::SM_charge_hydrodynamique_E_t( Courbe1D* ,const double&
|
|
, Courbe1D* ,int ,const double&
|
|
, Courbe1D* ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non defini pour l'element \n";
|
|
cout << "\n methode : SM_charge_hydrodynamique_E_t(... \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> explicite à tdt
|
|
Vecteur Element::SM_charge_hydrodynamique_E_tdt( Courbe1D* ,const double&
|
|
, Courbe1D* ,int ,const double&
|
|
, Courbe1D* ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non defini pour l'element \n";
|
|
cout << "\n methode : SM_charge_hydrodynamique_E_tdt(... \n";
|
|
Sortie(1);
|
|
return Vecteur();
|
|
};
|
|
// -> implicite,
|
|
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
|
|
// retourne le second membre et la matrice de raideur correspondant
|
|
Element::ResRaid Element::SMR_charge_hydrodynamique_I( Courbe1D* ,const double&
|
|
, Courbe1D* ,int ,const double&
|
|
, Courbe1D* ,const ParaAlgoControle & )
|
|
{ cout << "\n Erreur , fonction non defini pour l'element \n";
|
|
cout << "\n methode : SMR_charge_hydrodynamique_I(... \n";
|
|
Sortie(1);
|
|
return ResRaid();
|
|
};
|
|
|
|
|
|
// ======== choix d'un element =====================================
|
|
// choix d'un element derive etaffectation d'un 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
|
|
// fonctionnement : le choix est effectue grace a la liste static "listTypeElement"
|
|
// qui est rempli au moment du chargement du programme, par toutes
|
|
// classes derivees
|
|
Element* Element::Choix_element(int num_mail,int num_elt,Enum_geom id_geom,
|
|
Enum_interpol id_interpol,EnumElemTypeProblem id_typeProb
|
|
,const string& infos_annexes)
|
|
{ // déclaration d'une variable static qui permet de gagner du temps de recherche
|
|
static list <Element::NouvelleTypeElement>::iterator dernier_itt;
|
|
list <Element::NouvelleTypeElement>::iterator itt=dernier_itt;
|
|
Element * ptr = NULL;
|
|
if (!premier_passage_Choix_element)
|
|
// on teste de dernier choix d'élément
|
|
{if (((*itt).id_interpol == id_interpol) && ((*itt).id_geom == id_geom)
|
|
&& ((*itt).id_typeProblem == id_typeProb)&&((*itt).infos_annexes == infos_annexes))
|
|
{// on a trouve le bon element
|
|
ptr = ((*itt).el)->NouvelElement(num_mail,num_elt);
|
|
// on sauvegarde le pointeur pour la prochaine fois pour gagner du temps de recherche
|
|
dernier_itt=itt;
|
|
return ptr;
|
|
}
|
|
}
|
|
// si l'on n'a pas trouvé on balaie la liste des elements enregistre
|
|
for (itt=Element::listTypeElement.begin() ; itt != Element::listTypeElement.end(); itt++)
|
|
if (((*itt).id_interpol == id_interpol) && ((*itt).id_geom == id_geom)
|
|
&& ((*itt).id_typeProblem == id_typeProb)
|
|
&&((*itt).infos_annexes == infos_annexes))
|
|
{/*cout << "\n(*itt).infos_annexes.size() " << (*itt).infos_annexes.size();
|
|
cout << "\n infos_annexes.size() " << infos_annexes.size();
|
|
cout << "\n (*itt).infos_annexes " << (*itt).infos_annexes;
|
|
if ((((*itt).infos_annexes.size()==0)&&(infos_annexes.size()==0))
|
|
|| ((*itt).infos_annexes == infos_annexes)) */
|
|
{// on a trouve le bon element
|
|
ptr = ((*itt).el)->NouvelElement(num_mail,num_elt);
|
|
// on sauvegarde le pointeur pour la prochaine fois pour gagner du temps de recherche
|
|
dernier_itt=itt;
|
|
return ptr;
|
|
}
|
|
}
|
|
// cas ou l'on n'a pas trouve d'element
|
|
ptr = NULL;
|
|
itt = Element::listTypeElement.begin(); // pour éviter une erreur au prochain passage
|
|
return ptr;
|
|
};
|
|
|
|
// idem en fonction de la signature
|
|
Element* Element::Choix_element(int num_mail,int num_elt,Signature signa)
|
|
{ return Choix_element(num_mail,num_elt,signa.id_geom,signa.id_interpol,signa.id_problem
|
|
,signa.infos_annexes);
|
|
};
|
|
|
|
// renseignement d'un élément complet à partir d'un élément incomplet de même type
|
|
// retourne les nouveaux noeuds construit à partir de l'interpolation incomplète.
|
|
// dans le cas l'élément n'est pas concerné, retourne une liste vide
|
|
// ramène également une liste de même dimension contenant les bornes en numéros de noeuds
|
|
// entre lesquelles il faut définir les nouveaux numéros de noeuds si l'on veut conserver
|
|
// une largeur de bande optimisée du même type
|
|
// nbnt+1: est le premier numéro de noeud utilisable pour les nouveaux noeuds
|
|
list <Noeud *> Element::Construct_from_imcomplet(const Element & ,list <DeuxEntiers> & ,int )
|
|
{ list <Noeud *> li;
|
|
if (this->id_interpol != QUADRACOMPL)
|
|
// l'élément n'est pas concerné
|
|
return li;
|
|
else
|
|
{ cout << "\n fonction non implante actuellement pour l'element ";
|
|
Affiche();
|
|
Sortie(1);
|
|
}
|
|
return li; // pour faire taire le compilo
|
|
};
|
|
|
|
// renseignement d'un élément quadratique incomplet à partir d'un élément linéaire de même type
|
|
// retourne les nouveaux noeuds construit à partir de l'interpolation linéqire.
|
|
// dans le cas où l'élément n'est pas concerné, retourne une liste vide
|
|
// ramène également une liste de même dimension contenant les bornes en numéros de noeuds
|
|
// entre lesquelles il faut définir les nouveaux numéros de noeuds si l'on veut conserver
|
|
// une largeur de bande optimisée du même type
|
|
// nbnt+1: est le premier numéro de noeud utilisable pour les nouveaux noeuds
|
|
list <Noeud *> Element::Construct_from_lineaire(const Element & ,list <DeuxEntiers> & , int )
|
|
{ list <Noeud *> li;
|
|
if (this->id_interpol != LINEAIRE)
|
|
// l'élément n'est pas concerné
|
|
return li;
|
|
else
|
|
{ cout << "\n fonction non implante actuellement pour l'element ";
|
|
Affiche();
|
|
Sortie(1);
|
|
}
|
|
return li; // pour faire taire le compilo
|
|
};
|
|
|
|
// réaffectation d'un pointeur de noeud
|
|
// ramène faux si l'opération n'est pas possible
|
|
bool Element::Reaffectation_pointeur_noeud(Noeud * ancien, Noeud * nouveau)
|
|
{ // on balaie les noeuds de l'éléments
|
|
int nbn = tab_noeud.Taille();
|
|
for (int i=1;i<=nbn;i++)
|
|
{ if (tab_noeud(i)==ancien)
|
|
{ tab_noeud(i) = nouveau;
|
|
return true;
|
|
}
|
|
}
|
|
// cas ou l'on n'a pas trouvé le noeud
|
|
return false;
|
|
};
|
|
|
|
// ======== sortie fichier de commande ====================================
|
|
// ramène un tableau de pointeur d'élément qui sont concerné
|
|
// par la sortie des commandes
|
|
Tableau <Element*> Element::Info_commande_Element(UtilLecture * )
|
|
{ // tout d'abord on balaie la liste des elements enregistre pour savoir le nombre
|
|
// d'element concerné
|
|
string ordd = "concerne"; int nbel=0; int nbmail=0;
|
|
list <Element::NouvelleTypeElement>::iterator itt;
|
|
for (itt=Element::listTypeElement.begin() ; itt != Element::listTypeElement.end(); itt++)
|
|
{bool ret = ((*itt).el)->Element_possible();
|
|
if (ret)
|
|
nbel++;
|
|
}
|
|
// maintenant on peut dimensionner le tableau de manière a_doc
|
|
Tableau <Element*> retour(nbel);
|
|
// on cree le tableau d'element
|
|
nbel=1;
|
|
for (itt=Element::listTypeElement.begin() ; itt != Element::listTypeElement.end(); itt++)
|
|
{bool ret = ((*itt).el)->Element_possible();
|
|
if (ret)
|
|
{ retour(nbel) = ((*itt).el)->NouvelElement(nbmail,nbel);
|
|
nbel++;
|
|
}
|
|
}
|
|
return retour;
|
|
};
|
|
|
|
//=====================================================================================
|
|
// METHODES PROTEGEES utilisables par les classes derivees :
|
|
//=====================================================================================
|
|
|
|
// affichage d'info en fonction de ordre
|
|
// ordre = "commande" : affichage d'un exemple d'entree pour l'élément
|
|
void Element::Info_com_El
|
|
(int nbnoeu,UtilLecture * entreePrinc,string& ordre,Tableau<Noeud *> * tabMaillageNoeud)
|
|
{ if (ordre == "commande")
|
|
{ // def des noeuds de l'élément
|
|
tab_noeud.Change_taille(nbnoeu);
|
|
for (int i=1;i<=nbnoeu;i++)
|
|
tab_noeud(i) = (*tabMaillageNoeud)(i);
|
|
// construction du tableau de ddl des noeuds de biellette
|
|
ConstTabDdl();
|
|
// affichage de l'élément
|
|
ofstream & sort = *(entreePrinc->Commande_pointInfo());
|
|
sort << "\n " << setw (6) << this->Num_elt()
|
|
<< " " << this->Geometrie()
|
|
<< " " << this->Interpolation() << " ";
|
|
// sortie de la connection
|
|
int compteur_ligne=6;
|
|
for (int n1=1;n1<= nbnoeu;n1++,compteur_ligne++)
|
|
{ if (compteur_ligne > 10)
|
|
{ compteur_ligne = 0; sort << "\n";}
|
|
sort << setw (6) << n1 <<" ";
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// ---------------- lecture écriture dans base info ----------------
|
|
// pour les données spécifiques à element
|
|
|
|
// cas donne le niveau de la récupération
|
|
// = 1 : on récupère tout
|
|
// = 2 : on récupère uniquement les données variables (supposées comme telles)
|
|
void Element::Lect_bas_inf_element
|
|
(ifstream& ent,const Tableau<Noeud *> * tabMaillageNoeud,const int cas)
|
|
{switch (cas)
|
|
{ case 1 : // ------- on récupère tout -------------------------
|
|
{ // le tableau de connection des noeuds
|
|
int tab_noeudTaille; string toto;
|
|
ent >> toto >> tab_noeudTaille >> toto;
|
|
if (tab_noeud.Taille() != tab_noeudTaille)
|
|
{ cout << "\nErreur : valeur incorrecte du nombre de noeud !\n";
|
|
cout << "Element::Lect_bas_inf_element(...)";
|
|
Sortie(1);
|
|
};
|
|
int nb;
|
|
for (int i=1;i<= tab_noeudTaille; i++)
|
|
{ ent >> nb;
|
|
tab_noeud(i) = (*tabMaillageNoeud)(nb);
|
|
};
|
|
break;
|
|
}
|
|
case 2 : // ----------- lecture uniquement de se qui varie --------------------
|
|
{ // ici on lit et on vérifie que la connexion est correcte mais on ne change rien
|
|
int tab_noeudTaille; string toto;
|
|
// sort << "connexion " << tab_noeudTaille << " noeuds: ";
|
|
ent >> toto >> tab_noeudTaille >> toto;
|
|
bool erreur_connexion=false;
|
|
if (tab_noeud.Taille() != tab_noeudTaille)
|
|
erreur_connexion = true;
|
|
Tableau <int> inter(tab_noeudTaille);
|
|
for (int i=1;i<= tab_noeudTaille; i++)
|
|
{ ent >> inter(i);
|
|
if (inter(i) != tab_noeud(i)->Num_noeud())
|
|
{erreur_connexion = true;}
|
|
};
|
|
|
|
if (erreur_connexion)
|
|
{ cout << "\nErreur : valeur incorrecte du nombre de noeud lu !"
|
|
<< " element nb: "<< num_elt << " maillage " << num_maillage;
|
|
cout << " \n la connexion en cours :";
|
|
cout << "connexion " << tab_noeud.Taille() << " noeuds: ";
|
|
for (int i=1;i<= tab_noeud.Taille(); i++)
|
|
cout << tab_noeud(i)->Num_noeud() << " ";
|
|
cout << "\n connexion lue: " << tab_noeudTaille << " noeuds: ";
|
|
for (int i=1;i<= tab_noeudTaille; i++)
|
|
cout << inter(i) << " ";
|
|
cout << "\n";
|
|
if (ParaGlob::NiveauImpression() > 5)
|
|
cout << "Element::Lect_bas_inf_element(...)";
|
|
Sortie(1);
|
|
};
|
|
// lecture du volume
|
|
ent >> toto >> volume;
|
|
|
|
// --- cas des intégrales volumiques:
|
|
// 1) les intégrales de volume
|
|
string mot;
|
|
ent >> mot;
|
|
if (mot != "int_vol" )
|
|
{ cout << "\n *** erreur en lecture du .info, le mot cle lu est "<<mot
|
|
<< " on attendait int_vol , la suite va etre erronee, on stop la lecture "
|
|
<< endl;
|
|
Sortie(1);
|
|
};
|
|
int indic_test=0; ent >> indic_test; // on ne continue que si indic est diff de 0
|
|
if (indic_test)
|
|
{ int taille=indic_test;
|
|
for (int i=1; i<= taille;i++)
|
|
{// lecture avec création éventuelle si le type n'existe pas
|
|
TypeQuelconque_enum_etendu tqnevez =
|
|
TypeQuelconque_enum_etendu::Lecture_avec_creation_eventuelle(ent);
|
|
// on parcours la liste actuelle pour trouver la bonne grandeur éventuelle
|
|
int indic = 0 ; // init
|
|
if (enu_integ_vol_TQ != NULL)
|
|
indic = enu_integ_vol_TQ->Contient(tqnevez);
|
|
// maintenant, éventuellement indic = le numéro du conteneur existant
|
|
if (indic)
|
|
{ (*integ_vol_typeQuel_t)(indic).Grandeur_pointee()->Lecture_grandeur(ent);
|
|
}
|
|
else // cas ou la grandeur n'existe pas
|
|
{ // c'est un peu plus délicat car on ne sait pas ce que l'on doit lire
|
|
// on lit l'entête du type quelconque
|
|
// -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes
|
|
TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE);
|
|
// lecture de l'entête et récup d'enu
|
|
EnuTypeQuelParticulier enu = pour_lire.Lecture_un(ent);
|
|
// création d'une grandeur associée et lecture des information sur le flot
|
|
TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent);
|
|
// création du type quelconque
|
|
TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur);
|
|
delete grandeur; // car il ne sert plus à rien
|
|
// maintenant on va mettre à jour le stockage interne
|
|
// ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue
|
|
// à l'initialisation du .info
|
|
taille = integ_vol_typeQuel->Taille()+1;
|
|
integ_vol_typeQuel->Change_taille(taille);
|
|
integ_vol_typeQuel_t->Change_taille(taille);
|
|
(*integ_vol_typeQuel)(taille) = typQ;
|
|
(*integ_vol_typeQuel_t)(taille) = typQ;
|
|
index_Integ_vol_typeQuel->Change_taille(taille);
|
|
// par défaut on met l'index à -1, ce qui veut dire que la grandeur est
|
|
// pour l'instant figé, tant que le calcul n'a pas démarré et que
|
|
// l'utilisateur a indiqué qu'il désirait continuer l'intégration
|
|
(*index_Integ_vol_typeQuel)(taille) = -1;
|
|
enu_integ_vol_TQ->Change_taille(taille);
|
|
(*enu_integ_vol_TQ)(taille)=tqnevez;
|
|
};
|
|
|
|
};
|
|
};
|
|
|
|
// 2) les intégrales de volume et en temps
|
|
ent >> mot;
|
|
if (mot != "int_vol_t" )
|
|
{ cout << "\n *** erreur en lecture du .info, le mot cle lu est "<<mot
|
|
<< " on attendait int_vol_t , la suite va etre erronee, on stop la lecture "
|
|
<< endl;
|
|
Sortie(1);
|
|
};
|
|
int indic_test_t=0; ent >> indic_test_t; // on ne continue que si indic est diff de 0
|
|
if (indic_test_t)
|
|
{ int taille=indic_test_t;
|
|
for (int i=1; i<= taille;i++)
|
|
{// lecture avec création éventuelle si le type n'existe pas
|
|
TypeQuelconque_enum_etendu tqnevez =
|
|
TypeQuelconque_enum_etendu::Lecture_avec_creation_eventuelle(ent);
|
|
// on parcours la liste actuelle pour trouver la bonne grandeur éventuelle
|
|
int indic = 0 ; // init
|
|
if (enu_integ_vol_t_TQ != NULL)
|
|
indic = enu_integ_vol_t_TQ->Contient(tqnevez);
|
|
// maintenant, éventuellement indic = le numéro du conteneur existant
|
|
if (indic)
|
|
// cas simple où la grandeur exise déjà
|
|
{ (*integ_vol_t_typeQuel_t)(indic).Grandeur_pointee()->Lecture_grandeur(ent);
|
|
}
|
|
else // cas ou la grandeur n'existe pas
|
|
{ // c'est un peu plus délicat car on ne sait pas ce que l'on doit lire
|
|
// on lit l'entête du type quelconque
|
|
// -> on crée un grandeur quelconque sans grandeur associé ceci pour lire les entêtes
|
|
TypeQuelconque pour_lire(RIEN_TYPEQUELCONQUE);
|
|
// lecture de l'entête et récup d'enu
|
|
EnuTypeQuelParticulier enu = pour_lire.Lecture_un(ent);
|
|
// création d'une grandeur associée et lecture des information sur le flot
|
|
TypeQuelconque::Grandeur* grandeur =NevezGrandeurParticuliereEnLecture(enu,ent);
|
|
// création du type quelconque
|
|
TypeQuelconque typQ(pour_lire.EnuTypeQuelconque(),pour_lire.Enum(),*grandeur);
|
|
delete grandeur; // car il ne sert plus à rien
|
|
// maintenant on va mettre à jour le stockage interne
|
|
// ici on rajoute à la fin des tableaux, donc cela ne change pas ce qui a été lue
|
|
// à l'initialisation du .info
|
|
taille = integ_vol_t_typeQuel->Taille()+1;
|
|
integ_vol_t_typeQuel->Change_taille(taille);
|
|
integ_vol_t_typeQuel_t->Change_taille(taille);
|
|
(*integ_vol_t_typeQuel)(taille) = typQ;
|
|
(*integ_vol_t_typeQuel_t)(taille) = typQ;
|
|
index_Integ_vol_t_typeQuel->Change_taille(taille);
|
|
// par défaut on met l'index à -1, ce qui veut dire que la grandeur est
|
|
// pour l'instant figé, tant que le calcul n'a pas démarré et que
|
|
// l'utilisateur a indiqué qu'il désirait continuer l'intégration
|
|
(*index_Integ_vol_t_typeQuel)(taille) = -1;
|
|
enu_integ_vol_t_TQ->Change_taille(taille);
|
|
(*enu_integ_vol_t_TQ)(taille)=tqnevez;
|
|
};
|
|
};
|
|
};
|
|
|
|
break;
|
|
}
|
|
default :
|
|
{ cout << "\nErreur : valeur incorrecte du type de lecture !\n";
|
|
cout << "Element::Lect_bas_inf_element( "
|
|
<< " cas= " << cas << endl;
|
|
Sortie(1);
|
|
}
|
|
};
|
|
};
|
|
// cas donne le niveau de sauvegarde
|
|
// = 1 : on sauvegarde tout
|
|
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
|
|
void Element::Ecri_bas_inf_element(ofstream& sort,const int cas)
|
|
{ // en fait ici on sauvegarde la même chose dans tous les cas, par contre la sortie
|
|
// totale est documentée.
|
|
switch (cas)
|
|
{ case 1 : // ------- on sauvegarde tout -------------------------
|
|
{ // le tableau de connection des noeuds
|
|
int tab_noeudTaille = tab_noeud.Taille();
|
|
sort << "connexion " << tab_noeudTaille << " noeuds: ";
|
|
for (int i=1;i<= tab_noeudTaille; i++)
|
|
sort << tab_noeud(i)->Num_noeud() << " ";
|
|
sort << "\n";
|
|
break;
|
|
}
|
|
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
|
|
{ // on sauvegarde néanmoins la connexion, car cela permettra de détecter une variation
|
|
// éventuelle de la numérotation, ce qui conduit à des erreurs de restart, très difficile
|
|
// à localiser !!
|
|
// donc le tableau de connection des noeuds
|
|
int tab_noeudTaille = tab_noeud.Taille();
|
|
sort << "connexion " << tab_noeudTaille << " noeuds: ";
|
|
for (int i=1;i<= tab_noeudTaille; i++)
|
|
sort << tab_noeud(i)->Num_noeud() << " ";
|
|
sort << "\n vol= " << volume << " ";
|
|
// --- cas des grandeurs intégrés éventuelles
|
|
// 1) les intégrales de volume
|
|
sort << "\n int_vol ";
|
|
if (integ_vol_typeQuel == NULL)
|
|
{sort << 0 << " "; }
|
|
else // sinon on sort les informations
|
|
{ int taille = integ_vol_typeQuel->Taille();
|
|
sort << taille ;
|
|
for (int i=1; i<= taille;i++)
|
|
{ sort << " \n " << (*enu_integ_vol_TQ)(i) << " "; // l'identificateur
|
|
// puis la grandeur à t
|
|
(*integ_vol_typeQuel_t)(i).Const_Grandeur_pointee()->Ecriture_grandeur(sort);
|
|
};
|
|
};
|
|
// 2) les intégrales de volume et en temps
|
|
sort << "\n int_vol_t ";
|
|
if (integ_vol_t_typeQuel == NULL)
|
|
{sort << 0 << " "; }
|
|
else // sinon on sort les informations
|
|
{ int taille = integ_vol_t_typeQuel->Taille();
|
|
sort << taille ;
|
|
for (int i=1; i<= taille;i++)
|
|
{ sort << " \n " << (*enu_integ_vol_t_TQ)(i) << " "; // l'identificateur
|
|
// puis la grandeur à t
|
|
(*integ_vol_t_typeQuel_t)(i).Const_Grandeur_pointee()->Ecriture_grandeur(sort);
|
|
};
|
|
};
|
|
sort << "\n";
|
|
break;
|
|
}
|
|
default :
|
|
{ cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
|
|
cout << "ElemMeca::Ecriture_bas_inf(ofstream& sort,const int cas)"
|
|
<< " cas= " << cas << endl;
|
|
Sortie(1);
|
|
}
|
|
};
|
|
};
|
|
|
|
|