Herezh_dev/herezh_pp/Elements/Thermique/Biellette/BielletteThermi.cc

1672 lines
81 KiB
C++
Executable file

// FICHIER : BielletteThermi.cc
// CLASSE : BielletteThermi
// 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 "Debug.h"
# include <iostream>
using namespace std; //introduces namespace std
#include <stdlib.h>
#include "Sortie.h"
#include "BielletteThermi.h"
#include "FrontPointF.h"
#include "FrontSegLine.h"
#include "TypeConsTens.h"
#include "TypeQuelconqueParticulier.h"
//----------------------------------------------------------------
// def des donnees commune a tous les elements
// la taille n'est pas defini ici car elle depend de la lecture
//----------------------------------------------------------------
BielletteThermi::DonneeCommune * BielletteThermi::doCo = NULL;
BielletteThermi::UneFois BielletteThermi::unefois;
BielletteThermi::NombresConstruire BielletteThermi::nombre_V;
BielletteThermi::ConstrucElementbiel BielletteThermi::construcElementbiel;
// constructeur définissant les nombres (de noeud, de point d'integ ..)
// utilisé dans la construction des éléments
BielletteThermi::NombresConstruire::NombresConstruire()
{ nbne = 2; // le nombre de noeud de l'élément
nbneA = 2;// le nombre de noeud des aretes
nbi = 1; // le nombre de point d'intégration pour le calcul mécanique
nbiEr = 2;// le nombre de point d'intégration pour le calcul d'erreur
nbiA = 1; // le nombre de point d'intégration pour le calcul de second membre linéique
nbiMas = 2; // le nombre de point d'intégration pour le calcul de la matrice masse
};
// ---- definition du constructeur de la classe conteneur de donnees communes ------------
BielletteThermi::DonneeCommune::DonneeCommune (GeomSeg& seg,DdlElement& tab,DdlElement& tabErr,DdlElement& tab_Err1flux,
Met_biellette& met_bie,
Tableau <Vecteur *> & resEr,Mat_pleine& raidEr,
GeomSeg& seEr,Vecteur& residu_int,Mat_pleine& raideur_int,
Tableau <Vecteur* > & residus_extN,Tableau <Mat_pleine* >& raideurs_extN,
Tableau <Vecteur* > & residus_extA,Tableau <Mat_pleine* >& raideurs_extA,
Mat_pleine& mat_masse,GeomSeg& seMa,int nbi) :
segment(seg),tab_ddl(tab),tab_ddlErr(tabErr),tab_Err1FLUX(tab_Err1flux)
,met_biellette(met_bie)
,matGeom(tab.NbDdl(),tab.NbDdl())
,matInit(tab.NbDdl(),tab.NbDdl())
,d_gradTB(),d_fluxH(),d2_gradTB(nbi)
,resErr(resEr),raidErr(raidEr)
,segmentEr(seEr)
,residu_interne(residu_int),raideur_interne(raideur_int)
,residus_externeN(residus_extN),raideurs_externeN(raideurs_extN)
,residus_externeA(residus_extA),raideurs_externeA(raideurs_extA)
,matrice_masse(mat_masse)
,segmentMas(seMa)
{
// Tableau <CoordonneeB> d_gradTB; // place pour la variation du gradient
// Tableau <CoordonneeH> d_fluxH; // place pour la variation du flux
// Tableau < Tableau2 <CoordonneeB> * > d2_gradTB; // variation seconde des déformations
int nbddl = tab.NbDdl();
CoordonneeB interB(1); // intermédiaire
for (int ni=1;ni<=nbi;ni++)
{d2_gradTB(ni) = new Tableau2 <CoordonneeB> ;
d2_gradTB(ni)->Change_taille(nbddl);
};
d_gradTB.Change_taille(nbddl,interB);
CoordonneeH interH(1); // intermédiaire
d_fluxH.Change_taille(nbddl,interH);
};
BielletteThermi::DonneeCommune::DonneeCommune(DonneeCommune& a) :
segment(a.segment),tab_ddl(a.tab_ddl),tab_ddlErr(a.tab_ddlErr),tab_Err1FLUX(a.tab_Err1FLUX)
,met_biellette(a.met_biellette),matGeom(a.matGeom),matInit(a.matInit)
,d2_gradTB(a.d2_gradTB),resErr(a.resErr),raidErr(a.raidErr),segmentEr(a.segmentEr)
,d_gradTB(a.d_gradTB),d_fluxH(a.d_fluxH)
,residu_interne(a.residu_interne),raideur_interne(a.raideur_interne)
,residus_externeN(a.residus_externeN),raideurs_externeN(a.raideurs_externeN)
,residus_externeA(a.residus_externeA),raideurs_externeA(a.raideurs_externeA)
,matrice_masse(a.matrice_masse),segmentMas(a.segmentMas)
{};
BielletteThermi::DonneeCommune::~DonneeCommune()
{ int nbddl = tab_ddl.NbDdl();
int nbi = d2_gradTB.Taille();
for (int ni=1;ni<=nbi;ni++)
{ if (d2_gradTB(ni)!= NULL)
delete d2_gradTB(ni);
};
};
// ---------- fin definition de la classe conteneur de donnees communes ------------
// -+-+ definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
BielletteThermi::UneFois::UneFois () : // constructeur par défaut
doCoMemb(NULL),CalResPrem_t(0),CalResPrem_tdt(0),CalimpPrem(0),dualSortbiel(0)
,CalSMlin_t(0),CalSMlin_tdt(0),CalSMRlin(0)
,CalSMvol_t(0),CalSMvol_tdt(0),CalSMvol(0)
,CalDynamique(0),CalPt_0_t_tdt(0)
,nbelem_in_Prog(0)
{};
BielletteThermi::UneFois::~UneFois ()
{ delete doCoMemb;
};
// -+-+ fin definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
// ---------- fin definition de la classe conteneur de donnees communes ------------
BielletteThermi::BielletteThermi () :
// Constructeur par defaut
ElemThermi(),lesPtThermiInt(),donnee_specif()
{// on intervient seulement à partir du deuxième élément,
if (unefois.nbelem_in_Prog == 0)
{ unefois.nbelem_in_Prog++; // au premier passage on se contente d'incrémenter
}
else // sinon on construit
{ lesPtIntegThermiInterne = &lesPtThermiInt; // association avec le pointeur d'ElemThermi
id_interpol=BIE1; // donnees de la classe mere
id_geom=POUT; //
tab_noeud.Change_taille(nombre_V.nbne);
// initialisation par défaut
doCo = BielletteThermi::Init ();
unefois.nbelem_in_Prog++;
};
};
BielletteThermi::BielletteThermi (double sect,int num_maill,int num_id):
// Constructeur utile si la section de l'element et
// le numero de l'element sont connus
ElemThermi(num_maill,num_id,BIE1,POUT),lesPtThermiInt(),donnee_specif(sect)
{// on intervient seulement à partir du deuxième élément,
if (unefois.nbelem_in_Prog == 0)
{ unefois.nbelem_in_Prog++; // au premier passage on se contente d'incrémenter
}
else // sinon on construit
{ lesPtIntegThermiInterne = &lesPtThermiInt; // association avec le pointeur d'ElemThermi
tab_noeud.Change_taille(nombre_V.nbne);
// initialisation
doCo = BielletteThermi::Init (donnee_specif);
unefois.nbelem_in_Prog++;
};
};
// Constructeur fonction d'un numero de maillage et d'identification
BielletteThermi::BielletteThermi (int num_maill,int num_id) :
ElemThermi(num_maill,num_id,BIE1,POUT),lesPtThermiInt(),donnee_specif()
{// on intervient seulement à partir du deuxième élément,
if (unefois.nbelem_in_Prog == 0)
{ unefois.nbelem_in_Prog++; // au premier passage on se contente d'incrémenter
}
else // sinon on construit
{ lesPtIntegThermiInterne = &lesPtThermiInt; // association avec le pointeur d'ElemThermi
tab_noeud.Change_taille(nombre_V.nbne);
// initialisation par défaut
doCo = BielletteThermi::Init ();
unefois.nbelem_in_Prog++;
};
};
BielletteThermi::BielletteThermi (double sect,int num_maill,int num_id,const Tableau<Noeud *>& tab):
// Constructeur utile si la section de l'element, le numero de l'element et
// le tableau des noeuds sont connus
ElemThermi(num_maill,num_id,tab,BIE1,POUT),lesPtThermiInt(),donnee_specif(sect)
{// on intervient seulement à partir du deuxième élément,
if (unefois.nbelem_in_Prog == 0)
{ unefois.nbelem_in_Prog++; // au premier passage on se contente d'incrémenter
}
else // sinon on construit
{ lesPtIntegThermiInterne = &lesPtThermiInt; // association avec le pointeur d'ElemThermi
if (tab_noeud.Taille() != 2)
{ cout << "\n erreur de dimensionnement du tableau de noeud \n";
cout << " BielletteThermi::BielletteThermi (double sect,int num_id,const Tableau<Noeud *>& tab)\n";
Sortie (1); }
// construction du tableau de ddl spécifique à l'élément pour ses
ConstTabDdl();
// initialisation
bool sans_init_noeud = true;
doCo = BielletteThermi::Init (donnee_specif,sans_init_noeud);
unefois.nbelem_in_Prog++;
};
};
BielletteThermi::BielletteThermi (const BielletteThermi& biel) :
ElemThermi (biel),lesPtThermiInt(biel.lesPtThermiInt),donnee_specif(biel.donnee_specif)
// Constructeur de copie
{ if (unefois.nbelem_in_Prog == 1)
{ cout << "\n **** erreur pour l'element BielletteThermi, le constructeur de copie ne doit pas etre utilise"
<< " pour le premier element !! " << endl;
Sortie (1);
}
else
{ lesPtIntegThermiInterne = &lesPtThermiInt; // association avec le pointeur d'ElemThermi
// initialisation
unefois.nbelem_in_Prog++;
};
};
BielletteThermi::~BielletteThermi ()
// Destructeur
{ LibereTenseur();
if (unefois.nbelem_in_Prog != 0)
unefois.nbelem_in_Prog--;
// defArete pointe sur la même grandeur que def donc pour éviter
// une destruction lors du destructeur générale dans elemméca on le met à null
if (defArete.Taille() != 0)
defArete(1) = NULL;
Destruction();
};
// Lecture des donnees de la classe sur fichier
void
BielletteThermi::LectureDonneesParticulieres
(UtilLecture * entreePrinc,Tableau<Noeud *> * tabMaillageNoeud)
{ int nb;
tab_noeud.Change_taille(2);
for (int i=1; i<= 2; i++)
{ *(entreePrinc->entree) >> nb;
if ((entreePrinc->entree)->rdstate() == 0)
// pour mémoire ici on a
/* enum io_state
{ badbit = 1<<0, // -> 1 dans rdstate()
eofbit = 1<<1, // -> 2
failbit = 1<<2, // -> 4
goodbit = 0 // -> O
};*/
tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
#ifdef ENLINUX
else if ((entreePrinc->entree)->fail())
// on a atteind la fin de la ligne et on appelle un nouvel enregistrement
{ entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
*(entreePrinc->entree) >> nb;
tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
}
#else
/* #ifdef SYSTEM_MAC_OS_X_unix
else if ((entreePrinc->entree)->fail())
// on a atteind la fin de la ligne et on appelle un nouvel enregistrement
{ entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
*(entreePrinc->entree) >> nb;
tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
}
#else*/
else if ((entreePrinc->entree)->eof())
// la lecture est bonne mais on a atteind la fin de la ligne
{ tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture
// si ce n'est pas la fin de la lecture on appelle un nouvel enregistrement
if (i != 2) entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
}
// #endif
#endif
else // cas d'une erreur de lecture
{ cout << "\n erreur de lecture inconnue ";
entreePrinc->MessageBuffer("** lecture des données particulières **");
cout << "BielletteThermi::LectureDonneesParticulieres";
Affiche();
Sortie (1);
}
}
// construction du tableau de ddl des noeuds de biellette
ConstTabDdl();
};
// calcul d'un point dans l'élément réel en fonction des coordonnées dans l'élément de référence associé
// temps: indique si l'on veut les coordonnées à t = 0, ou t ou tdt
// 1) cas où l'on utilise la place passée en argument
Coordonnee & BielletteThermi::Point_physique(const Coordonnee& c_int,Coordonnee & co,Enum_dure temps)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// a) on commence par définir les bonnes grandeurs dans la métrique
if( !(unefois.CalPt_0_t_tdt ))
{ unefois.CalPt_0_t_tdt += 1;
Tableau<Enum_variable_metrique> tab(3);
tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// b) calcul de l'interpolation
const Vecteur& phi = doCo->segment.Phi(c_int);
// c) calcul du point
switch (temps)
{ case TEMPS_0 : co = doCo->met_biellette.PointM_0(tab_noeud,phi); break;
case TEMPS_t : co = doCo->met_biellette.PointM_t(tab_noeud,phi); break;
case TEMPS_tdt : co = doCo->met_biellette.PointM_tdt(tab_noeud,phi); break;
}
// d) retour
return co;
};
// 3) cas où l'on veut les coordonnées aux 1, 2 ou trois temps selon la taille du tableau t_co
void BielletteThermi::Point_physique(const Coordonnee& c_int,Tableau <Coordonnee> & t_co)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// a) on commence par définir les bonnes grandeurs dans la métrique
if( !(unefois.CalPt_0_t_tdt ))
{ unefois.CalPt_0_t_tdt += 1;
Tableau<Enum_variable_metrique> tab(3);
tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// b) calcul de l'interpolation
const Vecteur& phi = doCo->segment.Phi(c_int);
// c) calcul des point
switch (t_co.Taille())
{ case 3 : t_co(3) = doCo->met_biellette.PointM_tdt(tab_noeud,phi);
case 2 : t_co(2) = doCo->met_biellette.PointM_t(tab_noeud,phi);
case 1 : t_co(1) = doCo->met_biellette.PointM_0(tab_noeud,phi);
}
};
// Calcul du residu local à t ou tdt en fonction du booleen atdt
Vecteur* BielletteThermi::CalculResidu (bool atdt,const ParaAlgoControle & pa)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
Tableau <CoordonneeB >& d_gradTB = (doCo->d_gradTB);// "
// dimensionnement de la metrique
if (!atdt)
{if( !(unefois.CalResPrem_t ))
{ unefois.CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
doCo->met_biellette.PlusInitVariables(tab) ;
};}
else
{if( !(unefois.CalResPrem_tdt ))
{unefois.CalResPrem_tdt += 1;
Tableau<Enum_variable_metrique> tab(11);
tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
tab(10) = igradVBB_tdt;tab(11) = iVtdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};};
// initialisation du résidu
residu->Zero();
Vecteur poids =(doCo->segment).TaWi(); // poids d'interpolation = 2
ElemThermi::Cal_explicit ( doCo->tab_ddl,d_gradTB,1,poids,pa,atdt);
// prise en compte de la section
double section_moyenne = 0.;
section_moyenne = CalSectionMoyenne_et_vol_pti(atdt);
(*residu) *= section_moyenne;
energie_totale *= section_moyenne;
E_Hourglass *= section_moyenne; // meme si l'énergie d'hourglass est nulle
E_elem_bulk_tdt*= section_moyenne; // idem
P_elem_bulk *= section_moyenne; // idem
volume *= section_moyenne;
return residu;
};
// Calcul du residu local et de la raideur locale,
// pour le schema implicite
Element::ResRaid BielletteThermi::Calcul_implicit (const ParaAlgoControle & pa)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
Tableau <CoordonneeB>& d_gradTB = (doCo->d_gradTB);// "
Tableau <CoordonneeH >& d_fluxH = (doCo->d_fluxH);// "
bool cald_Dvirtuelle = true; //false; non pour l'instant toujours vrai car en fait pas de calcul
if (unefois.CalimpPrem == 0)
{ unefois.CalimpPrem = 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
doCo->met_biellette.PlusInitVariables(tab) ;
// on ne calcul la dérivée de la déformation virtuelle qu'une fois
// car elle est constante dans le temps et indépendante des coordonnées
// non pour l'instant toujours vrai car en fait pas de calcul cald_Dvirtuelle=true;
};
// // par défaut on initialise les coordonnées à t et tdt aux mêmes valeurs
// // qu'à 0, ceci pour calculer ensuite les métiques
// const Coordonnee& co1 = tab_noeud(1)->Coord0();
// tab_noeud(1)->Change_coord1(co1);
// tab_noeud(1)->Change_coord2(co1);
// const Coordonnee& co2 = tab_noeud(2)->Coord0();
// tab_noeud(2)->Change_coord1(co2);
// tab_noeud(2)->Change_coord2(co2);
// initialisation du résidu
residu->Zero();
// initialisation de la raideur
raideur->Zero();
Vecteur poids =(doCo->segment).TaWi(); // poids d'intégration = 2
// void Cal_implicit (DdlElement & tab_ddl,Tableau <CoordonneeB >& d_gradTB
// ,Tableau < Tableau2 <CoordonneeB> * > d2_gradTB,Tableau <CoordonneeH >& d_fluxH,int nbint
// ,const Vecteur& poids,const ParaAlgoControle & pa,bool cald_DGradTvirtuelle);
ElemThermi::Cal_implicit(doCo->tab_ddl, d_gradTB,(doCo->d2_gradTB),d_fluxH,nombre_V.nbi
,poids,pa,cald_Dvirtuelle);
// ElemThermi::Cal_implicit (DdlElement & tab_ddl
// ,Tableau <CoordonneeB >& d_gradTB,Tableau < Tableau2 <CoordonneeB>* > d2_gradTB_
// ,Tableau <CoordonneeH >& d_fluxH,int nbint
// ,const Vecteur& poids,const ParaAlgoControle & pa,bool cald_DGradTvirtuelle)
// prise en compte de la section
double section_moyenne = 0.;
const bool atdt=true;
section_moyenne = CalSectionMoyenne_et_vol_pti(atdt);
(*residu) *= section_moyenne;
(*raideur) *= section_moyenne;
energie_totale *= section_moyenne;
E_Hourglass *= section_moyenne; // meme si l'énergie d'hourglass est nulle
E_elem_bulk_tdt*= section_moyenne; // idem
P_elem_bulk *= section_moyenne; // idem
volume *= section_moyenne;
Element::ResRaid el;
el.res = residu;
el.raid = raideur;
return el;
};
// Calcul de la matrice masse pour l'élément
Mat_pleine * BielletteThermi::CalculMatriceMasse (Enum_calcul_masse type_calcul_masse)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// dimensionement de la métrique si nécessaire
if (!(unefois.CalDynamique ))
{ unefois.CalDynamique += 1;
Tableau<Enum_variable_metrique> tab(5);
tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;
tab(4) = igijBB_tdt;tab(5) = igradVmoyBB_t;
doCo->met_biellette.PlusInitVariables(tab) ;
// on vérifie le bon dimensionnement de la matrice
if (type_calcul_masse == MASSE_CONSISTANTE)
// dans le cas où la masse est consistante il faut la redimensionner
{ int nbddl = doCo->tab_ddl.NbDdl();
(doCo->matrice_masse).Initialise (nbddl,nbddl,0.);
}
};
Vecteur poids =(doCo->segmentMas).TaWi(); // poids d'intégration = 2
// appel de la routine générale
ElemThermi::Cal_Mat_masse (doCo->tab_ddl,type_calcul_masse,
nombre_V.nbiMas,(doCo->segmentMas).TaPhi(),nombre_V.nbne
,poids);
(*mat_masse) *= donnee_specif.secti.section0; // prise en compte de l'épaisseur
return mat_masse;
};
//------- calcul d'erreur, remontée des contraintes -------------------
// 1) calcul du résidu et de la matrice de raideur pour le calcul d'erreur
Element::Er_ResRaid BielletteThermi::ContrainteAuNoeud_ResRaid()
{
if(!( unefois.CalResPrem_t ))
{ unefois.CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// appel du programme général
int tabn_taille = tab_noeud.Taille();
ElemThermi:: FluxAuNoeud_ResRaid(tab_noeud.Taille()
,(doCo->segment).TaPhi()
,(doCo->segment).TaWi()
,doCo-> resErr,doCo->raidErr
,(doCo->segmentEr).TaPhi()
,(doCo->segmentEr).TaWi());
// on tient compte de la section à t, supposée déjà calculée ou récupérée
for (int i=1;i<= tabn_taille;i++)
(*doCo-> resErr(i)) *= donnee_specif.secti.section_t;
doCo->raidErr *= donnee_specif.secti.section_t;
return (Element::Er_ResRaid( &(doCo-> resErr),&(doCo->raidErr)));
};
// 2) remontée aux erreurs aux noeuds
Element::Er_ResRaid BielletteThermi::ErreurAuNoeud_ResRaid()
{ if(!( unefois.CalResPrem_t ))
{ unefois.CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// appel du programme général
int tabn_taille = tab_noeud.Taille();
ElemThermi::Cal_ErrAuxNoeuds(tab_noeud.Taille(), (doCo->segment).TaPhi(),
(doCo->segment).TaWi(),doCo-> resErr );
// on tient compte de la section à t, supposée déjà calculée ou récupérée
for (int i=1;i<= tabn_taille;i++)
(*doCo-> resErr(i)) *= donnee_specif.secti.section_t;
doCo->raidErr *= donnee_specif.secti.section_t;
return (Element::Er_ResRaid( &(doCo-> resErr),&(doCo->raidErr)));
};
// actualisation des ddl et des grandeurs actives de t+dt vers t
void BielletteThermi::TdtversT()
{ lesPtThermiInt.TdtversT(); // contrainte
if (tabSaveDon(1) != NULL) tabSaveDon(1)->TdtversT();
if (tabSaveTP(1) != NULL) tabSaveTP(1)->TdtversT();
if (tabSaveDefDon(1) != NULL) tabSaveDefDon(1)->TdtversT();
donnee_specif.secti.section_t = donnee_specif.secti.section_tdt;
ElemThermi::TdtversT_(); // appel de la procédure mère
};
// actualisation des ddl et des grandeurs actives de t vers tdt
void BielletteThermi::TversTdt()
{ lesPtThermiInt.TversTdt(); // contrainte
if (tabSaveDon(1) != NULL) tabSaveDon(1)->TversTdt();
if (tabSaveTP(1) != NULL) tabSaveTP(1)->TversTdt();
if (tabSaveDefDon(1) != NULL)tabSaveDefDon(1)->TversTdt();
donnee_specif.secti.section_tdt = donnee_specif.secti.section_t;
ElemThermi::TversTdt_(); // appel de la procédure mère
};
// calcul de l'erreur sur l'élément. Ce calcul n'est disponible
// qu'une fois la remontée aux contraintes effectuées sinon aucune
// action. En retour la valeur de l'erreur sur l'élément
// type indique le type de calcul d'erreur :
void BielletteThermi::ErreurElement(int type,double& errElemRelative
,double& numerateur, double& denominateur)
{ if(!( unefois.CalResPrem_t ))
{ unefois.CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// appel du programme général
ElemThermi::Cal_ErrElem(type,errElemRelative,numerateur,denominateur,
tab_noeud.Taille(),(doCo->segment).TaPhi(),
(doCo->segment).TaWi(),
(doCo->segmentEr).TaPhi(),(doCo->segmentEr).TaWi());
};
// 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()
// la méthode est différente de la méthode générale car il faut prendre en compte la section de l'élément
const DeuxCoordonnees& BielletteThermi::Boite_encombre_element(Enum_dure temps)
{ // on commence par calculer la boite d'encombrement pour l'élément médian
Element::Boite_encombre_element( temps);
// ensuite on augmente sytématiquement dans toutes directions d'une valeur sqrt(s)/2 majorée
double sSur2maj = sqrt(donnee_specif.secti.section_tdt) * 0.5
* ParaGlob::param->ParaAlgoControleActifs().Extra_boite_prelocalisation();
// ajout d'un extra dans toutes les directions
sSur2maj += ParaGlob::param->ParaAlgoControleActifs().Ajout_extra_boite_prelocalisation();
// mise à jour
boite_encombre.Premier().Ajout_meme_valeur(-sSur2maj); // le min
boite_encombre.Second().Ajout_meme_valeur(sSur2maj); // le max
// retour
return boite_encombre;
};
//============= lecture écriture dans base info ==========
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void BielletteThermi::Lecture_base_info
(ifstream& ent,const Tableau<Noeud *> * tabMaillageNoeud,const int cas)
{// tout d'abord appel de la lecture de la classe ElemThermi
ElemThermi::Lecture_bas_inf(ent,tabMaillageNoeud,cas);
// traitement du cas particulier de la biellette
switch (cas)
{ case 1 : // ------- on récupère tout -------------------------
{ // construction du tableau de ddl des noeuds du triangle
ConstTabDdl();
// récup contraintes et déformation
// les données spécifiques
string nom;
ent >> nom;
if (nom == "epaisStockeDansElement")
ent >> nom >> donnee_specif.secti.section0
>> nom >> donnee_specif.secti.section_t
>> nom >> donnee_specif.secti.section_tdt
>> nom >> donnee_specif.variation_section;
lesPtThermiInt.Lecture_base_info(ent,cas);
break;
}
case 2 : // ----------- lecture uniquement de se qui varie --------------------
{ // récup contraintes et déformation
lesPtThermiInt.Lecture_base_info(ent,cas);
// les données spécifiques
string nom;
ent >> nom >> donnee_specif.secti.section_tdt;
donnee_specif.secti.section_t = donnee_specif.secti.section_tdt;
break;
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de lecture !\n";
cout << "BielletteThermi::Lecture_base_info(ofstream& sort,int cas)"
<< " 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 BielletteThermi::Ecriture_base_info(ofstream& sort,const int cas)
{// tout d'abord appel de l'écriture de la classe ElemThermi
ElemThermi::Ecriture_bas_inf(sort,cas);
// traitement du cas particulier de la biellette
switch (cas)
{ case 1 : // ------- on sauvegarde tout -------------------------
{
// des tenseurs déformation et contrainte,
lesPtThermiInt.Ecriture_base_info(sort,cas);
// les données spécifiques
sort << "\n epaisStockeDansElement " << " section0= " << donnee_specif.secti.section0
<< " section_t= " << donnee_specif.secti.section_t
<< " section_tdt= " << donnee_specif.secti.section_tdt
<< " variation= " << donnee_specif.variation_section;
break;
}
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
{ // des tenseurs déformation et contrainte,
lesPtThermiInt.Ecriture_base_info(sort,cas);
sort << "\n section_tdt= " << donnee_specif.secti.section_tdt;
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
cout << "BielletteThermi::Ecriture_base_info(ofstream& sort,int cas)"
<< " cas= " << cas << endl;
Sortie(1);
}
}
};
// Calcul de la matrice géométrique et initiale
ElemThermi::MatGeomInit BielletteThermi::MatricesGeometrique_Et_Initiale (const ParaAlgoControle & pa)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
Tableau <CoordonneeB>& d_gradTB = (doCo->d_gradTB);// "
Tableau <CoordonneeH>& d_fluxH = (doCo->d_fluxH);// "
bool cald_Dvirtuelle = false;
if (unefois.CalimpPrem == 0)
{ unefois.CalimpPrem = 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
doCo->met_biellette.PlusInitVariables(tab) ;
// on ne calcul la dérivée de la déformation virtuelle qu'une fois
// car elle est constante dans le temps et indépendante des coordonnées
cald_Dvirtuelle=true;
};
// Par simplicité
Mat_pleine & matGeom = doCo->matGeom;
Mat_pleine & matInit = doCo->matInit;
// mise à zéro de la matrice géométrique
matGeom.Initialise();
Vecteur poids =(doCo->segment).TaWi(); // poids d'interpolation = 2
// prise en compte de la section
double section_moyenne = 0.;
const bool atdt=true;
section_moyenne = CalSectionMoyenne_et_vol_pti(atdt);
poids(1) *= section_moyenne;
ElemThermi::Cal_matGeom_Init
(matGeom,matInit,doCo->tab_ddl, d_gradTB,
doCo->d2_gradTB,d_fluxH,1,poids,pa,cald_Dvirtuelle);
return MatGeomInit(&matGeom,&matInit);
} ;
// retourne les tableaux de ddl associés aux noeuds, gere par l'element
// ce tableau et specifique a l'element
const DdlElement & BielletteThermi::TableauDdl() const
{ // --- debug
// cout << "\n debug BielletteThermi::TableauDdl() ";
// for (int i=1;i<=2;i++)
// { int nbddl = doCo->tab_ddl.NbDdl(i);
// cout << "\n noeud "<< i <<": ddl: ";
// for (int j=1; j<= nbddl;j++)
// cout << " j= "<< j << " " << Nom_ddl(doCo->tab_ddl(i).tb(j))<<" ";
// };
// cout << endl;
// fin --- debug
return doCo->tab_ddl;
};
// liberation de la place pointee
void BielletteThermi::Libere ()
{Element::Libere (); // liberation de residu et raideur
LibereTenseur() ; // liberation des tenseur intermediaires
};
// acquisition ou modification d'une loi de comportement
void BielletteThermi::DefLoi (LoiAbstraiteGeneral * NouvelleLoi)
{ // verification du type de loi
if ((NouvelleLoi->Dimension_loi() != 1) && (NouvelleLoi->Dimension_loi() != 4))
{ cout << "\n Erreur, la loi de comportement a utiliser avec des biellettes";
cout << " doit etre de type 1D, \n ici est de type = "
<< (NouvelleLoi->Dimension_loi()) << " !!! " << endl;
Sortie(1);
}
// idem pour le type de déformation mécanique associé
tabSaveDefDon(1) = def->New_et_Initialise();
// a priori pour l'instant ne sert à rien ici // cas d'une loi mécanique
// if (GroupeMecanique(NouvelleLoi->Id_categorie()))
// {loiComp = (Loi_comp_abstraite *) NouvelleLoi;
// // initialisation du stockage particulier, ici 1 pt d'integ
// tabSaveDon(1) = loiComp->New_et_Initialise();
// // idem pour le type de déformation mécanique associé
// tabSaveDefDon(1) = def->New_et_Initialise();
// // définition du type de déformation associé à la loi
// loiComp->Def_type_deformation(*def);
// // on active les données particulières nécessaires au fonctionnement de la loi de comp
// loiComp->Activation_donnees(tab_noeud,dilatation,lesPtThermiInt);
// };
// cas d'une loi thermo physique
if (GroupeThermique(NouvelleLoi->Id_categorie()))
{loiTP = (CompThermoPhysiqueAbstraite *) NouvelleLoi;
// initialisation du stockage particulier, ici 1 pt d'integ
tabSaveTP(1) = loiTP->New_et_Initialise();
// définition du type de déformation associé à la loi
//loiTP->Def_type_deformation(*def);
// on active les données particulières nécessaires au fonctionnement de la loi de comp
loiTP->Activation_donnees(tab_noeud);
};
// cas d'une loi de frottement
if (GroupeFrottement(NouvelleLoi->Id_categorie()))
loiFrot = (CompFrotAbstraite *) NouvelleLoi;
};
// test si l'element est complet
int BielletteThermi::TestComplet()
{ int res = ElemThermi::TestComplet(); // test dans la fonction mere
if ( donnee_specif.secti.section0 == section_defaut)
{ cout << "\n la section de la biellette n'est pas defini \n";
res = 0; }
if ( tab_noeud(1) == NULL)
{ cout << "\n les noeuds de la biellette ne sont pas defini \n";
res = 0; }
else
{ int testi =1;
int posi = Id_nom_ddl("X1") -1;
int dim = ParaGlob::Dimension();
for (int i =1; i<= dim; i++)
for (int j=1;j<=2;j++)
if(!(tab_noeud(j)->Existe_ici(Enum_ddl(posi+i))))
testi = 0;
if(testi == 0)
{ cout << "\n les ddls X1,X2 etc des noeuds de la biellette ne sont pas defini \n";
cout << " \n utilisez BielletteThermi::ConstTabDdl() pour completer " ;
res = 0; }
}
return res;
};
// ajout du tableau de ddl des noeuds de biellette
void BielletteThermi::ConstTabDdl()
{
// tout d'abord on s'intéresse au xi qui servent pour la métrique
// mais qui sont hors service
Tableau <Ddl> ta(ParaGlob::Dimension()+1);
int posi = Id_nom_ddl("X1") -1;
int dim = ParaGlob::Dimension();
for (int i =1; i<= dim; i++)
{Ddl inter((Enum_ddl(i+posi)),0.,HSFIXE);
ta(i) = inter;
}
// maintenant on ajoute le ddl thermique
Ddl inter(TEMP,0.,LIBRE);
ta(dim+1)=inter;
// attribution des ddls aux noeuds
tab_noeud(1)->PlusTabDdl(ta);
tab_noeud(2)->PlusTabDdl(ta);
};
// procesure permettant de completer l'element apres
// sa creation avec les donnees du bloc transmis
// peut etre appeler plusieurs fois
Element* BielletteThermi::Complete(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD)
{ // complétion avec bloc
if (bloc.Nom(1) == "sections")
{ donnee_specif.secti.section0 = bloc.Val(1);
// on initialise aussi les grandeurs à t et tdt
donnee_specif.secti.section_tdt = donnee_specif.secti.section_t = bloc.Val(1);
return this;
}
else if (bloc.Nom(1) == "variation_section")
{ donnee_specif.variation_section = bloc.Val(1);
// on initialise aussi les grandeurs à t et tdt
return this;
}
else
return ElemThermi::Complete_ElemThermi(bloc,lesFonctionsnD);
};
// affichage dans la sortie transmise, des variables duales "nom"
// dans le cas ou nom est vide, affichage de "toute" les variables
void BielletteThermi::AfficheVarDual(ofstream& sort, Tableau<string>& nom)
{// affichage de l'entête de l'element
sort << "\n******************************************************************";
sort << "\n Element bielette (2 noeuds 1 point d'integration) ";
sort << "\n******************************************************************";
// appel de la procedure de ElemThermi
if (!(unefois.dualSortbiel) && (unefois.CalimpPrem))
{ VarDualSort(sort,nom,1,1);
unefois.dualSortbiel += 1;
}
else if ((unefois.dualSortbiel) && (unefois.CalimpPrem))
VarDualSort(sort,nom,1,11);
else if (!(unefois.dualSortbiel) && (unefois.CalResPrem_tdt))
{ VarDualSort(sort,nom,1,2);
unefois.dualSortbiel += 1;
}
else if ((unefois.dualSortbiel) && (unefois.CalResPrem_tdt))
VarDualSort(sort,nom,1,12);
// sinon on ne fait rien
};
// récupération des valeurs au numéro d'ordre = iteg pour
// les grandeur enu
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
Tableau <double> BielletteThermi::Valeur_a_diff_temps(bool absolue,Enum_dure enu_t,const List_io<Ddl_enum_etendu>& enu,int iteg)
{ // appel de la procedure de ElemThermi
int cas;
if (!(unefois.dualSortbiel) && (unefois.CalimpPrem))
{ cas=1;unefois.dualSortbiel = 1;
}
else if ((unefois.dualSortbiel) && (unefois.CalimpPrem))
{ cas = 11;}
else if (!(unefois.dualSortbiel) && (unefois.CalResPrem_tdt))
{ cas=2;unefois.dualSortbiel += 1;
}
else if ((unefois.dualSortbiel) && (unefois.CalResPrem_tdt))
{ cas = 12;}
// sinon pour l'instant pb, car il faut définir des variable dans la métrique
else
{ cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul"
<< " pour inialiser les conteneurs des tenseurs resultats ";
if (ParaGlob::NiveauImpression() >= 4)
cout << "\n cas non prévu, unefois.dualSortbiel= " << unefois.dualSortbiel
<< " unefois.CalimpPrem= " << unefois.CalimpPrem
<< "\n BielletteThermi::Valeur_a_diff_temps(Enum_dure enu_t...";
Sortie(1);
};
return ElemThermi::Valeur_multi(absolue,enu_t,enu,iteg,cas);
};
// récupération des valeurs au numéro d'ordre = iteg pour les grandeurs enu
// ici il s'agit de grandeurs tensorielles, le retour s'effectue dans la liste
// de conteneurs quelconque associée
void BielletteThermi::ValTensorielle_a_diff_temps(bool absolue,Enum_dure enu_t,List_io<TypeQuelconque>& enu,int iteg)
{ // appel de la procedure de ElemThermi
int cas;
if (!(unefois.dualSortbiel ) && (unefois.CalimpPrem ))
{ cas=1;unefois.dualSortbiel += 1;
}
else if ((unefois.dualSortbiel ) && (unefois.CalimpPrem ))
{ cas = 11;}
else if (!(unefois.dualSortbiel ) && (unefois.CalResPrem_tdt ))
{ cas=2;unefois.dualSortbiel += 1;
}
else if ((unefois.dualSortbiel ) && (unefois.CalResPrem_tdt ))
{ cas = 12;}
// sinon pour l'instant pb, car il faut définir des variable dans la métrique
else
{ cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul"
<< " pour inialiser les conteneurs des tenseurs resultats ";
if (ParaGlob::NiveauImpression() >= 4)
cout << "\n cas non prévu, unefois.dualSortbiel= " << unefois.dualSortbiel
<< " unefois.CalimpPrem= " << unefois.CalimpPrem
<< "\n BielletteThermi::ValTensorielle_a_diff_temps(Enum_dure enu_t...";
Sortie(1);
};
ElemThermi::Valeurs_Tensorielles(absolue,enu_t,enu,iteg,cas);
};
// cas d'un chargement volumique,
// force indique la force volumique appliquée
// retourne le second membre résultant
// ici on considère la section de la biellette pour constituer le volume
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur BielletteThermi::SM_charge_volumique_E(const Coordonnee& force,bool atdt,const ParaAlgoControle & pa)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if(!(unefois.CalSMvol_t ))
{ unefois.CalSMvol_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
doCo->met_biellette.PlusInitVariables(tab) ;
};}
else
{if(!(unefois.CalSMvol_tdt ))
{ unefois.CalSMvol_tdt += 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};};
// initialisation du résidu
residu->Zero();
// appel du programme général d'elemmeca et retour du vecteur second membre
// multiplié par la section pour avoir le volume, on considère que la section est à jour
double section = donnee_specif.secti.section_tdt;
if (!atdt) section = donnee_specif.secti.section_t;
return (section * ElemThermi::SM_charge_vol_E (doCo->tab_ddl,(doCo->segment).TaPhi()
,tab_noeud.Taille(),(doCo->segment).TaWi(),force,pa));
};
// calcul des seconds membres suivant les chargements
// cas d'un chargement volumique,
// force indique la force volumique appliquée
// retourne le second membre résultant
// ici on l'épaisseur de l'élément pour constituer le volume -> 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 BielletteThermi::SMR_charge_volumique_I
(const Coordonnee& force,const ParaAlgoControle & pa)
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// initialisation du résidu
residu->Zero();
// initialisation de la raideur
raideur->Zero();
// -- définition des constantes de la métrique si nécessaire
// en fait on fait appel aux même éléments que pour le calcul implicite
if (!(unefois.CalSMvol_tdt ))
{ unefois.CalSMvol_tdt += 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// appel du programme général d'ElemThermi
ElemThermi::SMR_charge_vol_I (doCo->tab_ddl,(doCo->segment).TaPhi()
,tab_noeud.Taille(),(doCo->segment).TaWi(),force,pa);
// prise en compte de la section
(*residu) *= donnee_specif.secti.section_t;
(*raideur) *= donnee_specif.secti.section_t;
Element::ResRaid el;
el.res = residu;
el.raid = raideur;
return el;
};
// cas d'un chargement lineique, sur l'aretes de la biellette
// force indique la force lineique appliquée
// numarete indique le numéro de l'arete chargée ici 1
// retourne le second membre résultant
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur BielletteThermi::SM_charge_lineique_E(const Coordonnee& force,int ,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extA)(1))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf = Frontiere_lineique(1,true);
BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if( !(unefois.CalSMlin_t ))
{ unefois.CalSMlin_t += 1;
Tableau<Enum_variable_metrique> tab(8);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = igradVBB_t;
doCo->met_biellette.PlusInitVariables(tab) ;
};}
else
{if( !(unefois.CalSMlin_tdt ))
{ unefois.CalSMlin_tdt += 1;
Tableau<Enum_variable_metrique> tab(8);
tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
tab(8) = igradVBB_tdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(1) == NULL)
defArete(1) = def; // a priori idem que la biellette
// appel du programme général d'ElemThermi et retour du vecteur second membre
return ElemThermi::SM_charge_line_E (doCo->tab_ddl,1,(doCo->segment).TaPhi()
,tab_noeud.Taille(),(doCo->segment).TaWi(),force,pa);
};
// 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 ici 1 par défaut
// retourne le second membre résultant
// -> 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 BielletteThermi::SMR_charge_lineique_I
(const Coordonnee& force,int ,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
((*res_extA)(1))->Zero();
((*raid_extA)(1))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf =Frontiere_lineique(1,true);
BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if( !(unefois.CalSMRlin ))
{ unefois.CalSMRlin += 1;
Tableau<Enum_variable_metrique> tab(15);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = igradVBB_tdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(1) == NULL)
defArete(1) = def; // a priori idem que la biellette
// appel du programme général d'ElemThermi et retour du vecteur second membre
return ElemThermi::SMR_charge_line_I (doCo->tab_ddl,1
,(doCo->segment).TaPhi(),tab_noeud.Taille(),(doCo->segment).TaWi(),force,pa);
};
// cas d'un chargement lineique suiveuse, sur l'aretes frontière de la biellette (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
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur BielletteThermi::SM_charge_lineique_Suiv_E(const Coordonnee& force,int ,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extA)(1))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf = Frontiere_lineique(1,true);
BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if( !(unefois.CalSMlin_t ))
{ unefois.CalSMlin_t += 1;
Tableau<Enum_variable_metrique> tab(8);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = igradVBB_t;
doCo->met_biellette.PlusInitVariables(tab) ;
};}
else
{if( !(unefois.CalSMlin_tdt ))
{ unefois.CalSMlin_tdt += 1;
Tableau<Enum_variable_metrique> tab(8);
tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
tab(8) = igradVBB_tdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(1) == NULL)
defArete(1) = def; // a priori idem que la biellette
// appel du programme général d'ElemThermi et retour du vecteur second membre
return ElemThermi::SM_charge_line_Suiv_E (doCo->tab_ddl,1,(doCo->segment).TaPhi()
,tab_noeud.Taille(),(doCo->segment).TaWi(),force,pa);
};
// cas d'un chargement lineique suiveuse, sur l'aretes frontière de la biellette (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
// -> 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 BielletteThermi::SMR_charge_lineique_Suiv_I
(const Coordonnee& force,int ,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
((*res_extA)(1))->Zero();
((*raid_extA)(1))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf = Frontiere_lineique(1,true);
BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if( !(unefois.CalSMRlin ))
{ unefois.CalSMRlin += 1;
Tableau<Enum_variable_metrique> tab(15);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = igradVBB_tdt;
doCo->met_biellette.PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(1) == NULL)
defArete(1) = def; // a priori idem que la biellette
// appel du programme général d'ElemThermi et retour du vecteur second membre
return ElemThermi::SMR_charge_line_Suiv_I (doCo->tab_ddl,1
,(doCo->segment).TaPhi(),tab_noeud.Taille(),(doCo->segment).TaWi(),force,pa);
};
// 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 ou à tdt en fonction de la variable booléenne atdt
Vecteur BielletteThermi::SM_charge_hydrodynamique_E( Courbe1D* frot_fluid,const double& poidvol
, Courbe1D* coef_aero_n,int num,const double& coef_mul
, Courbe1D* coef_aero_t,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extN)(num))->Zero(); // ici les frontières sont des points
BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// on récupère ou on crée la frontière points
Frontiere_points(num,true);
// ici on fait l'hypothèse d'une section circulaire, n'ayant pas d'autres infos pour l'instant sur les
// dimensions de la section, d'où la surface frontale approximativement s'en déduie
double section = donnee_specif.secti.section_tdt;
if (!atdt) section = donnee_specif.secti.section_t;
double dimension_transversale = sqrt(section/ConstMath::Pi);
// on utilise l'élément géométique de l'élément, pour TaPhi et TaWi pour les passages de paramètres,
// mais ces infos ne sont pas utilisées car pour les frontières points, pas de points d'integ
// appel du programme général d'ElemThermi et retour du vecteur second membre
return ElemThermi::SM_charge_hydrodyn_E (poidvol,doCo->segment.TaPhi(),1
,frot_fluid,doCo->segment.TaWi()
,coef_aero_n,num,coef_mul,coef_aero_t,pa,atdt);
};
// -> 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 BielletteThermi::SMR_charge_hydrodynamique_I( Courbe1D* frot_fluid,const double& poidvol
, Courbe1D* coef_aero_n,int num,const double& coef_mul
, Courbe1D* coef_aero_t,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
((*res_extN)(num))->Zero();
((*raid_extN)(num))->Zero();
BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
// on récupère ou on crée la frontière points
Frontiere_points(num,true);
// ici on fait l'hypothèse d'une section circulaire, n'ayant pas d'autres infos pour l'instant sur les
// dimensions de la section, d'où la surface frontale approximativement s'en déduie
double section = donnee_specif.secti.section_tdt;
double dimension_transversale = sqrt(section/ConstMath::Pi);
// on utilise l'élément géométique de l'élément, pour TaPhi et TaWi pour les passages de paramètres,
// mais ces infos ne sont pas utilisées car pour les frontières points, pas de points d'integ
// appel du programme général d'ElemThermi et retour du vecteur second membre
Element::ResRaid el(ElemThermi::SM_charge_hydrodyn_I (poidvol,doCo->segment.TaPhi(),1
,frot_fluid,doCo->segment.TaWi(),tabb(posi_tab_front_point+num)->DdlElem()
,coef_aero_n,num,coef_mul,coef_aero_t,pa));
(*el.res) *= dimension_transversale;
(*el.raid) *= dimension_transversale;
return el;
};
// calcul de la nouvelle section moyenne finale (sans raideur)
// ramène la section moyenne calculée à atdt
const double& BielletteThermi::CalSectionMoyenne_et_vol_pti(const bool atdt)
{ // dépend si l'on veut une variation ou non
if (donnee_specif.variation_section)
{// S(t+\Delta t) = \frac{(S(t)~\sqrt{g(t)})}{\sqrt{g(t+\Delta t)}}\left ( \frac{K_{t}}{(K_{t} + (P(t+\Delta t) - P(t)))} \right )
// il faut avoir en tête que P = - trace(sig)/3 !!!
//en thermique pour l'instant on ne tient pas compte de la variation, mais dès que cela est possible
// on tiendra compte de la dilatation thermique
Sect& sect = donnee_specif.secti; // pour simplifier
return sect.section0;
};
//
//
//
// // .. en bouclant sur les pt d'integ enregistré ..
// // -- on récupère et on calcule les jacobiens moyens à t(ou 0) et final
// double jacobien_moy_ini = 0.; double jacobien_moy_fin = 0.; // init
// // -- de même on récupère et on calcul la trace moyenne de la contrainte
// double traceSig_moy = 0.; double traceSig_moy_ini = 0.;
// // -- de même on récupère et on calcul le module de compressibilité moyen
// double troisK_moy = 0.;
// for (int i=1;i<= nombre_V.nbi;i++)
// { // cas de la compressibilité
// const double& troisK = 3. * (*lesPtIntegMecaInterne)(i).ModuleCompressibilite_const();
// troisK_moy += troisK;
// // cas des jacobiens
// const double& jacobien_0 = *(tabSaveDefDon(i)->Meti_00().jacobien_);
// if (atdt)
// { const double& jacobien_ini = *(tabSaveDefDon(i)->Meti_t().jacobien_);
// jacobien_moy_ini += jacobien_ini;
// const double& jacobien_fin = *(tabSaveDefDon(i)->Meti_tdt().jacobien_);
// jacobien_moy_fin += jacobien_fin;
// // cas de la trace de sigma
// const double traceSig = (*lesPtIntegMecaInterne)(i).SigHH_const() && (*(tabSaveDefDon(i)->Meti_tdt().gijBB_));
// traceSig_moy += traceSig;
// const double traceSig_ini = (*lesPtIntegMecaInterne)(i).SigHH_t_const() && (*(tabSaveDefDon(i)->Meti_t().gijBB_));
// traceSig_moy_ini += traceSig_ini;
// (*lesPtIntegMecaInterne)(i).Volume_pti() *= (sect.section_t * jacobien_ini) / jacobien_fin
// * troisK / (troisK - traceSig+traceSig_ini);
// }
// else
// { const double& jacobien_ini = *(tabSaveDefDon(i)->Meti_00().jacobien_);
// jacobien_moy_ini += jacobien_ini;
// const double& jacobien_fin = *(tabSaveDefDon(i)->Meti_t().jacobien_);
// jacobien_moy_fin += jacobien_fin;
// // cas de la trace de sigma
// const double traceSig = (*lesPtIntegMecaInterne)(i).SigHH_const() && (*(tabSaveDefDon(i)->Meti_t().gijBB_));
// traceSig_moy += traceSig;
// (*lesPtIntegMecaInterne)(i).Volume_pti() *= (sect.section0 * jacobien_ini) / jacobien_fin
// * troisK / (troisK - traceSig);
// };
// };
// jacobien_moy_ini /= nombre_V.nbi;
// jacobien_moy_fin /= nombre_V.nbi;
// traceSig_moy /= nombre_V.nbi;
// troisK_moy /= nombre_V.nbi;
// // d'où le calcul de la nouvelle section en utilisant la relation:
// // (V-V_0)/V = trace(sigma)/3 /K_moy
// if (atdt)
// { // là on utilise uniquement l'incrément: cf. partie théorique d'herezh
// // S(t+\Delta t) = \frac{(S(t)~\sqrt{g(t)})}{\sqrt{g(t+\Delta t)}}\left ( \frac{K_{t}}{(K_{t} + (P(t+\Delta t) - P(t)))} \right )
// sect.section_tdt = (sect.section_t * jacobien_moy_ini) / jacobien_moy_fin
// * troisK_moy / (troisK_moy - traceSig_moy+traceSig_moy_ini);
//
//// ancienne nouvelle formule, via la def logarithmique
//// double ratio = traceSig_moy/troisK_moy;
//// sect.section_tdt = (sect.section0 * jacobien_moy_t) / jacobien_moy_fin
//// * exp(ratio);
//// ancienne formule * troisK_moy / (troisK_moy - traceSig_moy);
// //--debug
// //if (num_elt==1)
// // { Noeud* noe = tab_noeud(1);
// // double R_0 = noe->Coord0().Norme(); double R = noe->Coord2().Norme();
// //cout << "\n e0= " << epais.section_tdt<< " troisK_moy=" << troisK_moy << " traceSig_moy=" << traceSig_moy
// // << " J0= " << jacobien_moy_0 << " J= " << jacobien_moy_fin << " R_0 " << R_0 << " R= " << R;
// // };
// //-- fin debug
// return sect.section_tdt;
// }
// else
// {// dans le cas où on n'a pas d'incrément, on retiend la formule intégrée
// // dans laquelle on suppose que le K ne varie pas ... donc une formule qui n'est
// // pas vraiment valide pour des lois complexes !!
// double ratio = traceSig_moy/troisK_moy;
// sect.section_t = (sect.section0 * jacobien_moy_ini) / jacobien_moy_fin
// * exp(ratio);
//// * troisK_moy / (troisK_moy - traceSig_moy);
// return sect.section_t;
// };
// }
// else
// // si on ne veut pas de variation
// {if (atdt) { return donnee_specif.secti.section_tdt;}
// else { return donnee_specif.secti.section_t;};
// };
};
// retourne la liste abondée de tous les données particulières interne actuellement utilisées
// par l'élément (actif ou non), sont exclu de cette liste les données particulières des noeuds
// reliées à l'élément
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> BielletteThermi::Les_types_particuliers_internes(bool absolue) const
{ // on commence par récupérer la liste général provenant d'ElemMeca
List_io <TypeQuelconque> ret = ElemThermi::Les_types_particuliers_internes(absolue);
// ensuite on va ajouter les données particulières aux sfe
Grandeur_scalaire_double grand_courant; // def d'une grandeur courante
// $$$ cas de la section initiale
TypeQuelconque typQ1(SECTION_MOY_INITIALE,SIG11,grand_courant);
ret.push_back(typQ1);
// $$$ cas de la section finale
TypeQuelconque typQ2(SECTION_MOY_FINALE,SIG11,grand_courant);
ret.push_back(typQ2);
return ret;
};
// récupération de grandeurs particulières au numéro d'ordre = iteg
// celles-ci peuvent être quelconques
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void BielletteThermi::Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ,int iteg)
{
// on balaie la liste transmise pour les grandeurs propres
List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
// on commence par appeler la fonction de la classe m่re
// il n'y aura pas de calcul des grandeurs inactivées
ElemThermi::Grandeur_particuliere (absolue,liTQ,iteg);
// puis les grandeurs sp้cifiques
for (il=liTQ.begin();il!=ilfin;il++)
{TypeQuelconque& tipParticu = (*il); // pour simplifier
if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
switch (tipParticu.EnuTypeQuelconque().EnumTQ())
{
// 1) -----cas de la section moyenne initiale, ici elle ne d้pend pas du point d'int้gration
case SECTION_MOY_INITIALE:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.secti.section0;
(*il).Active();
break;
}
// 2) -----cas de la section moyenne finale, ici elle ne d้pend pas du point d'int้gration
case SECTION_MOY_FINALE: // on inactive la grandeur quelconque
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.secti.section_tdt;
(*il).Active();
break;
}
default: // on ne fait rien
break;
};
};
};
// Calcul des frontieres de l'element
// creation des elements frontieres et retour du tableau de ces elements
// la création n'a lieu qu'au premier appel
// ou lorsque l'on force le paramètre force a true
// dans ce dernier cas seul les frontière effacées sont recréée
Tableau <ElFrontiere*> const & BielletteThermi::Frontiere(bool force)
{ int cas = 6; // on veut des lignes et des points
return Frontiere_elethermi(cas,force);
//
// // le calcul et la création ne sont effectués qu'au premier appel
// // ou lorsque l'on veut forcer une recréation
// if (((ind_front_lin == 0) && (ind_front_surf == 0) && (ind_front_point == 0))
// || force )
//// if ((ind_front_point == 0) || force || (ind_front_point == 2))
// { // dimensionnement des tableaux intermediaires
// Tableau <Noeud *> tab(1); // les noeuds des points frontieres
// DdlElement ddelem(1); // les ddlelements des points frontieres
// int tail;
// if ((ParaGlob::Dimension() == 1) && (ind_front_lin > 0))
// tail = 3; // deux points et une ligne
// else if (ParaGlob::Dimension() == 1) // cas sans ligne
// tail = 2; // 2 points
// else // cas d'une dimension 2 et 3
// { tail = 3; // deux points et une ligne
// ind_front_lin = 1;
// }
// tabb.Change_taille(tail); // le tableau total de frontières
//
// // premier point
// tab(1) = tab_noeud(1);
// ddelem.Change_un_ddlNoeudElement(1,doCo->tab_ddl(1));
// if (tabb(1+posi_tab_front_point) == NULL)
// tabb(1+posi_tab_front_point) = new FrontPointF (tab,ddelem);
// // second point
// tab(1) = tab_noeud(2);
// ddelem.Change_un_ddlNoeudElement(1,doCo->tab_ddl(2));
// if (tabb(2+posi_tab_front_point) == NULL)
// tabb(2+posi_tab_front_point) = new FrontPointF (tab,ddelem);
// // 3 ieme cote eventuelle
// if (ind_front_lin > 0)
// // cas où il y a une ligne, c'est forcément le premier élément
// if (tabb(1) == NULL)
// tabb(1) = new FrontSegLine(tab_noeud,doCo->tab_ddl);
//
// // mise à jour des indicateurs
// ind_front_point = 1;
// }
//
// return tabb;
};
//// ramène la frontière point
//// éventuellement création des frontieres points de l'element et stockage dans l'element
//// si c'est la première fois sinon il y a seulement retour de l'elements
//// a moins que le paramètre force est mis a true
//// dans ce dernier cas la frontière effacéee est recréée
//// num indique le numéro du point à créer (numérotation EF)
//ElFrontiere* const BielletteThermi::Frontiere_points(int num,bool force)
// { // le calcul et la création ne sont effectués qu'au premier appel
// // ou lorsque l'on veut forcer une recréation
// #ifdef MISE_AU_POINT
// if ((num > 2)||(num <=0))
// { cout << "\n *** erreur, pour les biellettes il n'y a que deux frontieres point ! "
// << "\n Frontiere_points(int num,bool force)";
// Sortie(1);
// }
// #endif
//
// if ((ind_front_point == 0) || force || (ind_front_point == 2))
// {Tableau <Noeud *> tab(1); // les noeuds des points frontieres
// DdlElement ddelem(1); // les ddlelements des points frontieres
// // on regarde si les frontières points existent sinon on les crée
// if (ind_front_point == 1)
// return (ElFrontiere*)tabb(posi_tab_front_point+num);
// else if ( ind_front_point == 2)
// // cas où certaines frontières existent
// if (tabb(posi_tab_front_point+num) != NULL)
// return (ElFrontiere*)tabb(posi_tab_front_point+num);
// // dans tous les autres cas on construit la frontière point
// // on commence par dimensionner le tableau de frontière
// if ((ind_front_lin > 0) && (ind_front_point==0))
// // cas où il y a une frontière ligne (mais pas de point)
// { tabb.Change_taille(3); posi_tab_front_point = 1;}
// else if ((ind_front_lin == 0) && (ind_front_point==0))
// // cas où aucune frontière existe, on crée pour les points
// { tabb.Change_taille(2); posi_tab_front_point = 0;};
// // dans les deux autres cas ((ind_front_lin == 0) && (ind_front_point>0)) et
// // ((ind_front_lin > 0) && (ind_front_point>0)), les points existant déjà on n'a rien n'a faire
// // on définit les deux points par simplicité
// // premier point
// tab(1) = tab_noeud(1);
// ddelem.Change_un_ddlNoeudElement(1,doCo->tab_ddl(1));
// if (tabb(1+posi_tab_front_point) == NULL)
// tabb(1+posi_tab_front_point) = new FrontPointF (tab,ddelem);
// // second point
// tab(1) = tab_noeud(2);
// ddelem.Change_un_ddlNoeudElement(1,doCo->tab_ddl(2));
// if (tabb(2+posi_tab_front_point) == NULL)
// tabb(2+posi_tab_front_point) = new FrontPointF (tab,ddelem);
// ind_front_point=1; // mise à jour de l'indicateur
// };
// return (ElFrontiere*)tabb(num+posi_tab_front_point);
// };
//// ramène la frontière linéique
//// éventuellement création des frontieres linéique de l'element et stockage dans l'element
//// si c'est la première fois et en 3D sinon il y a seulement retour de l'elements
//// a moins que le paramètre force est mis a true
//// dans ce dernier cas la frontière effacéee est recréée
//// num indique le numéro de l'arête à créer (numérotation EF)
//ElFrontiere* const BielletteThermi::Frontiere_lineique(int num,bool )
// { // le calcul et la création ne sont effectués qu'au premier appel
// // ou lorsque l'on veut forcer une recréation
// #ifdef MISE_AU_POINT
// if (num != 1)
// { cout << "\n *** erreur, pour les biellettes il n'y a qu'une frontière ligne ! "
// << "\n Frontiere_lineique(int num,bool force)";
// Sortie(1);
// }
// #endif
//
// // on regarde si les frontières linéiques existent sinon on les crée
// if (ind_front_lin == 1)
// return (ElFrontiere*)tabb(1);
// else if ( ind_front_lin == 2)
// // cas où certaines frontières existent
// if (tabb(1) != NULL)
// return (ElFrontiere*)tabb(1);
// // dans tous les autres cas on construit la frontière ligne
// // on commence par dimensionner le tableau de frontière
// if (ind_front_point > 0)
// // cas où il y a des frontières points (mais pas ligne)
// // on décale le tableau
// { tabb.Change_taille(3);
// tabb(3) = tabb(2);
// tabb(2) = tabb(1);
// posi_tab_front_point = 1;
// }
// else
// // cas d'une frontière linéique
// tabb.Change_taille(1);
// // on définit la ligne
// tabb(1) = new FrontSegLine(tab_noeud,doCo->tab_ddl);
// ind_front_lin = 1; // mise à jour de l'indicateur
// // et normalement posi_tab_front_ligne = 0, car jamais changé
// return (ElFrontiere*)tabb(num);
// };
//
//// ramène la frontière surfacique
//// éventuellement création des frontieres surfacique de l'element et stockage dans l'element
//// si c'est la première fois sinon il y a seulement retour de l'elements
//// a moins que le paramètre force est mis a true
//// dans ce dernier cas la frontière effacéee est recréée
//// num indique le numéro de la surface à créer (numérotation EF)
//// ici normalement la fonction ne doit pas être appelée
//ElFrontiere* const BielletteThermi::Frontiere_surfacique(int ,bool )
// { cout << "\n *** erreur, pour les biellettes il n'y a pas de frontiere surface ! "
// << "\n Frontiere_surfacique(int ,bool force = false)";
// Sortie(1);
// return NULL;
// };
// =====>>>> methodes privées appelees par les classes dérivees <<<<=====
// fonction d'initialisation servant au niveau du constructeur
BielletteThermi::DonneeCommune * BielletteThermi::Init
(Donnee_specif donnee_spec,bool sans_init_noeud)
{ // bien que la grandeur donnee_specif est défini dans la classe generique
// le fait de le passer en paramètre permet de tout initialiser dans Init
// et ceci soit avec les valeurs par défaut soit avec les bonnes valeurs
donnee_specif =donnee_spec;
// le fait de mettre les pointeurs a null permet
// de savoir que l'element n'est pas complet
tab_noeud.Change_taille(nombre_V.nbne);
// dans le cas d'un constructeur avec tableau de noeud, il ne faut pas mettre
// les pointeurs à nuls d'où le test
if (!sans_init_noeud)
for (int i =1;i<= nombre_V.nbne;i++) tab_noeud(i) = NULL;
// definition des donnees communes aux BielletteThermixxx
// a la premiere definition d'une instance
if (unefois.doCoMemb == NULL)
BielletteThermi::Def_DonneeCommune();
unefois.doCoMemb = doCo ;
met = &(doCo->met_biellette); // met est defini dans ElemThermi
// def pointe sur la deformation specifique a l'element pour le calcul thermique
def = new Deformation(*met,tab_noeud,(doCo->segment).TaDphi(),(doCo->segment).TaPhi());
// idem pour la remontee aux contraintes et le calcul d'erreur
defEr = new Deformation(*met,tab_noeud,(doCo->segmentEr).TaDphi(),(doCo->segmentEr).TaPhi());
// idem pour la remontee aux contraintes et le calcul d'erreur
defMas = new Deformation(*met,tab_noeud,(doCo->segmentMas).TaDphi(),(doCo->segmentMas).TaPhi());
// idem pour le calcul de second membre
defArete.Change_taille(1); // 1 arrête utilisée pour le second membre
// la déformation sera construite si nécessaire au moment du calcul de second membre
defArete(1) = NULL;
//dimensionnement des deformations et contraintes etc..
int dimtens = 1;
lesPtThermiInt.Change_taille_PtIntegThermi(1,dimtens);
// stockage des donnees particulieres de la loi de comportement au point d'integ
tabSaveDon.Change_taille(nombre_V.nbi);
tabSaveTP.Change_taille(nombre_V.nbi);
tabSaveDefDon.Change_taille(nombre_V.nbi);
tab_energ.Change_taille(nombre_V.nbi);
tab_energ_t.Change_taille(nombre_V.nbi);
// initialisation des pointeurs définis dans la classe Element concernant les résidus et
// raideur
// --- cas de la puissance interne ---
residu = &(doCo->residu_interne); // residu local
raideur = &(doCo->raideur_interne); // raideur locale
// --- cas de la dynamique -----
mat_masse = &(doCo->matrice_masse);
// --- cas des efforts externes concernant les noeuds ------
res_extN = &(doCo->residus_externeN); // pour les résidus et second membres
raid_extN= &(doCo->raideurs_externeN);// pour les raideurs
// --- cas des efforts externes concernant les aretes ------
res_extA = &(doCo->residus_externeA); // pour les résidus et second membres
raid_extA= &(doCo->raideurs_externeA);// pour les raideurs
return doCo;
};
// fonction privee
// dans cette fonction il ne doit y avoir que les données communes !!
void BielletteThermi::Def_DonneeCommune()
{ int nbn = nombre_V.nbne;
// interpollation : element geometrique correspondant: 1 pt integ, 2 noeuds
GeomSeg seg(nombre_V.nbi,nbn) ;
// degre de liberte: ici de thermique
int dim = ParaGlob::Dimension();
DdlElement tab_ddl(nbn,dim);
int posi = Id_nom_ddl("TEMP");
int i =1;
for (int j=1; j<= nbn; j++)
tab_ddl.Change_Enum(j,i,Enum_ddl(posi));
// cas des ddl éléments secondaires pour le calcul d'erreur
// def du nombre de composantes du tenseur de contrainte en absolu
int nbcomposante = ParaGlob::Dimension();
DdlElement tab_ddlErr(nbn,nbcomposante);
posi = Id_nom_ddl("FLUXD1") -1;
for (int j=1; j<= nbn; j++)
{ // on definit le nombre de composante du flux en absolu
switch (nbcomposante)
{ case 3 : tab_ddlErr.Change_Enum(j,3,Enum_ddl(3+posi)); // cas de FLUXD3
case 2 : tab_ddlErr.Change_Enum(j,2,Enum_ddl(2+posi)); // cas de FLUXD2
case 1 : tab_ddlErr.Change_Enum(j,1,Enum_ddl(1+posi)); // cas de FLUXD1
};
};
// egalement pour tab_Err1FLUX, def d'un tableau de un ddl : enum FLUXD1
// par noeud
DdlElement tab_Err1FLUX(nbn,DdlNoeudElement(FLUXD1));
// toujours pour le calcul d'erreur definition des fonctions d'interpolation
// pour le calcul du hession de la fonctionnelle :
// 2 points d'integration et 2 noeuds
GeomSeg segEr(nombre_V.nbiEr,nbn) ;
// pour le calcul de la matrice masse definition des fonctions d'interpolation
// 2 points d'integration et 2 noeuds, en particulier pour le calcul de la masse consistante
GeomSeg segMa(nombre_V.nbiMas,nbn) ;
// def metrique
// on definit les variables a priori toujours utiles
Tableau<Enum_variable_metrique> tab(24);
tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt ;
tab(4) = igiB_0; tab(5) = igiB_t; tab(6) = igiB_tdt;
tab(7) = igiH_0; tab(8) = igiH_t; tab(9) = igiH_tdt ;
tab(10)= igijBB_0; tab(11)= igijBB_t; tab(12)= igijBB_tdt;
tab(13)= igijHH_0; tab(14)= igijHH_t; tab(15)= igijHH_tdt ;
tab(16)= id_gijBB_tdt; tab(17)= id_giH_tdt; tab(18)= id_gijHH_tdt;
tab(19)= idMtdt ; tab(20)= id_jacobien_tdt;tab(21)= id2_gijBB_tdt;
tab(22)= igradVBB_tdt; tab(23) = iVtdt; tab(24)= idVtdt;
// dim du pb , nb de vecteur de la base , tableau de ddl et la def de variables
// ici il s'agit des ddl Xi + ddl de thermique: a priori les ddl de Xi
// ne serviront que pour les pb couplés
int posi_x1 = Id_nom_ddl("X1") -1;
DdlElement tab_ddl_metrique(nbn,dim+1); // une métrique d'élément contenant les Xi et la température
for (int i =1; i<= dim; i++)
for (int j=1; j<= nbn; j++)
{for (int i =1; i<= dim; i++)
tab_ddl_metrique.Change_Enum(j,i,Enum_ddl(i+posi)); // cas des Xi
tab_ddl_metrique.Change_Enum(j,dim+1,TEMP);
};
Met_biellette metri(ParaGlob::Dimension(),tab_ddl_metrique,tab,nbn) ;
// ---- cas du calcul d'erreur sur sigma ou epsilon
// les tenseurs sont exprimees en absolu donc nombre de composante fonction
// de la dimension absolue
Tableau <Vecteur *> resEr(nbcomposante);
for (int i = 1;i<= nbcomposante; i++)
resEr(i)=new Vecteur (nbn); // une composante par noeud
Mat_pleine raidEr(nbn,nbn); // la raideur pour l'erreur
// dimensionnement des différents résidus et raideurs pour le calcul mécanique
int nbddl = tab_ddl.NbDdl();
Vecteur residu_int(nbddl); Mat_pleine raideur_int(nbddl,nbddl);
// cas de la dynamique
Mat_pleine matmasse(1,nbddl); // a priori on dimensionne en diagonale
// il y a deux extrémités mais identiques
Tableau <Vecteur* > residus_extN(2); residus_extN(1) = new Vecteur(dim);
residus_extN(2) = residus_extN(1);
int nbddlA = nombre_V.nbneA * dim; int nbA = 1; // 1 arêtes
Tableau <Vecteur* > residus_extA(nbA); residus_extA(1) = new Vecteur(nbddlA);
Tableau <Mat_pleine* > raideurs_extA(nbA); raideurs_extA(1) = new Mat_pleine(nbddlA,nbddlA);
Tableau <Mat_pleine* > raideurs_extN(2);raideurs_extN(1) = new Mat_pleine(dim,dim);
raideurs_extN(2) = raideurs_extN(1);
// definition de la classe static contenant toute les variables communes aux biellettes
doCo = new DonneeCommune(seg,tab_ddl,tab_ddlErr,tab_Err1FLUX,metri,resEr,raidEr,segEr,
residu_int,raideur_int,residus_extN,raideurs_extN,residus_extA,raideurs_extA
,matmasse,segMa,nombre_V.nbi);
};
// destructions de certaines grandeurs pointées, créées au niveau de l'initialisation
void BielletteThermi::Destruction()
{ // tout d'abord l'idée est de détruire certaines grandeurs pointées que pour le dernier élément
if ((unefois.nbelem_in_Prog == 0)&& (unefois.doCoMemb != NULL))
// cas de la destruction du dernier élément
{ BielletteThermi::DonneeCommune* doCo = unefois.doCoMemb; // pour simplifier l'écriture
int resErrTaille = doCo->resErr.Taille();
for (int i=1;i<= resErrTaille;i++)
delete doCo->resErr(i);
delete doCo->residus_externeN(1);
delete doCo->raideurs_externeN(1);
delete doCo->residus_externeA(1);
delete doCo->raideurs_externeA(1);
}
};