intégration des éléments de thermique (actuellement uniquement biel 1D)
This commit is contained in:
parent
11e3626b01
commit
f43e5da7ec
11 changed files with 9260 additions and 0 deletions
1672
Elements/Thermique/Biellette/BielletteThermi.cc
Executable file
1672
Elements/Thermique/Biellette/BielletteThermi.cc
Executable file
File diff suppressed because it is too large
Load diff
661
Elements/Thermique/Biellette/BielletteThermi.h
Executable file
661
Elements/Thermique/Biellette/BielletteThermi.h
Executable file
|
@ -0,0 +1,661 @@
|
|||
// 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/>.
|
||||
|
||||
/************************************************************************
|
||||
* DATE: 06/03/2023 *
|
||||
* $ *
|
||||
* AUTEUR: G RIO (mailto:gerardrio56@free.fr) *
|
||||
* $ *
|
||||
* PROJET: Herezh++ *
|
||||
* $ *
|
||||
************************************************************************
|
||||
* BUT: La classe BielletteThermi permet de declarer des elements *
|
||||
* biellettes et de realiser le calcul du residu local et de la raideur*
|
||||
* locale pour une loi de comportement donnee. La dimension de l'espace *
|
||||
* pour un tel element est 1. *
|
||||
* *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * *
|
||||
* VERIFICATION: *
|
||||
* *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* ! ! ! ! *
|
||||
* $ *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
|
||||
* MODIFICATIONS: *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* $ *
|
||||
************************************************************************/
|
||||
// -----------classe pour un calcul de mecanique---------
|
||||
|
||||
|
||||
|
||||
#ifndef BIELLETTETHERMI_H
|
||||
#define BIELLETTETHERMI_H
|
||||
|
||||
#include "ParaGlob.h"
|
||||
#include "ElemThermi.h"
|
||||
//#include "Loi_comp_abstraite.h"
|
||||
#include "Met_abstraite.h"
|
||||
#include "Met_biellette.h"
|
||||
#include "Noeud.h"
|
||||
#include "UtilLecture.h"
|
||||
#include "Tenseur.h"
|
||||
#include "NevezTenseur.h"
|
||||
#include "Deformation.h"
|
||||
#include "ElFrontiere.h"
|
||||
#include "GeomSeg.h"
|
||||
#include "ParaAlgoControle.h"
|
||||
#include "FrontSegLine.h"
|
||||
#include "Section.h"
|
||||
|
||||
class ConstrucElementbiel;
|
||||
|
||||
/// @addtogroup groupe_des_elements_finis
|
||||
/// @{
|
||||
///
|
||||
|
||||
|
||||
class BielletteThermi : public ElemThermi
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
// CONSTRUCTEURS :
|
||||
// Constructeur par defaut
|
||||
BielletteThermi ();
|
||||
|
||||
// Constructeur fonction d'une section et eventuellement d'un numero
|
||||
// d'identification et de maillage
|
||||
BielletteThermi (double sect,int num_maill=0,int num_id=-3);
|
||||
|
||||
// Constructeur fonction d'un numero de maillage et d'identification
|
||||
BielletteThermi (int num_maill,int num_id);
|
||||
|
||||
// Constructeur fonction d'une section, d'un numero de maillage et d'identification,
|
||||
// du tableau de connexite des noeuds
|
||||
BielletteThermi (double sect,int num_maill,int num_id,const Tableau<Noeud *>& tab);
|
||||
|
||||
// Constructeur de copie
|
||||
BielletteThermi (const BielletteThermi& biel);
|
||||
|
||||
|
||||
// DESTRUCTEUR :
|
||||
~BielletteThermi ();
|
||||
|
||||
// création d'un élément de copie: utilisation de l'opérateur new et du constructeur de copie
|
||||
// méthode virtuelle
|
||||
Element* Nevez_copie() const { Element * el= new BielletteThermi(*this); return el;};
|
||||
|
||||
// Surcharge de l'operateur = : realise l'egalite entre deux instances de BielletteThermi
|
||||
BielletteThermi& operator= (BielletteThermi& biel);
|
||||
|
||||
// METHODES :
|
||||
// 1) derivant des virtuelles pures
|
||||
// Lecture des donnees de la classe sur fichier
|
||||
void LectureDonneesParticulieres (UtilLecture *,Tableau<Noeud *> * );
|
||||
|
||||
// Calcul du residu local et de la raideur locale,
|
||||
// pour le schema implicite
|
||||
Element::ResRaid Calcul_implicit (const ParaAlgoControle & pa);
|
||||
|
||||
// Calcul du residu local a t
|
||||
// pour le schema explicit par exemple
|
||||
Vecteur* CalculResidu_t (const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::CalculResidu(false,pa);};
|
||||
|
||||
// Calcul du residu local a tdt
|
||||
// pour le schema explicit par exemple
|
||||
Vecteur* CalculResidu_tdt (const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::CalculResidu(true,pa);};
|
||||
|
||||
// Calcul de la matrice masse pour l'élément
|
||||
Mat_pleine * CalculMatriceMasse (Enum_calcul_masse id_calcul_masse) ;
|
||||
|
||||
// --------- calcul dynamique ---------
|
||||
// calcul de la longueur d'arrête de l'élément minimal
|
||||
// divisé par la célérité la plus rapide dans le matériau
|
||||
double Long_arrete_mini_sur_c(Enum_dure temps)
|
||||
{ return ElemThermi::Interne_Long_arrete_mini_sur_c(temps);};
|
||||
|
||||
//------- 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 ContrainteAuNoeud_ResRaid();
|
||||
// 2) remontée aux erreurs aux noeuds
|
||||
Element::Er_ResRaid ErreurAuNoeud_ResRaid();
|
||||
|
||||
// retourne les tableaux de ddl associés aux noeuds, gere par l'element
|
||||
// ce tableau et specifique a l'element
|
||||
const DdlElement & TableauDdl() const ;
|
||||
|
||||
|
||||
// Libere la place occupee par le residu et eventuellement la raideur
|
||||
// par l'appel de Libere de la classe mere et libere les differents tenseurs
|
||||
// intermediaires cree pour le calcul et les grandeurs pointee
|
||||
// de la raideur et du residu
|
||||
void Libere ();
|
||||
|
||||
// acquisition d'une loi de comportement
|
||||
void DefLoi (LoiAbstraiteGeneral * NouvelleLoi);
|
||||
|
||||
// test si l'element est complet
|
||||
// = 1 tout est ok, =0 element incomplet
|
||||
int TestComplet();
|
||||
|
||||
// procesure permettant de completer l'element apres
|
||||
// sa creation avec les donnees du bloc transmis
|
||||
// peut etre appeler plusieurs fois
|
||||
Element* Complete(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD);
|
||||
// Compléter pour la mise en place de la gestion de l'hourglass
|
||||
Element* Complet_Hourglass(LoiAbstraiteGeneral * NouvelleLoi, const BlocGen & bloc) {return this;};
|
||||
|
||||
// ramene l'element geometrique
|
||||
ElemGeomC0& ElementGeometrique() const { return doCo->segment;};
|
||||
// ramene l'element geometrique en constant
|
||||
const ElemGeomC0& ElementGeometrique_const() const { return doCo->segment;};
|
||||
|
||||
// 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 & Point_physique(const Coordonnee& c_int,Coordonnee & co,Enum_dure temps);
|
||||
// 3) cas où l'on veut les coordonnées aux 1, 2 ou trois temps selon la taille du tableau t_co
|
||||
void Point_physique(const Coordonnee& c_int,Tableau <Coordonnee> & t_co);
|
||||
|
||||
// -- connaissances particulières sur l'élément
|
||||
// ramène l'épaisseur de l'élément
|
||||
// =0. si la notion d'épaisseurs ne veut rien dire pour l'élément
|
||||
virtual double Section(Enum_dure enu , const Coordonnee& ) {return S(enu);};
|
||||
// ramène l'épaisseur moyenne de l'élément (indépendante du point)
|
||||
// =0. si la notion d'épaisseurs ne veut rien dire pour l'élément
|
||||
virtual double SectionMoyenne(Enum_dure enu ) {return S(enu);};
|
||||
|
||||
// affichage dans la sortie transmise, des variables duales "nom"
|
||||
// dans le cas ou nom est vide, affichage de "toute" les variables
|
||||
void AfficheVarDual(ofstream& sort, Tableau<string>& nom);
|
||||
|
||||
// affichage d'info en fonction de ordre
|
||||
// ordre = "commande" : affichage d'un exemple d'entree pour l'élément
|
||||
void Info_com_Element(UtilLecture * entreePrinc,string& ordre,Tableau<Noeud *> * tabMaillageNoeud)
|
||||
{ return Element::Info_com_El(2,entreePrinc,ordre,tabMaillageNoeud);};
|
||||
|
||||
// retourne un numero d'ordre d'un point le plus près ou est exprimé la grandeur enum
|
||||
// par exemple un point d'intégration, mais n'est utilisable qu'avec des méthodes particulières
|
||||
// par exemple CoordPtInteg, ou Valeur_a_diff_temps
|
||||
// car le numéro d'ordre peut-être différent du numéro d'intégration au sens classique
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
int PointLePlusPres(Enum_dure temps,Enum_ddl enu, const Coordonnee& M)
|
||||
{ return PtLePlusPres(temps,enu,M);};
|
||||
|
||||
// recuperation des coordonnées du point de numéro d'ordre iteg pour
|
||||
// la grandeur enu
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// si erreur retourne erreur à true
|
||||
Coordonnee CoordPtInteg(Enum_dure temps,Enum_ddl enu,int iteg,bool& erreur)
|
||||
{ return CoordPtInt(temps,enu,iteg,erreur);};
|
||||
|
||||
// récupération des valeurs au numéro d'ordre = iteg pour
|
||||
// les grandeur enu
|
||||
Tableau <double> Valeur_a_diff_temps(bool absolue,Enum_dure enu_t,const List_io<Ddl_enum_etendu>& enu,int iteg) ;
|
||||
|
||||
// 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 ValTensorielle_a_diff_temps(bool absolue,Enum_dure enu_t,List_io<TypeQuelconque>& enu,int iteg);
|
||||
|
||||
// ramene vrai si la surface numéro ns existe pour l'élément
|
||||
// dans le cas de la biellette il n'y a pas de surface
|
||||
bool SurfExiste(int ) const
|
||||
{ return false;};
|
||||
|
||||
// ramene vrai si l'arête numéro na existe pour l'élément
|
||||
bool AreteExiste(int na) const {if (na==1) return true; else return false;};
|
||||
|
||||
|
||||
//============= 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 Lecture_base_info
|
||||
(ifstream& ent,const Tableau<Noeud *> * tabMaillageNoeud,const int cas) ;
|
||||
// cas donne le niveau de sauvegarde
|
||||
// = 1 : on sauvegarde tout
|
||||
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
|
||||
void Ecriture_base_info(ofstream& sort,const int cas) ;
|
||||
|
||||
// METHODES VIRTUELLES:
|
||||
// --------- calculs utils dans le cadre de la recherche du flambement linéaire
|
||||
// Calcul de la matrice géométrique et initiale
|
||||
ElemThermi::MatGeomInit MatricesGeometrique_Et_Initiale (const ParaAlgoControle & pa) ;
|
||||
// retourne la liste des données particulières actuellement utilisés
|
||||
// par l'élément (actif ou non), sont exclu de cette liste les données particulières des noeuds
|
||||
// reliés à 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> Les_types_particuliers_internes(bool absolue) const;
|
||||
|
||||
// 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 Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ,int iteg);
|
||||
|
||||
// inactive les ddl du problème primaire de mécanique
|
||||
inline void Inactive_ddl_primaire()
|
||||
{ElemThermi::Inact_ddl_primaire(doCo->tab_ddl);};
|
||||
// active les ddl du problème primaire de mécanique
|
||||
inline void Active_ddl_primaire()
|
||||
{ElemThermi::Act_ddl_primaire(doCo->tab_ddl);};
|
||||
// --------- calcul d'erreur, calculs du champs de Flux continu ---------
|
||||
|
||||
// ajout des ddl de flux pour les noeuds de l'élément
|
||||
inline void Plus_ddl_Flux()
|
||||
{ElemThermi::Ad_ddl_Flux(doCo->tab_ddlErr);};
|
||||
// inactive les ddl du problème de recherche d'erreur : les flux
|
||||
inline void Inactive_ddl_Flux()
|
||||
{ElemThermi::Inact_ddl_Flux(doCo->tab_ddlErr);};
|
||||
// active les ddl du problème de recherche d'erreur : les flux
|
||||
inline void Active_ddl_Flux()
|
||||
{ElemThermi::Act_ddl_Flux(doCo->tab_ddlErr);};
|
||||
// active le premier ddl du problème de recherche d'erreur : SIGMA11
|
||||
inline void Active_premier_ddl_Flux()
|
||||
{ElemThermi::Act_premier_ddl_Flux();};
|
||||
|
||||
// lecture de données diverses sur le flot d'entrée
|
||||
void LectureFlux(UtilLecture * entreePrinc)
|
||||
{if (unefois.CalResPrem_t == 1)
|
||||
ElemThermi::LectureDesFlux (false,entreePrinc,lesPtThermiInt.TabfluxH_t());
|
||||
else
|
||||
{ ElemThermi::LectureDesFlux (true,entreePrinc,lesPtThermiInt.TabfluxH_t());
|
||||
unefois.CalResPrem_t = 1;
|
||||
};
|
||||
};
|
||||
|
||||
// retour des flux en absolu retour true si elle existe sinon false
|
||||
bool FluxAbsolues(Tableau <Vecteur>& tabFlux)
|
||||
{ if (unefois.CalResPrem_t == 1)
|
||||
ElemThermi::FluxEnAbsolues(false,lesPtThermiInt.TabfluxH_t(),tabFlux);
|
||||
else
|
||||
{ unefois.CalResPrem_t = 1;
|
||||
ElemThermi::FluxEnAbsolues(true,lesPtThermiInt.TabfluxH_t(),tabFlux);
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
// 2) derivant des virtuelles
|
||||
// retourne un tableau de ddl element, correspondant à la
|
||||
// composante de sigma -> SIG11, pour chaque noeud qui contiend
|
||||
// des ddl de contrainte
|
||||
// -> utilisé pour l'assemblage de la raideur d'erreur
|
||||
inline DdlElement& Tableau_de_Flux1() const
|
||||
{return doCo->tab_Err1FLUX;} ;
|
||||
|
||||
// actualisation des ddl et des grandeurs actives de t+dt vers t
|
||||
void TdtversT();
|
||||
// actualisation des ddl et des grandeurs actives de t vers tdt
|
||||
void TversTdt();
|
||||
|
||||
// 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 ErreurElement(int type,double& errElemRelative
|
||||
,double& numerateur, double& denominateur);
|
||||
|
||||
// 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 l'épaisseur de l'élément
|
||||
virtual const DeuxCoordonnees& Boite_encombre_element(Enum_dure temps);
|
||||
|
||||
// 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
|
||||
// -> explicite à t
|
||||
Vecteur SM_charge_volumique_E_t(const Coordonnee& force,const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::SM_charge_volumique_E(force,false,pa);} ;
|
||||
// -> explicite à tdt
|
||||
Vecteur SM_charge_volumique_E_tdt(const Coordonnee& force,const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::SM_charge_volumique_E(force,true,pa);} ;
|
||||
// -> 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
|
||||
ResRaid SMR_charge_volumique_I(const Coordonnee& force,const ParaAlgoControle & 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
|
||||
// retourne le second membre résultant
|
||||
// -> explicite à t
|
||||
Vecteur SM_charge_lineique_E_t(const Coordonnee& force,int numArete,const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::SM_charge_lineique_E(force,numArete,false,pa);} ;
|
||||
// -> explicite à tdt
|
||||
Vecteur SM_charge_lineique_E_tdt(const Coordonnee& force,int numArete,const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::SM_charge_lineique_E(force,numArete,true,pa);} ;
|
||||
// -> 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
|
||||
ResRaid SMR_charge_lineique_I(const Coordonnee& force,int numArete,const ParaAlgoControle & pa) ;
|
||||
|
||||
// cas d'un chargement lineique suiveuse, sur l'arrête 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
|
||||
Vecteur SM_charge_lineique_Suiv_E_t(const Coordonnee& force,int numArete,const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::SM_charge_lineique_Suiv_E(force,numArete,false,pa);} ;
|
||||
// -> explicite à tdt
|
||||
Vecteur SM_charge_lineique_Suiv_E_tdt(const Coordonnee& force,int numArete,const ParaAlgoControle & pa)
|
||||
{ return BielletteThermi::SM_charge_lineique_Suiv_E(force,numArete,true,pa);} ;
|
||||
// -> 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
|
||||
ResRaid SMR_charge_lineique_Suiv_I(const Coordonnee& force,int numArete,const ParaAlgoControle & 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
|
||||
Vecteur SM_charge_hydrodynamique_E_t( Courbe1D* frot_fluid,const double& poidvol
|
||||
, Courbe1D* coef_aero_n,int numFace,const double& coef_mul
|
||||
, Courbe1D* coef_aero_t,const ParaAlgoControle & pa)
|
||||
{return SM_charge_hydrodynamique_E(frot_fluid,poidvol,coef_aero_n,numFace,coef_mul,coef_aero_t,false,pa);};
|
||||
// -> explicite à tdt
|
||||
Vecteur SM_charge_hydrodynamique_E_tdt( Courbe1D* frot_fluid,const double& poidvol
|
||||
, Courbe1D* coef_aero_n,int numFace,const double& coef_mul
|
||||
, Courbe1D* coef_aero_t,const ParaAlgoControle & pa)
|
||||
{return SM_charge_hydrodynamique_E(frot_fluid,poidvol,coef_aero_n,numFace,coef_mul,coef_aero_t,true,pa);};
|
||||
// -> 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
|
||||
ResRaid SMR_charge_hydrodynamique_I( Courbe1D* frot_fluid,const double& poidvol
|
||||
, Courbe1D* coef_aero_n,int numFace,const double& coef_mul
|
||||
, Courbe1D* coef_aero_t,const ParaAlgoControle & pa) ;
|
||||
|
||||
|
||||
// ========= définition et/ou construction des frontières ===============
|
||||
|
||||
// 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 & Frontiere(bool force = false);
|
||||
|
||||
|
||||
|
||||
// Retourne la section de l'element
|
||||
inline double S(Enum_dure enu = TEMPS_tdt)
|
||||
{ switch (enu)
|
||||
{ case TEMPS_0: return donnee_specif.secti.section0; break;
|
||||
case TEMPS_t: return donnee_specif.secti.section_t; break;
|
||||
case TEMPS_tdt: return donnee_specif.secti.section_tdt; break;
|
||||
};
|
||||
return 0.; // cas n'arrivant normalement jamais
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ajout du tableau specific de ddl des noeuds de la biellette
|
||||
// la procedure met a jour les ddl(relatif a l'element, c-a-d Xi)
|
||||
// des noeuds constituants l'element
|
||||
void ConstTabDdl();
|
||||
protected:
|
||||
|
||||
// ==== >>>> methodes virtuelles dérivant d'ElemThermi ============
|
||||
// ramene la dimension des vecteurs flux et gradient de température de l'élément
|
||||
int Dim_flux_gradT() const {return 1;};
|
||||
|
||||
// -------------------- calcul de frontières en protected -------------------
|
||||
|
||||
// --- fonction nécessaire pour la construction des Frontières linéiques ou surfaciques particulière à l'élément
|
||||
// adressage des frontières linéiques et surfacique
|
||||
// définit dans les classes dérivées, et utilisées pour la construction des frontières
|
||||
virtual ElFrontiere* new_frontiere_lin(int ,Tableau <Noeud *> & tab, DdlElement& ddelem)
|
||||
{ return ((ElFrontiere*) (new FrontSegLine(tab,ddelem)));};
|
||||
virtual ElFrontiere* new_frontiere_surf(int ,Tableau <Noeud *> & tab, DdlElement& ddelem)
|
||||
{return NULL;} // il n'y a pas de surface possible
|
||||
|
||||
|
||||
private :
|
||||
|
||||
// VARIABLES PRIVEES :
|
||||
|
||||
|
||||
class DonneeCommune
|
||||
{ public :
|
||||
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
|
||||
) ;
|
||||
DonneeCommune(DonneeCommune& a);
|
||||
~DonneeCommune();
|
||||
// variables
|
||||
GeomSeg segment ; // element geometrique correspondant
|
||||
DdlElement tab_ddl; // tableau des degres
|
||||
//de liberte des noeuds de l'element commun a tous les
|
||||
// elements: ici de thermique
|
||||
Met_biellette met_biellette;
|
||||
Mat_pleine matGeom ; // matrice géométrique
|
||||
Mat_pleine matInit ; // matrice initile
|
||||
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
|
||||
// calcul d'erreur
|
||||
DdlElement tab_ddlErr; // tableau des degres servant pour le calcul
|
||||
// d'erreur : contraintes
|
||||
DdlElement tab_Err1FLUX; // tableau du ddl FLUX pour chaque noeud,
|
||||
//servant pour le calcul d'erreur : contraintes, en fait pour l'assemblage
|
||||
Tableau <Vecteur *> resErr; // residu pour le calcul d'erreur
|
||||
Mat_pleine raidErr; // raideur pour le calcul d'erreur
|
||||
GeomSeg segmentEr; // contiend les fonctions d'interpolation et
|
||||
// les derivees pour le calcul du hessien dans
|
||||
//la résolution de la fonctionnelle d'erreur
|
||||
// -------- calcul de résidus, de raideur : interne ou pour les efforts extérieurs ----------
|
||||
// on utilise des pointeurs pour optimiser la place (même place pointé éventuellement)
|
||||
Vecteur residu_interne;
|
||||
Mat_pleine raideur_interne;
|
||||
Tableau <Vecteur* > residus_externeN; // pour les noeuds
|
||||
Tableau <Mat_pleine* > raideurs_externeN; // pour les noeuds
|
||||
Tableau <Vecteur* > residus_externeA; // pour l' aretes
|
||||
Tableau <Mat_pleine* > raideurs_externeA; // pour l' aretes
|
||||
// ------ données concernant la dynamique --------
|
||||
Mat_pleine matrice_masse;
|
||||
GeomSeg segmentMas; // contiend les fonctions d'interpolation et les dérivées
|
||||
// pour les calculs relatifs au calcul de la masse
|
||||
};
|
||||
|
||||
|
||||
// classe contenant tous les indicateurs statique qui sont modifiés une seule fois
|
||||
// et un pointeur sur les données statiques communes
|
||||
// la classe est interne, toutes les variables sont publique. Un pointeur sur une instance de la
|
||||
// classe est défini. Son allocation est effectuée dans les classes dérivées
|
||||
class UneFois
|
||||
{ public :
|
||||
UneFois () ; // constructeur par défaut
|
||||
~UneFois () ; // destructeur
|
||||
|
||||
// VARIABLES :
|
||||
public :
|
||||
DonneeCommune * doCoMemb;
|
||||
|
||||
// incicateurs permettant de dimensionner seulement au premier passage
|
||||
// utilise dans "CalculResidu" et "Calcul_implicit"
|
||||
int CalResPrem_t; int CalResPrem_tdt; // à t ou à tdt
|
||||
int CalimpPrem;
|
||||
int dualSortbiel; // pour la sortie des valeurs au pt d'integ
|
||||
int CalSMlin_t; // pour les seconds membres concernant les arretes
|
||||
int CalSMlin_tdt; // pour les seconds membres concernant les arretes
|
||||
int CalSMRlin; // pour les seconds membres concernant les arretes
|
||||
int CalSMvol_t; // pour les seconds membres concernant les volumes
|
||||
int CalSMvol_tdt; // pour les seconds membres concernant les volumes
|
||||
int CalSMvol; // pour les seconds membres concernant les volumes
|
||||
int CalDynamique; // pour le calcul de la matrice de masse
|
||||
int CalPt_0_t_tdt; // pour le calcul de point à 0 t et tdt
|
||||
// ---------- sauvegarde du nombre d'élément en cours --------
|
||||
int nbelem_in_Prog;
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
protected :
|
||||
// VARIABLES PROTÉGÉES :
|
||||
// les données spécifiques sont grouppées dans une structure pour sécuriser
|
||||
// le passage de paramètre dans init par exemple
|
||||
class Donnee_specif
|
||||
{ public :
|
||||
Donnee_specif() : // défaut
|
||||
secti(Element::section_defaut,Element::section_defaut,Element::section_defaut)
|
||||
,variation_section(true)
|
||||
{};
|
||||
Donnee_specif(double section) : // uniquement la section
|
||||
secti(section,section,section),variation_section(true)
|
||||
{};
|
||||
Donnee_specif(double epai0,double epai_t,double epai_tdt,bool variation) : // tous
|
||||
secti(epai0,epai_t,epai_tdt),variation_section(variation)
|
||||
{};
|
||||
Donnee_specif(const Donnee_specif& a) :
|
||||
secti(a.secti ),variation_section(a.variation_section)
|
||||
{}; // recopie via le constructeur de copie
|
||||
~Donnee_specif() {};
|
||||
Donnee_specif & operator = ( const Donnee_specif& a)
|
||||
{ secti = a.secti;variation_section=a.variation_section;
|
||||
return *this;};
|
||||
// data
|
||||
// sections de l'element
|
||||
Sect secti; // épaisseur
|
||||
bool variation_section; // permet éventuellement de ne pas prendre en compte la variation
|
||||
};
|
||||
Donnee_specif donnee_specif;
|
||||
|
||||
// grandeurs aux points d'intégration: contraintes, déformations, vitesses de def etc.
|
||||
LesPtIntegThermiInterne lesPtThermiInt;
|
||||
|
||||
// place memoire commune a tous les elements biellettes
|
||||
static DonneeCommune * doCo;
|
||||
// idem mais pour les indicateurs qui servent pour l'initialisation
|
||||
static UneFois unefois;
|
||||
|
||||
// type structuré pour construire les éléments
|
||||
class NombresConstruire
|
||||
{ public:
|
||||
NombresConstruire();
|
||||
int nbne; // le nombre de noeud de l'élément
|
||||
int nbneA ; // le nombre de noeud des aretes
|
||||
int nbi; // le nombre de point d'intégration pour le calcul mécanique
|
||||
int nbiEr; // le nombre de point d'intégration pour le calcul d'erreur
|
||||
int nbiA; // le nombre de point d'intégration pour le calcul de second membre linéique
|
||||
int nbiMas; // le nombre de point d'intégration pour le calcul de la matrice masse consistante
|
||||
};
|
||||
static NombresConstruire nombre_V; // les nombres propres à l'élément
|
||||
|
||||
// fonction privee
|
||||
// fonction d'initialisation servant au niveau du constructeur
|
||||
BielletteThermi::DonneeCommune * Init(Donnee_specif donnee_specif = Donnee_specif()
|
||||
,bool sans_init_noeud = false);
|
||||
void Def_DonneeCommune();
|
||||
// destructions de certaines grandeurs pointées, créées au niveau de l'initialisation
|
||||
void Destruction();
|
||||
|
||||
// pour l'ajout d'element dans la liste : listTypeElemen, geree par la class Element
|
||||
class ConstrucElementbiel : public ConstrucElement
|
||||
{ public : ConstrucElementbiel ()
|
||||
{ NouvelleTypeElement nouv(POUT,BIE1,THERMIQUE,this);
|
||||
if (ParaGlob::NiveauImpression() >= 4)
|
||||
cout << "\n initialisation BielletteThermi" << endl;
|
||||
Element::listTypeElement.push_back(nouv);
|
||||
};
|
||||
Element * NouvelElement(int nb_mail,int num) // un nouvel élément sans rien
|
||||
{Element * pt;
|
||||
pt = new BielletteThermi (nb_mail,num) ;
|
||||
return pt;};
|
||||
// ramene true si la construction de l'element est possible en fonction
|
||||
// des variables globales actuelles: ex en fonction de la dimension
|
||||
bool Element_possible() {return true;};
|
||||
};
|
||||
static ConstrucElementbiel construcElementbiel;
|
||||
|
||||
// Calcul du residu local a t ou tdt en fonction du booleen
|
||||
Vecteur* CalculResidu (bool atdt,const ParaAlgoControle & 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
|
||||
// -> explicite à t ou tdt en fonction de la variable booleenne atdt
|
||||
Vecteur SM_charge_volumique_E
|
||||
(const Coordonnee& force,bool atdt,const ParaAlgoControle & 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
|
||||
// retourne le second membre résultant
|
||||
// -> explicite à t ou tdt en fonction de la variable booleenne atdt
|
||||
Vecteur SM_charge_lineique_E
|
||||
(const Coordonnee& force,int numArete,bool atdt,const ParaAlgoControle & pa);
|
||||
// cas d'un chargement lineique suiveuse, sur l'arete 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
|
||||
Vecteur SM_charge_lineique_Suiv_E
|
||||
(const Coordonnee& force,int numArete,bool atdt,const ParaAlgoControle & pa);
|
||||
// cas d'un chargement surfacique hydro-dynamique,
|
||||
// voir méthode explicite plus haut, pour les arguments
|
||||
// retourne le second membre résultant
|
||||
// bool atdt : permet de spécifier à t ou a t+dt
|
||||
Vecteur SM_charge_hydrodynamique_E( Courbe1D* frot_fluid,const double& poidvol
|
||||
, Courbe1D* coef_aero_n,int numFace,const double& coef_mul
|
||||
, Courbe1D* coef_aero_t,bool atdt,const ParaAlgoControle & pa) ;
|
||||
// calcul de la nouvelle section moyenne finale (sans raideur)
|
||||
// mise à jour des volumes aux pti
|
||||
// ramène la section moyenne calculée à atdt
|
||||
const double& CalSectionMoyenne_et_vol_pti(const bool atdt);
|
||||
|
||||
};
|
||||
/// @} // end of group
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
1899
Elements/Thermique/ElemThermi.cc
Executable file
1899
Elements/Thermique/ElemThermi.cc
Executable file
File diff suppressed because it is too large
Load diff
893
Elements/Thermique/ElemThermi.h
Executable file
893
Elements/Thermique/ElemThermi.h
Executable file
|
@ -0,0 +1,893 @@
|
|||
// 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/>.
|
||||
|
||||
/************************************************************************
|
||||
* DATE: 06/03/2023 *
|
||||
* $ *
|
||||
* AUTEUR: G RIO (mailto:gerardrio56@free.fr) *
|
||||
* $ *
|
||||
* PROJET: Herezh++ *
|
||||
* $ *
|
||||
************************************************************************
|
||||
* BUT: Defini l'element generique de thermique. *
|
||||
* $ *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * *
|
||||
* VERIFICATION: *
|
||||
* *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* ! ! ! ! *
|
||||
* $ *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
|
||||
* MODIFICATIONS: *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* $ *
|
||||
************************************************************************/
|
||||
#ifndef ELEMTHERMI_H
|
||||
#define ELEMTHERMI_H
|
||||
|
||||
#include "Element.h"
|
||||
#include "Tenseur.h"
|
||||
#include "NevezTenseur.h"
|
||||
#include "Deformation.h"
|
||||
#include "Loi_comp_abstraite.h"
|
||||
#include "Enum_calcul_masse.h"
|
||||
#include "Basiques.h"
|
||||
#include "Enum_dure.h"
|
||||
#include "CompThermoPhysiqueAbstraite.h"
|
||||
#include "CompFrotAbstraite.h"
|
||||
#include "LesPtIntegThermiInterne.h"
|
||||
#include "Enum_StabHourglass.h"
|
||||
#include "EnergieThermi.h"
|
||||
|
||||
|
||||
/// @addtogroup groupe_des_elements_finis
|
||||
/// @{
|
||||
///
|
||||
|
||||
class ElemThermi : public Element
|
||||
{
|
||||
public :
|
||||
// VARIABLES PUBLIQUES :
|
||||
|
||||
// CONSTRUCTEURS :
|
||||
ElemThermi ();
|
||||
// Constructeur utile quand le numero de maillage et d'identification de l'element est connu
|
||||
ElemThermi (int num_maill,int num_id) ;
|
||||
// Constructeur utile quand le numero de maillage et d'identification et le tableau des noeuds
|
||||
// de l'element sont connu
|
||||
ElemThermi (int num_maill,int num_id,const Tableau<Noeud *>& tab);
|
||||
// Constructeur utile quand le numero de maillage et d'identification est connu,
|
||||
// ainsi que la geometrie et le type d'interpolation de l'element
|
||||
ElemThermi (int num_maill,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,string info="");
|
||||
// Constructeur utile quand le numero de maillage et d'identification est connu,
|
||||
// ainsi que la geometrie et le type d'interpolation de l'element
|
||||
ElemThermi (int num_maill,int num_id,char* nom_interpol,char* nom_geom,string info="");
|
||||
// Constructeur utile quand toutes les donnees de la classe Element sont connues
|
||||
ElemThermi (int num_maill,int num_id,const Tableau<Noeud *>& tab,Enum_interpol id_interp_elt,
|
||||
Enum_geom id_geom_elt,string info="");
|
||||
// Constructeur utile quand toutes les donnees de la classe Element sont connues
|
||||
ElemThermi (int num_maill,int num_id,const Tableau<Noeud *>& tab,char* nom_interpol,
|
||||
char* nom_geom,string info="");
|
||||
// Constructeur de copie
|
||||
ElemThermi (const ElemThermi& elt);
|
||||
|
||||
// DESTRUCTEUR :
|
||||
~ElemThermi ();
|
||||
|
||||
// METHODES PUBLIQUES :
|
||||
// test si l'element est complet
|
||||
// = 1 tout est ok, =0 element incomplet
|
||||
int TestComplet();
|
||||
|
||||
// calcul si un point est a l'interieur de l'element ou non
|
||||
// il faut que M est la dimension globale
|
||||
// les trois fonctions sont pour l'etude a t=0, t et tdt
|
||||
// retour : =0 le point est externe, =1 le point est interne ,
|
||||
// = 2 le point est sur la frontière à la précision près
|
||||
// coor_locales : s'il est différent de NULL, est affecté des coordonnées locales calculées,
|
||||
// uniquement précises si le point est interne
|
||||
int Interne_0(const Coordonnee& M,Coordonnee* coor_locales=NULL);
|
||||
int Interne_t(const Coordonnee& M,Coordonnee* coor_locales=NULL);
|
||||
int Interne_tdt(const Coordonnee& M,Coordonnee* coor_locales=NULL);
|
||||
|
||||
// récupération des énergies intégrées sur l'éléments, résultants d'un précédent calcul
|
||||
// explicite, ou implicite
|
||||
const EnergieThermi& EnergieTotaleElement() const {return energie_totale;};
|
||||
|
||||
// test pour savoir si le calcul de Flux en absolu est possible
|
||||
bool FluxAbsoluePossible();
|
||||
|
||||
// METHODES VIRTUELLES:
|
||||
|
||||
// retourne la liste de tous les types de ddl interne actuellement utilisés
|
||||
// par l'élément (actif ou non), sont exclu de cette liste les ddl des noeuds
|
||||
// reliés à l'élément (ddl implique grandeur uniquement scalaire !)
|
||||
virtual List_io <Ddl_enum_etendu> Les_type_de_ddl_internes(bool absolue) const ;
|
||||
// idem pour les grandeurs évoluées c'est-à-dire directement sous forme de vecteur, tenseurs ....
|
||||
virtual List_io <TypeQuelconque> Les_type_evolues_internes(bool absolue) const ;
|
||||
// idem pour les données particulières
|
||||
virtual List_io <TypeQuelconque> Les_types_particuliers_internes(bool absolue) const;
|
||||
|
||||
// retourne la liste de toutes les grandeurs quelconques relatives aux faces de
|
||||
// l'élément (actif ou non),
|
||||
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
||||
virtual List_io <TypeQuelconque> Les_type_quelconque_de_face(bool absolue) const ;
|
||||
|
||||
// retourne la liste de toutes les grandeurs quelconques relatives aux arêtes de
|
||||
// l'élément (actif ou non),
|
||||
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
||||
virtual List_io <TypeQuelconque> Les_type_quelconque_de_arete(bool absolue) const;
|
||||
|
||||
// --------- calculs utils dans le cadre de la recherche du flambement linéaire
|
||||
// dans un premier temps uniquement virtuelles, ensuite se sera virtuelle pure pour éviter
|
||||
// les oubli de définition ----> AMODIFIER !!!!!!!!
|
||||
// Calcul de la matrice géométrique et initiale
|
||||
class MatGeomInit // pour le retour des pointeurs sur des matrices stockées
|
||||
// une paire par classe d'éléments
|
||||
{ public : MatGeomInit(Mat_pleine * matG,Mat_pleine * matI) :
|
||||
matGeom(matG),matInit(matI) {};
|
||||
Mat_pleine * matGeom ;Mat_pleine * matInit ;
|
||||
};
|
||||
virtual MatGeomInit MatricesGeometrique_Et_Initiale (const ParaAlgoControle & pa) ;
|
||||
|
||||
// --------- calcul d'erreur, calculs du champs de Flux continu ---------
|
||||
// ajout des ddl de Flux pour les noeuds de l'élément
|
||||
virtual void Plus_ddl_Flux() = 0;
|
||||
// inactive les ddl du problème de recherche d'erreur : les Flux
|
||||
virtual void Inactive_ddl_Flux() = 0;
|
||||
// active les ddl du problème de recherche d'erreur : les Flux
|
||||
virtual void Active_ddl_Flux() = 0 ;
|
||||
// active le premier ddl du problème de recherche d'erreur : FLUX
|
||||
virtual void Active_premier_ddl_Flux() = 0 ;
|
||||
// retourne un tableau de ddl element, correspondant à la
|
||||
// composante de flux -> FLUX, pour chaque noeud qui contiend
|
||||
// des ddl de flux
|
||||
// -> utilisé pour l'assemblage de la raideur d'erreur
|
||||
//!!!!!!!!!!!!! pour l'instant en virtuelle il faudra après en
|
||||
// virtuelle pure !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
virtual DdlElement& Tableau_de_Flux1() const ;
|
||||
// retourne un tableau de ddl element, correspondant à la
|
||||
// composante d'erreur -> ERREUR, pour chaque noeud
|
||||
// -> utilisé pour l'assemblage de la raideur d'erreur
|
||||
//dans cette version tous les noeuds sont supposés avoi un ddl erreur
|
||||
// dans le cas contraire il faut redéfinir la fonction dans l'élément terminal
|
||||
virtual DdlElement Tableau_de_ERREUR() const ;
|
||||
// calcul de l'erreur sur l'élément. Ce calcul n'est disponible
|
||||
// qu'une fois la remontée aux Flux effectuées sinon aucune
|
||||
// action. En retour la valeur de l'erreur sur l'élément
|
||||
// type indique le type de calcul d'erreur :
|
||||
// = 1 : erreur = (int (delta sigma):(delta sigma) dv)/(int sigma:sigma dv)
|
||||
// le numerateur et le denominateur sont tel que :
|
||||
// errElemRelative = numerateur / denominateur , si denominateur different de 0
|
||||
// sinon denominateur = numerateur si numerateur est different de 0, sinon
|
||||
// tous sont nuls mais on n'effectue pas la division
|
||||
//!!!!!!!!!!!!! pour l'instant en virtuelle il faudra après en
|
||||
// virtuelle pure !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
virtual void ErreurElement(int type,double& errElemRelative
|
||||
,double& numerateur, double& denominateur);
|
||||
// les 3 routines qui suivent sont virtuelles, car la définition
|
||||
//qui est faite dans ElemThermi.cp considère qu'il y a un ddl erreur
|
||||
// par noeud de l'élément de manière systématique,
|
||||
// avec le status virtuel on peut définir dans la classe dérivée
|
||||
// un cas particulier
|
||||
// ajout des ddl d'erreur pour les noeuds de l'élément
|
||||
virtual void Plus_ddl_Erreur() ;
|
||||
// inactive les ddl d'erreur
|
||||
virtual void Inactive_ddl_Erreur() ;
|
||||
// active les ddl d'erreur
|
||||
virtual void Active_ddl_Erreur() ;
|
||||
// test pour savoir si l'erreur a été calculée
|
||||
bool ErreurDejaCalculee()
|
||||
{ if (fluxErreur == NULL)
|
||||
return false;
|
||||
else return true;};
|
||||
// sortie de l'erreur à l'élément
|
||||
double Erreur( )
|
||||
{ return (*fluxErreur);};
|
||||
|
||||
// lecture de données diverses sur le flot d'entrée
|
||||
// l'implantation est faite dans les classe dérivées
|
||||
virtual void LectureFlux(UtilLecture * entreePrinc) =0 ;
|
||||
|
||||
// retour des Flux en absolu retour true si elle existe sinon false
|
||||
virtual bool FluxAbsolues(Tableau <Vecteur>& tabFlux) = 0;
|
||||
|
||||
// --------- calcul dynamique ---------
|
||||
|
||||
// calcul de la longueur d'arrête de l'élément minimal
|
||||
// divisé par la célérité dans le matériau
|
||||
virtual double Long_arrete_mini_sur_c(Enum_dure temps) = 0;
|
||||
// cas du bulk viscosity
|
||||
double E_elem_bulk_t,E_elem_bulk_tdt,P_elem_bulk;
|
||||
static void ActiveBulkViscosity(int choix) {bulk_viscosity=choix;};
|
||||
static void InactiveBulkViscosity() {bulk_viscosity=false;};
|
||||
static void ChangeCoefsBulkViscosity(const DeuxDoubles & coef)
|
||||
{ c_traceBulk=coef.un;c_carreBulk=coef.deux;};
|
||||
|
||||
// initialisation pour le calcul de la matrice masse dans le cas de l'algorithme
|
||||
// de relaxation dynamique avec optimisation en continu de la matrice masse
|
||||
// casMass_relax: permet de choisir entre différentes méthodes de calcul de la masse
|
||||
void InitCalculMatriceMassePourRelaxationDynamique(int casMass_relax);
|
||||
// phase de calcul de la matrice masse dans le cas de l'algo de relaxation dynamique
|
||||
// mi=fonction de (alpha*K+beta*mu+gamma*Isig/3+theta/2*Sig_mises
|
||||
// ep: epaisseur, K module de compressibilite, mu: module de cisaillement, Isig trace de sigma,
|
||||
// Sig_mises la contrainte de mises
|
||||
// casMass_relax: permet de choisir entre différentes méthodes de calcul de la masse
|
||||
void CalculMatriceMassePourRelaxationDynamique
|
||||
(const double& alph, const double& beta, const double & lambda
|
||||
,const double & gamma,const double & theta, int casMass_relax);
|
||||
|
||||
// ---------- informations annexes ----------------
|
||||
|
||||
// récupération de la base locales au noeud noe, pour le temps: temps
|
||||
const BaseB & Gib_elemeca(Enum_dure temps, const Noeud * noe);
|
||||
|
||||
// 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 Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ,int iteg);
|
||||
|
||||
// récupération de grandeurs particulières pour une face 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 Grandeur_particuliere_face (bool absolue,List_io<TypeQuelconque>& liTQ,int face, int iteg);
|
||||
|
||||
// récupération de grandeurs particulières pour une arête 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 Grandeur_particuliere_arete (bool absolue,List_io<TypeQuelconque>& liTQ,int arete, int iteg);
|
||||
|
||||
|
||||
// récupération de la loi de frottement, dans le cas où elle n'existe pas
|
||||
// retour d'un pointeur nul
|
||||
CompFrotAbstraite* LoiDeFrottement() const {return loiFrot;};
|
||||
|
||||
// --- transfert des grandeurs des points d'intégration aux noeuds
|
||||
// transfert de ddl des points d'intégrations (de tous) d'un éléments (on ajoute aux noeuds, on ne remplace pas)
|
||||
// les ddl doivent déjà exister aux noeuds sinon erreur
|
||||
// il doit s'agir du même type de répartition de pt d'integ pour toutes les grandeurs
|
||||
// tab_val(i)(j) : valeur associée au i ième pt d'integ et au j ième ddl_enum_etendu
|
||||
void TransfertAjoutAuNoeuds(const List_io < Ddl_enum_etendu >& lietendu
|
||||
,const Tableau <Tableau <double> > & tab_val,int cas);
|
||||
// transfert de type quelconque des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds,
|
||||
// on ne remplace pas). Les types quelconques doivent déjà exister
|
||||
// un tableau dans tab_liQ correspondent aux grandeurs quelconque pour tous les pt integ,
|
||||
// tab_liQ(i) pour le pt d'integ i
|
||||
// liQ_travail: est une liste de travail qui sera utilisée dans le transfert
|
||||
void TransfertAjoutAuNoeuds(const Tableau <List_io < TypeQuelconque > >& tab_liQ
|
||||
,List_io < TypeQuelconque > & liQ_travail,int cas);
|
||||
|
||||
// accumulation aux noeuds de grandeurs venant de l'éléments vers ses noeuds (exemple la pression appliquée)
|
||||
// autres que celles aux pti classiques, mais directements disponibles
|
||||
// le contenu du conteneur stockées dans liQ est utilisé en variable intermédiaire
|
||||
void Accumul_aux_noeuds(const List_io < Ddl_enum_etendu >& lietendu
|
||||
,List_io < TypeQuelconque > & liQ,int cas);
|
||||
|
||||
|
||||
// modification de l'orientation de l'élément en fonction de cas_orientation
|
||||
// =0: inversion simple (sans condition) de l'orientation
|
||||
// si cas_orientation est diff de 0: on calcul le jacobien aux différents points d'intégration
|
||||
// 1. si tous les jacobiens sont négatifs on change d'orientation
|
||||
// 2. si tous les jacobiens sont positifs on ne fait rien
|
||||
// 3. si certains jacobiens sont positifs et d'autres négatifs message
|
||||
// d'erreur et on ne fait rien
|
||||
// ramène true: s'il y a eu changement effectif, sinon false
|
||||
bool Modif_orient_elem(int cas_orientation);
|
||||
|
||||
// calcul éventuel de la normale à un noeud
|
||||
// ce calcul existe pour les éléments 2D, 1D axi, et aussi pour les éléments 1D
|
||||
// qui possède un repère d'orientation
|
||||
// en retour coor = la normale si coor.Dimension() est = à la dimension de l'espace
|
||||
// si le calcul n'existe pas --> coor.Dimension() = 0
|
||||
// ramène un entier :
|
||||
// == 1 : calcul normal
|
||||
// == 0 : problème de calcul -> coor.Dimension() = 0
|
||||
// == 2 : indique que le calcul n'est pas licite pour le noeud passé en paramètre
|
||||
// c'est le cas par exemple des noeuds exterieurs pour les éléments SFE
|
||||
// mais il n'y a pas d'erreur, c'est seulement que l'élément n'est pas ad hoc pour
|
||||
// calculer la normale à ce noeud là
|
||||
// temps: indique à quel moment on veut le calcul
|
||||
virtual int CalculNormale_noeud(Enum_dure temps, const Noeud& noe,Coordonnee& coor);
|
||||
|
||||
// calcul si un point est a l'interieur de l'element ou non
|
||||
// il faut que M est la dimension globale
|
||||
// retour : =0 le point est externe, =1 le point est interne ,
|
||||
// = 2 le point est sur la frontière à la précision près
|
||||
// coor_locales : s'il est différent de NULL, est affecté des coordonnées locales calculées,
|
||||
// uniquement précises si le point est interne
|
||||
int Interne(Enum_dure temps,const Coordonnee& M,Coordonnee* coor_locales=NULL);
|
||||
// -- connaissances particulières sur l'élément
|
||||
// ramène l'épaisseur de l'élément
|
||||
// =0. si la notion d'épaisseurs ne veut rien dire pour l'élément
|
||||
virtual double Epaisseurs(Enum_dure , const Coordonnee& ) {return 0.;};
|
||||
// ramène l'épaisseur moyenne de l'élément (indépendante du point)
|
||||
// =0. si la notion d'épaisseurs ne veut rien dire pour l'élément
|
||||
virtual double EpaisseurMoyenne(Enum_dure ) {return 0.;};
|
||||
// ramène la section de l'élément
|
||||
// =0. si la notion de section ne veut rien dire pour l'élément
|
||||
virtual double Section(Enum_dure , const Coordonnee& ) {return 0.;};
|
||||
// ramène la section moyenne de l'élément (indépendante du point)
|
||||
// =0. si la notion de section ne veut rien dire pour l'élément
|
||||
virtual double SectionMoyenne(Enum_dure ) {return 0.;};
|
||||
|
||||
// fonction a renseigner par les classes dérivées, concernant les répercutions
|
||||
// éventuelles due à la suppression de tous les frontières
|
||||
// nums_i : donnent les listes de frontières supprimées
|
||||
virtual void Prise_en_compte_des_consequences_suppression_tous_frontieres();
|
||||
// idem pour une frontière (avant qu'elle soit supprimée)
|
||||
virtual void Prise_en_compte_des_consequences_suppression_une_frontiere(ElFrontiere* elemFront);
|
||||
|
||||
// -------------------- calcul de frontières -------------------
|
||||
|
||||
|
||||
// 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)
|
||||
virtual ElFrontiere* const Frontiere_points(int num,bool force);
|
||||
|
||||
// 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)
|
||||
virtual ElFrontiere* const Frontiere_lineique(int num,bool force);
|
||||
|
||||
// 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)
|
||||
virtual ElFrontiere* const Frontiere_surfacique(int num,bool force);
|
||||
|
||||
// -------------------- init éventuelle avant le chargement -------------------
|
||||
// initialisation éventuelle, nécessaire avant d'appliquer l'ensemble des charges
|
||||
// par exemple des stockages intermédiaires
|
||||
virtual void Initialisation_avant_chargement() {};
|
||||
|
||||
//=====================================================================================
|
||||
protected :
|
||||
//=====================================================================================
|
||||
// METHODES PROTEGEES utilisables par les classes derivees :
|
||||
|
||||
// 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
|
||||
// cas :
|
||||
// = 0 -> on veut toutes les frontières
|
||||
// = 1 -> on veut uniquement les surfaces
|
||||
// = 2 -> on veut uniquement les lignes
|
||||
// = 3 -> on veut uniquement les points
|
||||
// = 4 -> on veut les surfaces + les lignes
|
||||
// = 5 -> on veut les surfaces + les points
|
||||
// = 6 -> on veut les lignes + les points
|
||||
Tableau <ElFrontiere*> const & Frontiere_elethermi(int cas, bool force = false);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// cas où l'on intègre que selon une liste (un axe, un plan, un volume)
|
||||
// ---------------------------------------------------------------------
|
||||
// Calcul du residu local et de la raideur locale,
|
||||
// pour le schema implicite d'ou a l'instant t + dt
|
||||
// ddl represente les degres de liberte specifiques a l'element
|
||||
// tabDepsBB = vitesse de déformation, tabDeltaEpsBB = incrément de def entre t et t+dt
|
||||
// cald_Dvirtuelle = indique si l'on doit calculer la dérivée de la vitesse de déformation virtuelle
|
||||
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);
|
||||
|
||||
// Calcul du residu local a l'instant t ou tdt
|
||||
// atdt = true : calcul à tdt, valeur par défaut
|
||||
// = false: calcul à t
|
||||
// ddl represente les degres de liberte specifiques a l'element
|
||||
// nbint = nb de pt d'integration , poids = poids d'integration
|
||||
void Cal_explicit (DdlElement & ddl,Tableau <CoordonneeB >& d_gradTB,int nbint
|
||||
,const Vecteur& poids,const ParaAlgoControle & pa,bool atdt=true);
|
||||
|
||||
// Calcul de la matrice géométrique et de la matrice initiale
|
||||
// cette fonction est éventuellement appelée par les classes dérivées
|
||||
// ddl represente les degres de liberte specifiques a l'element
|
||||
// nbint = nb de pt d'integration , poids = poids d'integration
|
||||
// cald_Dvirtuelle = indique si l'on doit calculer la dérivée de la vitesse de déformation virtuelle
|
||||
void Cal_matGeom_Init (Mat_pleine & matGeom, Mat_pleine & matInit
|
||||
,DdlElement & ddl,Tableau <CoordonneeB >& d_gradTB,Tableau < Tableau2 <CoordonneeB> * > d2_gradTB
|
||||
,Tableau <CoordonneeH>& d_fluxH,int nbint,const Vecteur& poids
|
||||
,const ParaAlgoControle & pa,bool cald_Dvirtuelle);
|
||||
|
||||
// Calcul de la matrice masse selon différent choix donné par type_matrice_masse,
|
||||
// a l'instant initial.
|
||||
void Cal_Mat_masse (DdlElement & tab_ddl,Enum_calcul_masse type_matrice_masse,
|
||||
int nbint,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// cas où l'on intègre selon deux listes (ex un axe et un plan, etc.)
|
||||
// ---------------------------------------------------------------------
|
||||
// Calcul du residu local et de la raideur locale,
|
||||
// pour le schema implicite d'ou a l'instant t + dt
|
||||
// ddl represente les degres de liberte specifiques a l'element
|
||||
void Cal_implicitap (DdlElement & tab_ddl,Tableau <TenseurBB *> & d_epsBB
|
||||
,Tableau < Tableau2 <CoordonneeB> * > d2_gradTB,Tableau <CoordonneeH>& d_fluxH
|
||||
,int nbint1,Vecteur& poids1,int nbint2,const Vecteur& poids2
|
||||
,const ParaAlgoControle & pa);
|
||||
|
||||
// Calcul du residu local a l'instant t ou tdt
|
||||
// atdt = true : calcul à tdt, valeur par défaut
|
||||
// = false: calcul à t
|
||||
// ddl represente les degres de liberte specifiques a l'element
|
||||
// d_epsbb = variation des def
|
||||
// nbint = nb de pt d'integration , poids = poids d'integration
|
||||
void Cal_explicitap (DdlElement & ddl,Tableau <TenseurBB *>& d_epsBB
|
||||
,int nbint,const Vecteur& poids,bool atdt=true);
|
||||
|
||||
// Calcul de la matrice géométrique et de la matrice initiale
|
||||
// cette fonction est éventuellement appelée par les classes dérivées
|
||||
// ddl represente les degres de liberte specifiques a l'element
|
||||
// d_epsbb = variation des def
|
||||
// nbint = nb de pt d'integration , poids = poids d'integration
|
||||
void Cal_matGeom_Initap (Mat_pleine & matGeom, Mat_pleine & matInit
|
||||
,DdlElement & ddl,Tableau <TenseurBB *>& d_epsBB,Tableau < Tableau2 <CoordonneeB> * > d2_gradTB
|
||||
,Tableau <CoordonneeH>& d_fluxH,int nbint,const Vecteur& poids);
|
||||
|
||||
// -------------------------- calcul de second membre ---------------------------
|
||||
// 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
|
||||
// retourne le second membre résultant
|
||||
// nSurf : le numéro de la surface externe
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
Vecteur& SM_charge_surf_E (DdlElement & ddls,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa,bool atdt=true);
|
||||
// idem SM_charge_surf_E mais -> implicite,
|
||||
// pa : permet de déterminer si l'on fait ou non le calcul de la contribution à la raideur
|
||||
// retourne le second membre et la matrice de raideur correspondant
|
||||
Element::ResRaid SMR_charge_surf_I (DdlElement & ddls,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa);
|
||||
// calcul des seconds membres suivant les chargements
|
||||
// cas d'un chargement pression, sur les frontières des éléments
|
||||
// pression indique la pression appliquée
|
||||
// retourne le second membre résultant
|
||||
// nSurf : le numéro de la surface externe
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
Vecteur& SM_charge_pres_E (DdlElement & ddls,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,double pression
|
||||
,const ParaAlgoControle & pa,bool atdt=true);
|
||||
// idem SM_charge_pres_E mais -> 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 SMR_charge_pres_I (DdlElement & ddls,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,double pression
|
||||
,const ParaAlgoControle & pa);
|
||||
// cas d'un chargement lineique, sur les arêtes frontières des éléments
|
||||
// force indique la force lineique appliquée
|
||||
// retourne le second membre résultant
|
||||
// nArete : le numéro de l'arête externe
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
Vecteur& SM_charge_line_E (DdlElement & ddls,int nArete
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa,bool atdt=true);
|
||||
// idem SM_charge_line_E mais -> 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 SMR_charge_line_I (DdlElement & ddlA,int nArete
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa);
|
||||
|
||||
// cas d'un chargement lineique suiveur, sur les arêtes frontières des éléments
|
||||
// pas valable pour des éléments 3D !
|
||||
// force indique la force lineique appliquée
|
||||
// retourne le second membre résultant
|
||||
// nArete : le numéro de l'arête externe
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
Vecteur& SM_charge_line_Suiv_E (DdlElement & ddls,int nArete
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa,bool atdt=true);
|
||||
// idem SM_charge_line_E mais -> 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 SMR_charge_line_Suiv_I (DdlElement & ddlA,int nArete
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa);
|
||||
|
||||
|
||||
// cas d'un chargement surfacique suiveur, sur les surfaces de l'élément
|
||||
// la direction varie selon le système suivant: on définit les coordonnées matérielles
|
||||
// de la direction, ce qui sert ensuite à calculer les nouvelles directions. L'intensité
|
||||
// elle est constante.
|
||||
// force indique la force surfacique appliquée
|
||||
// retourne le second membre résultant
|
||||
// nSurf : le numéro de la surface externe
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
Vecteur& SM_charge_surf_Suiv_E (DdlElement & ddls,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa,bool atdt=true);
|
||||
// idem SM_charge_surf_Suiv_E mais -> 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 SMR_charge_surf_Suiv_I (DdlElement & ddlA,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa);
|
||||
|
||||
// cas d'un chargement volumique, sur l'élément
|
||||
// force indique la force volumique appliquée
|
||||
// retourne le second membre résultant
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
Vecteur& SM_charge_vol_E (DdlElement & ddls
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa,bool atdt=true);
|
||||
|
||||
// idem SM_charge_vol_E mais -> 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
|
||||
void SMR_charge_vol_I (DdlElement & ddls
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids,const Coordonnee& force
|
||||
,const ParaAlgoControle & pa);
|
||||
|
||||
// cas d'un chargement hydrostatique, sur les surfaces de l'élément
|
||||
// la charge dépend de la hauteur à la surface libre du liquide déterminée par un point
|
||||
// et une direction normale à la surface libre:
|
||||
// nSurf : le numéro de la surface externe
|
||||
// poidvol: indique le poids volumique du liquide
|
||||
// M_liquide : un point de la surface libre
|
||||
// dir_normal_liquide : direction normale à la surface libre
|
||||
// retourne le second membre résultant
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
Vecteur& SM_charge_hydro_E (DdlElement & ddls,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids
|
||||
,const Coordonnee& dir_normal_liquide,const double& poidvol
|
||||
,const Coordonnee& M_liquide
|
||||
,const ParaAlgoControle & pa,bool atdt=true);
|
||||
// idem SM_charge_hydro_E mais -> 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 SMR_charge_hydro_I (DdlElement & ddlA,int nSurf
|
||||
,const Tableau <Vecteur>& taphi,int nbne
|
||||
,const Vecteur& poids
|
||||
,const Coordonnee& dir_normal_liquide,const double& poidvol
|
||||
,const Coordonnee& M_liquide
|
||||
,const ParaAlgoControle & pa);
|
||||
|
||||
// cas d'un chargement aero-hydrodynamique, sur les frontières de l'élément
|
||||
// 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
|
||||
// retourne le second membre résultant
|
||||
// calcul à l'instant tdt ou t en fonction de la variable atdt
|
||||
// coef_mul: est un coefficient multiplicateur global (de tout)
|
||||
Vecteur& SM_charge_hydrodyn_E (const double& poidvol,const Tableau <Vecteur>& taphi,int nbne
|
||||
,Courbe1D* frot_fluid,const Vecteur& poids
|
||||
,Courbe1D* coef_aero_n,int numfront,const double& coef_mul
|
||||
,Courbe1D* coef_aero_t,const ParaAlgoControle & ,bool atdt=true);
|
||||
// idem SM_charge_hydrodyn_E mais -> 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 SM_charge_hydrodyn_I (const double& poidvol,const Tableau <Vecteur>& taphi,int nbne
|
||||
,Courbe1D* frot_fluid,const Vecteur& poids,DdlElement & ddls
|
||||
,Courbe1D* coef_aero_n,int numfront,const double& coef_mul
|
||||
,Courbe1D* coef_aero_t,const ParaAlgoControle & pa);
|
||||
|
||||
// -------------------- calcul de frontières en protected -------------------
|
||||
|
||||
// --- fonction nécessaire pour la construction des Frontières linéiques ou surfaciques particulière à l'élément
|
||||
// adressage des frontières linéiques et surfacique
|
||||
// définit dans les classes dérivées, et utilisées pour la construction des frontières
|
||||
virtual ElFrontiere* new_frontiere_lin(int num,Tableau <Noeud *> & tab, DdlElement& ddelem) = 0;
|
||||
virtual ElFrontiere* new_frontiere_surf(int num,Tableau <Noeud *> & tab, DdlElement& ddelem) = 0;
|
||||
|
||||
// -------------------- stabilisation d'hourglass -------------------
|
||||
// calcul d'élément de contrôle d'hourglass associée à un comportement
|
||||
void Init_hourglass_comp(const ElemGeomC0& elgeHour, const string & str_precision
|
||||
,LoiAbstraiteGeneral * loiHourglass,const BlocGen & bloc);
|
||||
|
||||
// stabilisation pour un calcul implicit
|
||||
void Cal_implicit_hourglass();
|
||||
|
||||
// stabilisation pour un calcul explicit
|
||||
void Cal_explicit_hourglass(bool atdt);
|
||||
|
||||
public :
|
||||
// récupération de l'energie d'hourglass éventuelle
|
||||
double Energie_Hourglass();
|
||||
// idem pour l'énergie et la puissance de bulk viscosity
|
||||
double Energie_Bulk() const {return E_elem_bulk_tdt;};
|
||||
double Puissance_Bulk() const {return P_elem_bulk;};
|
||||
protected :
|
||||
// -------------------- calcul d'erreur, remontée des Flux -------------------
|
||||
|
||||
// calcul du résidu et de la matrice de raideur pour le calcul d'erreur
|
||||
// cas d'une intégration suivant une seule liste
|
||||
void FluxAuNoeud_ResRaid(const int nbne,const Tableau <Vecteur>& taphi
|
||||
,const Vecteur& poids,Tableau <Vecteur *>& resErr,Mat_pleine& raidErr
|
||||
,const Tableau <Vecteur>& taphiEr,const Vecteur& poidsEr );
|
||||
|
||||
// calcul de l'erreur sur l'élément. Ce calcul n'est disponible
|
||||
// qu'une fois la remontée aux Flux effectuées sinon aucune
|
||||
// action. pour les autres arguments de retour, idem ErreurElement
|
||||
// qui est la fonction generique, les autres variables sont spécifiques
|
||||
// a l'element.
|
||||
void Cal_ErrElem(int type,double& errElemRelative
|
||||
,double& numerateur, double& denominateur,const int nbne,const Tableau <Vecteur>& taphi
|
||||
,const Vecteur& poids,const Tableau <Vecteur>& taphiEr,const Vecteur& poidsEr);
|
||||
|
||||
// calcul de l'erreur aux noeuds. Contrairement au cas des Flux
|
||||
// seul le résidu est calculé. Cas d'une intégration suivant une liste
|
||||
void Cal_ErrAuxNoeuds(const int nbne, const Tableau <Vecteur>& taphi,
|
||||
const Vecteur& poids,Tableau <Vecteur *>& resErr );
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// affichage dans la sortie transmise, des variables duales "nom"
|
||||
// aux differents points d'integration
|
||||
// dans le cas ou nom est vide, affichage de "toute" les variables
|
||||
// cas =1 -> premier passage pour de l'implicit
|
||||
// cas = 2 -> premier passage pour de l'explicit
|
||||
// cas = 11 -> passage autre que le premier pour de l'implicit
|
||||
// cas = 12 -> passage autre que le premier pour de l'explicit
|
||||
void VarDualSort(ofstream& sort, Tableau<string>& nom,int nbint,int cas);
|
||||
// utilitaires de VarDualSort
|
||||
// affiche en fonction d'indic les differentes variables et appel
|
||||
// AffDefContiD en fonction de la dimension i
|
||||
//
|
||||
void AffDefCont( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_dGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic);
|
||||
// cas 1D
|
||||
void AffDefCont1D( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_dGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic);
|
||||
// cas 2D
|
||||
void AffDefCont2D( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_dGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic);
|
||||
// cas 3D
|
||||
void AffDefCont3D( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_dGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic);
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// --- méthodes relatives aux calculs d'erreurs -----------
|
||||
// ---- utilisées par les classes dérivées ---------
|
||||
// ajout des ddl relatif aux Flux pour les noeuds de l'élément
|
||||
void Ad_ddl_Flux(const DdlElement& tab_ddlErr);
|
||||
// inactive les ddl du problème primaire de mécanique
|
||||
void Inact_ddl_primaire(DdlElement& tab_ddl);
|
||||
// active les ddl du problème primaire de mécanique
|
||||
void Act_ddl_primaire(DdlElement& tab_ddl);
|
||||
// inactive les ddl du problème de recherche d'erreur : les Flux
|
||||
void Inact_ddl_Flux(DdlElement& tab_ddlErr);
|
||||
// active les ddl du problème de recherche d'erreur : les Flux
|
||||
void Act_ddl_Flux(DdlElement& tab_ddlErr);
|
||||
// active le premier ddl du problème de recherche d'erreur : FLUX
|
||||
void Act_premier_ddl_Flux();
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// lecture des Flux sur le flot d'entrée
|
||||
void LectureDesFlux
|
||||
(bool cas,UtilLecture * entreePrinc,Tableau <CoordonneeH *>& tabfluxH);
|
||||
|
||||
// retour des Flux en absolu retour true si ils existent sinon false
|
||||
void FluxEnAbsolues
|
||||
(bool cas,Tableau <CoordonneeH *>& tabfluxH,Tableau <Vecteur>& tabflux);
|
||||
|
||||
|
||||
// ---------------- lecture écriture dans base info ----------------
|
||||
// programmes utilisés par les classes dérivées
|
||||
|
||||
// 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 Lecture_bas_inf
|
||||
(ifstream& ent,const Tableau<Noeud *> * tabMaillageNoeud,const int cas) ;
|
||||
// cas donne le niveau de sauvegarde
|
||||
// = 1 : on sauvegarde tout
|
||||
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
|
||||
void Ecriture_bas_inf(ofstream& sort,const int cas) ;
|
||||
|
||||
// --------- utilitaires pour la dynamique
|
||||
// calcul de la longueur d'arrête de l'élément minimal
|
||||
// divisé par la célérité la plus rapide dans le matériau
|
||||
// appelé par les classes dérivées
|
||||
// nb_noeud : =0 indique que l'on utilise tous les noeuds du tableau de noeuds
|
||||
// = un nombre > 0, indique le nombre de noeuds à utiliser au début du tableau
|
||||
double Interne_Long_arrete_mini_sur_c(Enum_dure temps,int nb_noeud=0);
|
||||
|
||||
// recuperation des coordonnées du point d'intégration numéro = iteg pour
|
||||
// la grandeur enu
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// si erreur retourne erreur à true
|
||||
Coordonnee CoordPtInt(Enum_dure temps,Enum_ddl enu,int iteg,bool& erreur);
|
||||
|
||||
// recuperation des coordonnées du point d'intégration numéro = iteg pour
|
||||
// la face : face
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// si erreur retourne erreur à true
|
||||
Coordonnee CoordPtIntFace(int face, Enum_dure temps,int iteg,bool& erreur);
|
||||
// recuperation des coordonnées du point d'intégration numéro = iteg pour
|
||||
// la face : face
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// si erreur retourne erreur à true
|
||||
Coordonnee CoordPtIntArete(int arete, Enum_dure temps,int iteg,bool& erreur);
|
||||
|
||||
|
||||
// procesure permettant de completer l'element, en ce qui concerne les variables gérés
|
||||
// par ElemThermi, apres sa creation avec les donnees du bloc transmis
|
||||
// peut etre appeler plusieurs fois
|
||||
Element* Complete_ElemThermi(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD);
|
||||
|
||||
// retourne le numero du pt d'ing le plus près ou est exprimé la grandeur enum
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
int PtLePlusPres(Enum_dure temps,Enum_ddl enu, const Coordonnee& M);
|
||||
|
||||
// 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> Valeur_multi(bool absolue,Enum_dure enu_t,const List_io<Ddl_enum_etendu>& enu
|
||||
,int iteg,int cas ) ;
|
||||
|
||||
// récupération des valeurs Tensorielles (et non scalaire comme avec Valeur_multi)
|
||||
// au numéro d'ordre = iteg pour les grandeur enu
|
||||
// enu contiend les grandeurs de retour
|
||||
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
||||
void Valeurs_Tensorielles(bool absolue,Enum_dure enu_t,List_io<TypeQuelconque>& enu
|
||||
,int iteg,int cas ) ;
|
||||
|
||||
// ==== >>>> methodes virtuelles definis dans les classes mères ============
|
||||
// ramene l'element geometrique correspondant au ddl passé en paramètre
|
||||
virtual ElemGeomC0& ElementGeometrie(Enum_ddl ddl) const ;
|
||||
// ramène le nombre de grandeurs génératrices pour un pt d'integ, correspondant à un type enuméré
|
||||
// peut-être surchargé pour des éléments particuliers
|
||||
virtual int NbGrandeurGene(Enum_ddl enu) const;
|
||||
|
||||
// ==== >>>> methodes virtuelles definis dans les classes dérivées ============
|
||||
// ramene la dimension des vecteurs flux et gradient de température de l'élément
|
||||
virtual int Dim_flux_gradT() const = 0;
|
||||
|
||||
// VARIABLES PROTEGEES :
|
||||
|
||||
//---- variables: Flux, déformations etc.. aux points d'intégrations -------
|
||||
// lesPtIntegThermiInterne pointe vers une entitée entièrement gérés par les classes dérivées
|
||||
// contenant les grandeurs mécaniques (Flux, déformations etc.) stockées aux points d'intégration
|
||||
LesPtIntegThermiInterne * lesPtIntegThermiInterne;
|
||||
|
||||
Loi_comp_abstraite * loiComp; // loi de comportement mécanique defini dans les classes derivees
|
||||
CompThermoPhysiqueAbstraite * loiTP; // éventuellement une loi de comportement thermo physique
|
||||
// defini dans les classes derivees
|
||||
CompFrotAbstraite * loiFrot; // éventuellement une loi de comportement au frottement pour ses frontières
|
||||
|
||||
bool dilatation; // indique si oui ou non on tiend compte de la dilatation thermique
|
||||
Met_abstraite * met; // definition specifique dans les classes derivees
|
||||
Deformation * def; // definition specifique dans les classes derivees
|
||||
// mais relative à la déformation mécanique
|
||||
Deformation * defEr; // idem que def mais pour la remonte aux Flux
|
||||
Tableau <Deformation *> defSurf; // idem mais pour les déformations des surfaces
|
||||
// externes (frontières) si cela est nécessaire
|
||||
Tableau <Deformation *> defArete; // idem mais pour les déformations des arretes
|
||||
// externes (frontières) si cela est nécessaire
|
||||
Deformation * defMas; // idem que def mais pour le calcul de la matrice masse
|
||||
double* fluxErreur; // erreur sur l'élément dans le calcul des densités de flux;
|
||||
Tableau <Loi_comp_abstraite::SaveResul *> tabSaveDon; // donnée particulière à la loi mécanique
|
||||
Tableau <CompThermoPhysiqueAbstraite::SaveResul *> tabSaveTP; // donnée parti à la loi thermo physique
|
||||
Tableau <Deformation::SaveDefResul *> tabSaveDefDon; // donnée particulière pour la déf
|
||||
Tableau <EnergieThermi > tab_energ,tab_energ_t; //les différentes énergies mécaniques mises en jeux
|
||||
// dimensionné dans les classes dérivées, a t+dt, et a t
|
||||
EnergieThermi energie_totale; // le bilan sur l'élément de l'énergie
|
||||
bool premier_calcul_thermi_impli_expli; // au premier calcul soit en implicite, explicite, mat geom
|
||||
// toutes les grandeurs à t=0 de la métrique sont calculées et stockées dans la déformation
|
||||
// ensuite elles ne sont plus calculées -> premier_calcul_thermi_impli_expli sert pour l'indiquer
|
||||
double masse_volumique; // masse volumique de l'élément
|
||||
//--- stabilisation d'hourglass éventuelle
|
||||
Enum_StabHourglass type_stabHourglass; // méthode de stabilisation
|
||||
double E_Hourglass;
|
||||
|
||||
private:
|
||||
Tableau <ElemThermi*> tab_elHourglass; // tableau de pointeurs éventuels sur des éléments servant à la stabilisation
|
||||
// les éléments sont définies au travers de l'appel à la méthode Cal_hourglass_comp, par une classe dérivée,
|
||||
double coefStabHourglass ; // coef de stabilisation
|
||||
Mat_pleine* raid_hourglass_transitoire; // raideur transitoire d'hourglass, éventuellement définie
|
||||
|
||||
// -------- pour faciliter les routines Interne_t _0 et _tdt + paramètres de contrôle ----
|
||||
static const Coordonnee & (Met_abstraite::*PointM)
|
||||
(const Tableau<Noeud *>& tab_noeud,const Vecteur& phi);
|
||||
static void (Met_abstraite::*BaseND)
|
||||
(const Tableau<Noeud *>& tab_noeud,
|
||||
const Mat_pleine& dphi,const Vecteur& phi,BaseB& bB,BaseH& bH);
|
||||
// ---------- cas du bulk viscosity -------------
|
||||
private: // pour éviter les modifications par les classes dérivées
|
||||
static int bulk_viscosity; // indique si oui ou non on utilise le bulk viscosity
|
||||
// en plus = 1: fonctionnement normal, =2 fonctionnement quelque soit
|
||||
// le signe de IDeps
|
||||
static double c_traceBulk; // coeff de la trace de D pour le bulk
|
||||
static double c_carreBulk; // coeff du carré de la trace de D pour le bulk
|
||||
static TenseurHH * sig_bulkHH; // variable de travail pour le bulk
|
||||
// ---------- pour le calcul de la masse pour la méthode de relaxation dynamique
|
||||
static Ddl_enum_etendu masse_relax_dyn; // simplement pour le définir une fois pour toute
|
||||
|
||||
protected:
|
||||
// pour une utilisation par les classes dérivées
|
||||
inline bool Bulk_visco_actif() {return bulk_viscosity;};
|
||||
inline double& C_traceBulk() {return c_traceBulk;};
|
||||
inline double& C_carreBulk() {return c_carreBulk;};
|
||||
// // calcul du Flux modifiée en fonction du bulk viscosity
|
||||
// // ramène l'énergie et la puissance par unité de volume, dépensée par le bulk
|
||||
// DeuxDoubles ModifContrainteBulk(const TenseurHH& gijHH_tdt,TenseurHH & sigHH,const TenseurBB & DepsBB_tdt
|
||||
// ,TenseurHH & sigbulkHH);
|
||||
// actualisation des ddl et des grandeurs actives de t+dt vers t
|
||||
void TdtversT_();
|
||||
// actualisation des ddl et des grandeurs actives de t vers tdt
|
||||
void TversTdt_();
|
||||
|
||||
// ---- utilitaires interne
|
||||
private:
|
||||
// calcul du mini du module d'young équivalent pour tous les points d'intégrations
|
||||
double Calcul_mini_E_qui(Enum_dure temps);
|
||||
// calcul du maxi du module d'young équivalent pour tous les points d'intégrations
|
||||
double Calcul_maxi_E_qui(Enum_dure temps);
|
||||
};
|
||||
/// @} // end of group
|
||||
|
||||
|
||||
|
||||
#endif
|
957
Elements/Thermique/ElemThermi2.cc
Executable file
957
Elements/Thermique/ElemThermi2.cc
Executable file
|
@ -0,0 +1,957 @@
|
|||
// 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 "ElemThermi.h"
|
||||
#include <iomanip>
|
||||
#include "ConstMath.h"
|
||||
#include "Util.h"
|
||||
#include "Coordonnee2.h"
|
||||
#include "Coordonnee3.h"
|
||||
#include "CharUtil.h"
|
||||
|
||||
|
||||
// actualisation des ddl et des grandeurs actives de t+dt vers t
|
||||
// appelé par les classes dérivées
|
||||
void ElemThermi::TdtversT_()
|
||||
{// on met à jour l'indicateur de premier calcul
|
||||
// s'il y a des sauvegardes de grandeur aux déformations
|
||||
// on ne regarde que le premier élément de tableau, a priori
|
||||
// il y a toujours un pt d'integ et l'organisation est identique pour tous les pt d'integ
|
||||
if (tabSaveDefDon(1) != NULL)
|
||||
premier_calcul_thermi_impli_expli=false;
|
||||
// cas des énergies
|
||||
int nbi= tab_energ.Taille();
|
||||
for (int ni=1;ni<= nbi; ni++)
|
||||
tab_energ_t(ni) = tab_energ(ni);
|
||||
E_elem_bulk_t = E_elem_bulk_tdt; // énergie due au bulk viscosity
|
||||
};
|
||||
// actualisation des ddl et des grandeurs actives de t vers tdt
|
||||
// appelé par les classes dérivées
|
||||
void ElemThermi::TversTdt_()
|
||||
{// on met à jour l'indicateur de premier calcul
|
||||
// on considère que si l'on revient en arrière, il vaut mieux re-initialiser les
|
||||
// grandeurs correspondantes au premier_calcul
|
||||
// s'il y a des sauvegardes de grandeur aux déformations
|
||||
if (tabSaveDefDon(1) != NULL)
|
||||
premier_calcul_thermi_impli_expli=true;
|
||||
// cas des énergies
|
||||
int nbi= tab_energ.Taille();
|
||||
for (int ni=1;ni<= nbi; ni++)
|
||||
tab_energ(ni) = tab_energ_t(ni);
|
||||
E_elem_bulk_tdt = E_elem_bulk_t; // énergie due au bulk viscosity
|
||||
};
|
||||
|
||||
// calcul du résidu et de la matrice de raideur pour le calcul d'erreur
|
||||
// cas d'une intégration suivant une seule liste
|
||||
void ElemThermi::FluxAuNoeud_ResRaid(const int nbne,const Tableau <Vecteur>& taphi
|
||||
,const Vecteur& poids,Tableau <Vecteur *>& resErr,Mat_pleine& raidErr
|
||||
,const Tableau <Vecteur>& taphiEr,const Vecteur& poidsEr)
|
||||
{ int dimAbsolue = ParaGlob::Dimension(); // dimension absolue
|
||||
// // dimension des tenseurs
|
||||
// int dim = lesPtIntegThermiInterne->DimTens();
|
||||
// // inialisation du second membre et de la raideur
|
||||
// int nbSM = resErr.Taille(); // nombre de second membre
|
||||
// for (int j =1; j<= nbSM; j++) // boucle sur les seconds membres
|
||||
// (*resErr(j)).Zero();
|
||||
// raidErr.Zero();
|
||||
// // Il faut déterminer l'ordre dans lequel on parcours les contraintes qui doit
|
||||
// // être compatible avec l'ordre des ddl
|
||||
// Tableau2 <int> ordre = OrdreContrainte(nbSM);
|
||||
// // création d'un tenseur au dimension absolu pour le calcul des contraintes
|
||||
// // dans la base absolue
|
||||
// TenseurHH& sigHH = *(NevezTenseurHH(dimAbsolue)) ;
|
||||
// // ====== calcul du second membre =======
|
||||
// int ni; // compteur globale de point d'integration
|
||||
// bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
|
||||
// // donc il faut calculer tous les éléments de la métrique
|
||||
// for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
|
||||
// {PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(ni);
|
||||
// // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
|
||||
// // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
|
||||
// const Met_abstraite::Expli& ex = def->Cal_explicit_t(premier_calcul);
|
||||
// // passage dans le repère absolu du tenseur contrainte final
|
||||
// sigHH = (*(ptIntegThermi.SigHH_t())).BaseAbsolue(sigHH,*ex.giB_t);
|
||||
// for (int ne =1; ne<= nbne; ne++) // 1ere boucle sur les noeuds
|
||||
// { // les résidus : mais il faut suivre l'ordre de l'enregistrement des ddl
|
||||
// for (int itot = 1; itot<= nbSM; itot++)
|
||||
// { int ix = (int) (ordre(itot,1)); int iy = (int) (ordre(itot,2));
|
||||
// (*resErr(itot))(ne) += taphi(ni)(ne)*sigHH(ix,iy) * (poids(ni) * (*ex.jacobien_t));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // ====== calcul de la raideur c'est à dire du hessien ========
|
||||
// // boucle sur les pt d'integ spécifiques à l'erreur
|
||||
// for (defEr->PremierPtInteg(), ni = 1;defEr->DernierPtInteg();defEr->NevezPtInteg(),ni++)
|
||||
// {
|
||||
// // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
|
||||
// // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
|
||||
// const Met_abstraite::Expli& ex = defEr->Cal_explicit_t(premier_calcul);
|
||||
// for (int ne =1; ne<= nbne; ne++) // 1ere boucle sur les noeuds
|
||||
// for (int me =1; me<= nbne; me++) // 2ere boucle sur les noeuds
|
||||
// raidErr(ne,me) += taphiEr(ni)(ne) * taphiEr(ni)(me) * poidsEr(ni) * (*ex.jacobien_t);
|
||||
// }
|
||||
// // liberation des tenseurs intermediaires
|
||||
// TenseurHH * ptsigHH = &sigHH; delete ptsigHH;
|
||||
// LibereTenseur();
|
||||
// // calcul de l'erreur relative
|
||||
|
||||
};
|
||||
|
||||
// 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
|
||||
// = 1 : erreur = (int (delta sigma):(delta sigma) dv)/(int sigma:sigma dv)
|
||||
// le numerateur et le denominateur sont tel que :
|
||||
// errElemRelative = numerateur / denominateur , si denominateur different de 0
|
||||
// sinon denominateur = numerateur si numerateur est different de 0, sinon
|
||||
// tous sont nuls mais on n'effectue pas la division , les autres variables sont spécifiques
|
||||
// a l'element.
|
||||
void ElemThermi::Cal_ErrElem(int type,double& errElemRelative,double& numerateur
|
||||
, double& denominateur,const int nbne,const Tableau <Vecteur>& taphi
|
||||
,const Vecteur& poids,const Tableau <Vecteur>& taphiEr,const Vecteur& poidsEr)
|
||||
{ int dimAbsolue = ParaGlob::Dimension(); // dimension absolue
|
||||
// // dimension des tenseurs
|
||||
// int dim = lesPtIntegThermiInterne->DimTens();
|
||||
// bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
|
||||
// // donc il faut calculer tous les éléments de la métrique
|
||||
// switch (type)
|
||||
// {case 1 : // cas du calcul aux moindres carrés
|
||||
//
|
||||
// {// création d'un tenseur au dimension absolu pour le calcul des contraintes
|
||||
// // dans la base absolue, on le choisit HB pour le double produit contracté
|
||||
// // mais en absolu la variance n'a pas d'importance
|
||||
// TenseurHB& sigHB = *(NevezTenseurHB(dimAbsolue)) ;
|
||||
// // idem au point d'intégration et un tenseur nul pour l'initialisation
|
||||
// TenseurHB& signiHB = *(NevezTenseurHB(dimAbsolue)) ;
|
||||
// TenseurHB& sigiHB = *(NevezTenseurHB(dimAbsolue)) ; // tenseur de travail
|
||||
// TenseurHB& nulHB = *(NevezTenseurHB(dimAbsolue)) ;
|
||||
// // ====== calcul des termes de l'erreur =======
|
||||
// // ---- tout d'abord on parcourt les points d'intégration de la mécanique
|
||||
// numerateur = 0.; denominateur = 0.; // initialisation
|
||||
// int ni; // compteur globale de point d'integration
|
||||
// for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
|
||||
// {PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(ni);
|
||||
// // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
|
||||
// // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
|
||||
// const Met_abstraite::Expli& ex = def->Cal_explicit_t(premier_calcul);
|
||||
// // passage dans le repère absolu du tenseur contrainte initiale
|
||||
// sigHB = (*(ptIntegThermi.SigHH_t())).BaseAbsolue(sigHB,*ex.giB_t);
|
||||
// // calcul du denominateur
|
||||
// denominateur += (sigHB && sigHB) * (poids(ni) * (*ex.jacobien_t));
|
||||
// // calcul de la premiere partie du numerateur, celle qui dépend des points d'intégration
|
||||
// // mécanique.
|
||||
// // 1) calcul au point d'intégration du tenseur des contraintes défini aux noeuds,
|
||||
// signiHB = nulHB; // initialisation
|
||||
// for (int ne =1; ne<= nbne; ne++) // boucle sur les noeuds
|
||||
// signiHB += taphi(ni)(ne) * ((tab_noeud(ne))->Contrainte(sigiHB));
|
||||
// // 2) intégrale de la partie dépendant de ni
|
||||
// numerateur += denominateur - 2 * (signiHB && sigHB) * (poids(ni) * (*ex.jacobien_t)) ;
|
||||
// }
|
||||
// // ---- on parcourt maintenant les points d'intégration pour le calcul d'erreur
|
||||
// // ---- ce qui permet de calculer la deuxième partie du numérateur
|
||||
// // boucle sur les pt d'integ spécifiques à l'erreur
|
||||
// for (defEr->PremierPtInteg(), ni = 1;defEr->DernierPtInteg();defEr->NevezPtInteg(),ni++)
|
||||
// {
|
||||
// // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
|
||||
// // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
|
||||
// const Met_abstraite::Expli& ex = defEr->Cal_explicit_t(premier_calcul);
|
||||
// // 1) calcul au point d'intégration du tenseur des contraintes défini aux noeuds,
|
||||
// signiHB = nulHB; // initialisation
|
||||
// for (int ne =1; ne<= nbne; ne++) // boucle sur les noeuds
|
||||
// signiHB += taphiEr(ni)(ne)*(tab_noeud(ne))->Contrainte(sigiHB);
|
||||
// // 2) intégrale de la partie dépendant de ni
|
||||
// numerateur += (signiHB && signiHB) * poidsEr(ni) * (*ex.jacobien_t);
|
||||
// }
|
||||
// // liberation des tenseurs intermediaires
|
||||
// TenseurHB * ptsigHB = &sigHB; delete ptsigHB;
|
||||
// ptsigHB = &signiHB; delete ptsigHB;ptsigHB = &sigiHB; delete ptsigHB;
|
||||
// ptsigHB = &nulHB; delete ptsigHB;
|
||||
// LibereTenseur();
|
||||
// // enregistrement de l'erreur pour l'élément
|
||||
// if (sigErreur == NULL) sigErreur = new double;
|
||||
// *sigErreur = numerateur;
|
||||
// break;
|
||||
// }
|
||||
// default :
|
||||
// { cout << "\nErreur : valeur incorrecte du type de calcul d'erreur !\n";
|
||||
// cout << "ElemThermi::ErreurElement(int type , type = \n" << type;
|
||||
// Sortie(1);
|
||||
// }
|
||||
// };
|
||||
// // --- calcul de l'erreur relative
|
||||
// if (denominateur <= ConstMath::trespetit)
|
||||
// // cas d'un champ de contraintes nulles initialement
|
||||
// if (numerateur <= ConstMath::trespetit)
|
||||
// // cas également du numérateur nul
|
||||
// errElemRelative = 0.;
|
||||
// else
|
||||
// // on fait denominateur = numérateur -> erreur relative = 1
|
||||
// errElemRelative = 1.;
|
||||
// else
|
||||
// // cas du dénominateur non nul
|
||||
// errElemRelative = numerateur / denominateur;
|
||||
};
|
||||
|
||||
|
||||
// calcul de l'erreur aux noeuds. Contrairement au cas des contraintes
|
||||
// seul le résidu est calculé. Cas d'une intégration suivant une liste
|
||||
void ElemThermi::Cal_ErrAuxNoeuds(const int nbne, const Tableau <Vecteur>& taphi,
|
||||
const Vecteur& poids,Tableau <Vecteur *>& resErr )
|
||||
{ int dimAbsolue = ParaGlob::Dimension(); // dimension absolue
|
||||
// // inialisation du second membre, on utilise le premier vecteur uniquement
|
||||
// (*resErr(1)).Zero();
|
||||
// // ====== calcul du second membre =======
|
||||
// int ni; // compteur globale de point d'integration
|
||||
// double volume = 0.; // le volume de l'élément
|
||||
// bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
|
||||
// // donc il faut calculer tous les éléments de la métrique
|
||||
// for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
|
||||
// {
|
||||
// // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
|
||||
// // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
|
||||
// const Met_abstraite::Expli& ex = def->Cal_explicit_t(premier_calcul);
|
||||
// for (int ne =1; ne<= nbne; ne++) // 1ere boucle sur les noeuds
|
||||
// (*resErr(1))(ne) += taphi(ni)(ne)*(*sigErreur) * (poids(ni) * (*ex.jacobien_t));
|
||||
// // calcul du volume
|
||||
// volume += (poids(ni) * (*ex.jacobien_t));
|
||||
// }
|
||||
// // on relativise par rapport au volume, car initialement sigErreur représente l'erreur
|
||||
// // totale sur tout l'élément. Donc on divise par le volume pour retrouver après résolution
|
||||
// // une valeur au noeud qui représente une valeur ponctuelle et non une valeur qui
|
||||
// // qui est relative à un volume
|
||||
// *resErr(1) /= volume;
|
||||
//// *resErr(1) = -sigErreur;
|
||||
// LibereTenseur();
|
||||
// // calcul de l'erreur relative
|
||||
|
||||
};
|
||||
|
||||
|
||||
// ajout des ddl relatif aux contraintes pour les noeuds de l'élément
|
||||
void ElemThermi::Ad_ddl_Flux(const DdlElement& tab_ddlErr)
|
||||
{ int nbne = tab_noeud.Taille();
|
||||
// for (int ne=1; ne<= nbne; ne++) // pour chaque noeud
|
||||
// { // création du tableau de ddl
|
||||
// int tab_ddlErr_Taille = tab_ddlErr(ne).tb.Taille(); // nb de ddl du noeud Thermi
|
||||
// Tableau <Ddl> ta(tab_ddlErr_Taille);
|
||||
// for (int i =1; i<= tab_ddlErr_Taille; i++)
|
||||
// ta(i) = Ddl (tab_ddlErr(ne).tb(i),0.,LIBRE);
|
||||
// // ajout du tableau dans le noeud
|
||||
// tab_noeud(ne)->PlusTabDdl(ta);
|
||||
// }
|
||||
};
|
||||
|
||||
// inactive les ddl du problème primaire de mécanique
|
||||
void ElemThermi::Inact_ddl_primaire(DdlElement& tab_ddl)
|
||||
{ int nbne = tab_noeud.Taille();
|
||||
for (int ne=1; ne<= nbne; ne++)
|
||||
tab_noeud(ne)->Met_hors_service(tab_ddl(ne).tb);
|
||||
};
|
||||
// active les ddl du problème primaire de mécanique
|
||||
void ElemThermi::Act_ddl_primaire(DdlElement& tab_ddl)
|
||||
{ int nbne = tab_noeud.Taille();
|
||||
for (int ne=1; ne<= nbne; ne++)
|
||||
tab_noeud(ne)->Met_en_service(tab_ddl(ne).tb);
|
||||
};
|
||||
// inactive les ddl du problème de recherche d'erreur : les contraintes
|
||||
void ElemThermi::Inact_ddl_Flux(DdlElement& tab_ddlErr)
|
||||
{ int nbne = tab_noeud.Taille();
|
||||
for (int ne=1; ne<= nbne; ne++)
|
||||
tab_noeud(ne)->Met_hors_service(tab_ddlErr(ne).tb);
|
||||
};
|
||||
// active les ddl du problème de recherche d'erreur : les contraintes
|
||||
void ElemThermi::Act_ddl_Flux(DdlElement& tab_ddlErr)
|
||||
{ int nbne = tab_noeud.Taille();
|
||||
for (int ne=1; ne<= nbne; ne++)
|
||||
tab_noeud(ne)->Met_en_service(tab_ddlErr(ne).tb);
|
||||
};
|
||||
// active le premier ddl du problème de recherche d'erreur : FLUX1
|
||||
void ElemThermi::Act_premier_ddl_Flux()
|
||||
{ int nbne = tab_noeud.Taille();
|
||||
for (int ne=1; ne<= nbne; ne++)
|
||||
tab_noeud(ne)->Met_en_service(FLUXD1);
|
||||
};
|
||||
|
||||
// retourne un tableau de ddl element, correspondant à la
|
||||
// composante de densité de flux -> FLUXD1, pour chaque noeud qui contiend
|
||||
// des ddl de contrainte
|
||||
// -> utilisé pour l'assemblage de la raideur d'erreur
|
||||
DdlElement& ElemThermi::Tableau_de_Flux1() const
|
||||
{ cout << "\n erreur, fonction non defini pour cette element "
|
||||
<< "\n ElemThermi::Tableau_de_Flux1()" << endl;
|
||||
Sortie(1);
|
||||
DdlElement * toto = new DdlElement();
|
||||
return *toto;
|
||||
};
|
||||
|
||||
// lecture des flux sur le flot d'entrée
|
||||
void ElemThermi::LectureDesFlux(bool cas,UtilLecture * entreePrinc,Tableau <CoordonneeH *>& tabfluxH)
|
||||
{ // dimensionnement de la metrique identique au cas d'un calcul explicite
|
||||
if( cas)
|
||||
{ Tableau<Enum_variable_metrique> tab(7);
|
||||
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 ;
|
||||
met->PlusInitVariables(tab) ;
|
||||
};
|
||||
int dimAbsolue = ParaGlob::Dimension(); // dimension absolue
|
||||
// dimension des flux
|
||||
int dim = (*(tabfluxH(1))).Dimension();
|
||||
// création d'un Coordonnee au dimension absolu pour récupérer les flux
|
||||
// dans la base absolue
|
||||
Coordonnee flux(dimAbsolue) ;
|
||||
int ni; // compteur globale de point d'integration
|
||||
bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
|
||||
// donc il faut calculer tous les éléments de la métrique
|
||||
for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
|
||||
{ // calcul des éléments de la métrique, on utilise le même calcul
|
||||
// que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
|
||||
const Met_abstraite::Expli& ex = def->Cal_explicit_t(premier_calcul);
|
||||
for (int i=1;i<= dimAbsolue;i++)
|
||||
// récupération des coordonnées du flux en absolu
|
||||
*(entreePrinc->entree) >> flux(i);
|
||||
// passage dans le repère local du flux final
|
||||
CoordonneeH & fluxH = *tabfluxH(ni); // pour simplifier
|
||||
fluxH.Change_dim(dim);
|
||||
for (int i = 1;i<=dim;i++)
|
||||
fluxH(i) = ex.giH_t->Coordo(i) * flux;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// retour des flux en absolu retour true si ils existes sinon false
|
||||
void ElemThermi::FluxEnAbsolues
|
||||
(bool cas,Tableau <CoordonneeH *>& tabfluxH,Tableau <Vecteur>& tabflux)
|
||||
{ // dimensionnement de la metrique identique au cas d'un calcul explicite
|
||||
if( cas)
|
||||
{ Tableau<Enum_variable_metrique> tab(7);
|
||||
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 ;
|
||||
met->PlusInitVariables(tab) ;
|
||||
};
|
||||
int dimAbsolue = ParaGlob::Dimension(); // dimension absolue
|
||||
// dimension des tenseurs
|
||||
int dim = (*(tabfluxH(1))).Dimension();
|
||||
// redimensionnement éventuel du tableau de sortie
|
||||
int nbi = tabfluxH.Taille();
|
||||
if (tabflux.Taille() != nbi)
|
||||
tabflux.Change_taille(nbi);
|
||||
for (int ni=1;ni<= nbi;ni++)
|
||||
if ( tabflux(ni).Taille() != dimAbsolue)
|
||||
tabflux(ni).Change_taille(dimAbsolue);
|
||||
int ni; // compteur globale de point d'integration
|
||||
bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
|
||||
// donc il faut calculer tous les éléments de la métrique
|
||||
for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
|
||||
{ // calcul des éléments de la métrique, on utilise le même calcul
|
||||
// que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
|
||||
const Met_abstraite::Expli& ex = def->Cal_explicit_t(premier_calcul);
|
||||
// passage dans le repère global du flux local
|
||||
Coordonnee flux; // init à 0
|
||||
for (int i=1;i<= dim;i++)
|
||||
flux += (*tabfluxH(ni))(i) * (ex.giB_t->Coordo(i));
|
||||
};
|
||||
};
|
||||
|
||||
// ---------------- lecture écriture dans base info ----------------
|
||||
// programmes utilisés par les classes dérivées
|
||||
|
||||
// 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 ElemThermi::Lecture_bas_inf
|
||||
(ifstream& ent,const Tableau<Noeud *> * tabMaillageNoeud,const int cas)
|
||||
{ // appel de la routine d'élément
|
||||
Element::Lect_bas_inf_element(ent,tabMaillageNoeud,cas);switch (cas)
|
||||
{ case 1 : // ------- on récupère tout -------------------------
|
||||
{ string toto,nom;
|
||||
// récup de la masse volumique
|
||||
ent >> toto >> masse_volumique ;
|
||||
// données thermique
|
||||
ent >> toto >> dilatation;
|
||||
// blocage éventuelle d'hourglass
|
||||
ent >> toto >> nom;
|
||||
type_stabHourglass=Id_Nom_StabHourglass(nom.c_str());
|
||||
break;
|
||||
}
|
||||
case 2 : // ----------- lecture uniquement de se qui varie --------------------
|
||||
{ break;
|
||||
}
|
||||
default :
|
||||
{ cout << "\nErreur : valeur incorrecte du type de lecture !\n";
|
||||
cout << "ElemThermi::Lecture_bas_inf (ifstream& ent,const int cas)"
|
||||
<< " cas= " << cas << endl;
|
||||
Sortie(1);
|
||||
}
|
||||
}
|
||||
// ------ lecture dans tous les cas -------
|
||||
// résultat d'erreur
|
||||
string toto;
|
||||
ent >> toto;
|
||||
if (toto == "erreur_de_densite_flux")
|
||||
{ if (fluxErreur == NULL)
|
||||
fluxErreur = new double;
|
||||
ent >> (*fluxErreur) ;
|
||||
}
|
||||
// données particulière pour les lois de comportement mécanique
|
||||
int tabSaveDonTaille = tabSaveDon.Taille();
|
||||
if ((tabSaveDonTaille != 0) && (tabSaveDon(1) != NULL)) ent >> toto;
|
||||
int num ; // numéro du pt d'integ, n'est pas vraiment utilisé mais c'est mieux que de lire un string
|
||||
for (int i=1; i<= tabSaveDonTaille; i++)
|
||||
if (tabSaveDon(i) != NULL)
|
||||
{ ent >> toto >> num;
|
||||
tabSaveDon(i)->Lecture_base_info(ent,cas);}
|
||||
// données particulière pour les lois de comportement thermo physique
|
||||
int tabSaveTPTaille = tabSaveTP.Taille();
|
||||
if ((tabSaveTPTaille != 0) && (tabSaveTP(1) != NULL)) ent >> toto;
|
||||
for (int i=1; i<= tabSaveTPTaille; i++)
|
||||
if (tabSaveTP(i) != NULL)
|
||||
{ ent >> toto >> num;
|
||||
tabSaveTP(i)->Lecture_base_info(ent,cas);}
|
||||
// données particulière pour la déformation mécanique
|
||||
int tabSaveDefDonTaille = tabSaveDefDon.Taille();
|
||||
if ((tabSaveDefDonTaille != 0) && (tabSaveDefDon(1) != NULL)) ent >> toto;
|
||||
for (int i=1; i<= tabSaveDefDonTaille; i++)
|
||||
if (tabSaveDefDon(i) != NULL)
|
||||
{ ent >> toto >> num;
|
||||
tabSaveDefDon(i)->Lecture_base_info(ent,cas);}
|
||||
// lecture des énergies
|
||||
int energ_taille = tab_energ_t.Taille();
|
||||
for (int i=1;i<= energ_taille;i++) ent >> tab_energ_t(i) ;
|
||||
// // énergie et puissance éventuelle de la partie bulk viscosity
|
||||
// ent >> toto >> E_elem_bulk_t >> toto >> P_elem_bulk;
|
||||
// E_elem_bulk_tdt = E_elem_bulk_t;
|
||||
};
|
||||
// cas donne le niveau de sauvegarde
|
||||
// = 1 : on sauvegarde tout
|
||||
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
|
||||
void ElemThermi::Ecriture_bas_inf(ofstream& sort,const int cas)
|
||||
{ // appel de la routine d'élément
|
||||
Element::Ecri_bas_inf_element(sort,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 -------------------------
|
||||
{ // écriture de la masse volumique,
|
||||
sort << "masse_volumique " << masse_volumique <<" " << "\n";
|
||||
// données thermique
|
||||
sort << "dilatation_thermique " << dilatation << " ";
|
||||
// blocage éventuelle d'hourglass
|
||||
sort << "\n hourglass: " << Nom_StabHourglass(type_stabHourglass) << " ";
|
||||
break;
|
||||
}
|
||||
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
|
||||
{ break;
|
||||
}
|
||||
default :
|
||||
{ cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
|
||||
cout << "ElemThermi::Ecriture_bas_inf(ofstream& sort,const int cas)"
|
||||
<< " cas= " << cas << endl;
|
||||
Sortie(1);
|
||||
}
|
||||
}
|
||||
// --- informations à sortir dans tous les cas ----
|
||||
// résultat d'erreur
|
||||
if (fluxErreur != NULL)
|
||||
sort << "erreur_de_densite_de_flux " << (*fluxErreur) <<" " << "\n";
|
||||
else
|
||||
sort << "pas_d'erreur_de_densite_de_flux \n";
|
||||
// données particulière pour les lois de comportement mécaniques
|
||||
int tabSaveDonTaille = tabSaveDon.Taille();
|
||||
if ((tabSaveDonTaille != 0) && (tabSaveDon(1) != NULL)) sort << " data_spec_loi_comp_meca ";
|
||||
for (int i=1; i<= tabSaveDonTaille; i++)
|
||||
if (tabSaveDon(i) != NULL)
|
||||
{ if (i==1) {sort << "pt_int= " <<i << " ";} else {sort << "\n pt_int= " <<i << " ";};
|
||||
tabSaveDon(i)->Ecriture_base_info(sort,cas);}
|
||||
// données particulière pour les lois de comportement thermo physiques
|
||||
int tabSaveTPTaille = tabSaveTP.Taille();
|
||||
if ((tabSaveTPTaille != 0) && (tabSaveTP(1) != NULL)) sort << " data_spec_loi_comp_ThemoPhysique ";
|
||||
for (int i=1; i<= tabSaveTPTaille; i++)
|
||||
if (tabSaveTP(i) != NULL)
|
||||
{ if (i==1) {sort << "pt_int= " <<i << " ";} else {sort << "\n pt_int= " <<i << " ";};
|
||||
tabSaveTP(i)->Ecriture_base_info(sort,cas);}
|
||||
// données particulière pour la déformation mécanique
|
||||
int tabSaveDefDonTaille = tabSaveDefDon.Taille();
|
||||
if ((tabSaveDefDonTaille != 0) && (tabSaveDefDon(1) != NULL)) sort << " data_spec_def ";
|
||||
for (int i=1; i<= tabSaveDefDonTaille; i++)
|
||||
if (tabSaveDefDon(i) != NULL)
|
||||
{ if (i==1) {sort << "pt_int= " <<i << " ";} else {sort << "\n pt_int= " <<i << " ";};
|
||||
tabSaveDefDon(i)->Ecriture_base_info(sort,cas);}
|
||||
// sortie des énergies
|
||||
int energ_taille = tab_energ_t.Taille();
|
||||
sort << "\n ";
|
||||
for (int i=1;i<= energ_taille;i++) sort << tab_energ_t(i) << " " ;
|
||||
// // énergie et puissance éventuelle de la partie bulk viscosity
|
||||
// sort << "\n E_el_bulk= " << E_elem_bulk_t << " P_el_bulk= " << P_elem_bulk;
|
||||
};
|
||||
|
||||
// calcul de la longueur d'arrête de l'élément minimal
|
||||
// divisé par la célérité la plus rapide dans le matériau
|
||||
// appelé par les classes dérivées
|
||||
// nb_noeud : =0 indique que l'on utilise tous les noeuds du tableau de noeuds
|
||||
// = un nombre > 0, indique le nombre de noeuds à utiliser au début du tableau
|
||||
double ElemThermi::Interne_Long_arrete_mini_sur_c(Enum_dure temps,int nb_noeud)
|
||||
{ int nbne = tab_noeud.Taille(); // récup du nombre de noeud
|
||||
if (nb_noeud != 0)
|
||||
nbne = nb_noeud;
|
||||
// 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;
|
||||
for (int i=1;i<= nbne;i++)
|
||||
// on itère sur les noeuds restants
|
||||
switch (temps)
|
||||
{ case TEMPS_0:
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case TEMPS_t:
|
||||
for (int j=i+1;j<= nbne;j++)
|
||||
{ double dist_new = (tab_noeud(i)->Coord1() - tab_noeud(j)->Coord1()).Norme();
|
||||
if (dist_new < dist) dist = dist_new;
|
||||
}
|
||||
break;
|
||||
case TEMPS_tdt:
|
||||
for (int j=i+1;j<= nbne;j++)
|
||||
{ double dist_new = (tab_noeud(i)->Coord2() - tab_noeud(j)->Coord2()).Norme();
|
||||
if (dist_new < dist) dist = dist_new;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
cout << "\n cas du temps non implante temps= " << Nom_dure(temps)
|
||||
<< "\n ElemThermi::Interne_Long_arrete_mini_sur_c(Enum_dure temps)";
|
||||
Sortie(1);
|
||||
}
|
||||
// traitement d'une erreur éventuelle
|
||||
if (dist <= ConstMath::petit)
|
||||
{ cout << "\n **** ERREUR une longueur d'arrete de l'element est nulle"
|
||||
<< "\n ElemThermi::Interne_Long_arrete_mini_sur_c(..."
|
||||
<< "\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
|
||||
};
|
||||
// on calcul la célérité
|
||||
double cc = sqrt(ElemThermi::Calcul_maxi_E_qui(temps)/masse_volumique);
|
||||
// calcul du résultat
|
||||
double l_sur_c = dist/cc;
|
||||
return l_sur_c;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// initialisation pour le calcul de la matrice masse dans le cas de l'algorithme
|
||||
// de relaxation dynamique avec optimisation en continu de la matrice masse
|
||||
// casMass_relax: permet de choisir entre différentes méthodes de calcul de la masse
|
||||
void ElemThermi::InitCalculMatriceMassePourRelaxationDynamique(int )
|
||||
{ // on active le calcul des invariants de contraintes
|
||||
int taille = lesPtIntegThermiInterne->NbPti();
|
||||
|
||||
// on définit le ddl étendu correspondant, s'il n'existe pas
|
||||
// on définit le Ddl_enum_etendu correspondant à la masse au noeud pour la méthode
|
||||
if (masse_relax_dyn.Nom_vide() )
|
||||
masse_relax_dyn = (Ddl_enum_etendu("masse_relax_dyn"));
|
||||
};
|
||||
|
||||
// phase de calcul de la matrice masse dans le cas de l'algo de relaxation dynamique
|
||||
// mi= lambda * delta_t**2 / 2 * (alpha*K+beta*mu+gamma*Isig/3+theta/2*Sig_mises)
|
||||
// avec delta_t=1 par défaut a priori, donc n'intervient pas ici
|
||||
// ep: epaisseur, K module de compressibilite, mu: module de cisaillement, Isig trace de sigma,
|
||||
// Sig_mises la contrainte de mises
|
||||
// casMass_relax: permet de choisir entre différentes méthodes de calcul de la masse
|
||||
void ElemThermi::CalculMatriceMassePourRelaxationDynamique
|
||||
(const double& alph, const double& beta, const double & lambda
|
||||
,const double & gamma,const double & theta, int casMass_relax)
|
||||
{ // 1)
|
||||
// on calcule la moyenne des grandeurs qui servent pour le calcul de la pseudo-masse que l'on distribue
|
||||
// également sur les noeuds
|
||||
double trace_moyenne= 0.; double mises_moyen= 0.;
|
||||
double compress_moy=0.; double cisaille_moy = 0.;
|
||||
int taille = lesPtIntegThermiInterne->NbPti();
|
||||
|
||||
cout << "\n stop *** pour l'instant la methode : ElemThermi::CalculMatriceMassePourRelaxationDynamique"
|
||||
<< " n'est pas encore operationnelle " << endl;
|
||||
Sortie(1);
|
||||
|
||||
// // on boucle sur les points d'intégrations
|
||||
// for (int i= 1; i<= taille; i++)
|
||||
// {PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(i);
|
||||
// const Vecteur & invariant = ptIntegThermi.SigInvar();
|
||||
// trace_moyenne += invariant(1) ; // le premier invariant c'est la trace
|
||||
// if (invariant.Taille() > 1)
|
||||
// mises_moyen += sqrt((3.*invariant(2)-invariant(1)*invariant(1))/2.);
|
||||
// compress_moy += ptIntegThermi.ModuleCompressibilite();
|
||||
// cisaille_moy += ptIntegThermi.ModuleCisaillement();
|
||||
// };
|
||||
|
||||
// --- tout d'abord la partie contrainte
|
||||
// double ensemble = (val_propre_sup + val_propre_inf + val_cisaillement) / taille;
|
||||
// on divise par taille, ce qui conduit à la moyenne sur les points d'intégration
|
||||
double ensemble = (gamma*trace_moyenne /3.+ 0.5*theta*mises_moyen ) / taille;
|
||||
// --- maintenant la partie raideur
|
||||
ensemble += (alph * compress_moy + beta * cisaille_moy) / taille;
|
||||
// --- pour avoir l'intégration totale on utilise le volume
|
||||
// ensemble *= volume;
|
||||
// --- et maintenant on distribue sur tous les noeuds de manière identique
|
||||
// ne fonctionne que si tous les noeuds sont actifs !!! (ce qui est un cas particulier courant)
|
||||
// la masse élémentaire pour chaque noeud
|
||||
// double masse_elementaire = ensemble * lambda * 0.5 / tab_noeud.Taille();
|
||||
// pour des membrannes on a:
|
||||
// mi= lambda * delta_t**2 / 2 * epaisseur/4 * (alpha*K+beta*mu+gamma*Isig/3+theta/2*Sig_mises)
|
||||
// avec delta_t=1 par défaut a priori, donc n'intervient pas ici
|
||||
// d'où le facteur 0.125, que l'on garde également pour le volume
|
||||
double masse_elementaire = ensemble * lambda * 0.125 ;
|
||||
|
||||
// prise en compte du type d'élément:
|
||||
double ParNoeud = 1.; // n'est utilisé que par la méthode de Barnes classique
|
||||
int nbn=tab_noeud.Taille();
|
||||
switch (Type_geom_generique(ElementGeometrique_const().TypeGeometrie()))
|
||||
{ case VOLUME : // par rapport à la surface, on utilise la racine cubique du volume
|
||||
{ double long_caracteristique = pow(Volume(),1./3.);
|
||||
masse_elementaire *= long_caracteristique;
|
||||
// ParNoeud = volume / nombre de noeuds, donc c'est la partie du volume
|
||||
// attribuée à chaque noeud
|
||||
ParNoeud = Volume() / nbn;
|
||||
break;
|
||||
}
|
||||
case SURFACE : // l'algorithme historique
|
||||
{ double epaisseur_moyenne = EpaisseurMoyenne(TEMPS_tdt);
|
||||
masse_elementaire *= epaisseur_moyenne;
|
||||
// ParNoeud = section / nombre de noeuds, donc c'est la partie de la section
|
||||
// attribuée à chaque noeud
|
||||
ParNoeud = Volume() / epaisseur_moyenne/ nbn;
|
||||
break;
|
||||
}
|
||||
case LIGNE :
|
||||
{ double section_moyenne = SectionMoyenne(TEMPS_tdt);
|
||||
double long_caracteristique = Volume()/section_moyenne;
|
||||
masse_elementaire *= long_caracteristique;
|
||||
// ParNoeud = longueur / nombre de noeuds, donc c'est la partie de la longueur
|
||||
// attribuée à chaque noeud
|
||||
ParNoeud = Volume() / section_moyenne/ nbn;
|
||||
break;
|
||||
}
|
||||
default :
|
||||
cout << "\nErreur : pour l'instant les types autres que volume, surface, ligne ne sont pas pris en compte dans la relaxation "
|
||||
<< " dynamique selon barnes !\n";
|
||||
cout << "\n ElemThermi::CalculMatriceMassePourRelaxationDynamique(.. \n";
|
||||
Sortie(1);
|
||||
};
|
||||
// on parcours les noeuds de l'élément et on remplace le cas échéent, la valeur de la masse au noeud.
|
||||
switch (casMass_relax)
|
||||
{ case 1: case 3: // cas 1 : on cumule aux noeuds, cas 3 on fait la moyenne (pas effectué ici, on ne fait
|
||||
// que préparer le travail pour le cas 3)
|
||||
{for (int inoe=1;inoe<=nbn;inoe++)
|
||||
{Noeud& noe = *tab_noeud(inoe);
|
||||
// on cumule
|
||||
noe.ModifDdl_etendu(masse_relax_dyn).Valeur() += masse_elementaire;
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 2: // cas 2 : on prend la masse maxi
|
||||
{for (int inoe=1;inoe<=nbn;inoe++)
|
||||
{Noeud& noe = *tab_noeud(inoe);
|
||||
const Ddl_etendu& masse_actuel =noe.DdlEtendue(masse_relax_dyn);
|
||||
// dans le cas où la masse actuelle est plus petite on la remplace
|
||||
if (masse_actuel.ConstValeur() <= masse_elementaire)
|
||||
noe.ModifDdl_etendu(masse_relax_dyn).Valeur() = masse_elementaire;
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 4: case 5: // on cumule (puis on moyennera pour le cas 4, autre part) et on divise par la section comme dans la formule de barnes
|
||||
{for (int inoe=1;inoe<=nbn;inoe++)
|
||||
{Noeud& noe = *tab_noeud(inoe);
|
||||
const Ddl_etendu& masse_actuel =noe.DdlEtendue(masse_relax_dyn);
|
||||
// on cumule
|
||||
if (masse_actuel.ConstValeur() <= masse_elementaire)
|
||||
// !!!! je pense que ce cas est très bizarre il faudra revoir ce que cela signifie.... !!
|
||||
noe.ModifDdl_etendu(masse_relax_dyn).Valeur() += (masse_elementaire/ParNoeud);
|
||||
};
|
||||
break;
|
||||
}
|
||||
}; //-- fin du switch
|
||||
};
|
||||
|
||||
// METHODES VIRTUELLES:
|
||||
|
||||
|
||||
// recuperation des coordonnées du point de numéro d'ordre = iteg pour
|
||||
// la grandeur enu
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// si erreur retourne erreur à true
|
||||
// utilisé par les classes dérivées
|
||||
Coordonnee ElemThermi::CoordPtInt(Enum_dure temps,Enum_ddl enu,int iteg,bool& err)
|
||||
{ Coordonnee ptret;err = false;
|
||||
// récupération de l'élément géométrique correspondant à Enu
|
||||
ElemGeomC0& ele = this->ElementGeometrie(enu);
|
||||
// récupération du tableau des fonctions d'interpolations
|
||||
const Tableau <Vecteur> & tabphi = ele.TaPhi();
|
||||
if ((iteg < 0) || (iteg > tabphi.Taille()))
|
||||
{ err = true;}
|
||||
else
|
||||
{ switch (temps)
|
||||
{ case TEMPS_0 : ptret = met->PointM_0(tab_noeud,tabphi(iteg)); break;
|
||||
case TEMPS_t : ptret = met->PointM_t(tab_noeud,tabphi(iteg)); break;
|
||||
case TEMPS_tdt : ptret = met->PointM_tdt(tab_noeud,tabphi(iteg)); break;
|
||||
}
|
||||
};
|
||||
return ptret; // retour
|
||||
};
|
||||
|
||||
|
||||
// recuperation des coordonnées du point d'intégration numéro = iteg pour
|
||||
// la face : face
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// si erreur retourne erreur à true
|
||||
Coordonnee ElemThermi::CoordPtIntFace(int face, Enum_dure temps,int iteg,bool& err)
|
||||
{ Coordonnee ptret;err = false;
|
||||
if (SurfExiste(face))
|
||||
{// récupération de l'élément géométrique correspondant à la face
|
||||
const ElFrontiere* elf = this->Frontiere_surfacique(face,false);
|
||||
if (elf != NULL) // cas où la frontière existe déjà
|
||||
{ const ElemGeomC0 & elegeom = elf->ElementGeometrique();
|
||||
// récupération du tableau des fonctions d'interpolations
|
||||
const Tableau <Vecteur> & tabphi = elegeom.TaPhi();
|
||||
if ((iteg < 0) || (iteg > tabphi.Taille()))
|
||||
{ err = true;}
|
||||
else
|
||||
{ switch (temps)
|
||||
{ case TEMPS_0 : ptret = met->PointM_0(tab_noeud,tabphi(iteg)); break;
|
||||
case TEMPS_t : ptret = met->PointM_t(tab_noeud,tabphi(iteg)); break;
|
||||
case TEMPS_tdt : ptret = met->PointM_tdt(tab_noeud,tabphi(iteg)); break;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
else // cas où la frontière n'existe pas, on renvoie une erreur
|
||||
// et on laisse la valeur par défaut pour ptret
|
||||
{err = true;
|
||||
};
|
||||
return ptret; // retour
|
||||
};
|
||||
|
||||
// recuperation des coordonnées du point d'intégration numéro = iteg pour
|
||||
// la face : face
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// si erreur retourne erreur à true
|
||||
Coordonnee ElemThermi::CoordPtIntArete(int arete, Enum_dure temps,int iteg,bool& err)
|
||||
{ Coordonnee ptret;err = false;
|
||||
if (AreteExiste(arete))
|
||||
{// récupération de l'élément géométrique correspondant à l'arête
|
||||
const ElFrontiere* elf = this->Frontiere_lineique(arete,false);
|
||||
if (elf != NULL) // cas où la frontière existe déjà
|
||||
{ const ElemGeomC0 & elegeom = elf->ElementGeometrique();
|
||||
// récupération du tableau des fonctions d'interpolations
|
||||
const Tableau <Vecteur> & tabphi = elegeom.TaPhi();
|
||||
if ((iteg < 0) || (iteg > tabphi.Taille()))
|
||||
{ err = true;}
|
||||
else
|
||||
{ switch (temps)
|
||||
{ case TEMPS_0 : ptret = met->PointM_0(tab_noeud,tabphi(iteg)); break;
|
||||
case TEMPS_t : ptret = met->PointM_t(tab_noeud,tabphi(iteg)); break;
|
||||
case TEMPS_tdt : ptret = met->PointM_tdt(tab_noeud,tabphi(iteg)); break;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
else // cas où la frontière n'existe pas, on renvoie une erreur
|
||||
// et on laisse la valeur par défaut pour ptret
|
||||
{err = true;
|
||||
};
|
||||
return ptret; // retour
|
||||
};
|
||||
|
||||
// retourne le numero du pt d'ing le plus près ou est exprimé la grandeur enum
|
||||
// temps: dit si c'est à 0 ou t ou tdt
|
||||
// utilisé par les classes dérivées
|
||||
int ElemThermi::PtLePlusPres(Enum_dure temps,Enum_ddl enu, const Coordonnee& M)
|
||||
{ int iret;
|
||||
// récupération de l'élément géométrique correspondant à Enu
|
||||
ElemGeomC0& ele = this->ElementGeometrie(enu);
|
||||
// récupération du tableau des fonctions d'interpolations
|
||||
const Tableau <Vecteur> & tabphi = ele.TaPhi();
|
||||
// on boucle sur les pt d'integ pour avoir le point le plus près
|
||||
int tabphitaille = tabphi.Taille();
|
||||
Coordonnee P; iret=1; double dist= ConstMath::tresgrand;
|
||||
for (int ipt = 1;ipt<=tabphitaille;ipt++)
|
||||
{ switch (temps)
|
||||
{ case TEMPS_0 : P = met->PointM_0(tab_noeud,tabphi(ipt)); break;
|
||||
case TEMPS_t : P = met->PointM_t(tab_noeud,tabphi(ipt)); break;
|
||||
case TEMPS_tdt : P = met->PointM_tdt(tab_noeud,tabphi(ipt)); break;
|
||||
}
|
||||
double di=(M-P).Norme();
|
||||
if (di < dist) { dist = di; iret = ipt;};
|
||||
}
|
||||
return iret; // retour
|
||||
};
|
||||
|
||||
// ==== >>>> methodes virtuelles redéfini éventuellement dans les classes dérivées ============
|
||||
|
||||
// ramene l'element geometrique correspondant au ddl passé en paramètre
|
||||
ElemGeomC0& ElemThermi::ElementGeometrie(Enum_ddl ddl) const
|
||||
{ Enum_ddl enu = PremierDdlFamille(ddl);
|
||||
switch (enu)
|
||||
{ case X1 : return ElementGeometrique(); break;
|
||||
case TEMP : return ElementGeometrique(); break;
|
||||
case FLUXD1 : return ElementGeometrique(); break;
|
||||
case GRADT1 : return ElementGeometrique(); break;
|
||||
case DGRADT1 : return ElementGeometrique(); break;
|
||||
case ERREUR : return ElementGeometrique(); break;
|
||||
default :
|
||||
{cout << "\n cas non prevu ou non encore implante: ddl= " << Nom_ddl(ddl)
|
||||
<< "\n ElemThermi::ElementGeometrie(Enum_ddl ddl) " ;
|
||||
Sortie(1);}
|
||||
}
|
||||
return ElementGeometrique(); // pour taire le compilo
|
||||
};
|
||||
|
||||
// ramène le nombre de grandeurs génératrices pour un pt d'integ, correspondant à un type enuméré
|
||||
// peut-être surchargé pour des éléments particuliers
|
||||
int ElemThermi::NbGrandeurGene(Enum_ddl ddl) const
|
||||
{ Enum_ddl enu = PremierDdlFamille(ddl);
|
||||
int nbGG = 0.; // par défaut
|
||||
switch (enu)
|
||||
{ case TEMP : case FLUXD1 :case GRADT1 :case DGRADT1 :
|
||||
{ // cas d'un calcul de thermique classique
|
||||
switch (Type_geom_generique(id_geom))
|
||||
{ case LIGNE : case POINT_G : nbGG = 1; break; // FLUXD1
|
||||
case SURFACE : nbGG = 2; break; // FLUXD1, FLUXD2
|
||||
case VOLUME : nbGG = 3; break; // FLUXD1 FLUXD2 FLUXD3
|
||||
default :
|
||||
cout << "\nErreur : cas non traite, id_geom= :" << Nom_type_geom(Type_geom_generique(id_geom))
|
||||
<< "ElemThermi::NbGrandeurGene(.. \n";
|
||||
Sortie(1);
|
||||
};
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{cout << "\n cas non prevu ou non encore implante: ddl= " << Nom_ddl(ddl)
|
||||
<< "\n ElemThermi::NbGrandeurGene(Enum_ddl ddl) " ;
|
||||
Sortie(1);}
|
||||
};
|
||||
return nbGG;
|
||||
};
|
||||
|
||||
// modification de l'orientation de l'élément en fonction de cas_orientation
|
||||
// =0: inversion simple (sans condition) de l'orientation
|
||||
// si cas_orientation est diff de 0: on calcul le jacobien aux différents points d'intégration
|
||||
// 1. si tous les jacobiens sont négatifs on change d'orientation
|
||||
// 2. si tous les jacobiens sont positifs on ne fait rien
|
||||
// 3. si certains jacobiens sont positifs et d'autres négatifs message
|
||||
// d'erreur et on ne fait rien
|
||||
// ramène true: s'il y a eu changement effectif, sinon false
|
||||
bool ElemThermi::Modif_orient_elem(int cas_orientation)
|
||||
{ // retour:
|
||||
bool retour=false; // par défaut pas de changement
|
||||
if (cas_orientation == 0) // cas où on inverse l'orientation sans condition particulière
|
||||
{ // on change l'orientation de l'élément
|
||||
retour = true;
|
||||
int nbnoe = tab_noeud.Taille();
|
||||
Tableau<Noeud *> tab_inter(tab_noeud); // on crée un tableau intermédiaire
|
||||
// on récupère la numérotation locale inverse
|
||||
const Tableau<int> tabi = ElementGeometrique().InvConnec();
|
||||
// on met à jour le tableau actuel
|
||||
for (int n=1;n<=nbnoe;n++)
|
||||
tab_noeud(n)=tab_inter(tabi(n));
|
||||
}
|
||||
else
|
||||
{ // si cas_orientation est diff de 0: on calcul le jacobien aux différents points d'intégration
|
||||
// 1. si tous les jacobiens sont négatifs on change d'orientation
|
||||
// 2. si tous les jacobiens sont positifs on ne fait rien
|
||||
// 3. si certains jacobiens sont positifs et d'autres négatifs message
|
||||
// d'erreur et on ne fait rien
|
||||
int cas=1; // a priori tout est ok
|
||||
// boucle sur les pt d'integ
|
||||
for (def->PremierPtInteg();def->DernierPtInteg();def->NevezPtInteg())
|
||||
{ double jacobien_0 = def->JacobienInitial();
|
||||
|
||||
if (jacobien_0 < 0)
|
||||
{if (cas ==1) // on a trouvé un jacobien négatif
|
||||
{cas =0; }
|
||||
}// si c'était positif --> négatif
|
||||
else // cas positif
|
||||
{if (cas == 0) // on a déjà changé
|
||||
{ cas = 2; break;} // on sort de la boucle
|
||||
};
|
||||
};
|
||||
// gestion de pb
|
||||
if (cas == 2)
|
||||
{ cout << "\n **** Attention **** element nb= "<< this->Num_elt() << " peut-etre trop distordu ?"
|
||||
<< " pt d'integ Thermi positif et negatif !! ";
|
||||
if (ParaGlob::NiveauImpression() > 7)
|
||||
{// on va essayer de sortir plus d'info
|
||||
int pti=1;cout << "\n les jacobiens initiaux \n";
|
||||
// on sort les valeurs des jacobiens
|
||||
for (def->PremierPtInteg();def->DernierPtInteg();def->NevezPtInteg(),pti++)
|
||||
{ cout << " pti= "<<pti << ", J= "<< def->JacobienInitial();};
|
||||
// les coordonnées des noeuds en suivant l'ordre de la table de connection locale
|
||||
int nbnoe = tab_noeud.Taille();
|
||||
cout << "\n les coordonnees de l'element \n";
|
||||
for (int ino=1;ino<=nbnoe;ino++)
|
||||
{ cout << "\n "<< ino << " " << tab_noeud(ino)->Coord0();
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
else if (cas == 0)
|
||||
{ switch (cas_orientation)
|
||||
{ case 1: // on change l'orientation de l'élément
|
||||
{retour = true;
|
||||
int nbnoe = tab_noeud.Taille();
|
||||
Tableau<Noeud *> tab_inter(tab_noeud); // on crée un tableau intermédiaire
|
||||
// on récupère la numérotation locale inverse
|
||||
const Tableau<int> tabi = ElementGeometrique().InvConnec();
|
||||
for (int n=1;n<=nbnoe;n++)
|
||||
tab_noeud(n)=tab_inter(tabi(n));
|
||||
break;
|
||||
}
|
||||
case -1: // on sort une information à l'écran
|
||||
{ cout << "\n element nb= "<< this->Num_elt() << "jacobien negatif " ;
|
||||
break;;
|
||||
}
|
||||
default:
|
||||
cout << "\n erreur le cas : " << cas_orientation
|
||||
<< " n'est pas actuellement pris en compte"
|
||||
<< "\n ElemThermi::Modif_orient_elem(...";
|
||||
Sortie(1);
|
||||
};
|
||||
};
|
||||
};
|
||||
// retour
|
||||
return retour;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
1143
Elements/Thermique/ElemThermi3.cc
Executable file
1143
Elements/Thermique/ElemThermi3.cc
Executable file
File diff suppressed because it is too large
Load diff
735
Elements/Thermique/ElemThermi4.cc
Executable file
735
Elements/Thermique/ElemThermi4.cc
Executable file
|
@ -0,0 +1,735 @@
|
|||
// 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 "ElemThermi.h"
|
||||
#include <iomanip>
|
||||
#include "ConstMath.h"
|
||||
#include "Util.h"
|
||||
#include "Coordonnee2.h"
|
||||
#include "Coordonnee3.h"
|
||||
#include "TypeQuelconqueParticulier.h"
|
||||
#include "TypeConsTens.h"
|
||||
|
||||
|
||||
|
||||
|
||||
// affichage dans la sortie transmise, des variables duales "nom"
|
||||
// aux differents points d'integration
|
||||
// dans le cas ou nom est vide, affichage de "toute" les variables
|
||||
void ElemThermi::VarDualSort(ofstream& sort, Tableau<string>& nom,int ,int cas)
|
||||
{ if ((cas == 1) || (cas == 2))
|
||||
{ // cas d'une premiere initialisation
|
||||
Tableau<Enum_variable_metrique> tab(5);
|
||||
tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt;
|
||||
tab(4) = igiH_0; tab(5) = igijHH_0;
|
||||
met->PlusInitVariables(tab) ;
|
||||
}
|
||||
// def de la dimension des Coordonnées
|
||||
int dim = ParaGlob::Dimension();
|
||||
// def de tenseurs pour la sortie
|
||||
Coordonnee fluxD(dim);
|
||||
CoordonneeH fluxDH(dim) ;
|
||||
Coordonnee gradT(dim);
|
||||
CoordonneeB gradTB(dim);
|
||||
CoordonneeB DgradTB(dim);
|
||||
Coordonnee DgradT(dim);
|
||||
CoordonneeB DeltagradTB(dim) ;
|
||||
Coordonnee DeltagradT(dim) ;
|
||||
Enum_dure temps;
|
||||
|
||||
// a priori ici on travaille en absolue
|
||||
bool absolue = true;
|
||||
|
||||
int ni; // compteur globale de point d'integration
|
||||
for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
|
||||
// for (int ni=1;ni<= nbi;ni++)
|
||||
{// éléments de métrique et matrices de passage
|
||||
TenseurHH* gijHH;TenseurBB* gijBB;
|
||||
Coordonnee* Mpt0;Coordonnee* Mptfin;
|
||||
BaseB * giB_0; BaseB * giB_tdt;
|
||||
BaseH * giH_0; BaseH * giH_tdt;
|
||||
Mat_pleine jB0(dim,dim),jBfin(dim,dim);
|
||||
if ((cas==1) || (cas==11))
|
||||
// calcul d'une ortho interessance de visualisation des tenseurs
|
||||
// cas de tenseur 3D -> Ia, cas 1D on prend un vecteur norme collineaire
|
||||
// avec g1, dans le cas 2D
|
||||
// la nouvelle base jB est calculee dans def par projection de "Ia" sur Galpha
|
||||
// le resultat est une matrice de passage utilisable pour le changement de base
|
||||
// jB0 a t=0, B pour les tenseurs BB, jH0 idem pour les tenseurs HH
|
||||
// resultat a t+dt
|
||||
{const Met_abstraite::InfoImp& ex = def->RemontImp(absolue,jB0,jBfin);
|
||||
temps=TEMPS_tdt;
|
||||
Mpt0 = ex.M0; Mptfin = ex.Mtdt;
|
||||
giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
|
||||
giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
|
||||
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
|
||||
}
|
||||
else if ((cas==2) || (cas==12))
|
||||
{ // resultat a tdt
|
||||
const Met_abstraite::InfoExp_tdt& ex= def->RemontExp_tdt(absolue,jB0,jBfin);
|
||||
temps=TEMPS_tdt;
|
||||
Mpt0 = ex.M0; Mptfin = ex.Mtdt;
|
||||
giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
|
||||
giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
|
||||
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
|
||||
}
|
||||
// calcul des grandeurs
|
||||
PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(ni);
|
||||
|
||||
fluxDH = (ptIntegThermi.FluxH());
|
||||
CoordonneeB interB(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interB += (*giB_tdt)(i) * fluxDH(i);
|
||||
fluxD = interB.Coor();
|
||||
|
||||
gradTB = (ptIntegThermi.GradTB());
|
||||
CoordonneeH interH(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += gradTB(i) * (*giH_tdt)(i);
|
||||
gradT = interH.Coor();
|
||||
|
||||
DgradTB = (ptIntegThermi.DgradTB());
|
||||
interH.Zero(); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += DgradTB(i) * (*giH_tdt)(i);
|
||||
DgradT = interH.Coor();
|
||||
|
||||
DeltagradTB = (ptIntegThermi.DeltaGradTB());
|
||||
interH.Zero(); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += DeltagradTB(i) * (*giH_tdt)(i);
|
||||
DeltagradT = interH.Coor();
|
||||
|
||||
// donnees propre a la loi thermique au pt d'integ
|
||||
CompThermoPhysiqueAbstraite::SaveResul* sTP = tabSaveTP(ni);
|
||||
// donnees propre a la loi mécanique au pt d'integ
|
||||
Loi_comp_abstraite::SaveResul* sDon=NULL; // les données spécifique mécanique
|
||||
if (sDon != NULL) {sDon = tabSaveDon(ni);}; // au pt d'integ si elles existes
|
||||
// données propre à la déformation au pt d'integ
|
||||
Deformation::SaveDefResul * sDefDon = tabSaveDefDon(ni);
|
||||
|
||||
|
||||
|
||||
// affichage
|
||||
sort << "\n=================== Point d\'integration [[[ " << ni<<" ]]] ==================" ;
|
||||
sort << "\nCoordonnees avant deformation " ; Mpt0->Affiche(sort,16);
|
||||
sort << "\nCoordonnees apres deformation " ; Mptfin->Affiche(sort,16);
|
||||
sort <<" \n et les variations " ; ((*Mptfin) - (*Mpt0)).Affiche(sort,16);
|
||||
if (nom.Taille() == 0)
|
||||
{ // cas d'une sortie complete
|
||||
for (int indic =1; indic<=11; indic++)
|
||||
AffDefCont
|
||||
(sort,sTP,gradTB,gradT,ptIntegThermi.Norme_gradT()
|
||||
,DgradTB,DgradT,ptIntegThermi.Norme_DGradT()
|
||||
,fluxDH,fluxD,ptIntegThermi.Norme_flux()
|
||||
,ptIntegThermi.Temperature(),indic) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// pour mémoire je laisse le reste
|
||||
// for (int ij = 1;ij<= nom.Taille(); ij++)
|
||||
// if (nom(ij) == "Green-Lagrange")
|
||||
// AffDefCont(sort,sDon,gradT0B,gradTB,DgradTB,DeltagradTB,fluxDH,epsHB,sigHB,valPropreEps,valPropreDeps,valPropreSig,Mises
|
||||
// ,epsAlmBB,epslogBB,1);
|
||||
};
|
||||
};
|
||||
// liberation des tenseurs intermediaires
|
||||
LibereTenseur();
|
||||
};
|
||||
void ElemThermi::AffDefCont( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_dGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic)
|
||||
{ int dim = fluxDH.Dimension();
|
||||
switch (dim)
|
||||
{ case 1:
|
||||
AffDefCont1D(sort,saveDon,gradTB,gradT,norme_gradT
|
||||
,DgradTB,DgradT,norme_dGradT
|
||||
,fluxDH,fluxD,norme_flux
|
||||
,temperature,indic);
|
||||
break;
|
||||
case 2:
|
||||
AffDefCont2D(sort,saveDon,gradTB,gradT,norme_gradT
|
||||
,DgradTB,DgradT,norme_dGradT
|
||||
,fluxDH,fluxD,norme_flux
|
||||
,temperature,indic);
|
||||
break;
|
||||
case 3:
|
||||
AffDefCont3D(sort,saveDon,gradTB,gradT,norme_gradT
|
||||
,DgradTB,DgradT,norme_dGradT
|
||||
,fluxDH,fluxD,norme_flux
|
||||
,temperature,indic);
|
||||
break;
|
||||
default :
|
||||
{cout << "\nerreur seules les cas 1D 2D 3D sont pris considere et non " << dim;
|
||||
cout << "\nElemThermi::AffDefCont( etc ..." << endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
void ElemThermi::AffDefCont1D( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_DGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic)
|
||||
{
|
||||
switch (indic)
|
||||
{case 1 :{ sort << "\nGradient de temperature dans repere global";
|
||||
sort << "\n gradT " ;
|
||||
sort << setw (16) << gradT(1) ;
|
||||
}
|
||||
break;
|
||||
case 2 :{ sort << "\nGradient de temperature dans repere global";
|
||||
sort << "\n gradTB " ;
|
||||
sort << setw (16) << gradTB(1) ;
|
||||
}
|
||||
break;
|
||||
case 3 :{ sort << "\nDensite de flux dans repere global";
|
||||
sort << "\n fluxD " ;
|
||||
sort << setw (16) << fluxD(1) ;
|
||||
}
|
||||
break;
|
||||
case 4 :{ sort << "\nDensite de flux dans repere local";
|
||||
sort << "\n fluxDH " ;
|
||||
sort << setw (16) << fluxDH(1) ;
|
||||
}
|
||||
break;
|
||||
case 5 :{ sort << "\nVitesse du gradient de temperature dans repere global";
|
||||
sort << "\n DgradT " ;
|
||||
sort << setw (16) << DgradT(1) ;
|
||||
}
|
||||
break;
|
||||
case 6 :{ sort << "\nVitesse du gradient de temperature dans repere local";
|
||||
sort << "\n DgradTB " ;
|
||||
sort << setw (16) << DgradTB(1) ;
|
||||
}
|
||||
break;
|
||||
case 7 :{ sort << "\n norme gradT ";
|
||||
sort << "\n norme_gradT " ;
|
||||
sort << setw (16) << norme_gradT ;
|
||||
}
|
||||
break;
|
||||
case 8 :{ sort << "\n norme DgradT ";
|
||||
sort << "\n norme_DGradT " ;
|
||||
sort << setw (16) << norme_DGradT ;
|
||||
}
|
||||
break;
|
||||
case 9 :{ sort << "\n norme fluxD ";
|
||||
sort << "\n norme_flux " ;
|
||||
sort << setw (16) << norme_flux;
|
||||
}
|
||||
break;
|
||||
case 10 :{ sort << "\n Temperature ";
|
||||
sort << "\n temperature " ;
|
||||
sort << setw (16) << temperature ;
|
||||
}
|
||||
break;
|
||||
case 11 :{ if (saveDon != NULL)
|
||||
{ sort << "\ngrandeurs attachees a la loi et au point ";
|
||||
loiTP->AfficheDataSpecif(sort,saveDon);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default :
|
||||
{cout << "\nerreur seules les cas de 1 a 11 sont pris en consideration et non " << indic;
|
||||
cout << "\nElemThermi::AffDefCont1D( etc ..." << endl;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
void ElemThermi::AffDefCont2D( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_DGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic)
|
||||
{
|
||||
string type_repere=" repere global";
|
||||
int dim_glob = ParaGlob::Dimension();
|
||||
if (dim_glob == 3)
|
||||
// lorsque que l'on sort des vecteur de dim 2 en dimension 3, on utilise un repère particulier local orthonormé
|
||||
type_repere=" repere orthonorme local";
|
||||
int dim_loc = gradTB.Dimension();
|
||||
|
||||
|
||||
switch (indic)
|
||||
{case 1 :{ sort << "\nGradient de temperature dans repere global";
|
||||
sort << "\n gradT \n" ;
|
||||
for (int i=1;i<=dim_glob;i++) sort << setw (16) << gradT(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 2 :{ sort << "\nGradient de temperature dans repere global";
|
||||
sort << "\n gradTB \n" ;
|
||||
for (int i=1;i<=dim_loc;i++) sort << setw (16) << gradTB(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 3 :{ sort << "\nDensite de flux dans repere global";
|
||||
sort << "\n fluxD \n" ;
|
||||
for (int i=1;i<=dim_glob;i++) sort << setw (16) << fluxD(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 4 :{ sort << "\nDensite de flux dans repere local";
|
||||
sort << "\n fluxDH \n" ;
|
||||
for (int i=1;i<=dim_loc;i++) sort << setw (16) << fluxDH(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 5 :{ sort << "\nVitesse du gradient de temperature dans repere global";
|
||||
sort << "\n DgradT \n" ;
|
||||
for (int i=1;i<=dim_glob;i++) sort << setw (16) << DgradT(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 6 :{ sort << "\nVitesse du gradient de temperature dans repere local";
|
||||
sort << "\n DgradTB \n" ;
|
||||
for (int i=1;i<=dim_loc;i++) sort << setw (16) << DgradTB(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 7 :{ sort << "\n norme gradT ";
|
||||
sort << "\n norme_gradT " ;
|
||||
sort << setw (16) << norme_gradT ;
|
||||
}
|
||||
break;
|
||||
case 8 :{ sort << "\n norme DgradT ";
|
||||
sort << "\n norme_DGradT " ;
|
||||
sort << setw (16) << norme_DGradT ;
|
||||
}
|
||||
break;
|
||||
case 9 :{ sort << "\n norme fluxD ";
|
||||
sort << "\n norme_flux " ;
|
||||
sort << setw (16) << norme_flux;
|
||||
}
|
||||
break;
|
||||
case 10 :{ sort << "\n Temperature ";
|
||||
sort << "\n temperature " ;
|
||||
sort << setw (16) << temperature ;
|
||||
}
|
||||
break;
|
||||
case 11 :{ if (saveDon != NULL)
|
||||
{ sort << "\ngrandeurs attachees a la loi et au point ";
|
||||
loiTP->AfficheDataSpecif(sort,saveDon);
|
||||
}
|
||||
}
|
||||
default :
|
||||
{cout << "\nerreur seules les cas de 1 a 11 sont pris en consideration et non " << indic;
|
||||
cout << "\nElemThermi::AffDefCont2D( etc ..." << endl;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
void ElemThermi::AffDefCont3D( ofstream& sort,CompThermoPhysiqueAbstraite::SaveResul * saveDon,
|
||||
CoordonneeB& gradTB,Coordonnee& gradT,double& norme_gradT,
|
||||
CoordonneeB& DgradTB,Coordonnee& DgradT,double& norme_DGradT,
|
||||
CoordonneeH& fluxDH,Coordonnee & fluxD,double& norme_flux,
|
||||
double& temperature, int indic)
|
||||
{int dim_glob = 3; int dim_loc = 3;
|
||||
switch (indic)
|
||||
{case 1 :{ sort << "\nGradient de temperature dans repere global";
|
||||
sort << "\n gradT \n" ;
|
||||
for (int i=1;i<=dim_glob;i++) sort << setw (16) << gradT(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 2 :{ sort << "\nGradient de temperature dans repere global";
|
||||
sort << "\n gradTB \n" ;
|
||||
for (int i=1;i<=dim_loc;i++) sort << setw (16) << gradTB(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 3 :{ sort << "\nDensite de flux dans repere global";
|
||||
sort << "\n fluxD \n" ;
|
||||
for (int i=1;i<=dim_glob;i++) sort << setw (16) << fluxD(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 4 :{ sort << "\nDensite de flux dans repere local";
|
||||
sort << "\n fluxDH \n" ;
|
||||
for (int i=1;i<=dim_loc;i++) sort << setw (16) << fluxDH(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 5 :{ sort << "\nVitesse du gradient de temperature dans repere global";
|
||||
sort << "\n DgradT \n" ;
|
||||
for (int i=1;i<=dim_glob;i++) sort << setw (16) << DgradT(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 6 :{ sort << "\nVitesse du gradient de temperature dans repere local";
|
||||
sort << "\n DgradTB \n" ;
|
||||
for (int i=1;i<=dim_loc;i++) sort << setw (16) << DgradTB(i) << " ";
|
||||
}
|
||||
break;
|
||||
case 7 :{ sort << "\n norme gradT ";
|
||||
sort << "\n norme_gradT " ;
|
||||
sort << setw (16) << norme_gradT ;
|
||||
}
|
||||
break;
|
||||
case 8 :{ sort << "\n norme DgradT ";
|
||||
sort << "\n norme_DGradT " ;
|
||||
sort << setw (16) << norme_DGradT ;
|
||||
}
|
||||
break;
|
||||
case 9 :{ sort << "\n norme fluxD ";
|
||||
sort << "\n norme_flux " ;
|
||||
sort << setw (16) << norme_flux;
|
||||
}
|
||||
break;
|
||||
case 10 :{ sort << "\n Temperature ";
|
||||
sort << "\n temperature " ;
|
||||
sort << setw (16) << temperature ;
|
||||
}
|
||||
break;
|
||||
case 11 :{ if (saveDon != NULL)
|
||||
{ sort << "\ngrandeurs attachees a la loi et au point ";
|
||||
loiTP->AfficheDataSpecif(sort,saveDon);
|
||||
}
|
||||
}
|
||||
default :
|
||||
{cout << "\nerreur seules les cas de 1 a 11 sont pris en consideration et non " << indic;
|
||||
cout << "\nElemThermi::AffDefCont2D( etc ..." << endl;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 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> ElemThermi::Valeur_multi
|
||||
(bool absolue,Enum_dure temps,const List_io<Ddl_enum_etendu>& enu,int iteg,int cas )
|
||||
|
||||
{ // ----- def de grandeurs de travail
|
||||
// def de la dimension des tenseurs
|
||||
int dim = ParaGlob::Dimension();
|
||||
PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(iteg);
|
||||
// recup de l'incrément de temps
|
||||
double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
|
||||
double unSurDeltat=0;
|
||||
if (Abs(deltat) >= ConstMath::trespetit)
|
||||
{unSurDeltat = 1./deltat;}
|
||||
else // si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
|
||||
{ // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
|
||||
if (unSurDeltat < 0)
|
||||
{ cout << "\n le pas de temps est négatif !! "; };
|
||||
unSurDeltat = ConstMath::tresgrand;
|
||||
};
|
||||
|
||||
// def de grandeurs pour la sortie
|
||||
Coordonnee fluxD(dim);
|
||||
CoordonneeH fluxDH(dim) ;
|
||||
Coordonnee gradT(dim);
|
||||
CoordonneeB gradTB(dim);
|
||||
CoordonneeB DgradTB(dim);
|
||||
Coordonnee DgradT(dim);
|
||||
CoordonneeB DeltagradTB(dim) ;
|
||||
Coordonnee DeltagradT(dim) ;
|
||||
|
||||
Coordonnee Mtdt(ParaGlob::Dimension()); // coordonnées éventuelles du point d'intégration considéré
|
||||
|
||||
Tableau <double> tab_ret (enu.size());
|
||||
// définition des grandeurs qui sont indépendante de la boucle sur les ddl_enum_etendue
|
||||
|
||||
def->ChangeNumInteg(iteg); // on change le numéro de point d'intégration courant
|
||||
if (((cas == 1) || (cas == 2)))
|
||||
{ // cas d'une premiere initialisation
|
||||
Tableau<Enum_variable_metrique> tab(5);
|
||||
tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt;
|
||||
tab(4) = igiH_0; tab(5) = igijHH_0;
|
||||
met->PlusInitVariables(tab) ;
|
||||
}
|
||||
// éléments de métrique et matrices de passage
|
||||
TenseurHH* gijHH;TenseurBB* gijBB;
|
||||
Coordonnee* Mpt0;Coordonnee* Mptfin;
|
||||
BaseB * giB_0; BaseB * giB_tdt;
|
||||
BaseH * giH_0; BaseH * giH_tdt;
|
||||
Mat_pleine jB0(dim,dim),jBfin(dim,dim);
|
||||
if ((cas==1) || (cas==11))
|
||||
// calcul d'une ortho interessance de visualisation des tenseurs
|
||||
// cas de tenseur 3D -> Ia, cas 1D on prend un vecteur norme collineaire
|
||||
// avec g1, dans le cas 2D
|
||||
// la nouvelle base jB est calculee dans def par projection de "Ia" sur Galpha
|
||||
// le resultat est une matrice de passage utilisable pour le changement de base
|
||||
// jB0 a t=0, B pour les tenseurs BB, jH0 idem pour les tenseurs HH
|
||||
// resultat a t+dt
|
||||
{const Met_abstraite::InfoImp& ex = def->RemontImp(absolue,jB0,jBfin);
|
||||
Mpt0 = ex.M0; Mptfin = ex.Mtdt;
|
||||
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
|
||||
giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
|
||||
giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
|
||||
}
|
||||
else if ((cas==2) || (cas==12))
|
||||
// resultat a t
|
||||
{const Met_abstraite::InfoExp_tdt& ex= def->RemontExp_tdt(absolue,jB0,jBfin);
|
||||
Mpt0 = ex.M0; Mptfin = ex.Mtdt;
|
||||
giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
|
||||
giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
|
||||
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
|
||||
};
|
||||
|
||||
// on définie des indicateurs pour ne pas faire plusieurs fois le même calcul
|
||||
List_io<Ddl_enum_etendu>::const_iterator ie,iefin=enu.end();
|
||||
bool besoin_coordonnees = false;
|
||||
for (ie=enu.begin(); ie!=iefin;ie++)
|
||||
{ if (Meme_famille((*ie).Enum(),X1)) besoin_coordonnees=true;
|
||||
};
|
||||
|
||||
// ----- maintenant on calcule les grandeurs nécessaires -----
|
||||
|
||||
fluxDH = (ptIntegThermi.FluxH());
|
||||
CoordonneeB interB(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interB += (*giB_tdt)(i) * fluxDH(i);
|
||||
fluxD = interB.Coor();
|
||||
|
||||
gradTB = (ptIntegThermi.GradTB());
|
||||
CoordonneeH interH(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += gradTB(i) * (*giH_tdt)(i);
|
||||
gradT = interH.Coor();
|
||||
|
||||
DgradTB = (ptIntegThermi.DgradTB());
|
||||
interH.Zero(); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += DgradTB(i) * (*giH_tdt)(i);
|
||||
DgradT = interH.Coor();
|
||||
|
||||
DeltagradTB = (ptIntegThermi.DeltaGradTB());
|
||||
interH.Zero(); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += DeltagradTB(i) * (*giH_tdt)(i);
|
||||
DeltagradT = interH.Coor();
|
||||
|
||||
if (besoin_coordonnees)
|
||||
Mtdt = def->Position_tdt();
|
||||
|
||||
// donnees propre a la loi thermique au pt d'integ
|
||||
CompThermoPhysiqueAbstraite::SaveResul* sTP = tabSaveTP(iteg);
|
||||
// donnees propre a la loi mécanique au pt d'integ
|
||||
Loi_comp_abstraite::SaveResul* sDon=NULL; // les données spécifique mécanique
|
||||
if (sDon != NULL) {sDon = tabSaveDon(iteg);}; // au pt d'integ si elles existes
|
||||
// données propre à la déformation au pt d'integ
|
||||
Deformation::SaveDefResul * sDefDon = tabSaveDefDon(iteg);
|
||||
|
||||
//----- fin du calcul des grandeurs nécessaires -----
|
||||
|
||||
// on balaie maintenant la liste des grandeurs à sortir
|
||||
int it; // it est l'indice dans le tableau de retour
|
||||
for (it=1,ie=enu.begin(); ie!=iefin;ie++,it++)
|
||||
{
|
||||
switch ((*ie).Enum())
|
||||
{ case FLUXD1 : tab_ret(it)= fluxD(1); break;
|
||||
case FLUXD2 : tab_ret(it)= fluxD(2); break;
|
||||
case FLUXD3 : tab_ret(it)= fluxD(3); break;
|
||||
case GRADT1 : tab_ret(it)= gradT(1); break;
|
||||
case GRADT2 : tab_ret(it)= gradT(2); break;
|
||||
case GRADT3 : tab_ret(it)= gradT(3); break;
|
||||
case DGRADT1 : tab_ret(it)= DgradT(1); break;
|
||||
case DGRADT2 : tab_ret(it)= DgradT(2); break;
|
||||
case DGRADT3 : tab_ret(it)= DgradT(3); break;
|
||||
case TEMP : tab_ret(it)= ptIntegThermi.Temperature(); break;
|
||||
case X1 : tab_ret(it)= Mtdt(1); break;
|
||||
case X2 : tab_ret(it)= Mtdt(2); break;
|
||||
case X3 : tab_ret(it)= Mtdt(3); break;
|
||||
default :
|
||||
{int posi = (*ie).Position()-NbEnum_ddl();
|
||||
switch (posi)
|
||||
{ case 107: /*norme_gradT*/ tab_ret(it)=ptIntegThermi.Norme_gradT() ;break;
|
||||
case 108: /*norme_DgradT*/ tab_ret(it)=ptIntegThermi.Norme_DGradT_const() ;break;
|
||||
case 109: /*norme_dens_flux*/ tab_ret(it)=ptIntegThermi.Norme_flux_const() ;break;
|
||||
case 111: /*DeltagradT1*/ tab_ret(it)=DeltagradT(1) ;break;
|
||||
case 112: /*DeltagradT2*/ tab_ret(it)=DeltagradT(2) ;break;
|
||||
case 113: /*DeltagradT3*/ tab_ret(it)=DeltagradT(3) ;break;
|
||||
default :
|
||||
{cout << "\n cas de ddl actuellement non traite "
|
||||
<< "\n pas de ddl " << (*ie).Nom() << " dans l'element "
|
||||
<< "\n ou cas non implante pour l'instant"
|
||||
<< "\n ElemThermi::Valeur_multi(....";
|
||||
};
|
||||
}; // fin cas **** 2 >>>>>
|
||||
};
|
||||
};
|
||||
|
||||
};// -- fin de la boucle sur la liste de Ddl_enum_etendu
|
||||
|
||||
// liberation des tenseurs intermediaires
|
||||
LibereTenseur();
|
||||
return tab_ret;
|
||||
};
|
||||
|
||||
|
||||
// récupération des valeurs Tensorielles (et non scalaire comme avec Valeur_multi)
|
||||
// au numéro d'ordre = iteg pour les grandeur enu
|
||||
// enu contiend les grandeurs de retour
|
||||
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
||||
void ElemThermi::Valeurs_Tensorielles(bool absolue,Enum_dure temps,List_io<TypeQuelconque>& enu
|
||||
,int iteg,int cas )
|
||||
|
||||
{ // ----- def de grandeurs de travail
|
||||
// def de la dimension des tenseurs
|
||||
int dim = ParaGlob::Dimension();
|
||||
PtIntegThermiInterne & ptIntegThermi = (*lesPtIntegThermiInterne)(iteg);
|
||||
|
||||
|
||||
// def de conteneur pour la sortie
|
||||
Coordonnee* fluxD=NULL; bool besoin_fluxD = false;
|
||||
Coordonnee* gradT=NULL; bool besoin_gradT = false;
|
||||
Coordonnee* DgradT=NULL; bool besoin_DgradT = false;
|
||||
Coordonnee* DeltagradT=NULL; bool besoin_deltagradT = false;
|
||||
|
||||
Coordonnee* Mtdt=NULL; // coordonnées éventuelles du point d'intégration considéré
|
||||
bool besoin_coordonnees = false;
|
||||
|
||||
double* erreur = NULL; bool besoin_erreur = false;
|
||||
|
||||
// --- dev d'un ensemble de variable booléenne pour gérer les sorties en une passe -----
|
||||
// on se réfère au informations définit dans la méthode: Les_type_evolues_internes()
|
||||
|
||||
// on initialise ces variables booléennes
|
||||
List_io<TypeQuelconque>::iterator ipq,ipqfin=enu.end();
|
||||
for (ipq=enu.begin();ipq!=ipqfin;ipq++)
|
||||
{switch ((*ipq).EnuTypeQuelconque().EnumTQ()) //,FLUXD, GRADT, DGRADT
|
||||
{case FLUXD : {besoin_fluxD=true;
|
||||
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
|
||||
fluxD = gr.ConteneurCoordonnee(); break;}
|
||||
case GRADT : {besoin_gradT=true;
|
||||
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
|
||||
gradT = gr.ConteneurCoordonnee(); break;}
|
||||
|
||||
case DGRADT : {besoin_DgradT=true;
|
||||
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
|
||||
DgradT = gr.ConteneurCoordonnee(); break;}
|
||||
case DELTAGRADT : {besoin_deltagradT=true;
|
||||
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) ((*ipq).Grandeur_pointee()));
|
||||
DeltagradT = gr.ConteneurCoordonnee(); break;}
|
||||
|
||||
default :
|
||||
{// on initialise la grandeur pour éviter d'avoir des valeurs aléatoires
|
||||
((*ipq).Grandeur_pointee())->InitParDefaut();
|
||||
if (ParaGlob::NiveauImpression() > 0)
|
||||
{cout << "\nWarning : attention cas non traite: "
|
||||
<< ((*ipq).EnuTypeQuelconque().NomPlein()) << "!\n";
|
||||
if (ParaGlob::NiveauImpression() > 5)
|
||||
cout << "\n ElemThermi::Valeurs_Tensorielles(....";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// definition générale
|
||||
def->ChangeNumInteg(iteg); // on change le numéro de point d'intégration courant
|
||||
if (((cas == 1) || (cas == 2)))
|
||||
{ // cas d'une premiere initialisation
|
||||
Tableau<Enum_variable_metrique> tab(5);
|
||||
tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt;
|
||||
tab(4) = igiH_0; tab(5) = igijHH_0;
|
||||
met->PlusInitVariables(tab) ;
|
||||
}
|
||||
// éléments de métrique et matrices de passage
|
||||
TenseurHH* gijHH;TenseurBB* gijBB;
|
||||
Coordonnee* Mpt0;Coordonnee* Mptfin;
|
||||
BaseB * giB_0; BaseB * giB_tdt;
|
||||
BaseH * giH_0; BaseH * giH_tdt;
|
||||
Mat_pleine jB0(dim,dim),jBfin(dim,dim);
|
||||
if ((cas==1) || (cas==11))
|
||||
// calcul d'une ortho interessance de visualisation des tenseurs
|
||||
// cas de tenseur 3D -> Ia, cas 1D on prend un vecteur norme collineaire
|
||||
// avec g1, dans le cas 2D
|
||||
// la nouvelle base jB est calculee dans def par projection de "Ia" sur Galpha
|
||||
// le resultat est une matrice de passage utilisable pour le changement de base
|
||||
// jB0 a t=0, B pour les tenseurs BB, jH0 idem pour les tenseurs HH
|
||||
// resultat a t+dt
|
||||
{const Met_abstraite::InfoImp& ex = def->RemontImp(absolue,jB0,jBfin);
|
||||
Mpt0 = ex.M0; Mptfin = ex.Mtdt;
|
||||
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
|
||||
giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
|
||||
giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
|
||||
}
|
||||
else if ((cas==2) || (cas==12))
|
||||
// resultat a t
|
||||
{const Met_abstraite::InfoExp_tdt& ex= def->RemontExp_tdt(absolue,jB0,jBfin);
|
||||
Mpt0 = ex.M0; Mptfin = ex.Mtdt;
|
||||
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
|
||||
giB_0 = ex.giB_0;giB_tdt = ex.giB_tdt;
|
||||
giH_0 = ex.giH_0; giH_tdt = ex.giH_tdt;
|
||||
}
|
||||
else
|
||||
{ cout << "\n erreur, cas non prevu! " << "\n ElemThermi::Valeurs_Tensorielles(..."; Sortie(1);};
|
||||
|
||||
// ----- calcul des grandeurs à sortir
|
||||
|
||||
// ----- maintenant on calcule les grandeurs nécessaires -----
|
||||
|
||||
if (besoin_fluxD)
|
||||
{CoordonneeH & fluxDH = (ptIntegThermi.FluxH());
|
||||
CoordonneeB interB(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interB += (*giB_tdt)(i) * fluxDH(i);
|
||||
(*fluxD) = interB.Coor();
|
||||
};
|
||||
|
||||
if (besoin_gradT)
|
||||
{CoordonneeB & gradTB = (ptIntegThermi.GradTB());
|
||||
CoordonneeH interH(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += gradTB(i) * (*giH_tdt)(i);
|
||||
(*gradT) = interH.Coor();
|
||||
};
|
||||
|
||||
if (besoin_DgradT)
|
||||
{CoordonneeB & DgradTB = (ptIntegThermi.DgradTB());
|
||||
CoordonneeH interH(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += DgradTB(i) * (*giH_tdt)(i);
|
||||
(*DgradT) = interH.Coor();
|
||||
};
|
||||
|
||||
if (besoin_deltagradT)
|
||||
{CoordonneeB & DeltagradTB = (ptIntegThermi.DeltaGradTB());
|
||||
CoordonneeH interH(dim); // variable inter
|
||||
for (int i=1;i<= dim; i++)
|
||||
interH += DeltagradTB(i) * (*giH_tdt)(i);
|
||||
(*DeltagradT) = interH.Coor();
|
||||
};
|
||||
|
||||
if (besoin_coordonnees)
|
||||
(*Mtdt) = def->Position_tdt();
|
||||
|
||||
|
||||
// donnees propre a la loi thermique au pt d'integ
|
||||
CompThermoPhysiqueAbstraite::SaveResul* sTP = tabSaveTP(iteg);
|
||||
// donnees propre a la loi mécanique au pt d'integ
|
||||
Loi_comp_abstraite::SaveResul* sDon=NULL; // les données spécifique mécanique
|
||||
if (sDon != NULL) {sDon = tabSaveDon(iteg);}; // au pt d'integ si elles existes
|
||||
// données propre à la déformation au pt d'integ
|
||||
Deformation::SaveDefResul * sDefDon = tabSaveDefDon(iteg);
|
||||
|
||||
// liberation des tenseurs intermediaires
|
||||
LibereTenseur();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
847
Elements/Thermique/ElemThermi5.cc
Executable file
847
Elements/Thermique/ElemThermi5.cc
Executable file
|
@ -0,0 +1,847 @@
|
|||
// 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 "ElemThermi.h"
|
||||
#include <iomanip>
|
||||
#include "ConstMath.h"
|
||||
#include "Util.h"
|
||||
#include "Coordonnee2.h"
|
||||
#include "Coordonnee3.h"
|
||||
#include "TypeQuelconqueParticulier.h"
|
||||
#include "TypeConsTens.h"
|
||||
#include "Loi_iso_elas3D.h"
|
||||
#include "Loi_iso_elas1D.h"
|
||||
#include "Loi_iso_elas2D_C.h"
|
||||
#include "FrontPointF.h"
|
||||
|
||||
|
||||
// -------------------- stabilisation d'hourglass -------------------
|
||||
// calcul d'élément de contrôle d'hourglass associée à un comportement
|
||||
// str_precision : donne le type particulier d'élément à construire
|
||||
void ElemThermi::Init_hourglass_comp(const ElemGeomC0& elgeHour, const string & str_precision
|
||||
,LoiAbstraiteGeneral * loiHourglass, const BlocGen & bloc)
|
||||
{
|
||||
//!!!! en fait pour l'instant on n'utilise pas elgehour, on considère que le nombre de pti complet est celui de l'élément sans info annexe !!!
|
||||
// sauf pour l'hexaèdre quadratique pour lequel on a définit un str_precision particulier
|
||||
// on met à jour les indicateurs
|
||||
if (Type_Enum_StabHourglass_existe(bloc.Nom(1)))
|
||||
{type_stabHourglass = Id_Nom_StabHourglass(bloc.Nom(1).c_str());
|
||||
coefStabHourglass = bloc.Val(1);
|
||||
}
|
||||
else
|
||||
{ cout << "\n erreur, le type " << bloc.Nom(2) << " de gestion d'hourglass n'existe pas !!";
|
||||
if (ParaGlob::NiveauImpression() > 5)
|
||||
cout << "\n ElemThermi::Init_hourglass_comp(...";
|
||||
cout << endl;
|
||||
Sortie(1);
|
||||
};
|
||||
switch (type_stabHourglass)
|
||||
{case STABHOURGLASS_PAR_COMPORTEMENT :
|
||||
{ // -- choix de l'element pour le calcul de la raideur -----
|
||||
// on recherche un élément de même type,
|
||||
// par défaut : numéro de maillage = le numéro de this, car c'est bien rattaché à ce maillage, mais l'élément est caché, donc non accessible par le maillage
|
||||
// numéro d'élément = 1000000 + numéro de this : a priori c'est deux numéros n'ont pas d'importance, car ils ne sont pas
|
||||
// rattachés à un maillage existant en tant que tel
|
||||
int nUmMail = this->Num_elt_const();
|
||||
int nUmElem = 1000000 + this->Num_elt();
|
||||
tab_elHourglass.Change_taille(1);
|
||||
tab_elHourglass(1) = (ElemThermi*) Element::Choix_element(nUmMail,nUmElem,Id_geometrie(),Id_interpolation(),Id_TypeProblem(),str_precision);
|
||||
|
||||
if (tab_elHourglass(1) == NULL)
|
||||
{ // l'operation a echouee
|
||||
cout << "\n Erreur dans le choix d'un element interne utilise pour le blocage d'hourglass ****** ";
|
||||
cout << "\n l\'element : " << Nom_interpol(id_interpol)
|
||||
<< " " << Nom_geom(id_geom) << " " << str_precision
|
||||
<< " n\'est pas present dans le programme ! " << endl;
|
||||
if (ParaGlob::NiveauImpression() > 5)
|
||||
cout << "\n ElemThermi::Init_hourglass_comp(..." << endl;
|
||||
Sortie (1);
|
||||
};
|
||||
// --- définition des noeuds de l'élément -----
|
||||
// on construit à partir des mêmes noeuds que ceux de l'élément père
|
||||
// affectation des noeuds au nouvel élément
|
||||
tab_elHourglass(1)->Tab_noeud() = this->Tab_noeud();
|
||||
//--- def de la loi de comportement ---
|
||||
// affectation de la loi
|
||||
tab_elHourglass(1)->DefLoi(loiHourglass);
|
||||
break;
|
||||
}
|
||||
case STABHOURGLASS_PAR_COMPORTEMENT_REDUIT :
|
||||
{ // ici on a besoin de deux éléments. Le premier sert à faire le calcul complet
|
||||
// le second sert à faire un calcul réduit, comme l'élément réel
|
||||
tab_elHourglass.Change_taille(2);
|
||||
|
||||
// -- choix pour le calcul de la raideur -----
|
||||
// on recherche un élément de même type,
|
||||
// par défaut : numéro de maillage = le numéro de this, car c'est bien rattaché à ce maillage, mais l'élément est caché, donc non accessible par le maillage
|
||||
// numéro d'élément = 1000000 + numéro de this : a priori c'est deux numéros n'ont pas d'importance, car ils ne sont pas
|
||||
// rattachés à un maillage existant en tant que tel
|
||||
//-- le premier élément:
|
||||
int nUmMail = this->Num_elt_const();
|
||||
int nUmElem = 1000000 + this->Num_elt();
|
||||
tab_elHourglass(1) = (ElemThermi*) Element::Choix_element(nUmMail,nUmElem,Id_geometrie(),Id_interpolation(),Id_TypeProblem(),str_precision);
|
||||
if (tab_elHourglass(1) == NULL)
|
||||
{ // l'operation a echouee
|
||||
cout << "\n Erreur dans le choix d'un element interne utilise pour le blocage d'hourglass ****** ";
|
||||
cout << "\n l\'element : " << Nom_interpol(id_interpol)
|
||||
<< " " << Nom_geom(id_geom) << " " << str_precision
|
||||
<< " n\'est pas present dans le programme ! " << endl;
|
||||
if (ParaGlob::NiveauImpression() > 5)
|
||||
cout << "\n ElemThermi::Init_hourglass_comp(..." << endl;
|
||||
Sortie (1);
|
||||
};
|
||||
//-- le second élément identique à this: on utilise le même numéro de maillage
|
||||
// même infos annexes
|
||||
nUmElem = 20000000 + this->Num_elt(); // on ajoute une unité pour le numéro
|
||||
tab_elHourglass(2) = (ElemThermi*) Element::Choix_element(nUmMail,nUmElem,Id_geometrie(),Id_interpolation(),Id_TypeProblem(),this->infos_annexes);
|
||||
|
||||
if (tab_elHourglass(2) == NULL)
|
||||
{ // l'operation a echouee
|
||||
cout << "\n Erreur dans le choix d'un element interne utilise pour le blocage d'hourglass ****** ";
|
||||
cout << "\n l\'element : " << Nom_interpol(id_interpol)
|
||||
<< " " << Nom_geom(id_geom) << " " << this->infos_annexes
|
||||
<< " n\'est pas present dans le programme ! " << endl;
|
||||
if (ParaGlob::NiveauImpression() > 5)
|
||||
cout << "\n ElemThermi::Init_hourglass_comp(..." << endl;
|
||||
Sortie (1);
|
||||
};
|
||||
// --- définition des noeuds de l'élément -----
|
||||
// on construit à partir des mêmes noeuds que ceux de l'élément père
|
||||
// affectation des noeuds au nouvel élément
|
||||
tab_elHourglass(1)->Tab_noeud() = this->Tab_noeud();
|
||||
tab_elHourglass(2)->Tab_noeud() = this->Tab_noeud();
|
||||
//--- def de la loi de comportement ---
|
||||
// affectation de la loi
|
||||
tab_elHourglass(1)->DefLoi(loiHourglass);
|
||||
tab_elHourglass(2)->DefLoi(loiHourglass);
|
||||
break;
|
||||
}
|
||||
|
||||
default :
|
||||
cout << "\n*** Erreur : cas de gestop, d'hourglass non defini !\n";
|
||||
cout << "\n ElemThermi::Cal_implicit_hourglass() \n";
|
||||
Sortie(1);
|
||||
};
|
||||
};
|
||||
|
||||
// stabilisation pour un calcul implicit
|
||||
void ElemThermi::Cal_implicit_hourglass()
|
||||
{ switch (type_stabHourglass)
|
||||
{case STABHOURGLASS_PAR_COMPORTEMENT :
|
||||
{ // --- calcul de la raideur de l'élément, dans le cas implicite ---
|
||||
Element::ResRaid resraid = tab_elHourglass(1)->Calcul_implicit (ParaGlob::param->ParaAlgoControleActifs());
|
||||
// on tiend compte du facteur de modération
|
||||
(*(resraid.raid)) *= coefStabHourglass;
|
||||
(*(resraid.res)) *= coefStabHourglass;
|
||||
// on met à jour la raideur et le résidu de l'élément principal
|
||||
(*raideur) += (*(resraid.raid));
|
||||
(*residu) += (*(resraid.res));
|
||||
|
||||
//---- debug
|
||||
//cout << "\n raideur locale après stabilisation d'hourglass ";
|
||||
//matRaideur.Affiche();
|
||||
//---- fin debug
|
||||
};
|
||||
break;
|
||||
case STABHOURGLASS_PAR_COMPORTEMENT_REDUIT :
|
||||
{ // --- calcul de la raideur de l'élément, dans le cas implicite ---
|
||||
// ici on calcul la partie supposée supplémentaire à celle déjà présente dans le calcul réduit
|
||||
|
||||
// au premier passage ou bien si on demande une grande précision de calcul, on calcul la raideur et le second membre,
|
||||
// ensuite on ne calcul que le second membre
|
||||
if ((raid_hourglass_transitoire == NULL)||(prepa_niveau_precision > 8))
|
||||
{// 1) calcul de la partie complète
|
||||
Element::ResRaid resraid1 = tab_elHourglass(1)->Calcul_implicit (ParaGlob::param->ParaAlgoControleActifs());
|
||||
// 2) calcul de la partie réduite
|
||||
Element::ResRaid resraid2 = tab_elHourglass(2)->Calcul_implicit (ParaGlob::param->ParaAlgoControleActifs());
|
||||
// on soustrait en gardant le résultat dans resraid1
|
||||
(*(resraid1.raid)) -= (*(resraid2.raid));
|
||||
(*(resraid1.res)) -= (*(resraid2.res));
|
||||
// on tiend compte du facteur de modération
|
||||
(*(resraid1.raid)) *= coefStabHourglass;
|
||||
(*(resraid1.res)) *= coefStabHourglass;
|
||||
// on sauvegarde la raideur
|
||||
raid_hourglass_transitoire = new Mat_pleine((*(resraid1.raid)));
|
||||
// on met à jour la raideur et le résidu de l'élément principal
|
||||
(*raideur) += (*(resraid1.raid));
|
||||
(*residu) += (*(resraid1.res));
|
||||
}
|
||||
else
|
||||
{// sinon on utilise la précédente raideur sauvegardée et on ne calcul que la partie résidue
|
||||
Vecteur* resHourglass1 = NULL;
|
||||
resHourglass1 = tab_elHourglass(1)->CalculResidu_tdt (ParaGlob::param->ParaAlgoControleActifs());
|
||||
Vecteur* resHourglass2 = NULL;
|
||||
resHourglass2 = tab_elHourglass(2)->CalculResidu_tdt (ParaGlob::param->ParaAlgoControleActifs());
|
||||
// on soustrait les résidus en gardant le résultat dans resraid1
|
||||
(*(resHourglass1)) -= (*(resHourglass2));
|
||||
// on tiend compte du facteur de modération
|
||||
(*(resHourglass1)) *= coefStabHourglass;
|
||||
// on met à jour le résidu de l'élément principal
|
||||
(*residu) += (*(resHourglass1));
|
||||
// pour la partie raideur: on met à jour la raideur de l'élément principal
|
||||
(*raideur) += (*raid_hourglass_transitoire);
|
||||
};
|
||||
|
||||
//---- debug
|
||||
//cout << "\n raideur locale après stabilisation d'hourglass ";
|
||||
//matRaideur.Affiche();
|
||||
//---- fin debug
|
||||
};
|
||||
break;
|
||||
case STABHOURGLASS_NON_DEFINIE :
|
||||
// on ne fait rien
|
||||
break;
|
||||
default :
|
||||
cout << "\n*** Erreur : cas de gestop, d'hourglass non defini !\n";
|
||||
cout << "\n ElemThermi::Cal_implicit_hourglass() \n";
|
||||
Sortie(1);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// stabilisation pour un calcul explicit
|
||||
void ElemThermi::Cal_explicit_hourglass(bool atdt)
|
||||
{ switch (type_stabHourglass)
|
||||
{case STABHOURGLASS_PAR_COMPORTEMENT :
|
||||
{ // --- calcul de la raideur de l'élément, dans le cas implicite ---
|
||||
Vecteur* resHourglass = NULL;
|
||||
if (atdt)
|
||||
{resHourglass = tab_elHourglass(1)->CalculResidu_tdt (ParaGlob::param->ParaAlgoControleActifs());}
|
||||
else
|
||||
{resHourglass = tab_elHourglass(1)->CalculResidu_t (ParaGlob::param->ParaAlgoControleActifs());};
|
||||
// on tiend compte du facteur de modération
|
||||
(*resHourglass) *= coefStabHourglass;
|
||||
// on met à jour le résidu de l'élément principal
|
||||
(*residu) += (*resHourglass);
|
||||
|
||||
//---- debug
|
||||
//cout << "\n raideur locale après stabilisation d'hourglass ";
|
||||
//matRaideur.Affiche();
|
||||
//---- fin debug
|
||||
};
|
||||
break;
|
||||
case STABHOURGLASS_NON_DEFINIE :
|
||||
// on ne fait rien
|
||||
break;
|
||||
default :
|
||||
cout << "\n*** Erreur : cas de gestop, d'hourglass non defini !\n";
|
||||
cout << "\n ElemThermi::Cal_implicit_hourglass() \n";
|
||||
Sortie(1);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
// récupération de l'energie d'hourglass éventuelle
|
||||
double ElemThermi::Energie_Hourglass()
|
||||
{ double enerHourglass = 0.;
|
||||
switch (type_stabHourglass)
|
||||
{case STABHOURGLASS_PAR_COMPORTEMENT :
|
||||
{ // on récupère les énergies stockées à l'élément
|
||||
const EnergieThermi& energieTotale = tab_elHourglass(1)->EnergieTotaleElement();
|
||||
enerHourglass = coefStabHourglass * (energieTotale.EnergieElastique()
|
||||
+ energieTotale.DissipationPlastique() + energieTotale.DissipationVisqueuse());
|
||||
};
|
||||
break;
|
||||
};
|
||||
return enerHourglass;
|
||||
};
|
||||
|
||||
// fonction a renseigner par les classes dérivées, concernant les répercutions
|
||||
// éventuelles due à la suppression de tous les frontières
|
||||
// nums_i : donnent les listes de frontières supprimées
|
||||
void ElemThermi::Prise_en_compte_des_consequences_suppression_tous_frontieres()
|
||||
{// il faut supprimer toutes les déformations liés aux frontières
|
||||
int tail_S = defSurf.Taille();
|
||||
for (int i=1;i<=tail_S;i++)
|
||||
{ delete defSurf(i);
|
||||
defSurf(i)=NULL;
|
||||
};
|
||||
int tail_A = defArete.Taille();
|
||||
for (int i=1;i<=tail_A;i++)
|
||||
{ delete defArete(i);
|
||||
defArete(i)=NULL;
|
||||
};
|
||||
};
|
||||
// idem pour une frontière (avant qu'elle soit supprimée)
|
||||
void ElemThermi::Prise_en_compte_des_consequences_suppression_une_frontiere(ElFrontiere* elemFront)
|
||||
{ int taille = tabb.Taille();
|
||||
// on choisit en fonction du type de frontière
|
||||
if (( elemFront->Type_geom_front() == LIGNE)&& (defArete.Taille()!=0))
|
||||
{int taille_ligne = taille - posi_tab_front_lin; // a priori = cas sans les points
|
||||
if (posi_tab_front_point != 0) // cas où il y a des points
|
||||
taille_ligne = posi_tab_front_point-posi_tab_front_lin;
|
||||
for (int i=1; i<=taille_ligne; i++)
|
||||
{if ((tabb(i+posi_tab_front_lin) == elemFront)&& (defArete(i) != NULL))
|
||||
{delete defArete(i);defArete(i)=NULL;break;}
|
||||
}
|
||||
}
|
||||
else if (( elemFront->Type_geom_front() == SURFACE) && (defSurf.Taille()!=0))
|
||||
{if (posi_tab_front_lin != 0) // si == 0 cela signifie qu'il n'y a pas de surface à supprimer !!
|
||||
{ for (int i=1; i<=posi_tab_front_lin; i++) // posi_tab_front_lin == le nombre de surfaces, qui sont obligatoirement en début de tableau
|
||||
if ((tabb(i) == elemFront)&& (defSurf(i) != NULL))
|
||||
{delete defSurf(i);defSurf(i)=NULL;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
|
||||
// cas :
|
||||
// = 0 -> on veut toutes les frontières
|
||||
// = 1 -> on veut uniquement les surfaces
|
||||
// = 2 -> on veut uniquement les lignes
|
||||
// = 3 -> on veut uniquement les points
|
||||
// = 4 -> on veut les surfaces + les lignes
|
||||
// = 5 -> on veut les surfaces + les points
|
||||
// = 6 -> on veut les lignes + les points
|
||||
Tableau <ElFrontiere*> const & ElemThermi::Frontiere_elethermi(int cas, 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
|
||||
int taille = tabb.Taille(); // la taille initiales des frontières
|
||||
if (force) // dans ce cas on commence par tout effacer
|
||||
{ // on efface les surfaces (s'il y en a)
|
||||
for (int i=1;i<=posi_tab_front_lin;i++)
|
||||
{if (tabb(i) != NULL)
|
||||
{delete tabb(i); //on commence par supprimer
|
||||
tabb(i)=NULL;
|
||||
// on supprime également éventuellement la déformation associée
|
||||
if (defSurf.Taille() != 0)
|
||||
if (defSurf(i) != NULL)
|
||||
{delete defSurf(i);defSurf(i)=NULL;};
|
||||
ind_front_surf = 0; // on indique qu'il ne reste plus de frontière surface
|
||||
};
|
||||
};
|
||||
// on efface les lignes (s'il y en a)
|
||||
for (int i=1;i<=posi_tab_front_point - posi_tab_front_lin;i++)
|
||||
{if (tabb(i+posi_tab_front_lin) != NULL)
|
||||
{delete tabb(i+posi_tab_front_lin); //on commence par supprimer
|
||||
tabb(i+posi_tab_front_lin)=NULL;
|
||||
// on supprime également éventuellement la déformation associée
|
||||
if (defArete.Taille() != 0)
|
||||
if (defArete(i) != NULL)
|
||||
{delete defArete(i);defArete(i)=NULL;};
|
||||
ind_front_lin = 0; // on indique qu'il ne reste plus de frontière ligne
|
||||
};
|
||||
};
|
||||
// on efface les points (s'il y en a)
|
||||
for (int i=1;i<=taille - posi_tab_front_point;i++)
|
||||
{if (tabb(i+posi_tab_front_point) != NULL)
|
||||
{delete tabb(i+posi_tab_front_point); //on commence par supprimer
|
||||
tabb(i+posi_tab_front_point)=NULL;
|
||||
ind_front_point = 0; // on indique qu'il ne reste plus de frontière ligne
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// -- maintenant on s'occupe de la construction conditionnelle
|
||||
bool built_surf = false;bool built_ligne = false; bool built_point = false;
|
||||
switch (cas)
|
||||
{case 0: built_surf = built_ligne = built_point = true; break;
|
||||
case 1: built_surf = true; break;
|
||||
case 2: built_ligne = true; break;
|
||||
case 3: built_point = true; break;
|
||||
case 4: built_surf = built_ligne = true; break;
|
||||
case 5: built_surf = built_point = true; break;
|
||||
};
|
||||
|
||||
if ( ((ind_front_surf == 0)&& (ind_front_lin == 0) && (ind_front_point == 0)) || force )
|
||||
{
|
||||
// récup de l'élément géométrique
|
||||
ElemGeomC0& el = ElementGeometrique();
|
||||
int tail_ar = el.NbSe(); // nombre potentiel d'arêtes
|
||||
int tail_fa = el.NbFe(); // nombre potentiel de faces
|
||||
int tail_po = el.Nbne(); // nombre potentiel de points
|
||||
// récup du tableau de ddl actuel
|
||||
const DdlElement & tdd = TableauDdl();
|
||||
|
||||
// --- on va construire en fonction des indicateurs des tableaux intermédiaires
|
||||
int new_posi_tab_front_point = 0; //init par défaut
|
||||
int new_posi_tab_front_lin = 0; //init par défaut
|
||||
int new_ind_front_point = 0;
|
||||
int new_ind_front_lin = 0;
|
||||
int new_ind_front_surf = 0;
|
||||
// -- pour les surfaces
|
||||
Tableau <ElFrontiere*> tabb_surf;
|
||||
if ((built_surf)&& ((ind_front_surf == 0)||force))
|
||||
{tabb_surf.Change_taille(tail_fa,NULL);// init par défaut
|
||||
for (int num=1;num<=tail_fa;num++)
|
||||
{ int nbnoe = el.Nonf()(num).Taille(); // nb noeud de la surface
|
||||
Tableau <Noeud *> tab(nbnoe); // les noeuds de la frontiere
|
||||
DdlElement ddelem(nbnoe); // les ddlelements des noeuds frontieres
|
||||
for (int i=1;i<= nbnoe;i++)
|
||||
{ tab(i) = tab_noeud(el.Nonf()(num)(i));
|
||||
ddelem.Change_un_ddlNoeudElement(i,tdd(el.Nonf()(num)(i)));
|
||||
};
|
||||
tabb_surf(num) = new_frontiere_surf(num,tab,ddelem);
|
||||
};
|
||||
// nouveau indicateur d'existence
|
||||
new_ind_front_surf = 1;
|
||||
// on positionne les nouvelles positions
|
||||
new_posi_tab_front_point += tail_fa;
|
||||
new_posi_tab_front_lin += tail_fa;
|
||||
};
|
||||
// -- pour les lignes
|
||||
Tableau <ElFrontiere*> tabb_ligne;
|
||||
if ((built_ligne)&& ((ind_front_lin == 0)||force))
|
||||
{tabb_ligne.Change_taille(tail_ar,NULL);// init par défaut
|
||||
for (int num=1;num<=tail_ar;num++)
|
||||
{ int nbnoe = el.NonS()(num).Taille(); // nb noeud de l'arête
|
||||
Tableau <Noeud *> tab(nbnoe); // les noeuds de l'arête frontiere
|
||||
DdlElement ddelem(nbnoe); // les ddlelements des noeuds frontieres
|
||||
for (int i=1;i<= nbnoe;i++)
|
||||
{ tab(i) = tab_noeud(el.NonS()(num)(i));
|
||||
ddelem.Change_un_ddlNoeudElement(i,tdd(el.NonS()(num)(i)));
|
||||
};
|
||||
tabb_ligne(num) = new_frontiere_lin(num,tab,ddelem);
|
||||
};
|
||||
// nouveau indicateur d'existence
|
||||
new_ind_front_lin = 1;
|
||||
// on positionne les nouvelles positions
|
||||
new_posi_tab_front_point += tail_ar;
|
||||
};
|
||||
// -- pour les points
|
||||
Tableau <ElFrontiere*> tabb_point;
|
||||
if ((built_point) && ((ind_front_point == 0)||force))
|
||||
{tabb_point.Change_taille(tail_po,NULL);// init par défaut
|
||||
// maintenant création des frontière point éventuellement
|
||||
Tableau <Noeud *> tab(1); // les noeuds de la frontiere (tab de travail)
|
||||
DdlElement ddelem(1); // les ddlelements des points frontieres (tab de travail)
|
||||
for (int i=1;i<=tail_po;i++)
|
||||
if (tabb_point(i) == NULL)
|
||||
{ tab(1) = tab_noeud(i);
|
||||
ddelem.Change_un_ddlNoeudElement(1,tdd(i));
|
||||
tabb_point(i) = new FrontPointF(tab,ddelem);
|
||||
};
|
||||
// nouveau indicateur d'existence
|
||||
new_ind_front_point = 1;
|
||||
};
|
||||
|
||||
// --- mise à jour du tableau globale et des indicateurs ad hoc
|
||||
int taille_finale = tabb_surf.Taille()+tabb_ligne.Taille()+tabb_point.Taille();
|
||||
tabb.Change_taille(taille_finale);
|
||||
// cas des points
|
||||
if (new_ind_front_point) // là is s'agit de nouveaux éléments
|
||||
{for (int i=tail_po;i>0;i--) // transfert pour les noeuds
|
||||
{ tabb(i+new_posi_tab_front_point) = tabb_point(i);}
|
||||
}
|
||||
else if (ind_front_point) // là il s'agit d'anciens éléments
|
||||
{for (int i=tail_po;i>0;i--) // transfert pour les noeuds en descendant
|
||||
{ tabb(i+new_posi_tab_front_point) = tabb(i+posi_tab_front_point);}
|
||||
};
|
||||
// cas des lignes
|
||||
if (new_ind_front_lin) // là il s'agit de nouveaux éléments
|
||||
{for (int i=1;i<=tail_ar;i++) // transfert
|
||||
{ tabb(i+new_posi_tab_front_lin) = tabb_ligne(i);}
|
||||
}
|
||||
else if (ind_front_lin) // là il s'agit d'anciens éléments
|
||||
{for (int i=tail_ar;i>0;i--) // transfert en descendant
|
||||
{ tabb(i+new_posi_tab_front_lin) = tabb(i+posi_tab_front_lin);}
|
||||
};
|
||||
// cas des surfaces
|
||||
if (new_ind_front_surf) // là is s'agit de nouveaux éléments
|
||||
{for (int i=1;i<=tail_fa;i++) // transfert
|
||||
{ tabb(i) = tabb_surf(i);}
|
||||
};
|
||||
// dans le cas où il y avait des anciens éléments, il n'y a rien n'a faire
|
||||
// car le redimentionnement de tabb ne change pas les premiers éléments
|
||||
|
||||
// mis à jour des indicateurs
|
||||
ind_front_surf = new_ind_front_surf;
|
||||
posi_tab_front_lin = new_posi_tab_front_lin;
|
||||
ind_front_lin = new_ind_front_lin;
|
||||
posi_tab_front_point = new_posi_tab_front_point;
|
||||
ind_front_point = new_ind_front_point;
|
||||
};
|
||||
// retour du tableau
|
||||
return (Tableau <ElFrontiere*>&)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 ElemThermi::Frontiere_points(int num,bool force)
|
||||
{ // -- tout d'abord on évacue le cas où il n'y a pas de frontière surfacique à calculer
|
||||
// récup de l'élément géométrique
|
||||
ElemGeomC0& el = ElementGeometrique();
|
||||
int tail_po = el.Nbne(); // nombre potentiel de points
|
||||
if (num > tail_po)
|
||||
return NULL;
|
||||
|
||||
// le calcul et la création ne sont effectués qu'au premier appel
|
||||
// ou lorsque l'on veut forcer une recréation
|
||||
// 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);
|
||||
};
|
||||
|
||||
// arrivée ici cela veut dire que la frontière point n'existe pas
|
||||
// on l'a reconstruit éventuellement
|
||||
|
||||
|
||||
// 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_point == 0) || force )
|
||||
{// récup du tableau de ddl
|
||||
const DdlElement & tdd = TableauDdl();
|
||||
int taille = tabb.Taille(); // la taille initiales des frontières
|
||||
int tail_fa = el.NbFe(); // nombre potentiel de faces
|
||||
int tail_ar = el.NbSe(); // nombre potentiel d'arêtes
|
||||
// dimensionnement du tableau de frontières ligne si nécessaire
|
||||
if (ind_front_point == 0)
|
||||
{if ((ind_front_lin > 0) && (ind_front_surf == 0))
|
||||
// cas où les frontières lignes existent seules, on ajoute les points
|
||||
{ int taille_finale = tail_ar + tail_po;
|
||||
tabb.Change_taille(taille_finale);
|
||||
for (int i=1;i<= tail_ar;i++) // transfert pour les lignes
|
||||
tabb(i) = tabb(i+tail_ar);
|
||||
posi_tab_front_point=tail_ar;
|
||||
posi_tab_front_lin = 0; // car on n'a pas de surface
|
||||
}
|
||||
else if ((ind_front_lin > 0) && (ind_front_surf > 0))
|
||||
// cas où les frontières lignes existent et surfaces et pas de points, donc on les rajoutes
|
||||
{ int taille_finale = tail_fa + tail_po+tail_ar;
|
||||
tabb.Change_taille(taille_finale);// les grandeurs pour les surfaces et les lignes sont
|
||||
// conservées, donc pas de transferts à prévoir
|
||||
posi_tab_front_point=tail_ar+tail_fa; // après les faces et les lignes
|
||||
posi_tab_front_lin = tail_fa; // après les surfaces
|
||||
}
|
||||
else
|
||||
{ // cas où il n'y a pas de frontières lignes
|
||||
if (ind_front_surf == 0) // cas où il n'y a pas de surface
|
||||
{tabb.Change_taille(tail_po,NULL); // on n'a pas de ligne, pas de point et pas de surface
|
||||
posi_tab_front_point = posi_tab_front_lin = 0;}
|
||||
else {tabb.Change_taille(tail_po+tail_fa); // cas où les surfaces existent
|
||||
// le redimensionnement n'affecte pas les surfaces qui sont en début de tableau
|
||||
posi_tab_front_lin = posi_tab_front_point = tail_fa; // après les surfaces
|
||||
};
|
||||
};
|
||||
// et on met les pointeurs de points en NULL
|
||||
for (int i=1;i<= tail_po;i++)
|
||||
{ tabb(i+posi_tab_front_point) = NULL;}
|
||||
};
|
||||
// maintenant création de la frontière point
|
||||
Tableau <Noeud *> tab(1); // les noeuds de la frontiere
|
||||
tab(1) = tab_noeud(num);
|
||||
DdlElement ddelem(1); // les ddlelements des points frontieres
|
||||
ddelem.Change_un_ddlNoeudElement(1,tdd(num));
|
||||
tabb(posi_tab_front_point+num) = new FrontPointF(tab,ddelem);
|
||||
// on met à jour l'indicateur ind_front_point
|
||||
ind_front_point = 1; // a priori
|
||||
for (int npoint=1;npoint<=tail_po;npoint++)
|
||||
if (tabb(posi_tab_front_point+npoint) == NULL)
|
||||
{ ind_front_point = 2; break;};
|
||||
};
|
||||
// maintenant normalement la frontière est créé on la ramène
|
||||
return (ElFrontiere*)tabb(posi_tab_front_point+num);
|
||||
};
|
||||
|
||||
// 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)
|
||||
// nbneA: nombre de noeuds des segments frontières
|
||||
// el : l'élément
|
||||
ElFrontiere* const ElemThermi::Frontiere_lineique(int num,bool force)
|
||||
{ // -- tout d'abord on évacue le cas où il n'y a pas de frontière linéique à calculer
|
||||
// récup de l'élément géométrique
|
||||
ElemGeomC0& el = ElementGeometrique();
|
||||
int tail_ar = el.NbSe(); // nombre potentiel d'arêtes
|
||||
if (num > tail_ar)
|
||||
return NULL;
|
||||
|
||||
// le calcul et la création ne sont effectués qu'au premier appel
|
||||
// ou lorsque l'on veut forcer une recréation
|
||||
// on regarde si les frontières linéiques existent sinon on les crée
|
||||
if (ind_front_lin == 1)
|
||||
{return (ElFrontiere*)tabb(posi_tab_front_lin+num);}
|
||||
else if ( ind_front_lin == 2)
|
||||
// cas où certaines frontières existent
|
||||
{if (tabb(posi_tab_front_lin+num) != NULL)
|
||||
return (ElFrontiere*)tabb(posi_tab_front_lin+num);
|
||||
};
|
||||
|
||||
// arrivée ici cela veut dire que la frontière ligne n'existe pas
|
||||
// on l'a reconstruit
|
||||
|
||||
|
||||
// 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) || force )
|
||||
{// récup du tableau de ddl
|
||||
const DdlElement & tdd = TableauDdl();
|
||||
int taille = tabb.Taille(); // la taille initiales des frontières
|
||||
int tail_fa = el.NbFe(); // nombre potentiel de faces
|
||||
int tail_po = el.Nbne(); // nombre potentiel de points
|
||||
// dimensionnement du tableau de frontières ligne si nécessaire
|
||||
if (ind_front_lin == 0)
|
||||
{if ((ind_front_point > 0) && (ind_front_surf == 0))
|
||||
// cas où les frontières points existent seules, on ajoute les lignes
|
||||
{ int taille_finale = tail_ar + tail_po;
|
||||
tabb.Change_taille(taille_finale);
|
||||
for (int i=1;i<= tail_po;i++)
|
||||
tabb(i+tail_ar) = tabb(i);
|
||||
posi_tab_front_point=tail_ar;
|
||||
posi_tab_front_lin = 0; // car on n'a pas de surface
|
||||
}
|
||||
else if ((ind_front_point > 0) && (ind_front_surf > 0))
|
||||
// cas où les frontières points existent et surfaces et pas de ligne, donc on les rajoutes
|
||||
{ int taille_finale = tail_fa + tail_po+tail_ar;
|
||||
tabb.Change_taille(taille_finale);// les grandeurs pour les surfaces sont conservées
|
||||
for (int i=1;i<= tail_po;i++) // transfert pour les noeuds
|
||||
{ tabb(i+tail_ar+tail_fa) = tabb(i+tail_fa);};
|
||||
posi_tab_front_point=tail_ar+tail_fa; // après les faces et les lignes
|
||||
posi_tab_front_lin = tail_fa; // après les surfaces
|
||||
}
|
||||
else
|
||||
{ // cas où il n'y a pas de frontières points
|
||||
if (ind_front_surf == 0) // cas où il n'y a pas de surface
|
||||
{tabb.Change_taille(tail_ar,NULL); // on n'a pas de ligne, pas de point et pas de surface
|
||||
posi_tab_front_lin = posi_tab_front_point = 0;}
|
||||
else {tabb.Change_taille(tail_ar+tail_fa); // cas où les surfaces existent
|
||||
// le redimensionnement n'affecte pas les surfaces qui sont en début de tableau
|
||||
posi_tab_front_lin = posi_tab_front_point = tail_fa; // après les surfaces
|
||||
};
|
||||
};
|
||||
// et on met les pointeurs de lignes en NULL
|
||||
for (int i=1;i<= tail_ar;i++) // transfert pour les noeuds
|
||||
{ tabb(i+posi_tab_front_lin) = NULL;}
|
||||
};
|
||||
// maintenant création de la ligne
|
||||
int nbnoe = el.NonS()(num).Taille(); // nb noeud de l'arête
|
||||
Tableau <Noeud *> tab(nbnoe); // les noeuds de l'arête frontiere
|
||||
DdlElement ddelem(nbnoe); // les ddlelements des noeuds frontieres
|
||||
for (int i=1;i<= nbnoe;i++)
|
||||
{ tab(i) = tab_noeud(el.NonS()(num)(i));
|
||||
ddelem.Change_un_ddlNoeudElement(i,tdd(el.NonS()(num)(i)));
|
||||
};
|
||||
tabb(posi_tab_front_lin+num) = new_frontiere_lin(num,tab,ddelem);
|
||||
ind_front_lin = 1; // a priori
|
||||
for (int nlign=1;nlign<=tail_ar;nlign++)
|
||||
if (tabb(posi_tab_front_lin+nlign) == NULL)
|
||||
{ ind_front_lin = 2; break;};
|
||||
};
|
||||
// maintenant normalement la frontière est créé on la ramène
|
||||
return (ElFrontiere*)tabb(posi_tab_front_lin+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)
|
||||
ElFrontiere* const ElemThermi::Frontiere_surfacique(int num,bool force)
|
||||
{ // -- tout d'abord on évacue le cas où il n'y a pas de frontière surfacique à calculer
|
||||
// récup de l'élément géométrique
|
||||
ElemGeomC0& el = ElementGeometrique();
|
||||
int tail_fa = el.NbFe(); // nombre potentiel de faces
|
||||
if (num > tail_fa)
|
||||
return NULL;
|
||||
|
||||
// le calcul et la création ne sont effectués qu'au premier appel
|
||||
// ou lorsque l'on veut forcer une recréation
|
||||
// on regarde si les frontières surfacique existent sinon on les crée
|
||||
if (ind_front_surf == 1)
|
||||
{return (ElFrontiere*)tabb(num);}
|
||||
else if ( ind_front_surf == 2)
|
||||
// cas où certaines frontières existent
|
||||
{if (tabb(num) != NULL)
|
||||
return (ElFrontiere*)tabb(num);
|
||||
};
|
||||
|
||||
// arrivée ici cela veut dire que la frontière surface n'existe pas
|
||||
// on l'a reconstruit
|
||||
|
||||
|
||||
// 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_surf == 0) || force )
|
||||
{// récup du tableau de ddl
|
||||
const DdlElement & tdd = TableauDdl();
|
||||
int taille = tabb.Taille(); // la taille initiales des frontières
|
||||
int tail_ar = el.NbSe(); // nombre potentiel d'arêtes
|
||||
int tail_po = el.Nbne(); // nombre potentiel de points
|
||||
// dimensionnement du tableau de frontières surfaces si nécessaire
|
||||
if (ind_front_surf == 0)
|
||||
{if ((ind_front_point > 0) && (ind_front_lin == 0))
|
||||
// cas où les frontières points existent seules, on ajoute les surfaces
|
||||
{ int taille_finale = tail_fa + tail_po;
|
||||
tabb.Change_taille(taille_finale);
|
||||
for (int i=1;i<= tail_po;i++)
|
||||
tabb(i+tail_fa) = tabb(i);
|
||||
posi_tab_front_lin=posi_tab_front_point=tail_fa;
|
||||
}
|
||||
else if ((ind_front_point > 0) && (ind_front_lin > 0))
|
||||
// cas où les frontières points existent et lignes et pas de surfaces, donc on les rajoutes
|
||||
{ int taille_finale = tail_fa + tail_po+tail_ar;
|
||||
tabb.Change_taille(taille_finale);
|
||||
// --transfert pour les noeuds et les lignes
|
||||
for (int i=1;i<= tail_po;i++) // transfert pour les noeuds
|
||||
{ tabb(i+tail_ar+tail_fa) = tabb(i+tail_ar);};
|
||||
for (int i=1;i<= tail_ar;i++) // transfert pour les lignes
|
||||
{ tabb(i+tail_fa) = tabb(i);};
|
||||
// --def des indicateurs
|
||||
posi_tab_front_point=tail_ar+tail_fa; // après les faces et les lignes
|
||||
posi_tab_front_lin = tail_fa; // après les surfaces
|
||||
}
|
||||
else
|
||||
{ // cas où il n'y a pas de frontières points
|
||||
if (ind_front_lin == 0) // cas où il n'y a pas de lignes
|
||||
{tabb.Change_taille(tail_fa,NULL); // on n'a pas de ligne, pas de point et pas de surface
|
||||
posi_tab_front_lin = posi_tab_front_point = tail_fa;
|
||||
} // on peut tout mettre à NULL
|
||||
else {tabb.Change_taille(tail_ar+tail_fa); // cas où les lignes existent
|
||||
for (int i=1;i<= tail_ar;i++) // transfert pour les lignes
|
||||
tabb(i+tail_fa) = tabb(i);
|
||||
posi_tab_front_lin = posi_tab_front_point = tail_fa; // après les surfaces
|
||||
};
|
||||
};
|
||||
// --et on met les pointeurs de surfaces en NULL
|
||||
for (int i=1;i<=tail_fa;i++)
|
||||
tabb(i)=NULL;
|
||||
};
|
||||
// maintenant création de la surface
|
||||
int nbnoe = el.Nonf()(num).Taille(); // b noeud de la surface
|
||||
Tableau <Noeud *> tab(nbnoe); // les noeuds de la frontiere
|
||||
DdlElement ddelem(nbnoe); // les ddlelements des noeuds frontieres
|
||||
for (int i=1;i<= nbnoe;i++)
|
||||
{ tab(i) = tab_noeud(el.Nonf()(num)(i));
|
||||
ddelem.Change_un_ddlNoeudElement(i,tdd(el.Nonf()(num)(i)));
|
||||
};
|
||||
tabb(num) = new_frontiere_surf(num,tab,ddelem);
|
||||
ind_front_surf = 1; // a priori
|
||||
for (int nsurf=1;nsurf<=tail_fa;nsurf++)
|
||||
if (tabb(nsurf) == NULL)
|
||||
{ ind_front_surf = 2; break;};
|
||||
};
|
||||
// maintenant normalement la frontière est créé on la ramène
|
||||
return (ElFrontiere*)tabb(num);
|
||||
};
|
||||
|
||||
|
||||
// calcul éventuel de la normale à un noeud
|
||||
// ce calcul existe pour les éléments 2D, 1D axi, et aussi pour les éléments 1D
|
||||
// qui possède un repère d'orientation
|
||||
// en retour coor = la normale si coor.Dimension() est = à la dimension de l'espace
|
||||
// si le calcul n'existe pas --> coor.Dimension() = 0
|
||||
// ramène un entier :
|
||||
// == 1 : calcul normal
|
||||
// == 0 : problème de calcul -> coor.Dimension() = 0
|
||||
// == 2 : indique que le calcul n'est pas licite pour le noeud passé en paramètre
|
||||
// c'est le cas par exemple des noeuds exterieurs pour les éléments SFE
|
||||
// mais il n'y a pas d'erreur, c'est seulement que l'élément n'est pas ad hoc pour
|
||||
// calculer la normale à ce noeud là
|
||||
// temps: indique à quel moment on veut le calcul
|
||||
// pour des éléments particulier (ex: SFE) la méthode est surchargée
|
||||
int ElemThermi::CalculNormale_noeud(Enum_dure temps,const Noeud& noe,Coordonnee& coor)
|
||||
{
|
||||
int retour = 1; // init du retour : on part d'un bon a priori
|
||||
Enum_type_geom enutygeom = Type_geom_generique(this->Id_geometrie());
|
||||
// if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
|
||||
if (enutygeom != SURFACE) // dans une première étape on ne s'occupe que des surfaces
|
||||
{coor.Libere(); // pas de calcul possible
|
||||
retour = 0;
|
||||
}
|
||||
else // sinon le calcul est possible
|
||||
{ // on commence par repérer le noeud dans la numérotation locale
|
||||
int nuoe=0;
|
||||
int borne_nb_noeud=tab_noeud.Taille()+1;
|
||||
for (int i=1;i< borne_nb_noeud;i++)
|
||||
{Noeud& noeloc = *tab_noeud(i);
|
||||
if ( (noe.Num_noeud() == noeloc.Num_noeud())
|
||||
&& (noe.Num_Mail() == noeloc.Num_Mail())
|
||||
)
|
||||
{nuoe = i; break;
|
||||
};
|
||||
};
|
||||
// on ne continue que si on a trouvé le noeud
|
||||
if (nuoe != 0)
|
||||
{ ElemGeomC0& elemgeom = ElementGeometrique(); // récup de la géométrie
|
||||
// récup des coordonnées locales du noeuds
|
||||
const Coordonnee& theta_noeud = elemgeom.PtelemRef()(nuoe);
|
||||
// récup des phi et dphi au noeud
|
||||
const Vecteur & phi = elemgeom.Phi(theta_noeud);
|
||||
const Mat_pleine& dphi = elemgeom.Dphi(theta_noeud);
|
||||
switch (temps)
|
||||
{case TEMPS_0 :
|
||||
{const BaseB& baseB = met->BaseNat_0(tab_noeud,dphi,phi);
|
||||
coor = Util::ProdVec_coor( baseB.Coordo(1), baseB.Coordo(2));
|
||||
coor.Normer();
|
||||
break;
|
||||
}
|
||||
case TEMPS_t :
|
||||
{const BaseB& baseB = met->BaseNat_t(tab_noeud,dphi,phi);
|
||||
coor = Util::ProdVec_coor( baseB.Coordo(1), baseB.Coordo(2));
|
||||
coor.Normer();
|
||||
break;
|
||||
}
|
||||
case TEMPS_tdt :
|
||||
{const BaseB& baseB = met->BaseNat_tdt(tab_noeud,dphi,phi);
|
||||
coor = Util::ProdVec_coor( baseB.Coordo(1), baseB.Coordo(2));
|
||||
coor.Normer();
|
||||
break;
|
||||
}
|
||||
default :
|
||||
cout << "\nErreur : valeur incorrecte du temps demande = "
|
||||
<< Nom_dure(temps) << " !\n";
|
||||
cout << "\n ElemThermi::CalculNormale_noeud(Enum_dure temps... \n";
|
||||
retour = 0;
|
||||
Sortie(1);
|
||||
};
|
||||
}
|
||||
else
|
||||
{cout << "\n *** erreur le noeud demande num= "<<noe.Num_noeud()
|
||||
<< " du maillage "<< noe.Num_Mail()
|
||||
<< " ne fait pas parti de l'element "
|
||||
<< num_elt << " du maillage "<< noe.Num_Mail()
|
||||
<< " on ne peut pas calculer la normale au noeud !!"
|
||||
<< "\n ElemThermi::CalculNormale_noeud(...";
|
||||
retour = 0;
|
||||
Sortie(1);
|
||||
}
|
||||
};
|
||||
// retour
|
||||
return retour;
|
||||
};
|
||||
|
76
Elements/Thermique/ExceptionsElemThermi.h
Executable file
76
Elements/Thermique/ExceptionsElemThermi.h
Executable file
|
@ -0,0 +1,76 @@
|
|||
// 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/>.
|
||||
|
||||
/************************************************************************
|
||||
* DATE: 06/03/2023 *
|
||||
* $ *
|
||||
* AUTEUR: G RIO (mailto:gerardrio56@free.fr) *
|
||||
* $ *
|
||||
* PROJET: Herezh++ *
|
||||
* $ *
|
||||
************************************************************************
|
||||
* BUT: Définir des classes d'exception pour la gestion d'erreur *
|
||||
* concernant les éléments thermiques. *
|
||||
* $ *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' * *
|
||||
* VERIFICATION: *
|
||||
* *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* ! ! ! ! *
|
||||
* $ *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
|
||||
* MODIFICATIONS: *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* $ *
|
||||
************************************************************************/
|
||||
#ifndef EXCEPTIONSELEMTHERMI_H
|
||||
#define EXCEPTIONSELEMTHERMI_H
|
||||
|
||||
|
||||
/// @addtogroup groupe_des_elements_finis
|
||||
/// @{
|
||||
///
|
||||
|
||||
// cas d'une erreur survenue à cause d'un jacobien négatif
|
||||
|
||||
class ErrJacobienNegatif_ElemThermi {};
|
||||
/// @} // end of group
|
||||
|
||||
|
||||
/// @addtogroup groupe_des_elements_finis
|
||||
/// @{
|
||||
///
|
||||
|
||||
// cas d'une erreur survenue à cause d'une variation de jacobien trop grande
|
||||
|
||||
class ErrVarJacobienMini_ElemThermi {};
|
||||
/// @} // end of group
|
||||
|
||||
#endif
|
243
Elements/Thermique/LesPtIntegThermiInterne.cc
Executable file
243
Elements/Thermique/LesPtIntegThermiInterne.cc
Executable file
|
@ -0,0 +1,243 @@
|
|||
// 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 "LesPtIntegThermiInterne.h"
|
||||
|
||||
|
||||
// contructeur par défaut
|
||||
LesPtIntegThermiInterne::LesPtIntegThermiInterne():
|
||||
tabPtInt(),tabfluxH(),tabfluxH_t()
|
||||
{};
|
||||
|
||||
// contructeur fonction du nombre de points d'intégration et de la dimension de tenseurs
|
||||
LesPtIntegThermiInterne::LesPtIntegThermiInterne(int nbpti, int dimtens):
|
||||
tabPtInt(nbpti,PtIntegThermiInterne(dimtens)),tabfluxH(nbpti),tabfluxH_t(nbpti)
|
||||
{ // on relie les tableaux entre eux
|
||||
for (int i=1; i<= nbpti; i++)
|
||||
{tabfluxH(i)= &tabPtInt(i).FluxH();
|
||||
tabfluxH_t(i)= &tabPtInt(i).FluxH_t();
|
||||
};
|
||||
};
|
||||
|
||||
// contructeur de copie
|
||||
LesPtIntegThermiInterne::LesPtIntegThermiInterne(const LesPtIntegThermiInterne& lespti):
|
||||
tabPtInt(lespti.tabPtInt),tabfluxH(lespti.tabfluxH.Taille())
|
||||
,tabfluxH_t(lespti.tabfluxH_t.Taille())
|
||||
{ // on relie les tableaux entre eux
|
||||
int nbpti = tabPtInt.Taille();
|
||||
for (int i=1; i<= nbpti; i++)
|
||||
{tabfluxH(i)= &tabPtInt(i).FluxH();
|
||||
tabfluxH_t(i)= &tabPtInt(i).FluxH_t();
|
||||
};
|
||||
};
|
||||
|
||||
// DESTRUCTEUR :
|
||||
// normalement il n'y a rien n'a faire car les pointeurs sont des copies
|
||||
LesPtIntegThermiInterne::~LesPtIntegThermiInterne()
|
||||
{ };
|
||||
|
||||
// Surcharge de l'operateur =
|
||||
LesPtIntegThermiInterne& LesPtIntegThermiInterne::operator= ( const LesPtIntegThermiInterne& lespti)
|
||||
{ int newTaille = lespti.NbPti();
|
||||
tabPtInt = lespti.tabPtInt;
|
||||
tabfluxH.Change_taille(newTaille);
|
||||
tabfluxH_t.Change_taille(newTaille);
|
||||
// on relie les tableaux entre eux
|
||||
int nbpti = tabPtInt.Taille();
|
||||
for (int i=1; i<= nbpti; i++)
|
||||
{tabfluxH(i)= &tabPtInt(i).FluxH();
|
||||
tabfluxH_t(i)= &tabPtInt(i).FluxH_t();
|
||||
};
|
||||
// retour
|
||||
return *this;
|
||||
};
|
||||
|
||||
// changement de taille donc de nombre de points d'intégration
|
||||
// fonction du nombre de points d'intégration et de la dimension de tenseurs
|
||||
// attention: il s'agit d'un dimentionnement pas défaut (les activations diverses
|
||||
// sont ensuite à faire: par exemple pour les invariants)
|
||||
void LesPtIntegThermiInterne::Change_taille_PtIntegThermi(int nbpti, int dimtens)
|
||||
{ // tout d'abord on adapte la taille
|
||||
tabPtInt.Change_taille(nbpti,PtIntegThermiInterne(dimtens));
|
||||
tabfluxH.Change_taille(nbpti);
|
||||
tabfluxH_t.Change_taille(nbpti);
|
||||
// on relie les tableaux entre eux
|
||||
for (int i=1; i<= nbpti; i++)
|
||||
{tabfluxH(i)= &tabPtInt(i).FluxH();
|
||||
tabfluxH_t(i)= &tabPtInt(i).FluxH_t();
|
||||
};
|
||||
};
|
||||
// idem, mais les instances ajoutées ou retirer ont la même dimension de tenseur que celles
|
||||
// qui existent déjà
|
||||
void LesPtIntegThermiInterne::Change_taille_PtIntegThermi(int nbpti)
|
||||
{ // tout d'abord on adapte la taille
|
||||
tabPtInt.Change_taille(nbpti);
|
||||
tabfluxH.Change_taille(nbpti);
|
||||
tabfluxH_t.Change_taille(nbpti);
|
||||
// on relie les tableaux entre eux
|
||||
for (int i=1; i<= nbpti; i++)
|
||||
{tabfluxH(i)= &tabPtInt(i).FluxH();
|
||||
tabfluxH_t(i)= &tabPtInt(i).FluxH_t();
|
||||
};
|
||||
};
|
||||
|
||||
// retour la dimension des coordonnées gérés
|
||||
int LesPtIntegThermiInterne::DimCoord() const
|
||||
{if (tabPtInt.Taille() != 0)
|
||||
{return tabPtInt(1).GradTB().Dimension();}
|
||||
else
|
||||
{return 0;};
|
||||
};
|
||||
|
||||
//============= 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 LesPtIntegThermiInterne::Lecture_base_info (ifstream& ent,const int cas)
|
||||
{switch (cas)
|
||||
{ case 1 : // ------- on récupère tout -------------------------
|
||||
{ string nom; ent >> nom; // on ne vérifie pas le nom car on considère que
|
||||
// ça a été écrit par le prog associé
|
||||
int taille = 0;
|
||||
ent >> nom >> taille; // lecture de la taille
|
||||
tabPtInt.Change_taille(taille);
|
||||
tabfluxH.Change_taille(taille);
|
||||
tabfluxH_t.Change_taille(taille);
|
||||
// lecture
|
||||
for (int i=1;i<=taille;i++)
|
||||
tabPtInt(i).Lecture_base_info (ent,cas);
|
||||
// on relie les tableaux entre eux
|
||||
for (int i=1; i<= taille; i++)
|
||||
{tabfluxH(i)= &tabPtInt(i).FluxH();
|
||||
tabfluxH_t(i)= &tabPtInt(i).FluxH_t();
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 2 : // ----------- lecture uniquement de se qui varie --------------------
|
||||
{ string nom; ent >> nom; // on ne vérifie pas le nom car on considère que
|
||||
// ça a été écrit par le prog associé
|
||||
// lecture
|
||||
int taille = tabPtInt.Taille();
|
||||
for (int i=1;i<=taille;i++)
|
||||
tabPtInt(i).Lecture_base_info (ent,cas);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{ cout << "\nErreur : valeur incorrecte du type de lecture !\n";
|
||||
cout << "LesPtIntegThermiInterne::Lecture_base_info(ifstream& ent,const "
|
||||
<< " 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 LesPtIntegThermiInterne::Ecriture_base_info(ofstream& sort,const int cas)
|
||||
{switch (cas)
|
||||
{ case 1 : // ------- on sauvegarde tout -------------------------
|
||||
{ sort << "\n grandeurs_aux_points_d_integration:" ;
|
||||
int taille = tabPtInt.Taille();
|
||||
sort << " taille= " << taille << " " ;
|
||||
for (int i=1;i<=taille;i++)
|
||||
tabPtInt(i).Ecriture_base_info(sort,cas);
|
||||
break;
|
||||
}
|
||||
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
|
||||
{ sort << "\n grandeurs_aux_points_d_integration:" ;
|
||||
int taille = tabPtInt.Taille();
|
||||
for (int i=1;i<=taille;i++)
|
||||
tabPtInt(i).Ecriture_base_info(sort,cas);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{ cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
|
||||
cout << "LesPtIntegThermiInterne::Ecriture_base_info(ofstream& sort,const int cas)"
|
||||
<< " cas= " << cas << endl;
|
||||
Sortie(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// actualisation des grandeurs actives de t+dt vers t, pour celles qui existent
|
||||
// sous ces deux formes
|
||||
void LesPtIntegThermiInterne::TdtversT()
|
||||
{ int taille = tabPtInt.Taille();
|
||||
for (int i=1;i<=taille;i++)
|
||||
tabPtInt(i).TdtversT();
|
||||
};
|
||||
|
||||
// actualisation des grandeurs actives de t vers tdt, pour celles qui existent
|
||||
// sous ces deux formes
|
||||
void LesPtIntegThermiInterne::TversTdt()
|
||||
{ int taille = tabPtInt.Taille();
|
||||
for (int i=1;i<=taille;i++)
|
||||
tabPtInt(i).TversTdt();
|
||||
};
|
||||
|
||||
|
||||
// surcharge de l'operateur de lecture
|
||||
istream & operator >> (istream & entree, LesPtIntegThermiInterne & lespti)
|
||||
{ // vérification du type
|
||||
string nom;
|
||||
entree >> nom;
|
||||
#ifdef MISE_AU_POINT
|
||||
if (nom != "LesPtIntegThermiInterne")
|
||||
{ cout << "\nErreur, en lecture d'une instance LesPtIntegThermiInterne "
|
||||
<< " on attendait LesPtIntegThermiInterne et on a lue: " << nom ;
|
||||
cout << "istream & operator >> (istream & entree, LesPtIntegThermiInterne & pti)\n";
|
||||
Sortie(1);
|
||||
};
|
||||
#endif
|
||||
// puis lecture des différents éléments
|
||||
lespti.tabPtInt.Entree(entree);
|
||||
// on s'occupe des pointeurs
|
||||
int nbpti = lespti.tabPtInt.Taille();
|
||||
lespti.tabfluxH.Change_taille(nbpti);
|
||||
lespti.tabfluxH_t.Change_taille(nbpti);
|
||||
// on relie les tableaux entre eux
|
||||
for (int i=1; i<= nbpti; i++)
|
||||
{lespti.tabfluxH(i)= &lespti.tabPtInt(i).FluxH();
|
||||
lespti.tabfluxH_t(i)= &lespti.tabPtInt(i).FluxH_t();
|
||||
};
|
||||
return entree;
|
||||
};
|
||||
|
||||
// surcharge de l'operateur d'ecriture
|
||||
ostream & operator << ( ostream & sort,const LesPtIntegThermiInterne & lespti)
|
||||
{ // tout d'abord un indicateur donnant le type
|
||||
sort << "LesPtIntegThermiInterne " ;
|
||||
// puis les différents éléments (pas les pointeurs qui n'ont aucun intérêt ici)
|
||||
lespti.tabPtInt.Sortir(sort);
|
||||
return sort;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
134
Elements/Thermique/LesPtIntegThermiInterne.h
Executable file
134
Elements/Thermique/LesPtIntegThermiInterne.h
Executable file
|
@ -0,0 +1,134 @@
|
|||
// 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/>.
|
||||
|
||||
/************************************************************************
|
||||
* DATE: 06/03/2023 *
|
||||
* $ *
|
||||
* AUTEUR: G RIO (mailto:gerardrio56@free.fr) *
|
||||
* $ *
|
||||
* PROJET: Herezh++ *
|
||||
* $ *
|
||||
************************************************************************
|
||||
* BUT: Classe pour stocker l'ensemble des informations aux points *
|
||||
* d'intégration thermique *
|
||||
* $ *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
|
||||
* VERIFICATION: *
|
||||
* *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* ! ! ! ! *
|
||||
* $ *
|
||||
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
|
||||
* MODIFICATIONS: *
|
||||
* ! date ! auteur ! but ! *
|
||||
* ------------------------------------------------------------ *
|
||||
* $ *
|
||||
************************************************************************/
|
||||
#ifndef LESPTINTEGTHERMIINTERNE_H
|
||||
#define LESPTINTEGTHERMIINTERNE_H
|
||||
|
||||
#include "PtIntegThermiInterne.h"
|
||||
|
||||
/// @addtogroup Groupe_concernant_les_points_integration
|
||||
/// @{
|
||||
///
|
||||
|
||||
|
||||
class LesPtIntegThermiInterne
|
||||
|
||||
{ // surcharge de l'operator de lecture
|
||||
friend istream & operator >> (istream &, LesPtIntegThermiInterne &);
|
||||
// surcharge de l'operator d'ecriture
|
||||
friend ostream & operator << (ostream &, const LesPtIntegThermiInterne &);
|
||||
|
||||
public :
|
||||
// CONSTRUCTEURS :
|
||||
// contructeur par défaut
|
||||
LesPtIntegThermiInterne();
|
||||
// contructeur fonction du nombre de points d'intégration et de la dimension des coordonnees
|
||||
LesPtIntegThermiInterne(int nbpti, int dimcoor);
|
||||
// contructeur de copie
|
||||
LesPtIntegThermiInterne(const LesPtIntegThermiInterne& lespti);
|
||||
|
||||
// DESTRUCTEUR :
|
||||
~LesPtIntegThermiInterne();
|
||||
|
||||
// METHODES PUBLIQUES :
|
||||
// Surcharge de l'operateur =
|
||||
LesPtIntegThermiInterne& operator= ( const LesPtIntegThermiInterne& lespti);
|
||||
|
||||
// le tableau des grandeurs aux points d'intégration
|
||||
// en lecture écriture
|
||||
Tableau <PtIntegThermiInterne>& TabPtIntThermi() {return tabPtInt;};
|
||||
// l'élément PtIntegThermiInterne de numéro i
|
||||
PtIntegThermiInterne& operator () (int i) {return tabPtInt(i);};
|
||||
|
||||
|
||||
// les tableaux des densité de flux
|
||||
Tableau <CoordonneeH *>& TabfluxH() {return tabfluxH;}; // densité flux finale
|
||||
Tableau <CoordonneeH *>& TabfluxH_t() {return tabfluxH_t;}; // densité flux au début de l'incrément
|
||||
// nombre de points d'intégration
|
||||
int NbPti() const {return tabPtInt.Taille();};
|
||||
// changement de taille donc de nombre de points d'intégration
|
||||
// fonction du nombre de points d'intégration et de la dimension des coordonnees
|
||||
void Change_taille_PtIntegThermi(int nbpti, int dimtens);
|
||||
// idem, mais les instances ajoutées ou retirer ont la même dimension de coordonnees que celles
|
||||
// qui existent déjà
|
||||
void Change_taille_PtIntegThermi(int nbpti);
|
||||
// retour la dimension des vecteurs gérés
|
||||
int DimCoord() const;
|
||||
// actualisation des grandeurs actives de t+dt vers t, pour celles qui existent
|
||||
// sous ces deux formes
|
||||
void TdtversT();
|
||||
// actualisation des grandeurs actives de t vers tdt, pour celles qui existent
|
||||
// sous ces deux formes
|
||||
void TversTdt();
|
||||
|
||||
//============= 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 Lecture_base_info (ifstream& ent,const int cas);
|
||||
// cas donne le niveau de sauvegarde
|
||||
// = 1 : on sauvegarde tout
|
||||
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
|
||||
void Ecriture_base_info(ofstream& sort,const int cas);
|
||||
|
||||
protected:
|
||||
// données protégées
|
||||
// grandeurs aux points d'intégration
|
||||
Tableau <PtIntegThermiInterne> tabPtInt;
|
||||
// densité de flux groupées sous forme de tableau, qui pointent sur celles de tabPtThermiInt
|
||||
Tableau <CoordonneeH *> tabfluxH; // densité flux finale
|
||||
Tableau <CoordonneeH *> tabfluxH_t; // densité flux au début de l'incrément
|
||||
|
||||
};
|
||||
/// @} // end of group
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue