Herezh_dev/herezh_pp/Elements/Element.cc

1653 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);
}
};
};