Herezh_dev/herezh_pp/Elements/Mecanique/SFE/SfeMembT.cc

1489 lines
76 KiB
C++
Executable file

// FICHIER : SfeMembT.cc
// CLASSE : SfeMembT
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
# include <iostream>
#include <cmath>
using namespace std; //introduces namespace std
#include <stdlib.h>
#include "Sortie.h"
#include "MathUtil.h"
#include "SfeMembT.h"
#include "TypeConsTens.h"
#include "FrontPointF.h"
#include "Loi_Umat.h"
#include "ExceptionsElemMeca.h"
#include "ExceptionsLoiComp.h"
#include "CharUtil.h"
// =========================== variables communes ===============================
// a priori les pointeurs de fonction pointent sur rien au debut
TenseurHH* SfeMembT::sig_bulk_pourSfe_HH = NULL; // variable de travail pour le bulk
// =========================== fin variables communes ===========================
// ---- definition du constructeur de la classe conteneur de donnees communes ------------
SfeMembT::DonnComSfe::DonnComSfe (ElemGeomC0* elCentre,const GeomSeg& seg,const DdlElement& tab
,DdlElement& tabErr,DdlElement& tab_Err1Sig,DdlElement& t_ddlXi_C
,const Met_Sfe1& met_gene,
Tableau <Vecteur *> & resEr,Mat_pleine& raidEr,
ElemGeomC0* elEr,GeomSeg& segEr,ElemGeomC0* elS,GeomSeg& segmS
,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,
Tableau <Vecteur* >& residus_extS,Tableau <Mat_pleine* >& raideurs_extS,
Mat_pleine& mat_masse,ElemGeomC0* elMas,const GeomSeg& segMas,int nbi,
Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan
,Tableau <int>& nMetddl,const Met_abstraite& met_cent ) :
eleCentre(elCentre),segment(seg),tab_ddl(tab),tab_ddlErr(tabErr),tab_Err1Sig11(tab_Err1Sig)
,tab_ddlXi_C(t_ddlXi_C),met_SfeMembT(met_gene)
,matGeom(tab.NbDdl(),tab.NbDdl()),matInit(tab.NbDdl(),tab.NbDdl())
,d_epsBB(tab.NbDdl()),d_sigHH(tab.NbDdl()),d2_epsBB(nbi)
,resErr(resEr),raidErr(raidEr),eleEr(elEr),segmentEr(segEr),eleS(elS),segS(segmS)
,residu_interne(residu_int),raideur_interne(raideur_int)
,residus_externeN(residus_extN),raideurs_externeN(raideurs_extN)
,residus_externeA(residus_extA),raideurs_externeA(raideurs_extA)
,residus_externeS(residus_extS),raideurs_externeS(raideurs_extS)
,matrice_masse(mat_masse),eleMas(elMas),segmentMas(segMas)
,tabType_rienCL(tabTypeCL),vplan_rien(vplan)
,nMetVTab_ddl(nMetddl),met_surf_cent(met_cent)
,sfematD(NULL),sferesD(NULL),noeud_a_prendre_en_compte(NULL)
{
int nbddl = tab.NbDdl();
int dim_tens = met_gene.Nbvec_des_bases();
for (int ni=1;ni<=nbi;ni++)
{d2_epsBB(ni).Change_taille(nbddl);
for (int i1=1; i1<= nbddl; i1++)
for (int i2=1; i2<= nbddl; i2++)
d2_epsBB(ni)(i1,i2) = NevezTenseurBB (dim_tens);
};
// int tailledeps = d_epsBB.Taille();
// for (int i=1;i<= tailledeps; i++)
for (int i=1;i<= nbddl; i++)
d_epsBB(i) = NevezTenseurBB (dim_tens);
// int tailledsig = d_sigHH.Taille();
// for (int j=1;j<= tailledsig; j++)
for (int j=1;j<= nbddl; j++)
d_sigHH(j) = NevezTenseurHH (dim_tens);
};
// Il ne doit exister qu'un exemplaire de la classe, donc au niveau du constructeur de copie les tableaux
// de pointeurs pointes sur les mêmes entités que la valeur passée en paramètre
SfeMembT::DonnComSfe::DonnComSfe(DonnComSfe& a) :
eleCentre(a.eleCentre),segment(a.segment)
,tab_ddl(a.tab_ddl),tab_ddlErr(a.tab_ddlErr),tab_Err1Sig11(a.tab_Err1Sig11)
,tab_ddlXi_C(a.tab_ddlXi_C),met_SfeMembT(a.met_SfeMembT),matGeom(a.matGeom)
,matInit(a.matInit),d2_epsBB(a.d2_epsBB),resErr(a.resErr),raidErr(a.raidErr)
,eleEr(a.eleEr),segmentEr(a.segmentEr),eleS(a.eleS),segS(a.segS)
,d_epsBB(a.d_epsBB),d_sigHH(a.d_sigHH)
,residu_interne(a.residu_interne),raideur_interne(a.raideur_interne)
,residus_externeN(a.residus_externeN),raideurs_externeN(a.raideurs_externeN)
,residus_externeA(a.residus_externeA),raideurs_externeA(a.raideurs_externeA)
,residus_externeS(a.residus_externeS),raideurs_externeS(a.raideurs_externeS)
,matrice_masse(a.matrice_masse),eleMas(a.eleMas),segmentMas(a.segmentMas)
,tabType_rienCL(a.tabType_rienCL),vplan_rien(a.vplan_rien)
,nMetVTab_ddl(a.nMetVTab_ddl),met_surf_cent(a.met_surf_cent)
,sfematD(NULL),sferesD(NULL),noeud_a_prendre_en_compte(NULL)
{ int nbddl = tab_ddl.NbDdl();
int nbi=d2_epsBB.Taille();
for (int ni=1;ni<=nbi;ni++)
for (int i1=1; i1<= nbddl; i1++)
for (int i2=1; i2<= nbddl; i2++)
d2_epsBB(ni)(i1,i2) = NevezTenseurBB (*(a.d2_epsBB(ni)(i1,i2)));
// int tailledeps = d_epsBB.Taille();
// for (int i=1;i<= tailledeps; i++)
for (int i=1;i<= nbddl; i++)
d_epsBB(i) = NevezTenseurBB (*(a.d_epsBB(i)));
// int tailledsig = d_sigHH.Taille();
// for (int j=1;j<= tailledsig; j++)
for (int j=1;j<= nbddl; j++)
d_sigHH(j) = NevezTenseurHH (*(d_sigHH(j)));
// cas d'une stabilisation éventuelle
if (a.sfematD != NULL)
sfematD = new Mat_pleine(*a.sfematD);
if (a.sferesD != NULL)
sferesD = new Vecteur (*a.sferesD);
if (a.noeud_a_prendre_en_compte != NULL)
noeud_a_prendre_en_compte = new Tableau<int> (*a.noeud_a_prendre_en_compte);
};
// certaines grandeurs pointées qui n'exitent qu'en un seul exemplaire
// ne seront supprimées que par l'ordre destruction,
SfeMembT::DonnComSfe::DonnComSfe::~DonnComSfe()
{ int nbddl = tab_ddl.NbDdl();
int nbi=d2_epsBB.Taille();
for (int ni=1;ni<=nbi;ni++)
for (int i1=1; i1<= nbddl; i1++)
for (int i2=1; i2<= nbddl; i2++)
delete d2_epsBB(ni)(i1,i2);
int tailledeps = d_epsBB.Taille();
for (int i=1;i<= tailledeps; i++)
delete d_epsBB(i);
int tailledsig = d_sigHH.Taille();
for (int j=1;j<= tailledsig; j++)
delete d_sigHH(j);
// cas d'une stabilisation éventuelle
if (sfematD != NULL)
delete sfematD;
if (sferesD != NULL)
delete sferesD;
if (noeud_a_prendre_en_compte != NULL)
delete noeud_a_prendre_en_compte;
};
// ---------- fin definition de la classe conteneur de donnees communes ------------
// -+-+ definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
SfeMembT::UneFois::UneFois () : // constructeur par défaut
doCoMemb(NULL),CalResPrem_t(0),CalResPrem_tdt(0),CalimpPrem(0),dualSortSfe(0)
,CalSMlin_t(0),CalSMlin_tdt(0),CalSMRlin(0)
,CalSMsurf_t(0),CalSMsurf_tdt(0),CalSMRsurf(0)
,CalSMvol_t(0),CalSMvol_tdt(0),CalSMvol(0)
,CalDynamique(0),CalPt_0_t_tdt(0)
,nbelem_in_Prog(0)
{};
SfeMembT::UneFois::~UneFois ()
{ delete doCoMemb;
};
// -+-+ fin definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
// CONSTRUCTEURS :
// Constructeur par defaut
SfeMembT::SfeMembT () :
ElemMeca(),lesPtMecaInt(),donnee_specif(),areteTypeCL(NULL),vplan(NULL)
,t_N_centre(),unefois(NULL),nombre(NULL)
{ lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca
};
// Constructeur fonction d'un numero
// d'identification , d'identificateur d'interpolation et de geometrie
SfeMembT::SfeMembT (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,string info) :
ElemMeca(num_mail,num_id,id_interp_elt,id_geom_elt,info),lesPtMecaInt(),donnee_specif()
,areteTypeCL(NULL),vplan(NULL),t_N_centre(),unefois(NULL),nombre(NULL)
{ lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca
};
// Constructeur fonction d'un numero de maillage et d'identification,
// du tableau de connexite des noeuds, d'identificateur d'interpolation et de geometrie
SfeMembT::SfeMembT (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,
const Tableau<Noeud *>& tab,string info) :
ElemMeca(num_mail,num_id,tab,id_interp_elt,id_geom_elt,info),lesPtMecaInt(),donnee_specif()
,areteTypeCL(NULL),vplan(NULL),t_N_centre(),unefois(NULL),nombre(NULL)
{ lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca
};
// Constructeur de copie
SfeMembT::SfeMembT (const SfeMembT& SfeM) :
ElemMeca (SfeM)
,lesPtMecaInt(SfeM.lesPtMecaInt)
,donnee_specif(SfeM.donnee_specif),unefois(SfeM.unefois),nombre(SfeM.nombre)
,areteTypeCL(SfeM.areteTypeCL),vplan(SfeM.vplan),t_N_centre(SfeM.t_N_centre)
{ lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca
// --- cas des différentes puissances et ... ---
SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
residu = &(CoSfe->residu_interne); // residu local
raideur = &(CoSfe->raideur_interne); // raideur locale
// --- cas de la dynamique -----
mat_masse = &(CoSfe->matrice_masse);
// --- cas des efforts externes concernant noeuds ------
res_extN = &(CoSfe->residus_externeN); // pour les résidus et second membres
raid_extN= &(CoSfe->raideurs_externeN);// pour les raideurs
// --- cas des efforts externes concernant les aretes ------
res_extA = &(CoSfe->residus_externeA); // pour les résidus et second membres
raid_extA= &(CoSfe->raideurs_externeA);// pour les raideurs
// --- cas des efforts externes concernant les faces ------
res_extS= &(CoSfe->residus_externeS); // pour les résidus et second membres
raid_extS= &(CoSfe->raideurs_externeS); // pour les raideurs
// pour les conditions limites on les crée si besoin
if (areteTypeCL != (&(unefois->doCoMemb->tabType_rienCL)))
{ // si ça ne pointe pas sur la valeur par défaut, alors c'est qu'il y a
// des CL particulières, on les crée donc à l'identique
areteTypeCL = new Tableau <EnuTypeCL> (*(SfeM.areteTypeCL));
vplan = new Tableau <Coordonnee3> (*(SfeM.vplan));
};
};
// DESTRUCTEUR :
SfeMembT::~SfeMembT ()
{ /* // on va libérer les déformations d'arrête et de surface qui sont un peu particulières
if (defArete.Taille() != 0)
if (defArete(1) != NULL)
{ delete defArete(1);
// on remet à null les pointeurs pour un appel correcte du destructeur d'elemMeca
for (int ia=1;ia<= 12; ia++)
defArete(ia) = NULL;
}
if (defSurf.Taille() != 0)
if (defSurf(1) != NULL)
{ delete defSurf(1);
// on remet à null les pointeurs pour un appel correcte du destructeur d'elemMeca
for (int ia=1;ia<= 12; ia++)
defSurf(ia) = NULL;
} */
// concernant tous les éléments qui sont définit qu'une seule fois, leur destruction est effectuée avec la méthode destruction
// appelée par les classes descendantes
LibereTenseur();
};
// Lecture des donnees de la classe sur fichier
void SfeMembT::LectureDonneesParticulieres
(UtilLecture * entreePrinc,Tableau<Noeud *> * tabMaillageNoeud)
{ int nb;int nbnte = nombre->nbnte;
tab_noeud.Change_taille(nbnte);
for (int i=1; i<= nbnte; i++)
{ *(entreePrinc->entree) >> nb;
if ((entreePrinc->entree)->rdstate() == 0)
// pour mémoire ici on a
/* enum io_state
{ badbit = 1<<0, // -> 1 dans rdstate()
eofbit = 1<<1, // -> 2
failbit = 1<<2, // -> 4
goodbit = 0 // -> O
};*/
tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
#ifdef ENLINUX
else if ((entreePrinc->entree)->fail())
// on a atteind la fin de la ligne et on appelle un nouvel enregistrement
{ entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
*(entreePrinc->entree) >> nb;
tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
}
#else
/* #ifdef SYSTEM_MAC_OS_X_unix
else if ((entreePrinc->entree)->fail())
// on a atteind la fin de la ligne et on appelle un nouvel enregistrement
{ entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
*(entreePrinc->entree) >> nb;
tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale
}
#else */
else if ((entreePrinc->entree)->eof())
// la lecture est bonne mais on a atteind la fin de la ligne
{ tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture
// si ce n'est pas la fin de la lecture on appelle un nouvel enregistrement
if (i != nbnte) entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement
}
// #endif
#endif
else // cas d'une erreur de lecture
{ cout << "\n erreur de lecture inconnue ";
entreePrinc->MessageBuffer("** lecture des données particulières **");
cout << "SfeMembT::LecDonPart";
Affiche(2);
Sortie (1);
}
};
// construction du tableau de ddl des noeuds de SfeMembT
ConstTabDdl();
// construction du tableau des noeuds du centre
t_N_centre.Change_taille(nombre->nbnce);
for (int i=1;i<= nombre->nbnce;i++)
t_N_centre(i)=tab_noeud(i);
};
// 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 & SfeMembT::Point_physique(const Coordonnee& ,Coordonnee & co,Enum_dure )
{ cout << "\n methode non encore implantee !!"
<< "\n Coordonnee & SfeMembT::Point_physique(...";
Sortie(1);
// d) retour
return co;
};
// 3) cas où l'on veut les coordonnées aux 1, 2 ou trois temps selon la taille du tableau t_co
void SfeMembT::Point_physique(const Coordonnee& ,Tableau <Coordonnee> & )
{ cout << "\n methode non encore implantee !!"
<< "\n void SfeMembT::Point_physique(...";
Sortie(1);
};
// vérification que la courbure ne soit pas anormale au temps enu
// inf_normale : indique en entrée le det mini pour la courbure en locale
// retour 1: si tout est ok,
// 0: une courbure trop grande a été détecté
// retour = -1 : il y a un pb inconnue dans le calcul
int SfeMembT::Test_courbure_anormale3(Enum_dure enu,double inf_normale)
{ SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
if (unefois->CalimpPrem == 0)
{ unefois->CalimpPrem = 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
};
// la variable de retour initialisée à 1 par défaut
int retour = 1;
// on gère les exceptions éventuelles en mettant le bloc sous surveillance
try
{ // puis les indices de boucle
int indice = 1;
int nbtotsurf = CoSfe->eleCentre->Nbi();
int nbtotepais =(CoSfe->segment).Nbi();
for (int nisur =1; nisur<= nbtotsurf; nisur++) // boucle sur les pt d'integ de surface
{for (int niepais =1; niepais<= nbtotepais; niepais++, indice++) // pt d'integ d'epaisseur
{((DeformationSfe1*) def)->ChangeNumIntegSfe1(nisur,niepais);
((DeformationSfe1*) def)->Mise_a_jour_data_specif(tabSaveDefDon(indice));
retour *= ((DeformationSfe1*) def)->Test_courbure_anormale(enu,inf_normale);
if (!retour)
break; // on arrête dès qu'un pb est repéré
}; // fin boucle sur les points d'intégration
if (!retour)
break; // on arrête dès qu'un pb est repéré
};
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch ( ... )
{ if (ParaGlob::NiveauImpression() > 3)
{cout << "\n warning: erreur generee par un element lors du test de verification de la courbure ";
};
retour = -1;
}
return retour;
};
// récupération des valeurs au numéro d'ordre = iteg pour les grandeurs enu
// ici il s'agit de grandeurs scalaire,
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
Tableau <double> SfeMembT::Valeur_a_diff_temps(bool absolue,Enum_dure enu_t,const List_io<Ddl_enum_etendu>& enu,int iteg)
{ // appel de la procedure de elem meca
int cas;
if (!(unefois->dualSortSfe ) && (unefois->CalimpPrem ))
{ cas=1;unefois->dualSortSfe += 1;
}
else if ((unefois->dualSortSfe ) && (unefois->CalimpPrem ))
{ cas = 11;}
else if (!(unefois->dualSortSfe ) && (unefois->CalResPrem_tdt ))
{ cas=2;unefois->dualSortSfe += 1;
}
else if ((unefois->dualSortSfe ) && (unefois->CalResPrem_tdt ))
{ cas = 12;}
// sinon problème
else
{ cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul"
<< " pour inialiser les conteneurs des tenseurs resultats ";
if (ParaGlob::NiveauImpression() >= 4)
cout << "\n cas non prévu, unefois->dualSortSfe= " << unefois->dualSortSfe
<< " unefois->CalimpPrem= " << unefois->CalimpPrem
<< "\n SfeMembT::Valeur_a_diff_temps(Enum_dure enu_t...";
Sortie(1);
};
return ElemMeca::Valeur_multi(absolue,enu_t,enu,iteg,cas);
};
// récupération des valeurs au numéro d'ordre = iteg pour les grandeurs enu
// ici il s'agit de grandeurs tensorielles, le retour s'effectue dans la liste
// de conteneurs quelconque associée
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void SfeMembT::ValTensorielle_a_diff_temps(bool absolue,Enum_dure enu_t,List_io<TypeQuelconque>& enu,int iteg)
{ // appel de la procedure de elem meca
int cas;
if (!(unefois->dualSortSfe ) && (unefois->CalimpPrem ))
{ cas=1;unefois->dualSortSfe += 1;
}
else if ((unefois->dualSortSfe ) && (unefois->CalimpPrem ))
{ cas = 11;}
else if (!(unefois->dualSortSfe ) && (unefois->CalResPrem_tdt ))
{ cas=2;unefois->dualSortSfe += 1;
}
else if ((unefois->dualSortSfe ) && (unefois->CalResPrem_tdt ))
{ cas = 12;}
// sinon problème
else
{ cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul"
<< " pour inialiser les conteneurs des tenseurs resultats ";
if (ParaGlob::NiveauImpression() >= 4)
cout << "\n cas non prévu, unefois->dualSortSfe= " << unefois->dualSortSfe
<< " unefois->CalimpPrem= " << unefois->CalimpPrem
<< "\n SfeMembT::ValTensorielle_a_diff_temps(Enum_dure enu_t...";
Sortie(1);
};
ElemMeca::Valeurs_Tensorielles(absolue,enu_t,enu,iteg,cas);
};
// Calcul du residu local à t ou tdt en fonction du booleen atdt
Vecteur* SfeMembT::CalculResidu (bool atdt,const ParaAlgoControle & pa)
{ SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
Tableau <TenseurBB *>& d_epsBB = (CoSfe->d_epsBB);// "
energie_totale.Initialisation_differenciee(energie_totale_t); // init de l'énergie totale sur l'élément
TenseurHH* sigHH_t_1 = (*lesPtIntegMecaInterne)(1).SigHH_t(); // simplification d'écriture
if (ElemMeca::Bulk_visco_actif())
{ if (sig_bulk_pourSfe_HH == NULL) {sig_bulk_pourSfe_HH = NevezTenseurHH(*sigHH_t_1);}
else if (sig_bulk_pourSfe_HH->Dimension() != sigHH_t_1->Dimension())
{delete sig_bulk_pourSfe_HH; sig_bulk_pourSfe_HH = NevezTenseurHH(*sigHH_t_1);};
};
// dimensionnement de la metrique
if (!atdt)
{if( !(unefois->CalResPrem_t ))
{ unefois->CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
};}
else
{if( !(unefois->CalResPrem_tdt ))
{unefois->CalResPrem_tdt += 1;
Tableau<Enum_variable_metrique> tab(11);
tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt;
tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ;
tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ;
tab(10) = igradVBB_tdt;tab(11) = iVtdt;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
};};
// dimensionnement du residu
int nbddl = CoSfe->tab_ddl.NbDdl();
if ( residu == NULL)
residu = new Vecteur(nbddl); // cas du premier passage
else
for (int i =1; i<= nbddl; i++) // cas des autres passages
(*residu)(i) = 0.; // on initialise a zero
double jacobien; // def du jacobien
int indice = 1;
int nbtotsurf =CoSfe->eleCentre->Nbi();
int nbtotepais =(CoSfe->segment).Nbi();
// préparation du calcul de l'épaisseur finale (qui dépend de tous les points d'intégration)
double somme_epaisseurs_finales = 0;
// on utilise une épaisseur intermédiaire pour la métrique
// de manière à utiliser l'épaisseur de l'incrément précédent
Epai epais_pour_metrique;
// on doit boucler à l'extérieur sur les pt de surface et à l'intérieur sur les pt d'épaisseurs
// pour profiter du fait que une fois un pt calculer, on n'a pas à recalculer la courbure !!!!!
for (int nisur =1; nisur<= nbtotsurf; nisur++) // boucle sur les pt d'integ de surface
for (int niepais =1; niepais<= nbtotepais; niepais++, indice++) // pt d'integ d'epaisseur
{ if ((donnee_specif.epais != NULL) // on change les épaisseurs si elles sont stockées
&& (!Loi_rien(loiComp->Id_comport()))
)
{ epais_pour_metrique = *(donnee_specif.epais);
epais_pour_metrique.epaisseur_tdt = epais_pour_metrique.epaisseur_t;
// ((DeformationSfe1*) def)->Change_epaisseur(*donnee_specif.epais); // au niveau de l'élément
((DeformationSfe1*) def)->Change_epaisseur(epais_pour_metrique);
};
((DeformationSfe1*) def)->ChangeNumIntegSfe1(nisur,niepais);
((DeformationSfe1*) def)->Mise_a_jour_data_specif(tabSaveDefDon(indice));
PtIntegMecaInterne & ptIntegMeca = (*lesPtIntegMecaInterne)(indice);
TenseurHH & sigHH = *(ptIntegMeca.SigHH());
TenseurBB & DepsBB_ = *(ptIntegMeca.DepsBB());
EnergieMeca& energ = tab_energ(indice);
EnergieMeca& energ_t = tab_energ_t(indice);
double poids = CoSfe->eleCentre->Wi(nisur) * (CoSfe->segment).Wi(niepais) ;
CompThermoPhysiqueAbstraite::SaveResul* sTP=NULL; // les données spécifique thermo physiques
if (loiTP != NULL) {sTP = tabSaveTP(indice);}; // au pt d'integ si elles existes
if ((loiComp->Id_comport()==LOI_VIA_UMAT) // cas de l'utilisation d'une loi umat
|| (loiComp->Id_comport()==LOI_VIA_UMAT_CP))
((Loi_Umat*) loiComp)->Mise_a_jour_nbe_nbptinteg(this->Num_elt(),indice);
double epaisseur_tdt = 0.; // ne sert que pour les éléments 2D avec épaisseurs stockées à l'élément
double epaisseur_pris_en_compte = 0.; // celle qui sera réellement prise en compte
// -- on gère les exceptions éventuelles en mettant le bloc sous surveillance
try // ce qui permet de donner les numéros d'éléments et de pti
{if (atdt)
{ const Met_abstraite::Expli_t_tdt& ex = loiComp->Cal_explicit_tdt
(tabSaveDon(indice), *def,CoSfe->tab_ddl,ptIntegMeca,d_epsBB,jacobien
,sTP,loiTP,dilatation,energ,energ_t,premier_calcul_meca_impli_expli);
// examen du cas où on désire utiliser la méthode d'atténuation des hautes fréquences avec le bulk viscosity
if (Bulk_visco_actif())
ModifContrainteBulk(TEMPS_tdt,*ex.gijHH_tdt,sigHH,DepsBB_ ,(*sig_bulk_pourSfe_HH));
// on tient compte de la variation d'épaisseur si l'épaisseur est stockée dans l'élément
// et que l'on n'a pas une loi rien
if ((donnee_specif.epais != NULL) && (!Loi_rien(loiComp->Id_comport())))
{ switch (loiComp->Comportement_3D_CP_DP_1D())
{ case COMP_CONTRAINTES_PLANES :
// en contrainte plane on recalcule l'épaisseur
{ CalEpaisseurAtdtExp_et_vol_pti(donnee_specif.epais->epaisseur0,pa,donnee_specif.epais->epaisseur_t
,ptIntegMeca,epaisseur_tdt,ex);
//------ le 7 nov 2016: changement car je ne veux pas utiliser la variation d'épaisseur
// qui est calculée dans les lois. C'est sans doute possible, bien qu'avec les lois additives et mélange
// ce n'est pas sûr que cela veuille dire quelque chose. Donc on essaie de sans passer
// De plus c'est cohérent avec les éléments membranes ...
// ---- remodif le 1 avril 2017 car la méthode précédente fait que l'élément converge très mal !!
// je ne sais pas trop pourquoi (avec une loi de déformation plane, cela converge immédiatement !)
// // en fait, on récupère la variation d'épaisseur calculée via la condition de contrainte plane
// // on utilise uniquement la variation d'épaisseur calculée à la surface médiane ??? pour l'instant
// epaisseur_tdt = loiComp->HsurH0(tabSaveDon(nisur)) * donnee_specif.epais->epaisseur0;
// il faudrait peut-être utiliser finalement la variation d'épaisseur calculée par la loi, comme pour les éléments
// membranes qui ont été modifiées pour tenir compte de la différence de def entre géométrique et la def méca
// Par exemple lors de critère de rupture, on aura le même pb qu'avec les plis
//*** à faire
epaisseur_pris_en_compte = donnee_specif.epais->epaisseur_tdt;
break;
}
case COMP_DEFORMATIONS_PLANES :
// en deformation plane, l'épaisseur ne change pas
{ epaisseur_tdt = donnee_specif.epais->epaisseur0;
ptIntegMeca.Volume_pti() *= donnee_specif.epais->epaisseur0;
epaisseur_pris_en_compte = donnee_specif.epais->epaisseur0;
break;
}
default :
cout << "\nErreur : cas de loi de comportement : " << Nom_comp((loiComp->Id_comport()))
<< " non prevu pour le calcul le l'epaisseur avec l'element SFE ";
cout << "\n SfeMembT::Calcul_implicit(.... \n";
Sortie(1);
};
};
somme_epaisseurs_finales += epaisseur_tdt; //pour le calcul final
}
else
{ const Met_abstraite::Expli& ex = loiComp->Cal_explicit_t
(tabSaveDon(indice), *def,CoSfe->tab_ddl,ptIntegMeca,d_epsBB,jacobien
,sTP,loiTP,dilatation,energ,energ_t,premier_calcul_meca_impli_expli);
// examen du cas où on désire utiliser la méthode d'atténuation des hautes fréquences avec le bulk viscosity
if (Bulk_visco_actif())
ModifContrainteBulk(TEMPS_t,*ex.gijHH_t,sigHH,DepsBB_ ,(*sig_bulk_pourSfe_HH));
// pour l'instant on expédie un message, car il y a des chances que cette partie disparaisse !!
cout << "\n attention *** calcul non operationnelle en explicite t, on ne tient pas compte de la"
<< " variation d'epaisseur !! (a modifier ) ";
};
}
catch (ErrNonConvergence_loiDeComportement excep)
// cas d'une d'une erreur survenue à cause d'une non convergence pour la résolution
// d'une loi de comportement incrémentale
{ cout << "\n erreur de loi de comportement element= " << this->Num_elt()
<< " point d'integration de surface= "<<nisur << " d'epaisseur= "<< niepais << endl;
throw excep;
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch ( ... )
{ cout << "\n erreur inconnue de loi de comportement, element= " << this->Num_elt()
<< " point d'integration de surface= "<<nisur << " d'epaisseur= "<< niepais << endl;
throw (Err_inconnue_ElemMeca());
};
if ((jacobien <= 0.)|| (std::isinf(jacobien))||( std::isnan(jacobien))) // vérif du jacobien
{ if ((std::isinf(jacobien))||( std::isnan(jacobien)))
// on met un message quelque soit le niveau d'impression
{ cout << "\n ********** attention on a trouve un jacobien infini ou nan !! = ("<<jacobien<<")********* " << endl; };
if (ParaGlob::NiveauImpression() >= 1)
{ cout << "\n ********** attention on a trouve un jacobien negatif!! ("<<jacobien<<")********* " << endl; };
};
if ((jacobien <= 0.) && (pa.JabobienNegatif() != 0)) // vérif du jacobien et traitement adéquate si besoin
{ switch (pa.JabobienNegatif())
{ case 1:
{ cout << "\n on annulle sa contribution. Element nb: " << Num_elt() << " ni_surf: " << nisur
<< " ni_ep: " << niepais;
break;
}
// dans les autres cas on ne fait rien
};
}
else
{ // on prend en compte toutes les variations
// dans le cas d'un élément 3D, épaisseur est stockée aux noeuds, donc ici la variable
// épaisseur_tdt ne devrait pas exister, en particulier le jacobien intègre déjà l'épaisseur
// pour éviter des tests et une recopie du code on laisse epaisseur_tdt, avec une valeur 1
// ce qui fait qu'elle n'intervient pas
if (donnee_specif.epais == NULL) epaisseur_pris_en_compte = 1.;
// il ne faut pas interpoler l'énergie à t, car elle était associée à un volume qui a changé
// donc il ne faut considérer que l'accroissement d'énergie
energie_totale.Ajout_differenciee(energ,energ_t,(poids * jacobien * epaisseur_pris_en_compte));
// energie_totale += (energ-energ_t) * (poids * jacobien * epaisseur_tdt);
// energie_totale += energ * (poids * jacobien * epaisseur_tdt);
//test si le jacobien due aux gi finaux est très différent du jacobien de la facette
//test si le jacobien due aux gi finaux est très différent du jacobien de la facette
Delta_Jacobien_anormal(tabSaveDefDon(indice),nisur,niepais);
for (int j =1; j<= nbddl; j++)
{int jloc = CoSfe->nMetVTab_ddl(j); // adressage indirecte
(*residu)(jloc) -= (sigHH && (*(d_epsBB(j)))) * jacobien * poids * epaisseur_pris_en_compte;
volume += jacobien * poids * epaisseur_tdt; // là on prend la vrai épaisseur
};
};
if (ElemMeca::Bulk_visco_actif()) // dans le cas du bulk on retire la contrainte du bulk, qui est non physique
{ sigHH -= (*sig_bulk_pourSfe_HH); } // ceci pour la sauvegarde ou autre utilisation
}; // fin boucle sur les points d'intégration
// on calcul éventuellement l'épaisseur moyenne finale si c'est un élément 2D
if ((donnee_specif.epais != NULL)&&(!Loi_rien(loiComp->Id_comport()))) // cas 2D
donnee_specif.epais->epaisseur_tdt = somme_epaisseurs_finales / (indice - 1);
// liberation des tenseurs intermediaires
LibereTenseur();
return residu;
};
// Calcul du residu local et de la raideur locale,
// pour le schema implicite
Element::ResRaid SfeMembT::Calcul_implicit (const ParaAlgoControle & pa)
{ SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
Tableau <TenseurBB *>& d_epsBB = (CoSfe->d_epsBB);// "
Tableau <TenseurHH *>& d_sigHH = (CoSfe->d_sigHH);// "
energie_totale.Initialisation_differenciee(energie_totale_t); // init de l'énergie totale sur l'élément
E_elem_bulk_tdt = E_elem_bulk_t; P_elem_bulk = 0.; // init pour l'énergie et la puissance associées au bulk
// init éventuel de la contrainte de bulk viscosity
TenseurHH* sigHH_t_1 = (*lesPtIntegMecaInterne)(1).SigHH_t(); // simplification d'écriture
if (ElemMeca::Bulk_visco_actif())
{ if (sig_bulk_pourSfe_HH == NULL) {sig_bulk_pourSfe_HH = NevezTenseurHH(*sigHH_t_1);}
else if (sig_bulk_pourSfe_HH->Dimension() != sigHH_t_1->Dimension())
{delete sig_bulk_pourSfe_HH; sig_bulk_pourSfe_HH = NevezTenseurHH(*sigHH_t_1);};
};
// init éventuel des intégrales de volume et temps
Init_Integ_vol_et_temps();
// --- init pour l'init de la stabilisation de membrane-biel éventuelle
const Met_abstraite::Impli* ex_final=NULL; // contiendra après les boucles la dernière métrique
Mise_a_jour_A_calculer_force_stab(); // permettra ensuite de savoir où le calcul doit être fait
bool cald_Dvirtuelle = false;
if (unefois->CalimpPrem == 0)
{ unefois->CalimpPrem = 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
// on ne calcul la dérivée de la déformation virtuelle qu'une fois
// car elle est constante dans le temps et indépendante des coordonnées
cald_Dvirtuelle=true;
};
// dimensionnement du residu
int nbddl = CoSfe->tab_ddl.NbDdl();
if ( residu == NULL)
residu = new Vecteur(nbddl); // cas du premier passage
else
for (int i =1; i<= nbddl; i++) // cas des autres passages
(*residu)(i) = 0.; // on initialise a zero
// dimensionnement de la raideur
if ( raideur == NULL)
raideur = new Mat_pleine(nbddl,nbddl); // cas du premier passage
else
for (int i =1; i<= nbddl; i++) // cas des autres passages
for (int j=1; j<= nbddl; j++) //
(*raideur)(i,j) = 0.; // on initialise a zero
double jacobien; // def du jacobien
Vecteur d_jacobien_tdt;
int indice = 1;
int nbtotsurf = CoSfe->eleCentre->Nbi();
int nbtotepais =(CoSfe->segment).Nbi();
// préparation du calcul de l'épaisseur finale (qui dépend de tous les points d'intégration)
double somme_epaisseurs_finales = 0;
// on utilise une épaisseur intermédiaire pour la métrique
// de manière à utiliser l'épaisseur de l'incrément précédent
Epai epais_pour_metrique;
//--debug
//if (num_elt == 89)
// { cout << "\n SfeMembT::Calcul_implicit debug ";
// cout << endl;
// };
// on doit boucler à l'extérieur sur les pt de surface et à l'intérieur sur les pt d'épaisseurs
// pour profiter du fait que une fois un pt calculer, on n'a pas à recalculer la courbure !!!!!
// ne sert plus** int nbint = nbtotsurf*nbtotepais; // nb total de pti
for (int nisur =1; nisur<= nbtotsurf; nisur++) // boucle sur les pt d'integ de surface
for (int niepais =1; niepais<= nbtotepais; niepais++, indice++) // pt d'integ d'epaisseur
{if ((donnee_specif.epais != NULL) // on change les épaisseurs si elles sont stockées
&& (!Loi_rien(loiComp->Id_comport()))
)
{ epais_pour_metrique = *(donnee_specif.epais);
epais_pour_metrique.epaisseur_tdt = epais_pour_metrique.epaisseur_t;
// ((DeformationSfe1*) def)->Change_epaisseur(*donnee_specif.epais); // au niveau de l'élément
((DeformationSfe1*) def)->Change_epaisseur(epais_pour_metrique);
};
((DeformationSfe1*) def)->ChangeNumIntegSfe1(nisur,niepais);
((DeformationSfe1*) def)->Mise_a_jour_data_specif(tabSaveDefDon(indice));
PtIntegMecaInterne & ptIntegMeca = (*lesPtIntegMecaInterne)(indice);
TenseurHH & sigHH = *(ptIntegMeca.SigHH());
TenseurBB & DepsBB_tdt = *(ptIntegMeca.DepsBB());
EnergieMeca& energ = tab_energ(indice);
EnergieMeca& energ_t = tab_energ_t(indice);
double poids = (CoSfe->eleCentre->Wi(nisur) * (CoSfe->segment).Wi(niepais)) * 0.5 ;
CompThermoPhysiqueAbstraite::SaveResul* sTP=NULL; // les données spécifique thermo physiques
if (loiTP != NULL) {sTP = tabSaveTP(indice);}; // au pt d'integ si elles existes
if ((loiComp->Id_comport()==LOI_VIA_UMAT) // cas de l'utilisation d'une loi umat
|| (loiComp->Id_comport()==LOI_VIA_UMAT_CP))
((Loi_Umat*) loiComp)->Mise_a_jour_nbe_nbptinteg(this->Num_elt(),indice);
// -- on gère les exceptions éventuelles en mettant le bloc sous surveillance
const Met_abstraite::Impli* ex_pointe = NULL; // c'est pour construire ex
try // ce qui permet de donner les numéros d'éléments et de pti
{ ex_pointe = &loiComp->Cal_implicit(tabSaveDon(indice), *def,CoSfe->tab_ddl
,ptIntegMeca,d_epsBB,jacobien,d_jacobien_tdt
,d_sigHH,pa,sTP,loiTP,dilatation,energ,energ_t
,premier_calcul_meca_impli_expli);
}
catch (ErrNonConvergence_loiDeComportement excep)
// cas d'une d'une erreur survenue à cause d'une non convergence pour la résolution
// d'une loi de comportement incrémentale
{ cout << "\n erreur de loi de comportement element= " << this->Num_elt()
<< " point d'integration de surface= "<<nisur << " d'epaisseur= "<< niepais << endl;
throw excep;
}
catch (ErrSortieFinale)
// cas d'une direction voulue vers la sortie
// on relance l'interuption pour le niveau supérieur
{ ErrSortieFinale toto;
throw (toto);
}
catch ( ... )
{ cout << "\n erreur inconnue de loi de comportement, element= " << this->Num_elt()
<< " point d'integration de surface= "<<nisur << " d'epaisseur= "<< niepais << endl;
throw (Err_inconnue_ElemMeca());
};
const Met_abstraite::Impli& ex=(*ex_pointe);
ex_final = ex_pointe; // stockage pour la stabilisation éventuelle de membraneBiel
// on calcul éventuellement la dérivée de la vitesse de déformation virtuelle
Tableau2 <TenseurBB *>& d2_epsBB = (CoSfe->d2_epsBB)(indice); // pour simplifier
if (cald_Dvirtuelle)
def->Cal_var_def_virtuelle(false,d2_epsBB);
// examen du cas où on désire utiliser la méthode d'atténuation des hautes fréquences avec le bulk viscosity
if (Bulk_visco_actif())
ModifContrainteBulk(TEMPS_tdt,*ex.gijHH_tdt,sigHH,DepsBB_tdt,(*sig_bulk_pourSfe_HH) );
double rap=1.; // pour le calcul éventuel du rapport de jacobien actuel
if (pa.MaxiVarJacobien() > 1.) // cas de la demande du calcul du rapport de jacobien
{if (Dabs(jacobien) > (*(ex.jacobien_0))) {rap = Dabs(jacobien) / (*(ex.jacobien_0));}
else {rap = (*(ex.jacobien_0)) / Dabs(jacobien) ;}
};
// on tient compte de la variation d'épaisseur pour ce point d'integ
double epaisseur_tdt = 0.; // ne sert que pour les éléments 2D avec épaisseurs stockées à l'élément
double epaisseur_pris_en_compte = 0.; // celle qui sera réellement prise en compte
if ((donnee_specif.epais != NULL) && (!Loi_rien(loiComp->Id_comport())) )
{ switch (loiComp->Comportement_3D_CP_DP_1D())
{ case COMP_CONTRAINTES_PLANES :
{
// en contrainte plane on recalcule l'épaisseur
CalEpaisseurAtdtImp_et_vol_pti(donnee_specif.epais->epaisseur0
,pa,donnee_specif.epais->epaisseur_t
,ptIntegMeca,epaisseur_tdt,ex);
//------ le 7 nov 2016: changement car je ne veux pas utiliser la variation d'épaisseur
// qui est calculée dans les lois. C'est sans doute possible, bien qu'avec les lois additives et mélange
// ce n'est pas sûr que cela veuille dire quelque chose. Donc on essaie de sans passer
// De plus c'est cohérent avec les éléments membranes ...
// ---- remodif le 1 avril 2017 car la méthode précédente fait que l'élément converge très mal !!
// je ne sais pas trop pourquoi (avec une loi de déformation plane, cela converge immédiatement !)
// // en fait, on récupère la variation d'épaisseur calculée via la condition de contrainte plane
// // on utilise uniquement la variation d'épaisseur calculée à la surface médiane ??? pour l'instant
// epaisseur_tdt = loiComp->HsurH0(tabSaveDon(nisur)) * donnee_specif.epais->epaisseur0;
// ************$la ligne qui suit est uniquement pour faire passer qq calcul ---> mais c'est faux !!!
// ************$la ligne qui suit est uniquement pour faire passer qq calcul ---> mais c'est faux !!!
// ************$la ligne qui suit est uniquement pour faire passer qq calcul ---> mais c'est faux !!!
// epaisseur_tdt = donnee_specif.epais->epaisseur0;
// on utilise l'épaisseur de l'incrément précédent
epaisseur_pris_en_compte = donnee_specif.epais->epaisseur_tdt;
break;
}
case COMP_DEFORMATIONS_PLANES :
// en deformation plane, l'épaisseur ne change pas
{ epaisseur_tdt = donnee_specif.epais->epaisseur0;
ptIntegMeca.Volume_pti() *= donnee_specif.epais->epaisseur0;
epaisseur_pris_en_compte = epaisseur_tdt;
break;
}
default :
cout << "\nErreur : cas de loi de comportement : " << Nom_comp((loiComp->Id_comport()))
<< " non prevu pour le calcul le l'epaisseur avec l'element SFE ";
cout << "\n SfeMembT::Calcul_implicit(.... \n";
Sortie(1);
};
};
somme_epaisseurs_finales += epaisseur_tdt; //pour le calcul final
//--------- pour le débug --------
// Deformation & defS = *defSurf(1); // pour simplifier l'écriture
// int nbddls = ddlS.NbDdl();
//------- pour le débug fin -------
if ((jacobien <= 0.)|| (std::isinf(jacobien))||( std::isnan(jacobien))) // vérif du jacobien
{ if ((std::isinf(jacobien))||( std::isnan(jacobien)))
// on met un message quelque soit le niveau d'impression
{ cout << "\n ********** attention on a trouve un jacobien infini ou nan !! = ("<<jacobien<<")********* " << endl; };
if (ParaGlob::NiveauImpression() >= 1)
{ cout << "\n ********** attention on a trouve un jacobien negatif!! ("<<jacobien<<")********* " << endl; };
};
if ((jacobien <= 0.) && (pa.JabobienNegatif()!= 0)) // vérif du jacobien et traitement adéquate si besoin
{ cout << "\n ParaGlob::NiveauImpression() = "<<ParaGlob::NiveauImpression() << " jacobien= " << jacobien << endl;
switch (pa.JabobienNegatif())
{ case 1:
{ cout << "\n on annulle sa contribution. Element nb: " << Num_elt() << " ni_surf: " << nisur
<< " ni_ep: " << niepais;
break;
}
case 2:
{ // on génère une exception
throw ErrJacobienNegatif_ElemMeca();break;
}
// dans les autres cas on ne fait rien
};
}
else if ((pa.MaxiVarJacobien() > 1.) && ( rap > pa.MaxiVarJacobien()))
{ if (ParaGlob::NiveauImpression() >= 3)
{ cout << "\n *** attention la variation maximale du jacobien est atteinte !! *** "
<< "\n ele= "<< Num_elt() << " ni_surf: " << nisur
<< " ni_ep: " << niepais << " jacobien= " << jacobien << " jacobien_0= "
<< (*(ex.jacobien_0)) << endl;
};
// on génère une exception
throw ErrVarJacobienMini_ElemMeca();break;
}
else
{ // on prend en compte toutes les variations
// dans le cas d'un élément 3D, épaisseur est stockée aux noeuds, donc ici la variable
// épaisseur_tdt ne devrait pas exister, en particulier le jacobien intègre déjà l'épaisseur
// pour éviter des tests et une recopie du code on laisse epaisseur_tdt, avec une valeur 1
// ce qui fait qu'elle n'intervient pas
if (donnee_specif.epais == NULL) epaisseur_pris_en_compte = 1.;
// on continue que s'il s'agit d'une loi différente de rien
if (!Loi_rien(loiComp->Id_comport()))
{// il ne faut pas interpoler l'énergie à t, car elle était associée à un volume qui a changé
// donc il ne faut considérer que l'accroissement d'énergie
energie_totale.Ajout_differenciee(energ,energ_t,(poids * jacobien * epaisseur_pris_en_compte));
// energie_totale += (energ-energ_t) * (poids * jacobien * epaisseur_tdt);
// energie_totale += energ * (poids * jacobien * epaisseur_tdt);
// l'ordre des ddl vient de la métrique: tous le xi, puis les épaisseurs, par contre dans le stockage
// local on doit avoir noeud1: ddlxi puis epais, noeud2: idem etc pour les noeuds centraux, puis ddl xi
// pour les noeuds externes. Si pas de ddl epais, tous les noeuds sont traités de la même manière
// on utilise un adressage indirecte
////--- debug
//if (Dabs(epaisseur_pris_en_compte - donnee_specif.epais->epaisseur0) > 0.01)
// {cout << "\n debug SfeMembT::Calcul_implicit: epai= "
// << epaisseur_pris_en_compte << " epai_0= "<< donnee_specif.epais->epaisseur0 << endl;
// };
//// --- fin debug
for (int j =1; j<= nbddl; j++) // 1ere boucle sur les ddl
{ int jloc = CoSfe->nMetVTab_ddl(j); // adressage indirecte
(*residu)(jloc) -= ((*(d_epsBB(j))) && sigHH ) * poids * jacobien* epaisseur_pris_en_compte;
/*//--debug
if ((*residu)(jloc) > 10.)
{ cout << "\n SfeMembT::Calcul_implicit debug ";
cout << "\n (*ex.giB_0)(1): " ;(*ex.giB_0)(1).Affiche();
cout << " (*ex.giB_0)(2): " ;(*ex.giB_0)(2).Affiche();
cout << " (*ex.giH_0)(1): " ;(*ex.giH_0)(1).Affiche();
cout << " (*ex.giH_0)(2): " ;(*ex.giH_0)(2).Affiche();
cout << "\n (*ex.giBB_0): " ;(*ex.gijBB_0).Ecriture(cout);
cout << "\n (*ex.giHH_0): " ;(*ex.gijHH_0).Ecriture(cout);
cout << "\n (*(d_epsBB(j))): " ;(*(d_epsBB(j))).Ecriture(cout);
cout << "\n sigHH: " ;sigHH.Ecriture(cout);
cout << endl;
ex_pointe = &loiComp->Cal_implicit(tabSaveDon(indice), *def,CoSfe->tab_ddl
,ptIntegMeca,d_epsBB,jacobien,d_jacobien_tdt
,d_sigHH,pa,sTP,loiTP,dilatation,energ,energ_t
,premier_calcul_meca_impli_expli);
Sortie(1);
};
//--fin debug */
//test si le jacobien due aux gi finaux est très différent du jacobien de la facette
//test si le jacobien due aux gi finaux est très différent du jacobien de la facette
Delta_Jacobien_anormal(tabSaveDefDon(indice),nisur,niepais);
volume += jacobien * poids * epaisseur_tdt; // là on prend la vraie épaisseur
for (int i =1; i<= nbddl; i++) // 2ere boucle sur les ddl
{ int iloc = CoSfe->nMetVTab_ddl(i); // adressage indirecte
(*raideur)(jloc,iloc) += ( ((*d_sigHH(i)) && (*(d_epsBB(j)))) * jacobien
+ (sigHH && (*((CoSfe->d2_epsBB)(indice)(j,i)))) * jacobien
+ (sigHH && (*(d_epsBB(j)))) * d_jacobien_tdt(i)
) * poids * epaisseur_pris_en_compte;
// on utilise toujour la variation de D, donc c'est maintenant directement intégré dans l'expression précédente, et la suite est commentée
// // on intègre la variation seconde si c'est demandé
// if (pa.Var_D())
// (*raideur)(jloc,iloc) += (sigHH && (*((CoSfe->d2_epsBB)(indice)(j,i))))
// * jacobien * poids * epaisseur_tdt;
// ---- pour test débug
// if (i < 10)
// (*raideur)(j,i) += (sigHH && (*(d_epsBB(j)))) * d_jacobien_tdt(i) * poids * donnee_specif.epaisseur_tdt;
};
};
};
// --- cas éventuel d'une stabilisation membrane-biel ---
// ici il s'agit de la contribution précise à chaque pti
if (pt_StabMembBiel != NULL)
if (!(pt_StabMembBiel->Aa_calculer()))
{ double poids_vol = poids * epaisseur_pris_en_compte;
Cal_implicit_StabMembBiel
(nisur,*ex_final,nbtotsurf,poids_vol,unefois->doCoMemb->noeud_a_prendre_en_compte);
};
};// fin du if sur la valeur non négative du jacobien
////--debug
//for (int i = 1; i<= 18; i++)
// { if ((*residu)(i) != 0. )
// { cout << "\n SfeMembT::Calcul_implicit debug ";
// cout << endl;
// };
////if (num_elt == 176)
//// { cout << "\n SfeMembT::Calcul_implicit debug ";
//// cout << endl;
// };
////--fin debug
if (ElemMeca::Bulk_visco_actif()) // dans le cas du bulk on retire la contrainte du bulk, qui est non physique
{ sigHH -= (*sig_bulk_pourSfe_HH); } // ceci pour la sauvegarde ou autre utilisation
}; // fin boucle sur les points d'intégration
#ifdef MISE_AU_POINT
if (ParaGlob::NiveauImpression() > 9)
{ cout << "\n Raideur et second membre locaux: ? (o/n) "; string rep(" ");
// procédure de lecture avec prise en charge d'un retour chariot
rep = lect_return_defaut(false,"n");
if ((rep == "0")||(rep == "o"))
{cout << "\n Raideur et second membre locaux: elem= " << Num_elt_const()
<< ", maillage= " << Num_maillage();
cout << "\n raideur: ";
raideur->Affiche();
cout << "\n second membre: " << (*residu);
};
};
#endif
// --- intervention dans le cas d'une stabilisation d'hourglass
// stabilisation pour un calcul implicit
if (type_stabHourglass)
Cal_implicit_hourglass();
// --- cas éventuel d'une stabilisation membrane-biel ---
// ici il s'agit soit du calcul approché d'initialisation, soit de la fin du calcul après la boucle
// modif: 10 janvier 2019 non c'est le calcul correct une fois la raideur calculée
if (pt_StabMembBiel != NULL)
{if (pt_StabMembBiel->Aa_calculer())
{Cal_implicit_StabMembBiel
(0,*ex_final, nbtotsurf,volume,unefois->doCoMemb->noeud_a_prendre_en_compte);}
else {Cal_implicit_StabMembBiel
(-1,*ex_final, nbtotsurf,volume,unefois->doCoMemb->noeud_a_prendre_en_compte);} ;
};
#ifdef MISE_AU_POINT
if (ParaGlob::NiveauImpression() > 9)
{ if ((type_stabHourglass)||(pt_StabMembBiel != NULL))
{cout << "\n apres stabilisation: Raideur et second membre locaux: ? (o/n) "; string rep(" ");
// procédure de lecture avec prise en charge d'un retour chariot
rep = lect_return_defaut(false,"n");
if ((rep == "0")||(rep == "o"))
{cout << "\n Raideur et second membre locaux: elem= " << Num_elt_const()
<< ", maillage= " << Num_maillage();
cout << "\n raideur: ";
raideur->Affiche();
cout << "\n second membre: " << (*residu);
};
};
};
#endif
////--debug
//for (int i = 1; i<= 18; i++)
// { if ((*residu)(i) != 0. )
// { cout << "\n SfeMembT::Calcul_implicit debug ";
// cout << endl;
// };
////if (num_elt == 176)
//// { cout << "\n SfeMembT::Calcul_implicit debug ";
//// cout << endl;
// };
////--fin debug
// on calcul éventuellement l'épaisseur moyenne finale si c'est un élément 2D
if ((donnee_specif.epais != NULL) && (!Loi_rien(loiComp->Id_comport())) )// cas 2D
donnee_specif.epais->epaisseur_tdt = somme_epaisseurs_finales / (indice - 1);
// liberation des tenseurs intermediaires
LibereTenseur();
Element::ResRaid el;
el.res = residu;
el.raid = raideur;
return el;
};
// Calcul de la matrice masse pour l'élément
// celle-ci est calculée uniquement pour l'élément centrale et en considérant
// que la masse volumique est constante dans l'épaisseur
Mat_pleine * SfeMembT::CalculMatriceMasse (Enum_calcul_masse type_calcul_masse)
{ SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionement de la métrique si nécessaire
if (!(unefois->CalDynamique ))
{ unefois->CalDynamique += 1;
Tableau<Enum_variable_metrique> tab(5);
tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;
tab(4) = igijBB_tdt; tab(5) = igradVmoyBB_t;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
// on vérifie le bon dimensionnement de la matrice
if (type_calcul_masse == MASSE_CONSISTANTE)
// dans le cas où la masse est consistante il faut la redimensionner
{ int nbddl = CoSfe->tab_ddl.NbDdl();
(CoSfe->matrice_masse).Initialise (nbddl,nbddl,0.);
}
};
if ((donnee_specif.epais != NULL) // on change les épaisseurs si elles sont stockées
&& (!Loi_rien(loiComp->Id_comport()))
)
((DeformationSfe1*) def)->Change_epaisseur(*donnee_specif.epais); // au niveau de l'élément
// appel de la routine générale
////************ non, ce n'est pas correcte pour les éléments 3D, il faut revoir le calcul de la masse
//// en utilisant d(OM)/d_ddl au lieu de phi^r
ElemMeca::Cal_Mat_masse (CoSfe->tab_ddl,type_calcul_masse,
nombre->nbisMas,CoSfe->eleMas->TaPhi(),nombre->nbnce
,CoSfe->eleMas->TaWi());
if ((donnee_specif.epais != NULL) // prise en compte de l'épaisseur finale, si elle est stockée
&& (!Loi_rien(loiComp->Id_comport()))
)
(*mat_masse) *= donnee_specif.epais->epaisseur_tdt; // au niveau de l'élément, sinon on est en 3D, donc c'est
// intégré dans le jacobien
return mat_masse;
};
//============= 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 SfeMembT::Lecture_base_info
(ifstream& ent,const Tableau<Noeud *> * tabMaillageNoeud,const int cas)
{// tout d'abord appel de la lecture de la classe elem_meca
ElemMeca::Lecture_bas_inf(ent,tabMaillageNoeud,cas);
// traitement du cas particulier de l'élément centrale
string nom;
switch (cas)
{ case 1 : // ------- on récupère tout -------------------------
{ // construction du tableau de ddl des noeuds de l'élément centrale
ConstTabDdl();
// récup contraintes et déformation
lesPtMecaInt.Lecture_base_info(ent,cas);
// les données spécifiques
ent >> nom;
if (nom == "epaisStockeDansElement")
{ // cas où les épaisseurs sont stockées dans l'élément
if (donnee_specif.epais == NULL) donnee_specif.epais = new Epai;
ent >> nom >> donnee_specif.epais->epaisseur0
>> nom >> donnee_specif.epais->epaisseur_t
>> nom >> donnee_specif.epais->epaisseur_tdt;
}
else
// cas d'un stockage au niveau des noeuds
{ if (donnee_specif.epais != NULL) delete donnee_specif.epais;};
// CL éventuelles :
ent >> nom ;
bool existe_CL; ent >> existe_CL;
if (existe_CL)
{if (areteTypeCL != (&(unefois->doCoMemb->tabType_rienCL)))
{ // si les tableaux n'existent pas on les crée
if (areteTypeCL == (&(unefois->doCoMemb->tabType_rienCL)))
areteTypeCL = new Tableau <EnuTypeCL> (3);
if (vplan == (&(unefois->doCoMemb->vplan_rien)))
vplan = new Tableau <Coordonnee3> (3);
// et on récupère les infos
ent >> nom; (*areteTypeCL)(1) = Id_nomTypeCL(nom); ent >> (*vplan)(1);
ent >> nom; (*areteTypeCL)(2) = Id_nomTypeCL(nom); ent >> (*vplan)(2);
ent >> nom; (*areteTypeCL)(3) = Id_nomTypeCL(nom); ent >> (*vplan)(3);
}
}
else
{// on supprime les tableaux locaux éventuels et on pointe vers les valeurs par défaut
if (areteTypeCL != (&(unefois->doCoMemb->tabType_rienCL))) delete areteTypeCL;
areteTypeCL = (&(unefois->doCoMemb->tabType_rienCL));
if (vplan != (&(unefois->doCoMemb->vplan_rien))) delete vplan;
vplan = (&(unefois->doCoMemb->vplan_rien));
};
break;
}
case 2 : // ----------- lecture uniquement de se qui varie --------------------
{ // récup contraintes et déformation
lesPtMecaInt.Lecture_base_info(ent,cas);
// les données spécifiques
bool avecEpaisDansElement = true;
ent >> avecEpaisDansElement;
if (avecEpaisDansElement)
{ if (donnee_specif.epais == NULL) donnee_specif.epais = new Epai;
ent >> nom >> donnee_specif.epais->epaisseur_tdt;
donnee_specif.epais->epaisseur_t = donnee_specif.epais->epaisseur_tdt;
};
// CL éventuelles : on ne les lit pas car elles sont généré éventuellement
// à chaque fois que l'on met les CL, sinon elles ne changent pas
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de lecture !\n";
cout << "SfeMembT::::Lecture_base_info(ifstream& ent,const "
<< "Tableau<Noeud *> * tabMaillageNoeud,const int cas)"
<< " cas= " << cas << endl;
Sortie(1);
}
}
};
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void SfeMembT::Ecriture_base_info(ofstream& sort,const int cas)
{// tout d'abord appel de l'écriture de la classe elem_meca
ElemMeca::Ecriture_bas_inf(sort,cas);
// traitement du cas particulier de l'élément central
switch (cas)
{ case 1 : // ------- on sauvegarde tout -------------------------
{
// des tenseurs déformation et contrainte,
lesPtMecaInt.Ecriture_base_info(sort,cas);
// les données spécifiques
if (donnee_specif.epais != NULL)
{ sort << "\n epaisStockeDansElement " << " epaisseur0= " << donnee_specif.epais->epaisseur0
<< " epaisseur_t= " << donnee_specif.epais->epaisseur_t
<< " epaisseur_tdt= " << donnee_specif.epais->epaisseur_tdt;
}
else { sort << "\n epaisStockeAuxNoeuds "; };
// CL éventuelles :
sort << " CL= ";
if (areteTypeCL != (&(unefois->doCoMemb->tabType_rienCL)))
{ // si ça ne pointe pas sur la valeur par défaut, alors c'est qu'il y a
// des CL particulières,
sort << " 1 ";
sort << NomTypeCL((*areteTypeCL)(1)) << " " << (*vplan)(1)
<< NomTypeCL((*areteTypeCL)(2)) << " " << (*vplan)(2)
<< NomTypeCL((*areteTypeCL)(3)) << " " << (*vplan)(3);
}
else
{sort << " 0 ";
};
break;
}
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
{ // des tenseurs déformation et contrainte,
lesPtMecaInt.Ecriture_base_info(sort,cas);
// les données spécifiques
if (donnee_specif.epais != NULL)
{ sort << "\n 1 epaisseur_tdt= " << donnee_specif.epais->epaisseur_tdt;}
else
{ sort << "\n 0 ";};
// CL éventuelles : on ne les sort pas car elles sont généré éventuellement
// à chaque fois que l'on met les CL, sinon elles ne changent pas
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
cout << "SfeMembT::::Ecriture_base_info(ofstream& sort,const int cas)"
<< " cas= " << cas << endl;
Sortie(1);
}
};
};
//------- calcul d'erreur, remontée des contraintes -------------------
// calcul du résidu et de la matrice de raideur pour le calcul d'erreur
// en fait on ne calculera l'erreur que sur la contrainte sur toute la surface
// mais sur le premier pt d'integ d'épaisseur
Element::Er_ResRaid SfeMembT::ContrainteAuNoeud_ResRaid()
{ SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if(!( unefois->CalResPrem_t ))
{unefois->CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
};
// appel du programme général
int tabn_taille = tab_noeud.Taille();
ElemMeca:: SigmaAuNoeud_ResRaid(tabn_taille,
CoSfe->eleCentre->TaPhi(),
CoSfe->eleCentre->TaWi(),
CoSfe-> resErr,CoSfe->raidErr,
CoSfe->eleEr->TaPhi(),
CoSfe->eleEr->TaWi());
// --- on tient compte de l'épaisseur à t, supposée déjà calculée ou récupérée
// dans le cas d'un élément 3D, épaisseur est stockée aux noeuds, donc ici la variable
// épaisseur_t ne devrait pas exister, en particulier le jacobien intègre déjà l'épaisseur
// pour éviter des tests et une recopie du code on laisse epaisseur_t, avec une valeur 1
// ce qui fait qu'elle n'intervient pas
double epaisseur = 0.; // init
if (donnee_specif.epais == NULL) {epaisseur = 1.;}
else {epaisseur = donnee_specif.epais->epaisseur_t;};
// on tient compte de l'épaisseur à t, supposée déjà calculée ou récupérée
int taille_resErr=CoSfe->resErr.Taille();
for (int i=1;i<= taille_resErr;i++)
(*CoSfe-> resErr(i)) *= epaisseur;
CoSfe->raidErr *= epaisseur;
return (Element::Er_ResRaid( &(CoSfe-> resErr),&(CoSfe->raidErr)));
} ;
// calcul du résidu pour le calcul d'erreur ramenée aux noeuds
Element::Er_ResRaid SfeMembT::ErreurAuNoeud_ResRaid()
{ SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if(!( unefois->CalResPrem_t ))
{ unefois->CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
};
// appel du programme général
int tabn_taille = tab_noeud.Taille();
ElemMeca::Cal_ErrAuxNoeuds(tabn_taille,
CoSfe->eleCentre->TaPhi(),CoSfe->eleCentre->TaWi()
,CoSfe-> resErr );
// --- on tient compte de l'épaisseur à t, supposée déjà calculée ou récupérée
// dans le cas d'un élément 3D, épaisseur est stockée aux noeuds, donc ici la variable
// épaisseur_t ne devrait pas exister, en particulier le jacobien intègre déjà l'épaisseur
// pour éviter des tests et une recopie du code on laisse epaisseur_t, avec une valeur 1
// ce qui fait qu'elle n'intervient pas
double epaisseur = 0.; // init
if (donnee_specif.epais == NULL) {epaisseur = 1.;}
else {epaisseur = donnee_specif.epais->epaisseur_t;};
int taille_resErr=CoSfe->resErr.Taille();
for (int i=1;i<= taille_resErr;i++)
(*CoSfe-> resErr(i)) *= epaisseur;
CoSfe->raidErr *= epaisseur;
return (Element::Er_ResRaid( &(CoSfe-> resErr),&(CoSfe->raidErr)));
} ;
// actualisation des ddl et des grandeurs actives de t+dt vers t
void SfeMembT::TdtversT()
{ lesPtMecaInt.TdtversT(); // contrainte
if (donnee_specif.epais != NULL)
donnee_specif.epais->epaisseur_t = donnee_specif.epais->epaisseur_tdt;
int taille = lesPtMecaInt.NbPti();
for (int ni=1;ni<= taille; ni++)
{ if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TdtversT();
if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TdtversT();
if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TdtversT();
}
ElemMeca::TdtversT_(); // appel de la procédure mère
};
// actualisation des ddl et des grandeurs actives de t vers tdt
void SfeMembT::TversTdt()
{ lesPtMecaInt.TversTdt(); // contrainte
if (donnee_specif.epais != NULL)
donnee_specif.epais->epaisseur_tdt = donnee_specif.epais->epaisseur_t;
int taille = lesPtMecaInt.NbPti();
for (int ni=1;ni<= taille; ni++)
{ if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TversTdt();
if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TversTdt();
if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TversTdt();
}
ElemMeca::TversTdt_(); // appel de la procédure mère
};
// calcul de l'erreur sur l'élément.
// en fait on ne calculera l'erreur que sur la contrainte sur toute la surface
// mais sur le premier pt d'integ d'épaisseur
void SfeMembT::ErreurElement(int type,double& errElemRelative
,double& numerateur, double& denominateur)
{ SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if(!( unefois->CalResPrem_t ))
{ unefois->CalResPrem_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
CoSfe->met_SfeMembT.PlusInitVariables(tab) ;
};
// appel du programme général
ElemMeca::Cal_ErrElem(type,errElemRelative,numerateur,denominateur,
tab_noeud.Taille(),CoSfe->eleCentre->TaPhi(),
CoSfe->eleCentre->TaWi(),
CoSfe->eleEr->TaPhi(),CoSfe->eleEr->TaWi());
} ;
// mise à jour de la boite d'encombrement de l'élément, suivant les axes I_a globales
// en retour coordonnées du point mini dans retour.Premier() et du point maxi dans .Second()
// la méthode est différente de la méthode générale car il faut prendre en compte l'épaisseur de l'élément
const DeuxCoordonnees& SfeMembT::Boite_encombre_element(Enum_dure temps)
{ int tab_taille= tab_noeud.Taille();
// on commence par calculer la boite d'encombrement pour l'élément médian
Element::Boite_encombre_element( temps);
// ensuite on augment sytématiquement dans toutes directions d'une valeur h/2 majorée
// h étant l'épaisseur maxi constatée
double epais_maxi=0.; // init
if (donnee_specif.epais != NULL)
{ // cas où les épaisseurs sont stockées sur l'élément
epais_maxi = donnee_specif.epais->epaisseur_tdt;
}
else
{ // cas où les épaisseurs sont stockées aux noeuds
for (int ine=1;ine<=nombre->nbnce;ine++) // balayage des noeuds
epais_maxi = MaX(epais_maxi,tab_noeud(ine)->Valeur_tdt(EPAIS));
};
double hSur2maj = epais_maxi * 0.5
* (ParaGlob::param->ParaAlgoControleActifs().Extra_boite_prelocalisation()-1.);
// ajout d'un extra dans toutes les directions
hSur2maj += ParaGlob::param->ParaAlgoControleActifs().Ajout_extra_boite_prelocalisation();
// mise à jour
boite_encombre.Premier().Ajout_meme_valeur(-hSur2maj); // le min
boite_encombre.Second().Ajout_meme_valeur(hSur2maj); // le max
// retour
return boite_encombre;
};
// ramène le nombre de points d'intégration de surface correspondant à un type énuméré
// ramène 0 si l'élément n'est pas une plaque ou coque
int SfeMembT::NbPtIntegSurface(Enum_ddl ddl ) const
{ switch (ddl)
{ case ERREUR : return nombre->nbisEr; break;
default : return nombre->nbis; break;
};
};
// ramène le nombre de points d'intégration en épaisseur correspondant à un type énuméré
// ramène 0 si l'élément n'est pas une plaque ou coque
int SfeMembT::NbPtIntegEpaiss(Enum_ddl ddl) const
{ switch (ddl)
{ case ERREUR : return nombre->nbieEr; break;
default : return nombre->nbie; break;
};
};
// ramene l'element geometrique de surface correspondant au ddl passé en paramètre
// ou null si ce n'est pas définie, dans ce cas si l'élément géométrique de surface est 2D
// cela signifie qu'il faut se référer à l'élément générique: ElementGeometrie(...
ElemGeomC0* SfeMembT::ElementGeometrieSurface(Enum_ddl ddl ) const
{ switch (ddl)
{ case ERREUR : return (unefois->doCoMemb->eleEr); break;
default : return (unefois->doCoMemb->eleCentre); break;
};
};
// ramene l'element geometrique d'épaisseur correspondant au ddl passé en paramètre
// ou null si ce n'est pas définie, dans ce cas si l'élément géométrique de surface est 2D
// cela signifie que tout est constant (identique) dans l'épaisseur
ElemGeomC0* SfeMembT::ElementGeometrieEpaiss(Enum_ddl ddl ) const
{ switch (ddl)
{ case ERREUR : return &(unefois->doCoMemb->segmentEr); break;
default : return &(unefois->doCoMemb->segment); break;
};
};
// 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 SfeMembT::PointLePlusPres(Enum_dure temps,Enum_ddl enu, const Coordonnee& M)
{ int iret;
// récupération des éléments géométriques correspondant à Enu
ElemGeomC0* elSur = this->ElementGeometrieSurface(enu);
ElemGeomC0* elEpa = this->ElementGeometrieEpaiss(enu);
// récupération des tableaux des fonctions d'interpolations
const Tableau <Vecteur> & tabphiS = elSur->TaPhi();
const Tableau < Mat_pleine > & tabDphiS = elSur->TaDphi();
const Tableau <Vecteur> & tabphiH = elEpa->TaPhi();
// on boucle sur les pt d'integ pour avoir le point le plus près
int nbptSur = tabphiS.Taille();
int nbptEpa = tabphiH.Taille();
Coordonnee P; iret=1; double dist= ConstMath::tresgrand;
int ipt=1;
for (int iptH = 1;iptH <= nbptEpa;iptH++)
for (int iptS = 1; iptS <= nbptSur;iptS++,ipt++)
{ switch (temps)
{ case TEMPS_0 : P = ((Met_Sfe1*) met)->PointSfe1M_0
(tab_noeud,tabphiS(iptS),tabDphiS(iptS),donnee_specif.epais,tabphiH(iptH)); break;
case TEMPS_t : P = ((Met_Sfe1*) met)->PointSfe1M_t
(tab_noeud,tabphiS(iptS),tabDphiS(iptS),donnee_specif.epais,tabphiH(iptH)); break;
case TEMPS_tdt : P = ((Met_Sfe1*) met)->PointSfe1M_tdt
(tab_noeud,tabphiS(iptS),tabDphiS(iptS),donnee_specif.epais,tabphiH(iptH)); break;
}
double di=(M-P).Norme();
if (di < dist) { dist = di; iret = ipt;};
}
return iret; // retour
};
// 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 SfeMembT::CoordPtInteg(Enum_dure temps,Enum_ddl enu,int iteg,bool& erreur)
{ Coordonnee ptret; // le retour
// récupération des éléments géométriques correspondant à Enu
ElemGeomC0* elSur = this->ElementGeometrieSurface(enu);
ElemGeomC0* elEpa = this->ElementGeometrieEpaiss(enu);
// récupération des tableaux des fonctions d'interpolations
const Tableau <Vecteur> & tabphiS = elSur->TaPhi();
const Tableau < Mat_pleine > & tabDphiS = elSur->TaDphi();
const Tableau <Vecteur> & tabphiH = elEpa->TaPhi();
// def du numéro d'integ en surface et épaisseur
int nbptSur = tabphiS.Taille();
int nbptEpa = tabphiH.Taille();
int iptS = iteg / nbptEpa +1; // division entière
int iptH = iteg - (iptS-1) * nbptEpa ;
// calcul du point
if ((iteg < 0) || (iteg > (nbptSur*nbptEpa)))
{ erreur = false;}
else
{ switch (temps)
{ case TEMPS_0 : ptret = ((Met_Sfe1*) met)->PointSfe1M_0
(tab_noeud,tabphiS(iptS),tabDphiS(iptS),donnee_specif.epais,tabphiH(iptH)); break;
case TEMPS_t : ptret = ((Met_Sfe1*) met)->PointSfe1M_t
(tab_noeud,tabphiS(iptS),tabDphiS(iptS),donnee_specif.epais,tabphiH(iptH)); break;
case TEMPS_tdt : ptret = ((Met_Sfe1*) met)->PointSfe1M_tdt
(tab_noeud,tabphiS(iptS),tabDphiS(iptS),donnee_specif.epais,tabphiH(iptH)); break;
}
}
return ptret; // retour
};