Herezh_dev/herezh_pp/Elements/Mecanique/Triangle/TriaMemb.cc

2579 lines
128 KiB
C++
Executable file

// FICHIER : TriaMemb.cc
// CLASSE : TriaMemb
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
# include <iostream>
using namespace std; //introduces namespace std
#include <stdlib.h>
#include "Sortie.h"
#include "MathUtil.h"
#include "TriaMemb.h"
#include "TypeConsTens.h"
#include "FrontPointF.h"
#include "TypeQuelconqueParticulier.h"
// -------------- definition de la classe conteneur de donnees communes ------------
// on utilise directement les valeurs pointées
TriaMemb::DonnComTria::DonnComTria
(GeomTriangle& tria,DdlElement& tab,DdlElement& tabErr,DdlElement& tab_Err1Sig,
Met_abstraite& met_gene,Tableau <Vecteur* > & resEr,Mat_pleine& raidEr,
GeomTriangle& triaEr,GeomTriangle& triaS,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,GeomTriangle& triaMas,int nbi,GeomTriangle* triHourg,
Mat_pleine* trimatD,Vecteur* triresD) :
tria(tria),tab_ddl(tab),tab_ddlErr(tabErr),tab_Err1Sig11(tab_Err1Sig),met_triaMemb(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),triaEr(triaEr)
,triaS(triaS),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),triaMas(triaMas),triaHourg(triHourg)
,triamatD(trimatD),triaresD(triresD)
{ int nbddl = tab.NbDdl();
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 (2);
};
int tailledeps = d_epsBB.Taille();
for (int i=1;i<= tailledeps; i++)
d_epsBB(i) = NevezTenseurBB (2);
int tailledsig = d_sigHH.Taille();
for (int j=1;j<= tailledsig; j++)
d_sigHH(j) = NevezTenseurHH (2);
};
TriaMemb::DonnComTria::DonnComTria(DonnComTria& a) :
tria(a.tria),tab_ddl(a.tab_ddl),tab_ddlErr(a.tab_ddlErr),tab_Err1Sig11(a.tab_Err1Sig11)
,met_triaMemb(a.met_triaMemb),matGeom(a.matGeom),matInit(a.matInit),d2_epsBB(a.d2_epsBB)
,resErr(a.resErr),raidErr(a.raidErr),triaEr(a.triaEr),triaS(a.triaS),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),triaMas(a.triaMas),triaHourg(a.triaHourg)
,triamatD(a.triamatD),triaresD(a.triaresD)
{ int nbddl = d_sigHH.Taille();
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++)
d_epsBB(i) = NevezTenseurBB (*(a.d_epsBB(i)));
int tailledsig = d_sigHH.Taille();
for (int j=1;j<= tailledsig; j++)
d_sigHH(j) = NevezTenseurHH (*(d_sigHH(j)));
};
TriaMemb::DonnComTria::~DonnComTria()
{ 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);
};
// ---------- fin definition de la classe conteneur de donnees communes ------------
// -+-+ definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
TriaMemb::UneFois::UneFois () : // constructeur par défaut
doCoMemb(NULL),CalResPrem_t(0),CalResPrem_tdt(0),CalimpPrem(0),dualSortTria(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)
{};
TriaMemb::UneFois::~UneFois ()
{ delete doCoMemb;
};
// -+-+ fin definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+
// CONSTRUCTEURS :
// Constructeur par defaut
TriaMemb::TriaMemb () :
ElemMeca(),lesPtMecaInt(),donnee_specif(),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
TriaMemb::TriaMemb (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()
,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
TriaMemb::TriaMemb (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()
,unefois(NULL),nombre(NULL)
{ lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca
};
// Constructeur de copie
TriaMemb::TriaMemb (const TriaMemb& TriaM) :
ElemMeca (TriaM)
,lesPtMecaInt(TriaM.lesPtMecaInt)
,donnee_specif(TriaM.donnee_specif),unefois(TriaM.unefois),nombre(TriaM.nombre)
{lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca
// --- cas des différentes puissances et ... ---
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
residu = &(CoTria->residu_interne); // residu local
raideur = &(CoTria->raideur_interne); // raideur locale
// --- cas de la dynamique -----
mat_masse = &(CoTria->matrice_masse);
// --- cas des efforts externes concernant noeuds ------
res_extN = &(CoTria->residus_externeN); // pour les résidus et second membres
raid_extN= &(CoTria->raideurs_externeN);// pour les raideurs
// --- cas des efforts externes concernant les aretes ------
res_extA = &(CoTria->residus_externeA); // pour les résidus et second membres
raid_extA= &(CoTria->raideurs_externeA);// pour les raideurs
// --- cas des efforts externes concernant les faces ------
res_extS= &(CoTria->residus_externeS); // pour les résidus et second membres
raid_extS= &(CoTria->raideurs_externeS); // pour les raideurs
};
// DESTRUCTEUR :
TriaMemb::~TriaMemb ()
{ /* // 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<= 4; ia++)
defArete(ia) = NULL;
}
if (defSurf.Taille() != 0)
if (defSurf(1) != NULL)
{ delete defSurf(1);
defSurf(1) = NULL;
} */
LibereTenseur();
};
// Lecture des donnees de la classe sur fichier
void TriaMemb::LectureDonneesParticulieres
(UtilLecture * entreePrinc,Tableau<Noeud *> * tabMaillageNoeud)
{ int nb;int nbne = nombre->nbne;
tab_noeud.Change_taille(nbne);
for (int i=1; i<= nbne; 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 != nbne) 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 << "TriaMemb::LecDonPart";
Affiche();
Sortie (1);
}
}
// construction du tableau de ddl des noeuds de TriaMemb
ConstTabDdl();
};
// calcul d'un point dans l'élément réel en fonction des coordonnées dans l'élément de référence associé
// temps: indique si l'on veut les coordonnées à t = 0, ou t ou tdt
// 1) cas où l'on utilise la place passée en argument
Coordonnee & TriaMemb::Point_physique(const Coordonnee& c_int,Coordonnee & co,Enum_dure temps)
{ TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// a) on commence par définir les bonnes grandeurs dans la métrique
if( !(unefois->CalPt_0_t_tdt ))
{ unefois->CalPt_0_t_tdt += 1;
Tableau<Enum_variable_metrique> tab(3);
tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};
// b) calcul de l'interpolation
const Vecteur& phi = CoTria->tria.Phi(c_int);
// c) calcul du point
switch (temps)
{ case TEMPS_0 : co = met->PointM_0(tab_noeud,phi); break;
case TEMPS_t : co = met->PointM_t(tab_noeud,phi); break;
case TEMPS_tdt : co = met->PointM_tdt(tab_noeud,phi); break;
}
// d) retour
return co;
};
// 3) cas où l'on veut les coordonnées aux 1, 2 ou trois temps selon la taille du tableau t_co
void TriaMemb::Point_physique(const Coordonnee& c_int,Tableau <Coordonnee> & t_co)
{ TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// a) on commence par définir les bonnes grandeurs dans la métrique
if( !(unefois->CalPt_0_t_tdt ))
{ unefois->CalPt_0_t_tdt += 1;
Tableau<Enum_variable_metrique> tab(3);
tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};
// b) calcul de l'interpolation
const Vecteur& phi = CoTria->tria.Phi(c_int);
// c) calcul des point
switch (t_co.Taille())
{ case 3 : t_co(3) = met->PointM_tdt(tab_noeud,phi);
case 2 : t_co(2) = met->PointM_t(tab_noeud,phi);
case 1 : t_co(1) = met->PointM_0(tab_noeud,phi);
}
};
// Calcul du residu local à t ou tdt en fonction du booleen atdt
Vecteur* TriaMemb::CalculResidu (bool atdt,const ParaAlgoControle & pa)
{
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
Tableau <TenseurBB *>& d_epsBB = (CoTria->d_epsBB);// "
// 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;
CoTria->met_triaMemb.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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};
};
// initialisation du résidu
residu->Zero();
ElemMeca::Cal_explicit ( CoTria->tab_ddl,d_epsBB
,nombre->nbi,(CoTria->tria).TaWi(),pa,atdt);
// maintenant la nouvelle épaisseur est utilisée directement dans ElemMeca::Cal_explicit
// et y est également calculée
// 19 nov: en fait il ne faut pas prendre en compte l'épaisseur méca: cf. doc théorique
// faux: --- modif 15 nov 2017 ---
// prise en compte de l'epaisseur : variation ou non en fonction du fait que l'on soit en def ou contrainte plane
// on regarde le type de variation d'épaisseur que l'on veut
// et que l'on n'a pas une loi rien
if (donnee_specif.use_epais_moyenne && (!Loi_rien(loiComp->Id_comport())))
{double epaisseur_moyenne = 0.;
switch (loiComp->Comportement_3D_CP_DP_1D())
{case COMP_CONTRAINTES_PLANES :
// en contrainte plane on recalcule l'épaisseur
{const bool atdt=true;
epaisseur_moyenne = CalEpaisseurMoyenne_et_transfert_pti(atdt);
#ifdef MISE_AU_POINT
if (epaisseur_moyenne < 0.)
{ cout << "\n erreur*** on a trouve une epaisseur moyenne negative = " << epaisseur_moyenne
<< "\n TriaMemb::CalculResidu (.... \n";
//// --- debug
//cout << "\n *** debug TriaMemb::CalculResidu ( ";
// CalEpaisseurMoyenne_et_transfert_pti(atdt);
// ElemMeca::Cal_explicit ( CoTria->tab_ddl,d_epsBB
// ,nombre->nbi,(CoTria->tria).TaWi(),pa,atdt);
//Sortie(1);
////--- fin debug ---
};
#endif
break;
}
case COMP_DEFORMATIONS_PLANES :
// en deformation plane, l'épaisseur ne change pas
{ epaisseur_moyenne = H_moy(TEMPS_0);
// donnee_specif.epais.epaisseur0;
for (int i=1;i<= nombre->nbi;i++)
(*lesPtIntegMecaInterne)(i).Volume_pti() *= epaisseur_moyenne;
//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 triangulaire ";
cout << "\n TriaMemb::CalculResidu (.... \n";
Sortie(1);
};
(*residu) *= epaisseur_moyenne;
energie_totale *= epaisseur_moyenne;
E_Hourglass *= epaisseur_moyenne; // meme si l'énergie d'hourglass est nulle
E_elem_bulk_tdt*= epaisseur_moyenne; // idem
P_elem_bulk *= epaisseur_moyenne; // idem
volume *= epaisseur_moyenne;
};
// retour
return residu;
};
// Calcul du residu local et de la raideur locale,
// pour le schema implicite
Element::ResRaid TriaMemb::Calcul_implicit (const ParaAlgoControle & pa)
{ TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
Tableau <TenseurBB *>& d_epsBB = (CoTria->d_epsBB);// "
Tableau <TenseurHH *>& d_sigHH = (CoTria->d_sigHH);// "
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;
CoTria->met_triaMemb.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;
};
// initialisation du résidu
residu->Zero();
// initialisation de la raideur
raideur->Zero();
ElemMeca::Cal_implicit (CoTria->tab_ddl,d_epsBB,(CoTria->d2_epsBB),d_sigHH,
nombre->nbi,(CoTria->tria).TaWi(),pa,cald_Dvirtuelle);
// maintenant la nouvelle épaisseur est utilisée directement dans ElemMeca::Cal_explicit
// et y est également calculée
// 19 nov: en fait il ne faut pas prendre en compte l'épaisseur méca: cf. doc théorique
// faux: --- modif 15 nov 2017 ---
// prise en compte de l'epaisseur : variation ou non en fonction du fait que l'on soit en def ou contrainte plane
// on regarde le type de variation d'épaisseur que l'on veut
// et que l'on n'a pas une loi rien
if (donnee_specif.use_epais_moyenne && (!Loi_rien(loiComp->Id_comport())))
{double epaisseur_moyenne = 0.;
switch (loiComp->Comportement_3D_CP_DP_1D())
{case COMP_CONTRAINTES_PLANES :
// en contrainte plane on recalcule l'épaisseur
{ const bool atdt=true;
epaisseur_moyenne = CalEpaisseurMoyenne_et_transfert_pti(atdt);
break;
}
case COMP_DEFORMATIONS_PLANES :
// en deformation plane, l'épaisseur ne change pas
{ epaisseur_moyenne = H_moy(TEMPS_0);
//donnee_specif.epais.epaisseur0;
for (int i=1;i<= nombre->nbi;i++)
(*lesPtIntegMecaInterne)(i).Volume_pti() *= epaisseur_moyenne;
//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 triangulaire ";
cout << "\n TriaMemb::Calcul_implicit (.... \n";
Sortie(1);
};
(*residu) *= epaisseur_moyenne;
(*raideur) *= epaisseur_moyenne;
energie_totale *= epaisseur_moyenne;
E_Hourglass *= epaisseur_moyenne; // meme si l'énergie d'hourglass est nulle
E_elem_bulk_tdt*= epaisseur_moyenne; // idem
P_elem_bulk *= epaisseur_moyenne; // idem
volume *= epaisseur_moyenne;
};
Element::ResRaid el;
el.res = residu;
el.raid = raideur;
return el;
};
// Calcul de la matrice masse pour l'élément
Mat_pleine * TriaMemb::CalculMatriceMasse (Enum_calcul_masse type_calcul_masse)
{ TriaMemb::DonnComTria* CoTria = 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;
CoTria->met_triaMemb.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 = CoTria->tab_ddl.NbDdl();
(CoTria->matrice_masse).Initialise (nbddl,nbddl,0.);
}
};
// appel de la routine générale
ElemMeca::Cal_Mat_masse (CoTria->tab_ddl,type_calcul_masse,
nombre->nbiMas,(CoTria->triaMas).TaPhi(),nombre->nbne
,(CoTria->triaMas).TaWi());
// on regarde le type de variation d'épaisseur que l'on veut
if (donnee_specif.use_epais_moyenne)
(*mat_masse) *= H_moy(TEMPS_0);
//donnee_specif.epais.epaisseur0; // prise en compte de l'épaisseur
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 TriaMemb::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 du triangle
switch (cas)
{ case 1 : // ------- on récupère tout -------------------------
{ // construction du tableau de ddl des noeuds du triangle
ConstTabDdl();
// récup contraintes et déformation
lesPtMecaInt.Lecture_base_info(ent,cas);
// les données spécifiques
string nom;
ent >> nom;
if (nom == "epaisStockeDansElement")
{double titi;
for (int i=1; i<= nombre->nbi;i++)
ent >> nom >> titi
>> nom >> donnee_specif.epais(i).epaisseur0
>> nom >> donnee_specif.epais(i).epaisseur_t
>> nom >> donnee_specif.epais(i).epaisseur_tdt;
};
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
string nom;double titi;
ent >> nom; // le mot clé
for (int i=1; i<= nombre->nbi;i++)
{ent >> nom >> titi >> donnee_specif.epais(i).epaisseur_tdt;
donnee_specif.epais(i).epaisseur_t = donnee_specif.epais(i).epaisseur_tdt;
};
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de lecture !\n";
cout << "TriaMemb::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 TriaMemb::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 du triangle
switch (cas)
{ case 1 : // ------- on sauvegarde tout -------------------------
{
// des tenseurs déformation et contrainte,
lesPtMecaInt.Ecriture_base_info(sort,cas);
// les données spécifiques
sort << "\n epaisStockeDansElement ";
for (int i=1; i<= nombre->nbi;i++)
sort << " pti: "<< i << " epaisseur0= " << donnee_specif.epais(i).epaisseur0
<< " epaisseur_t= " << donnee_specif.epais(i).epaisseur_t
<< " epaisseur_tdt= " << donnee_specif.epais(i).epaisseur_tdt;
break;
}
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
{ // des tenseurs déformation et contrainte,
lesPtMecaInt.Ecriture_base_info(sort,cas);
sort << "\n epaisseur_tdt= ";
for (int i=1; i<= nombre->nbi;i++)
sort << " pti: "<< i << " " << donnee_specif.epais(i).epaisseur_tdt;
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type d'écriture !\n";
cout << "TriaMemb::Ecriture_base_info(ofstream& sort,const int cas)"
<< " cas= " << cas << endl;
Sortie(1);
}
};
};
// 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> TriaMemb::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->dualSortTria ) && (unefois->CalimpPrem ))
{ cas=1;unefois->dualSortTria += 1;
}
else if ((unefois->dualSortTria ) && (unefois->CalimpPrem ))
{ cas = 11;}
else if (!(unefois->dualSortTria ) && (unefois->CalResPrem_tdt ))
{ cas=2;unefois->dualSortTria += 1;
}
else if ((unefois->dualSortTria ) && (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->dualSortTria= " << unefois->dualSortTria
<< " unefois->CalimpPrem= " << unefois->CalimpPrem
<< "\n TriaMemb::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 TriaMemb::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->dualSortTria ) && (unefois->CalimpPrem ))
{ cas=1;unefois->dualSortTria += 1;
}
else if ((unefois->dualSortTria ) && (unefois->CalimpPrem ))
{ cas = 11;}
else if (!(unefois->dualSortTria) && (unefois->CalResPrem_tdt ))
{ cas=2;unefois->dualSortTria += 1;
}
else if ((unefois->dualSortTria ) && (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->dualSortTria= " << unefois->dualSortTria
<< " unefois->CalimpPrem= " << unefois->CalimpPrem
<< "\n TriaMemb::ValTensorielle_a_diff_temps(Enum_dure enu_t...";
Sortie(1);
};
ElemMeca::Valeurs_Tensorielles(absolue,enu_t,enu,iteg,cas);
};
//------- 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 TriaMemb::ContrainteAuNoeud_ResRaid()
{ TriaMemb::DonnComTria* CoTria = 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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};
// appel du programme général
int tabn_taille = tab_noeud.Taille();
ElemMeca::SigmaAuNoeud_ResRaid(tabn_taille,
(CoTria->tria).TaPhi(),
(CoTria->tria).TaWi(),
CoTria-> resErr,CoTria->raidErr,
(CoTria->triaEr).TaPhi(),
(CoTria->triaEr).TaWi());
// on tient compte de l'épaisseur à t, supposée déjà calculée ou récupérée
// on regarde le type de variation d'épaisseur que l'on veut
if (donnee_specif.use_epais_moyenne)
{int taille_resErr=CoTria->resErr.Taille();
double epais_t = H_moy(TEMPS_t);
for (int i=1;i<= taille_resErr;i++)
(*CoTria-> resErr(i)) *= epais_t; //donnee_specif.epais.epaisseur_t;
CoTria->raidErr *= epais_t;//donnee_specif.epais.epaisseur_t;
};
return (Element::Er_ResRaid( &(CoTria-> resErr),&(CoTria->raidErr)));
};
// 2) calcul du résidu et de la matrice de raideur pour le calcul d'erreur
Element::Er_ResRaid TriaMemb::ErreurAuNoeud_ResRaid()
{ TriaMemb::DonnComTria* CoTria = 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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};
// appel du programme général
int tabn_taille = tab_noeud.Taille();
ElemMeca::Cal_ErrAuxNoeuds(tabn_taille,
(CoTria->tria).TaPhi(),(CoTria->tria).TaWi()
,CoTria-> resErr );
// on tient compte de l'épaisseur à t, supposée déjà calculée ou récupérée
// on regarde le type de variation d'épaisseur que l'on veut
if (donnee_specif.use_epais_moyenne)
{int taille_resErr=CoTria->resErr.Taille();
double epais_t = H_moy(TEMPS_t);
for (int i=1;i<= taille_resErr;i++)
(*CoTria-> resErr(i)) *= epais_t;//donnee_specif.epais.epaisseur_t;
CoTria->raidErr *= epais_t;//donnee_specif.epais.epaisseur_t;
};
return (Element::Er_ResRaid( &(CoTria-> resErr),&(CoTria->raidErr)));
};
// actualisation des ddl et des grandeurs actives de t+dt vers t
void TriaMemb::TdtversT()
{ lesPtMecaInt.TdtversT(); // contrainte
for (int ni=1;ni<= nombre->nbi; ni++)
{ if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TdtversT();
if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TdtversT();
if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TdtversT();
donnee_specif.epais(ni).epaisseur_t = donnee_specif.epais(ni).epaisseur_tdt;
};
ElemMeca::TdtversT_(); // appel de la procédure mère
};
// actualisation des ddl et des grandeurs actives de t vers tdt
void TriaMemb::TversTdt()
{ lesPtMecaInt.TversTdt(); // contrainte
for (int ni=1;ni<= nombre->nbi; ni++)
{ if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TversTdt();
if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TversTdt();
if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TversTdt();
donnee_specif.epais(ni).epaisseur_tdt = donnee_specif.epais(ni).epaisseur_t;
};
ElemMeca::TversTdt_(); // appel de la procédure mère
};
// calcul de l'erreur sur l'élément. Ce calcul n'est disponible
// qu'une fois la remontée aux contraintes effectuées sinon aucune
// action. En retour la valeur de l'erreur sur l'élément
// type indique le type de calcul d'erreur :
void TriaMemb::ErreurElement(int type,double& errElemRelative
,double& numerateur, double& denominateur)
{ TriaMemb::DonnComTria* CoTria = 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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};
// appel du programme général
ElemMeca::Cal_ErrElem(type,errElemRelative,numerateur,denominateur,
tab_noeud.Taille(),(CoTria->tria).TaPhi(),
(CoTria->tria).TaWi(),
(CoTria->triaEr).TaPhi(),(CoTria->triaEr).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& TriaMemb::Boite_encombre_element(Enum_dure temps)
{ // on commence par calculer la boite d'encombrement pour l'élément médian
Element::Boite_encombre_element( temps);
// ensuite on augmente sytématiquement dans toutes directions d'une valeur h/2 majorée
double hSur2maj = H_moy(TEMPS_tdt) * 0.5 //donnee_specif.epais.epaisseur_tdt * 0.5
* ParaGlob::param->ParaAlgoControleActifs().Extra_boite_prelocalisation();
// 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;
};
// cas d'un chargement volumique,
// force indique la force volumique appliquée
// retourne le second membre résultant
// ici on considère l'épaisseur de l'élément pour constituer le volume
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur TriaMemb::SM_charge_volumique_E
(const Coordonnee& force,Fonction_nD* pt_fonct,bool atdt,const ParaAlgoControle & pa,bool sur_volume_finale_)
{ TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if(!(unefois->CalSMvol_t ))
{ unefois->CalSMvol_t += 1;
Tableau<Enum_variable_metrique> tab(10);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t;
tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ;
tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};}
else
{if (!(unefois->CalSMvol_tdt ))
{ unefois->CalSMvol_tdt += 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};};
// initialisation du résidu
residu->Zero();
// appel du programme général d'elemmeca et retour du vecteur second membre
if (donnee_specif.use_epais_moyenne)
{// retour multiplié par l'épaisseur pour avoir le volume, on considère que l'épaisseur est à jour
double epaisseur = H_moy(TEMPS_tdt);//donnee_specif.epais.epaisseur_tdt;
if (!atdt) epaisseur = H_moy(TEMPS_t); //donnee_specif.epais.epaisseur_t;
return (epaisseur * ElemMeca::SM_charge_vol_E (CoTria->tab_ddl,(CoTria->tria).TaPhi()
,tab_noeud.Taille(),(CoTria->tria).TaWi(),force,pt_fonct,pa,sur_volume_finale_));
}
else // sinon tout ce fait dans ElemMeca
return (ElemMeca::SM_charge_vol_E (CoTria->tab_ddl,(CoTria->tria).TaPhi()
,tab_noeud.Taille(),(CoTria->tria).TaWi(),force,pt_fonct,pa,sur_volume_finale_));
};
// calcul des seconds membres suivant les chargements
// cas d'un chargement volumique,
// force indique la force volumique appliquée
// retourne le second membre résultant
// ici on l'épaisseur de l'élément pour constituer le volume -> implicite,
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
// retourne le second membre et la matrice de raideur correspondant
Element::ResRaid TriaMemb::SMR_charge_volumique_I
(const Coordonnee& force,Fonction_nD* pt_fonct,const ParaAlgoControle & pa,bool sur_volume_finale_)
{ TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// initialisation du résidu
residu->Zero();
// initialisation de la raideur
raideur->Zero();
// -- définition des constantes de la métrique si nécessaire
// en fait on fait appel aux même éléments que pour le calcul implicite
if (!(unefois->CalSMvol_tdt ))
{ unefois->CalSMvol_tdt += 1;
Tableau<Enum_variable_metrique> tab(20);
tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0;
tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt;
tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt;
tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt;
tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ;
tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};
// appel du programme général d'elemmeca
ElemMeca::SMR_charge_vol_I (CoTria->tab_ddl
,(CoTria->tria).TaPhi(),tab_noeud.Taille()
,(CoTria->tria).TaWi(),force,pt_fonct,pa,sur_volume_finale_);
// prise en compte de l'epaisseur
if (donnee_specif.use_epais_moyenne)
{double epaisseur_moyenne = H_moy(TEMPS_t);
(*residu) *= epaisseur_moyenne;//donnee_specif.epais.epaisseur_t;
(*raideur) *= epaisseur_moyenne;//donnee_specif.epais.epaisseur_t;
};
Element::ResRaid el;
el.res = residu;
el.raid = raideur;
return el;
};
// calcul des seconds membres suivant les chargements
// cas d'un chargement surfacique, sur les frontières des éléments
// force indique la force surfacique appliquée
// numface indique le numéro de la face chargée
// retourne le second membre résultant
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur TriaMemb::SM_charge_surfacique_E
(const Coordonnee& force,Fonction_nD* pt_fonct,int ,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if ( !(unefois->CalSMsurf_t ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};}
else
{if ( !(unefois->CalSMsurf_tdt ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defSurf(1) == NULL)
defSurf(1) = new Deformation
(*met,tabb(1)->TabNoeud(),(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
// 1 pour dire que c'est la première surface externe
return ElemMeca::SM_charge_surf_E (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),tab_noeud.Taille()
,(CoTria->triaS).TaWi(),force,pt_fonct,pa);
};
// cas d'un chargement surfacique, sur les frontières des éléments
// force indique la force surfacique appliquée
// numface indique le numéro de la face chargée
// retourne le second membre résultant
// -> 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 TriaMemb::SMR_charge_surfacique_I
(const Coordonnee& force,Fonction_nD* pt_fonct,int ,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
// normalement numface = 1
((*res_extS)(1))->Zero();
((*raid_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if ( !(unefois->CalSMRsurf ))
{ unefois->CalSMRsurf += 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;
met->PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
// on utilise la même déformation pour toutes les arrêtes.
if (defSurf(1) == NULL)
defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(),
(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SMR_charge_surf_I (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),(tabb(1)->TabNoeud()).Taille()
,(CoTria->triaS).TaWi(),force,pt_fonct,pa);
};
// cas d'un chargement de type pression, sur les frontières des éléments
// pression indique la pression appliquée
// numface indique le numéro de la face chargée
// retourne le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de
// surface externe -> message d'erreur d'où le virtuel et non virtuel pur
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur TriaMemb::SM_charge_pression_E(double pression,Fonction_nD* pt_fonct,int ,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if ( !(unefois->CalSMsurf_t ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};}
else
{if ( !(unefois->CalSMsurf_tdt ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defSurf(1) == NULL)
defSurf(1) = new Deformation
(*met,tabb(1)->TabNoeud(),(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
// 1 pour dire que c'est la première surface externe
return ElemMeca::SM_charge_pres_E (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),tab_noeud.Taille()
,(CoTria->triaS).TaWi(),pression,pt_fonct,pa);
};
// cas d'un chargement de type pression, sur les frontières des éléments
// pression indique la pression appliquée
// numface indique le numéro de la face chargée
// retourne le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de
// surface externe -> message d'erreur d'où le virtuel et non virtuel pur -> 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 TriaMemb::SMR_charge_pression_I
(double pression,Fonction_nD* pt_fonct,int ,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
((*res_extS)(1))->Zero();
((*raid_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if ( !(unefois->CalSMRsurf ))
{ unefois->CalSMRsurf += 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;
met->PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
// on utilise la même déformation pour toutes les arrêtes.
if (defSurf(1) == NULL)
defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(),
(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SMR_charge_pres_I (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),(tabb(1)->TabNoeud()).Taille()
,(CoTria->triaS).TaWi(),pression,pt_fonct,pa);
};
// cas d'un chargement de type pression unidirectionnelle, sur les frontières des éléments
// presUniDir indique le vecteur appliquée
// numface indique le numéro de la face chargée: ici 1
// retourne le second membre résultant
// -> explicite à t ou tdt en fonction de la variable booleenne atdt
Vecteur TriaMemb::SM_charge_presUniDir_E
(const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int ,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if ( !(unefois->CalSMsurf_t ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};}
else
{if ( !(unefois->CalSMsurf_tdt ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defSurf(1) == NULL)
defSurf(1) = new Deformation
(*met,tabb(1)->TabNoeud(),(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SM_charge_surf_Suiv_E (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),tab_noeud.Taille()
,(CoTria->triaS).TaWi(),presUniDir,pt_fonct,pa,atdt);
};
// -> implicite,
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
// retourne le second membre et la matrice de raideur correspondant
Element::ResRaid TriaMemb::SMR_charge_presUniDir_I
(const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int numface,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
((*res_extS)(1))->Zero();
((*raid_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if ( !(unefois->CalSMRsurf ))
{ unefois->CalSMRsurf += 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;
met->PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
// on utilise la même déformation pour toutes les arrêtes.
if (defSurf(1) == NULL)
defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(),
(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SMR_charge_surf_Suiv_I (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),(tabb(1)->TabNoeud()).Taille()
,(CoTria->triaS).TaWi(),presUniDir,pt_fonct,pa);
};
// cas d'un chargement lineique, sur les arêtes frontières des éléments
// force indique la force lineique appliquée
// numArete indique le numéro de l'arête chargée
// retourne le second membre résultant
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur TriaMemb::SM_charge_lineique_E
(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extA)(numArete))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf =Frontiere_lineique(numArete,true);
// on utilise la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// récupération de la métrique associée à l'élément qui est commune a tous les triangles
// du même type
Met_abstraite * meta= elf->Metrique();
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if( !(unefois->CalSMlin_t ))
{ unefois->CalSMlin_t += 1;
Tableau<Enum_variable_metrique> tab(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;
meta->PlusInitVariables(tab) ;
};}
else
{if( !(unefois->CalSMlin_tdt ))
{ unefois->CalSMlin_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;
meta->PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(numArete) == NULL)
defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
(CoTria->segS).TaDphi(),(CoTria->segS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SM_charge_line_E (elf->DdlElem(),numArete
,(CoTria->segS).TaPhi(),(elf->TabNoeud()).Taille()
,(CoTria->segS).TaWi(),force,pt_fonct,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
// NB: il y a une définition par défaut pour les éléments qui n'ont pas
// d'arete externe -> message d'erreur d'où le virtuel et non virtuel pur
// -> 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 TriaMemb::SMR_charge_lineique_I
(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
((*res_extA)(numArete))->Zero();
((*raid_extA)(numArete))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf =Frontiere_lineique(numArete,true);
// on utilise la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// récupération de la métrique associée à l'élément qui est commune a tous les triangles
// du même type
Met_abstraite * meta= elf->Metrique();
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if( !(unefois->CalSMRlin ))
{ unefois->CalSMRlin += 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;
meta->PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(numArete) == NULL)
defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
(CoTria->segS).TaDphi(),(CoTria->segS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SMR_charge_line_I (elf->DdlElem(),numArete
,(CoTria->segS).TaPhi(),(elf->TabNoeud()).Taille()
,(CoTria->segS).TaWi(),force,pt_fonct,pa);
};
// cas d'un chargement lineique suiveuse, sur les aretes frontières des éléments 2D (uniquement)
// force indique la force lineique appliquée
// numarete indique le numéro de l'arete chargée
// retourne le second membre résultant
// -> explicite à t ou tdt en fonction de la variable booléenne atdt
Vecteur TriaMemb::SM_charge_lineique_Suiv_E
(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu
((*res_extA)(numArete))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf =Frontiere_lineique(numArete,true);
// on utilise la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// récupération de la métrique associée à l'élément qui est commune a tous les triangles
// du même type
Met_abstraite * meta= elf->Metrique();
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if (!atdt)
{if( !(unefois->CalSMlin_t ))
{ unefois->CalSMlin_t += 1;
Tableau<Enum_variable_metrique> tab(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;
meta->PlusInitVariables(tab) ;
};}
else
{if( !(unefois->CalSMlin_tdt ))
{ unefois->CalSMlin_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;
meta->PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(numArete) == NULL)
defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
(CoTria->segS).TaDphi(),(CoTria->segS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SM_charge_line_Suiv_E (elf->DdlElem(),numArete
,(CoTria->segS).TaPhi(),(elf->TabNoeud()).Taille()
,(CoTria->segS).TaWi(),force,pt_fonct,pa);
};
// cas d'un chargement lineique suiveuse, sur les aretes frontières des éléments 2D (uniquement)
// force indique la force lineique appliquée
// numarete indique le numéro de l'arete chargée
// retourne le second membre résultant -> 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 TriaMemb::SMR_charge_lineique_Suiv_I
(const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa)
{ // initialisation du vecteur résidu et de la raideur
((*res_extA)(numArete))->Zero();
((*raid_extA)(numArete))->Zero();
// on récupère ou on crée la frontière arrête
ElFrontiere* elf = Frontiere_lineique(numArete,true);
// on utilise la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// récupération de la métrique associée à l'élément qui est commune a tous les triangles
// du même type
Met_abstraite * meta= elf->Metrique();
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if( !(unefois->CalSMRlin ))
{ unefois->CalSMRlin += 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;
meta->PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
if (defArete(numArete) == NULL)
defArete(numArete) = new Deformation(*meta,elf->TabNoeud(),
(CoTria->segS).TaDphi(),(CoTria->segS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SMR_charge_line_Suiv_I (elf->DdlElem(),numArete
,(CoTria->segS).TaPhi(),(elf->TabNoeud()).Taille()
,(CoTria->segS).TaWi(),force,pt_fonct,pa);
};
// cas d'un chargement de type pression hydrostatique, sur les frontières des éléments
// 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
// retourne le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de
// surface externe -> message d'erreur d'où le virtuel et non virtuel pur
// -> explicite à t ou à tdt en fonction de la variable booléenne atdt
Vecteur TriaMemb::SM_charge_hydrostatique_E(const Coordonnee& dir_normal_liquide,const double& poidvol
,int ,const Coordonnee& M_liquide,bool atdt
,const ParaAlgoControle & pa
,bool sans_limitation)
{ // initialisation du vecteur résidu
((*res_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
// // récupération de la métrique associée à l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// définition des constantes de la métrique si nécessaire
if (!atdt)
{if ( !(unefois->CalSMsurf_t ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};}
else
{if ( !(unefois->CalSMsurf_tdt ))
{ unefois->CalSMsurf_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;
CoTria->met_triaMemb.PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (defSurf(1) == NULL)
defSurf(1) = new Deformation
(*met,tabb(1)->TabNoeud(),(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SM_charge_hydro_E (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),(tabb(1)->TabNoeud()).Taille()
,(CoTria->triaS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa,atdt);
};
// cas d'un chargement de type pression hydrostatique, sur les frontières des éléments
// 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
// retourne le second membre résultant
// NB: il y a une définition par défaut pour les éléments qui n'ont pas de
// surface externe -> message d'erreur d'où le virtuel et non virtuel pur
// -> 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 TriaMemb::SMR_charge_hydrostatique_I (const Coordonnee& dir_normal_liquide,const double& poidvol
,int ,const Coordonnee& M_liquide
,const ParaAlgoControle & pa
,bool sans_limitation)
{ // initialisation du vecteur résidu et de la raideur
((*res_extS)(1))->Zero();
((*raid_extS)(1))->Zero();
// on récupère ou on crée la frontière surfacique
Frontiere_surfacique(1,true);
// on pourrait utiliser la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// mais on utilise celle de l'élément
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// dimensionnement de la metrique
if ( !(unefois->CalSMRsurf ))
{ unefois->CalSMRsurf += 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;
met->PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
if (defSurf(1) == NULL)
defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(),
(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
// appel du programme général d'elemmeca et retour du vecteur second membre
return ElemMeca::SMR_charge_hydro_I (tabb(1)->DdlElem(),1
,(CoTria->triaS).TaPhi(),(tabb(1)->TabNoeud()).Taille()
,(CoTria->triaS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa);
};
// cas d'un chargement surfacique hydro-dynamique,
// Il y a trois forces: une suivant la direction de la vitesse: de type traînée aerodynamique
// Fn = poids_volu * fn(V) * S * (normale*u) * u, u étant le vecteur directeur de V (donc unitaire)
// une suivant la direction normale à la vitesse de type portance
// Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire, normal à V, et dans le plan n et V
// une suivant la vitesse tangente de type frottement visqueux
// T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
// coef_mul: est un coefficient multiplicateur global (de tout)
// retourne le second membre résultant
// // -> explicite à t ou à tdt en fonction de la variable booléenne atdt
Vecteur TriaMemb::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)
{ int dime = ParaGlob::Dimension();
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
Met_abstraite * meta; ElemGeomC0* elemGeom; // définit dans le choix suivant
// on utilise la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// récupération de la métrique associée à l'élément qui est commune a tous les triangles
// du même type
if (dime == 3) // il s'agit de surface
// initialisation du vecteur résidu et de la raideur pour la surface
{((*res_extS)(numface))->Zero(); ((*raid_extS)(numface))->Zero();
Frontiere_surfacique(numface,true);// on récupère ou on crée la frontière surfacique
meta= tabb(numface)->Metrique();
elemGeom = &(CoTria->triaS); // récup de l'élément géométrique
}
else // dime 2: il s'agit de ligne
// initialisation du vecteur résidu et de la raideur pour une arrête
{((*res_extA)(numface))->Zero(); ((*raid_extA)(numface))->Zero();
ElFrontiere* elf = Frontiere_lineique(numface,true);// on récupère ou on crée la frontière lineique
meta= elf->Metrique();
elemGeom = &(CoTria->segS); // récup de l'élément géométrique
};
// dimensionnement de la metrique
// définition des constantes de la métrique si nécessaire
if (!atdt)
{if (((dime == 3)&& !(unefois->CalSMsurf_t)) || ((dime == 2)&& !(unefois->CalSMlin_t)))
{ if (dime == 3) {unefois->CalSMsurf_t += 1;} else {unefois->CalSMlin_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;
meta->PlusInitVariables(tab) ;
};}
else
{if (((dime == 3)&& !(unefois->CalSMsurf_tdt )) || ((dime == 2)&& !(unefois->CalSMlin_tdt )))
{ if (dime == 3) {unefois->CalSMsurf_tdt += 1;} else {unefois->CalSMlin_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;
meta->PlusInitVariables(tab) ;
};};
// on définit la déformation a doc si elle n'existe pas déjà
if (dime == 3)
{ if (defSurf(numface) == NULL)
defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
}
else
{ if (defArete(numface) == NULL)
defArete(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
(CoTria->segS).TaDphi(),(CoTria->segS).TaPhi());
};
// appel du programme général d'ElemMeca et retour du vecteur second membre
return ElemMeca::SM_charge_hydrodyn_E (poidvol,elemGeom->TaPhi(),(tabb(numface)->TabNoeud()).Taille()
,frot_fluid,elemGeom->TaWi()
,coef_aero_n,numface,coef_mul,coef_aero_t,pa,atdt);
};
// -> implicite,
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
// retourne le second membre et la matrice de raideur correspondant
Element::ResRaid TriaMemb::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)
{ int dime = ParaGlob::Dimension();
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
Met_abstraite * meta; ElemGeomC0* elemGeom; // définit dans le choix suivant
// on utilise la métrique des éléments de frontière
// avec l'instance déformation dédiée pour
// récupération de la métrique associée à l'élément qui est commune a tous les triangles
// du même type
if (dime == 3) // il s'agit de surface
// initialisation du vecteur résidu et de la raideur pour la surface
{((*res_extS)(numface))->Zero(); ((*raid_extS)(numface))->Zero();
Frontiere_surfacique(numface,true);// on récupère ou on crée la frontière surfacique
meta= tabb(numface)->Metrique();
elemGeom = &(CoTria->triaS); // récup de l'élément géométrique
}
else // dime 2: il s'agit de ligne
// initialisation du vecteur résidu et de la raideur pour une arrête
{((*res_extA)(numface))->Zero(); ((*raid_extA)(numface))->Zero();
ElFrontiere* elf = Frontiere_lineique(numface,true);// on récupère ou on crée la frontière lineique
meta= elf->Metrique();
elemGeom = &(CoTria->segS); // récup de l'élément géométrique
};
// dimensionnement de la metrique
// définition des constantes de la métrique si nécessaire
if (((dime == 3)&& !(unefois->CalSMRsurf )) || ((dime == 2)&& !(unefois->CalSMRlin )))
{ if (dime == 3) {unefois->CalSMRsurf += 1;} else {unefois->CalSMRlin += 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;
meta->PlusInitVariables(tab) ;
};
// on définit la déformation a doc si elle n'existe pas déjà
if (dime == 3)
{ if (defSurf(numface) == NULL)
defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
(CoTria->triaS).TaDphi(),(CoTria->triaS).TaPhi());
}
else
{ if (defArete(numface) == NULL)
defArete(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(),
(CoTria->segS).TaDphi(),(CoTria->segS).TaPhi());
};
// appel du programme général d'ElemMeca et retour du vecteur second membre
return ElemMeca::SM_charge_hydrodyn_I (poidvol,elemGeom->TaPhi(),(tabb(numface)->TabNoeud()).Taille()
,frot_fluid,elemGeom->TaWi(),tabb(numface)->DdlElem()
,coef_aero_n,numface,coef_mul
,coef_aero_t,pa);
};
// 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 & TriaMemb::Frontiere(bool force)
{ // en 3D on veut des faces et des lignes
int cas = 0; // init
if ((ParaGlob::Dimension()==3)&& (!ParaGlob::AxiSymetrie()))
{cas = 4;}
else if (ParaGlob::Dimension()==2)
{cas = 2;};
// = 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
return Frontiere_elemeca(cas,force);
// {// le calcul et la création ne sont effectués qu'au premier appel
// // ou lorsque l'on veut forcer une recréation
// if (((ind_front_lin == 0) && (ind_front_surf == 0) && (ind_front_point == 0))
// || force )
//// if ((ind_front_lin == 0) || force || (ind_front_lin == 2))
// {TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// ElemGeomC0 & el = (CoTria->tria);
// DdlElement & tdd = CoTria->tab_ddl;
// // dimensionnement des tableaux intermediaires
// Tableau <Noeud *> tab(nombre->nbneA); // les noeuds des segments frontieres
// DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres
//
// int tail;
// if ((ParaGlob::Dimension() == 2) && (ind_front_surf == 0))
// tail = 3; // trois cotes et pas de surface
// else if (ParaGlob::Dimension() == 2) // cas avec la surface en 2D
// tail = 4; // trois cotes et la facette elle meme
// else if (ParaGlob::Dimension() == 3)
// tail = 4; // trois cotes et la facette elle meme
// #ifdef MISE_AU_POINT
// else
// { cout << "\n erreur de dimension dans Tria, dim = " << ParaGlob::Dimension();
// cout << "\n alors que l'on doit avoir 2 ou 3 !! " << endl;
// Sortie (1);
// }
// #endif
//
// if ((ind_front_point > 0) && (ind_front_lin == 0) && (ind_front_surf == 0))
// // cas où les frontières points existent seule
// { int tail_p = nombre->nbne; // le nombre de noeuds
// int taille_f = tail + tail_p;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_p;i++)
// { tabb(i+tail) = tabb(i);
// tabb(i) = NULL;
// }
// posi_tab_front_point=tail;
// }
// else if ((ind_front_point > 0) && (ind_front_lin == 0) && (ind_front_surf > 0))
// // cas où les frontières points existent et surface et pas de ligne
// { int tail_p = nombre->nbne; // le nombre de noeuds
// int taille_f = tail + tail_p + 1;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_p;i++) // transfert pour les noeuds
// { tabb(i+tail) = tabb(i+1);tabb(i+1) = NULL;}
// posi_tab_front_point=tail;
// // pour la surface, c'est la première, elle y reste
// }
// else if ((ind_front_point > 0) && (ind_front_lin > 0) && (ind_front_surf == 0))
// // cas où les frontières points existent et ligen et pas de surface
// { int tail_af = nombre->nbne+el.NonS().Taille(); // nombre d'arête + noeud
// int taille_f = tail + tail_af;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_af;i++) // transfert pour les noeuds
// { tabb(i+tail) = tabb(i);tabb(i) = NULL;}
// posi_tab_front_point +=tail;
// posi_tab_front_lin +=tail;
// }
// else
// { // cas où il n'y a pas de frontières points
// if (ind_front_surf == 0) // dimensionnement éventuelle
// tabb.Change_taille(tail); // le tableau total de frontières
// };
//
// // positionnement du début des lignes
// posi_tab_front_lin = 0; // par défaut
// // création éventuelle de la surface
// if (tail == 4)
// {if (tabb(1) == NULL)
// { int nbnoe = el.Nonf()(1).Taille(); // nb noeud de la face
// Tableau <Noeud *> tab(nbnoe); // les noeuds des faces frontieres
// DdlElement ddelem(nombre->nbne); // les ddlelements des noeuds frontieres
// for (int i=1;i<= nbnoe;i++)
// { tab(i) = tab_noeud(el.Nonf()(1)(i));
// ddelem.Change_un_ddlNoeudElement(i,tdd(el.Nonf()(1)(i)));
// // ddelem(i) = tdd(el.Nonf()(1)(i));
// }
// tabb(1) = new_frontiere_surf(tab,ddelem);
// // mise à jour de l'indicateur de création de face
// ind_front_surf = 1;
// };
// // mise à jour du début des lignes
// posi_tab_front_lin = 1;
// };
// // création éventuelle des lignes
// for (int nlign=1;nlign<=3;nlign++)
// if (tabb(posi_tab_front_lin+nlign) == NULL)
// { int nbnoe = el.NonS()(nlign).Taille(); // nb noeud de l'arête
// Tableau <Noeud *> tab(nbnoe); // les noeuds de l'arête frontiere
// DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres
// for (int i=1;i<= nbnoe;i++)
// { tab(i) = tab_noeud(el.NonS()(nlign)(i));
// ddelem.Change_un_ddlNoeudElement(i,tdd(el.NonS()(nlign)(i)));
// // ddelem(i) = tdd(el.NonS()(nlign)(i));
// }
// tabb(posi_tab_front_lin+nlign) = new_frontiere_lin(tab,ddelem);
// }
// // mise à jour de l'indicateur
// ind_front_lin = 1;
// }
// // 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 TriaMemb::Frontiere_points(int num,bool force)
// { // le calcul et la création ne sont effectués qu'au premier appel
// // ou lorsque l'on veut forcer une recréation
// #ifdef MISE_AU_POINT
// if ((num > nombre->nbne)||(num <=0))
// { cout << "\n *** erreur, le noeud demande pour frontiere: " << num << " esten dehors de la numeration de l'element ! "
// << "\n Frontiere_points(int num,bool force)";
// Sortie(1);
// }
// #endif
//
// if ((ind_front_point == 0) || force || (ind_front_point == 2))
// {Tableau <Noeud *> tab(1); // les noeuds des points frontieres
// DdlElement ddelem(1); // les ddlelements des points frontieres
// // on regarde si les frontières points existent sinon on les crée
// if (ind_front_point == 1)
// return (ElFrontiere*)tabb(posi_tab_front_point+num);
// else if ( ind_front_point == 2)
// // cas où certaines frontières existent
// if (tabb(posi_tab_front_point+num) != NULL)
// return (ElFrontiere*)tabb(posi_tab_front_point+num);
// // dans tous les autres cas on construit la frontière point
// // on commence par dimensionner le tableau de frontière, comme les frontières points sont
// // les dernières, il suffit de les ajouter, d'où on redimentionne le tableau mais on ne créra
// // que la frontière adoc
// // def de la taille
// int taille_actuelle = tabb.Taille();
// if ((ind_front_point == 0) && ((ind_front_lin > 0) || (ind_front_surf > 0)))
// // cas où les frontières lignes ou surfaces existent, mais pas les points
// { int tail_p = nombre->nbne; // le nombre de noeuds
// int taille_f = taille_actuelle + tail_p;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_p;i++)
// { tabb(i+taille_actuelle) = tabb(i);tabb(i) = NULL;};
// posi_tab_front_point +=taille_actuelle;
// if (ind_front_lin > 0) posi_tab_front_lin += taille_actuelle;
// }
// else if (ind_front_point == 0)
// // cas où aucune frontière n'existe
// {tabb.Change_taille(nombre->nbne);};
// // dans les autres cas, les frontières points exitent donc pas à dimensionner
// // on définit tous les points par simplicité
// for (int i=1;i<=nombre->nbne;i++)
// {tab(1) = tab_noeud(i);ddelem.Change_un_ddlNoeudElement(1,unefois->doCoMemb->tab_ddl(i));
// if (tabb(i+posi_tab_front_point) == NULL)
// tabb(i+posi_tab_front_point) = new FrontPointF (tab,ddelem);
// };
// };
// return (ElFrontiere*)tabb(num+posi_tab_front_point);
// };
//
//// ramène la frontière linéique
//// éventuellement création des frontieres linéique de l'element et stockage dans l'element
//// si c'est la première fois et en 3D sinon il y a seulement retour de l'elements
//// a moins que le paramètre force est mis a true
//// dans ce dernier cas la frontière effacéee est recréée
//// num indique le numéro de l'arête à créer (numérotation EF)
//ElFrontiere* const TriaMemb::Frontiere_lineique(int num,bool force)
//{ // le calcul et la création ne sont effectués qu'au premier appel
// // ou lorsque l'on veut forcer une recréation
// // on regarde si les frontières linéiques existent sinon on les crée
// if (!force)
// {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);
// };
// }
// else // cas où on veut forcer une nouvelle création
// { if (ind_front_lin != 0)
// if (tabb(posi_tab_front_lin+num) != NULL)
// {delete tabb(posi_tab_front_lin+num); //on commence par supprimer
// tabb(posi_tab_front_lin+num)=NULL;
// // on supprime également éventuellement la déformation associée pour un calcul d'arête
// if (defArete.Taille() != 0)
// {delete defArete(num);defArete(num)=NULL;};
// if (ind_front_lin == 1)
// ind_front_lin = 2; // on indique
// };
// };
// // 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 || (ind_front_lin == 2))
// {TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// ElemGeomC0 & el = (CoTria->tria);
// DdlElement & tdd = CoTria->tab_ddl;
// // dimensionnement des tableaux intermediaires
// Tableau <Noeud *> tab(nombre->nbneA); // les noeuds des segments frontieres
// DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres
//
//
// int taille = tabb.Taille(); // la taille initiales des frontières
// int tail_fa = 1; // nombre potentiel de faces
// int tail_ar = 3; // nombre potentiel d'arêtes
// // 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 seule
// { int tail_p = nombre->nbne; // le nombre de noeuds
// int taille_f = tail_ar + tail_p;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_p;i++)
// { tabb(i+tail_ar) = tabb(i);
// tabb(i) = NULL;
// }
// posi_tab_front_point=tail_ar;
// }
// else if ((ind_front_point > 0) && (ind_front_surf > 0))
// // cas où les frontières points existent et surface et pas de ligne
// { int tail_p = nombre->nbne; // le nombre de noeuds
// int taille_f = tail_ar + tail_p + 1;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_p;i++) // transfert pour les noeuds
// { tabb(i+tail_ar+1) = tabb(i+1);tabb(i+1) = NULL;}
// posi_tab_front_point=tail_ar+1;
// // pour la surface, c'est la première, elle y reste
// }
// else
// { // cas où il n'y a pas de frontières points
// if (ind_front_surf == 0) // cas où il n'y a pas la surface
// {tabb.Change_taille(tail_ar,NULL); // on n'a pas de ligne, pas de point et pas de surface
// posi_tab_front_lin = 0;} // on peut tout mettre à NULL
// else {tabb.Change_taille(tail_ar+tail_fa); // cas où les surfaces existent
// for (int i=1;i<=tail_ar;i++)
// tabb(i+tail_fa)=NULL;
// posi_tab_front_lin = 1;};
// };
// };
// // création de la ligne éventuellement
// if ((tabb(posi_tab_front_lin+num) == NULL) || force)
// { 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(nombre->nbneA); // 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(tab,ddelem);
// ind_front_lin = 1; // a priori
// for (int nlign=1;nlign<=3;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 de la frontiere surfacique de l'element et stockage dans l'element
//// si c'est la première fois sinon il y a seulement retour de l'elements
//// a moins que le paramètre force est mis a true
//// dans ce dernier cas la frontière effacéee est recréée
//// num indique le numéro de la surface à créer (numérotation EF) ici normalement uniquement 1 possible
//ElFrontiere* const TriaMemb::Frontiere_surfacique(int ,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
// if ((ind_front_surf == 0) || force || (ind_front_surf == 2))
// { TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
// ElemGeomC0 & el = (CoTria->tria);
// DdlElement & tdd = CoTria->tab_ddl;
// int taille = tabb.Taille(); // la taille initiales des frontières
// int tail_s = 1; // nombre de faces
// int tail_a = el.NonS().Taille(); // nombre d'arête
// posi_tab_front_lin = 1; // init indice de début d'arrête dans tabb
//
// // def de la taille
// if ((ind_front_point > 0) && (ind_front_lin == 0) && (ind_front_surf == 0))
// // cas où les frontières points existent seule
// { int tail_p = nombre->nbne; // le nombre de noeuds
// int taille_f = tail_s + tail_p;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_p;i++)
// { tabb(i+tail_s) = tabb(i);tabb(i) = NULL;};
// posi_tab_front_point=tail_s;
// }
// else if ((ind_front_point > 0) && (ind_front_lin > 0) && (ind_front_surf == 0))
// // cas où les frontières points existent et ligne et pas de surface
// { int tail_af = nombre->nbne+el.NonS().Taille(); // nombre d'arête + noeud
// int taille_f = tail_s + tail_af;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_af;i++) // transfert pour les noeuds
// { tabb(i+tail_s) = tabb(i);tabb(i) = NULL;}
// posi_tab_front_point +=tail_s;
// posi_tab_front_lin +=tail_s;
// }
// else if ((ind_front_point == 0) && (ind_front_lin > 0) && (ind_front_surf == 0))
// // cas où les frontières ligne existent seule
// { int tail_a = el.NonS().Taille(); // nombre d'arête
// int taille_f = tail_s + tail_a;
// tabb.Change_taille(taille_f);
// for (int i=1;i<= tail_a;i++) // transfert pour les noeuds
// { tabb(i+tail_s) = tabb(i);tabb(i) = NULL;}
// posi_tab_front_point +=tail_s;
// posi_tab_front_lin +=tail_s;
// }
// else if (ind_front_surf == 0) // cas autre, où la frontière surface n'existe pas
// // et qu'il n'y a pas de ligne ni de point
// tabb.Change_taille(tail_s); // le tableau total de frontières
// // création éventuelle de la face
// if (tabb(1) == NULL)
// { int nbnoe = nombre->nbne; // nb noeud de la surface
// Tableau <Noeud *> tab(nbnoe); // les noeuds de la surface
// DdlElement ddelem(nbnoe); // les ddlelements des noeuds frontieres
// for (int i=1;i<= nbnoe;i++)
// { tab(i) = tab_noeud(el.Nonf()(1)(i));
// ddelem.Change_un_ddlNoeudElement(i,tdd(el.Nonf()(1)(i)));
// // ddelem(i) = tdd(el.Nonf()(1)(i));
// }
// tabb(1) = new_frontiere_surf(tab,ddelem);
// }
// // mise à jour de l'indicateur
// ind_front_surf = 1;
// }
// return (ElFrontiere*)tabb(1);
// };
// liberation de la place pointee
void TriaMemb::Libere ()
{Element::Libere (); // liberation de residu et raideur
LibereTenseur() ; // liberation des tenseur intermediaires
};
// acquisition ou modification d'une loi de comportement
void TriaMemb::DefLoi (LoiAbstraiteGeneral * NouvelleLoi)
{ // verification du type de loi
if ((NouvelleLoi->Dimension_loi() != 2) && (NouvelleLoi->Dimension_loi() != 4))
{ cout << "\n Erreur, la loi de comportement a utiliser avec des TriaMembs";
cout << " doit etre de type 2D, \n ici elle est de type = "
<< (NouvelleLoi->Dimension_loi()) << "D !!! " << endl;
Sortie(1);
}
// cas d'une loi mécanique
if (GroupeMecanique(NouvelleLoi->Id_categorie()))
{loiComp = (Loi_comp_abstraite *) NouvelleLoi;
// initialisation du stockage particulier, ici en fonction du nb de pt d'integ
int imaxi = tabSaveDon.Taille();
for (int i=1;i<= imaxi;i++) tabSaveDon(i) = loiComp->New_et_Initialise();
// idem pour le type de déformation mécanique associé
int iDefmax = tabSaveDefDon.Taille();
for (int i=1;i<= iDefmax;i++) tabSaveDefDon(i) = def->New_et_Initialise();
// définition du type de déformation associé à la loi
loiComp->Def_type_deformation(*def);
// on active les données particulières nécessaires au fonctionnement de la loi de comp
loiComp->Activation_donnees(tab_noeud,dilatation,lesPtMecaInt);
};
// cas d'une loi thermo physique
if (GroupeThermique(NouvelleLoi->Id_categorie()))
{loiTP = (CompThermoPhysiqueAbstraite *) NouvelleLoi;
// initialisation du stockage particulier thermo physique,
int imax = tabSaveTP.Taille();
for (int i=1;i<= imax;i++) tabSaveTP(i) = loiTP->New_et_Initialise();
// on active les données particulières nécessaires au fonctionnement de la loi de comp
loiTP->Activation_donnees(tab_noeud);
};
// cas d'une loi de frottement
if (GroupeFrottement(NouvelleLoi->Id_categorie()))
loiFrot = (CompFrotAbstraite *) NouvelleLoi;
};
// test si l'element est complet
int TriaMemb::TestComplet()
{ int res = ElemMeca::TestComplet(); // test dans la fonction mere
bool pas_epaisseur = false;
if(donnee_specif.epais.Taille() == 0) pas_epaisseur=true;
if (!pas_epaisseur)
if (donnee_specif.epais(1).epaisseur0 == epaisseur_defaut)
pas_epaisseur = true;
if (pas_epaisseur)
{ cout << "\n l\'epaisseur de l\'element triangulaire n\'est pas defini \n";
res = 0; };
if ( tab_noeud(1) == NULL)
{ cout << "\n les noeuds de l\'element triangulaire ne sont pas defini \n";
res = 0; }
else
{ int testi =1;
int posi = Id_nom_ddl("X1") -1;
int dim = ParaGlob::Dimension();
int jmaxi = tab_noeud.Taille();
for (int i =1; i<= dim; i++)
for (int j=1;j<=jmaxi;j++)
if(!(tab_noeud(j)->Existe_ici(Enum_ddl(posi+i))))
testi = 0;
if(testi == 0)
{ cout << "\n les ddls Xi des noeuds de la facette ne sont pas defini \n";
cout << " \n utilisez TriaMemb::ConstTabDdl() pour completer " ;
res = 0; }
}
return res;
};
// procesure permettant de completer l'element apres
// sa creation avec les donnees du bloc transmis
// ici il s'agit de l'epaisseur et de la masse volumique
Element* TriaMemb::Complete(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD)
{ // complétion avec bloc
if (bloc.Nom(1) == "epaisseurs")
{ // deux cas suivant que l'épaisseur est un réel ou que c'est une fonction nD
donnee_specif.epais.Change_taille(nombre->nbi);
if (bloc.Nom(2) == "_") // cas fixe
{double epaiss = bloc.Val(1);
for (int i=1; i<= nombre->nbi;i++)
donnee_specif.epais(i).epaisseur_tdt = donnee_specif.epais(i).epaisseur_t
= donnee_specif.epais(i).epaisseur0 = epaiss;
}
else // cas fct nD, on va calculer l'épaisseur pour chaque pti
{ // on récupère la fct nD
Fonction_nD* fctnD_epais=NULL;
if (lesFonctionsnD->Existe(bloc.Nom(2)))
{fctnD_epais= lesFonctionsnD->Trouve(bloc.Nom(2));}
else // sinon c'est un problème
{ cout << "\n *** erreur dans la definition de l'epaisseur via la fonction nD "
<< bloc.Nom(2) << ", a priori cette fonction n'est pas disponible!! "
<< "\n TriaMemb::Complete(...)";
Sortie(1);
};
// on vérifie qu'en retour la fonction ramène un seule scalaire
if (fctnD_epais->NbComposante() != 1)
{ cout << "\n *** erreur dans la definition de l'epaisseur via la fonction nD "
<< bloc.Nom(2) << ", la fonction ramene " << fctnD_epais->NbComposante()
<< " composantes !! au lieu d'une seule valeur !"
<< "\n TriaMemb::Complete(...)";
Sortie(1);
};
// pour l'instant on n'accepte qu'une dépendance aux coordonnées initiales du point
// d'intégration et par ailleurs à des grandeurs globales
if (fctnD_epais->Depend_M0() < 0)
{// on va boucler sur les pti
for (int ni=1; ni<= nombre->nbi;ni++)
{// on récupère les coordonnées du pti
bool erreur = false;
Coordonnee M = CoordPtInteg(TEMPS_0,X1,ni,erreur);
if (erreur)
{ cout << "\n *** erreur dans le calcul des coordonnees du point d'integration "
<< ni << ", on ne peut pas initialiser l'epaisseur "
<< "\n TriaMemb::Complete(...)";
Sortie(1);
}
else // sinon c'est ok
{ Tableau <Coordonnee> tab_M(1,M);
Tableau <double> & tava = fctnD_epais->Val_FnD_Evoluee(NULL,&tab_M,NULL); // pour simplifier
donnee_specif.epais(ni).epaisseur_tdt = donnee_specif.epais(ni).epaisseur_t
= donnee_specif.epais(ni).epaisseur0 = tava(1);
};
};
}
else
{ cout << "\n *** erreur dans le calcul de l'epaisseur via la fonction nD "
<< bloc.Nom(2) << ", cette fonction ne depend pas seulement des coordonnees initiales ! "
<< "\n TriaMemb::Complete(...)";
Sortie(1);
};
// // on commence par récupérer les conteneurs des grandeurs à fournir
// List_io <Ddl_enum_etendu>& li_enu_scal = fctnD_epais->Li_enu_etendu_scalaire();
// List_io <TypeQuelconque >& li_quelc = fctnD_epais->Li_equi_Quel_evolue();
// bool absolue = true; // on se place systématiquement en absolu
// int cas = 1; // il faut vérifier
// for (int ni=1; ni<= nombre->nbi;ni++)
// { // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire
// Tableau <double> val_ddl_enum(ElemMeca::Valeur_multi(absolue,TEMPS_tdt,li_enu_scal,ni,cas));
// // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur
// Valeurs_Tensorielles(absolue, TEMPS_tdt,li_quelc,ni,cas);
// // calcul de la valeur et retour dans tab_ret
// Tableau <double> & tab_ret = fctnD_epais->Valeur_FnD_Evoluee
// (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL);
// donnee_specif.epais(ni).epaisseur_tdt = donnee_specif.epais(ni).epaisseur_t
// = donnee_specif.epais(ni).epaisseur0 = tab_ret(1);
// };
};
return this;
}
// cas de la définition d'une stabilisation transversale pour membrane ou biel
else if (bloc.Nom(1) == "stabilisation_transvers_membrane_biel_")
{// l'objectif ici est d'allouer la raideur et résidu local spécifique à l'élément
int nbddl = (*residu).Taille();
if (unefois->doCoMemb->triamatD == NULL)
unefois->doCoMemb->triamatD = new Mat_pleine(nbddl,nbddl);
if (unefois->doCoMemb->triaresD == NULL)
unefois->doCoMemb->triaresD = new Vecteur(nbddl);
// on renseigne les pointeurs d'ElemeMeca
ElemMeca::matD = unefois->doCoMemb->triamatD;
ElemMeca::resD = unefois->doCoMemb->triaresD;
// ensuite les autres informations sont gérées par ElemMeca
return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD);
}
else // concernant la stabilisation éventuelle transversale, c'est dans elemMeca
return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD);
};
// Compléter pour la mise en place de la gestion de l'hourglass
Element* TriaMemb::Complet_Hourglass(LoiAbstraiteGeneral * loiHourglass, const BlocGen & bloc)
{ // on initialise le traitement de l'hourglass
string str_precision; // string vide indique que l'on veut utiliser un élément normal
// // dans le cas où il s'agit d'élément Quadratique il faut utiliser 27 pti par défaut
// if ((id_interpol == QUADRATIQUE) || (id_interpol == QUADRACOMPL))
// str_precision = "_cm27pti";
ElemMeca::Init_hourglass_comp(*(unefois->doCoMemb->triaHourg),str_precision,loiHourglass,bloc);
// dans le cas où l'hourglass a été activé mais que l'élément n'a pas
// de traitement particulier associé, alors on désactive l'hourglass
if ( ((type_stabHourglass == STABHOURGLASS_PAR_COMPORTEMENT) || (type_stabHourglass == STABHOURGLASS_PAR_COMPORTEMENT_REDUIT))
&&(unefois->doCoMemb->triaHourg == NULL))
type_stabHourglass = STABHOURGLASS_NON_DEFINIE;
return this;
};
// ajout du tableau de ddl des noeuds
void TriaMemb::ConstTabDdl()
{
Tableau <Ddl> ta(ParaGlob::Dimension());
int posi = Id_nom_ddl("X1") -1;
int dim = ParaGlob::Dimension();
for (int i =1; i<= dim; i++)
{//Ddl inter((Enum_ddl(i+posi)),0.,LIBRE);
//ta(i) = inter;
ta(i) = Ddl ((Enum_ddl(i+posi)),0.,LIBRE);
}
// attribution des ddls aux noeuds
for (int ne=1; ne<= nombre->nbne; ne++)
tab_noeud(ne)->PlusTabDdl(ta);
};
// =====>>>> methodes privées appelees par les classes dérivees <<<<=====
// fonction d'initialisation servant dans les classes derivant
// au niveau du constructeur
// cas sans variable, initialisation par défaut
TriaMemb::DonnComTria* TriaMemb::Init (bool sans_init_noeud)
{Donnee_specif pardefaut;
return TriaMemb::Init(pardefaut,sans_init_noeud);
};
// fonction d'initialisation servant dans les classes derivant
// au niveau du constructeur
TriaMemb::DonnComTria* TriaMemb::Init
(Donnee_specif donnee_spec,bool sans_init_noeud)
{ // bien que la grandeur donnee_specif est défini dans la classe generique
// le fait de le passer en paramètre permet de tout initialiser dans Init
// et ceci soit avec les valeurs par défaut soit avec les bonnes valeurs
donnee_specif =donnee_spec;
// le fait de mettre les pointeurs a null permet
// de savoir que l'element n'est pas complet
// dans le cas d'un constructeur avec tableau de noeud, il ne faut pas mettre
// les pointeurs à nuls d'où le test
if (!sans_init_noeud)
for (int i =1;i<= nombre->nbne;i++) tab_noeud(i) = NULL;
// definition des donnees communes aux TriaMembxxx
// a la premiere definition d'une instance
if (unefois->doCoMemb == NULL)
unefois->doCoMemb = TriaMemb::Def_DonneeCommune();
TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
met = &(CoTria->met_triaMemb); // met est defini dans elemeca
// def pointe sur la deformation specifique a l'element pour le calcul mecanique
def = new Deformation(*met,tab_noeud,(CoTria->tria).TaDphi(),(CoTria->tria).TaPhi());
// idem pour la remonte aux contraintes et le calcul d'erreur
defEr = new Deformation(*met,tab_noeud,(CoTria->triaEr).TaDphi(),(CoTria->triaEr).TaPhi());
// idem pour les calculs relatifs à la matrice de masse
defMas = new Deformation(*met,tab_noeud,(CoTria->triaMas).TaDphi(),(CoTria->triaMas).TaPhi());
// idem pour le calcul de second membre
defSurf.Change_taille(1); // une seule surface pour le second membre
defSurf(1) = NULL; // la déformation sera construite si nécessaire au moment du calcul de
// second membre
// idem pour le calcul de second membre
defArete.Change_taille(3); // 3 arrêtes utilisées pour le second membre
// la déformation sera construite si nécessaire au moment du calcul de second membre
for (int ia=1;ia<=3;ia++)
defArete(ia) = NULL;
//dimensionnement des deformations et contraintes etc..
int dimtens = 2;
lesPtMecaInt.Change_taille_PtIntegMeca(nombre->nbi,dimtens);
// attribution des numéros de référencement dans le conteneur
for (int ni = 1; ni<= nombre->nbi; ni++)
{lesPtMecaInt(ni).Change_Nb_mail(this->num_maillage);
lesPtMecaInt(ni).Change_Nb_ele(this->num_elt);
lesPtMecaInt(ni).Change_Nb_pti(ni);
};
// stockage des donnees particulieres de la loi de comportement mécanique au point d'integ
tabSaveDon.Change_taille(nombre->nbi);
// stockage des donnees particulieres de la loi de comportement thermo physique au point d'integ
tabSaveTP.Change_taille(nombre->nbi);
// stockage des donnees particulieres de la déformation mécanique au point d'integ
tabSaveDefDon.Change_taille(nombre->nbi);
tab_energ.Change_taille(nombre->nbi);
tab_energ_t.Change_taille(nombre->nbi);
// initialisation des pointeurs définis dans la classe Element concernant les résidus et
// raideur
// --- cas de la puissance interne ---
residu = &(CoTria->residu_interne); // residu local
raideur = &(CoTria->raideur_interne); // raideur locale
// --- cas de la dynamique -----
mat_masse = &(CoTria->matrice_masse);
// --- cas des efforts externes concernant les points ------
res_extN = &(CoTria->residus_externeN); // pour les résidus et second membres
raid_extN= &(CoTria->raideurs_externeN);// pour les raideurs
// --- cas des efforts externes concernant les aretes ------
res_extA = &(CoTria->residus_externeA); // pour les résidus et second membres
raid_extA= &(CoTria->raideurs_externeA);// pour les raideurs
// --- cas des efforts externes concernant les faces ------
res_extS= &(CoTria->residus_externeS); // pour les résidus et second membres
raid_extS= &(CoTria->raideurs_externeS); // pour les raideurs
return CoTria;
};
// fonction permettant le calcul de CoTria
TriaMemb::DonnComTria* TriaMemb::Def_DonneeCommune()
{ // interpolation et définition du nombre de pt d'integ
// pour les pt d'integ on tient compte du fait que l'on peut avoir plusieurs fois
// le même nombre de pt mais qui sont placé différemment
GeomTriangle tri(donnee_specif.cas_pti_nbi*1000 + nombre->nbi,nombre->nbne);
// degre de liberte
int dim = ParaGlob::Dimension();
// cas des ddl éléments primaires
DdlElement tab_ddl(nombre->nbne,dim);
int posi = Id_nom_ddl("X1") -1;
for (int i =1; i<= dim; i++)
for (int j=1; j<= nombre->nbne; j++)
// tab_ddl (j,i) = Enum_ddl(i+posi);
tab_ddl.Change_Enum(j,i,Enum_ddl(i+posi));
// cas des ddl éléments secondaires pour le calcul d'erreur
// def du nombre de composantes du tenseur de contrainte en absolu
int nbcomposante = ParaGlob::NbCompTens ();
DdlElement tab_ddlErr(nombre->nbne,nbcomposante);
posi = Id_nom_ddl("SIG11") -1;
// uniquement deux cas a considéré 3 ou 6 composantes
for (int j=1; j<= nombre->nbne; j++)
{// on definit le nombre de composante de sigma en absolu
if (nbcomposante == 3)
// dans l'énumération les composantes ne sont pas a suivre
{//tab_ddlErr (j,1) = Enum_ddl(1+posi); // cas de SIG11
//tab_ddlErr (j,2) = Enum_ddl(2+posi); // cas de SIG22
//tab_ddlErr (j,3) = Enum_ddl(4+posi); // cas de SIG12
tab_ddlErr.Change_Enum(j,1,Enum_ddl(1+posi)); // cas de SIG11
tab_ddlErr.Change_Enum(j,2,Enum_ddl(2+posi)); // cas de SIG22
tab_ddlErr.Change_Enum(j,3,Enum_ddl(4+posi)); // cas de SIG12
}
else if (nbcomposante == 6)
// les composantes sont a suivre dans l'enumération
for (int i= 1;i<= nbcomposante; i++)
// tab_ddlErr (j,i) = Enum_ddl(i+posi);
tab_ddlErr.Change_Enum(j,i,Enum_ddl(i+posi));
}
// egalement pour tab_Err1Sig11, def d'un tableau de un ddl : enum SIG11
// par noeud
DdlElement tab_Err1Sig11(nombre->nbne,DdlNoeudElement(SIG11));
// toujours pour le calcul d'erreur definition des fonctions d'interpolation
// pour le calcul du hession de la fonctionnelle
GeomTriangle triEr(donnee_specif.cas_pti_nbiEr*1000 + nombre->nbiEr,nombre->nbne);
// pour les calculs relatifs à la matrice masse
GeomTriangle triMas(donnee_specif.cas_pti_nbiMas*1000 + nombre->nbiMas,nombre->nbne);
// pour le calcul relatifs à la stabilisation d'hourglass
GeomTriangle* triHourg = NULL;
if (nombre->nbiHour > 0)
triHourg = new GeomTriangle(nombre->nbiHour,nombre->nbne);
// pour le calcul des seconds membres
GeomTriangle triaS(donnee_specif.cas_pti_nbiS*1000 + nombre->nbiS,nombre->nbne);
GeomSeg segS(nombre->nbiA,nombre->nbneA);
// def metrique
// on definit les variables a priori toujours utiles
Tableau<Enum_variable_metrique> tab(24);
tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt ;
tab(4) = igiB_0; tab(5) = igiB_t; tab(6) = igiB_tdt;
tab(7) = igiH_0; tab(8) = igiH_t; tab(9) = igiH_tdt ;
tab(10)= igijBB_0; tab(11)= igijBB_t; tab(12)= igijBB_tdt;
tab(13)= igijHH_0; tab(14)= igijHH_t; tab(15)= igijHH_tdt ;
tab(16)= id_gijBB_tdt; tab(17)= id_giH_tdt; tab(18)= id_gijHH_tdt;
tab(19)= idMtdt ; tab(20)= id_jacobien_tdt;tab(21)= id2_gijBB_tdt;
tab(22)= igradVBB_tdt; tab(23) = iVtdt; tab(24)= idVtdt;
// dim du pb , nb de vecteur de la base = 2 ici, tableau de ddl et la def de variables
Met_abstraite metri(ParaGlob::Dimension(),2,tab_ddl,tab,nombre->nbne);
// ---- cas du calcul d'erreur sur sigma ou epsilon
// les tenseurs sont exprimees en absolu donc nombre de composante fonction
// de la dimension absolue
Tableau <Vecteur*> resEr(nbcomposante);
for (int i=1; i<= nbcomposante; i++)
resEr(i)=new Vecteur (nombre->nbne);
Mat_pleine raidEr(nombre->nbne,nombre->nbne); // la raideur pour l'erreur
// dimensionnement des différents résidus et raideurs pour le calcul mécanique
int nbddl = tab_ddl.NbDdl();
Vecteur residu_int(nbddl); Mat_pleine raideur_int(nbddl,nbddl);
// cas de la dynamique
Mat_pleine matmasse(1,nbddl); // a priori on dimensionne en diagonale
// cas des noeuds
Tableau <Vecteur* > residus_extN(nombre->nbne); residus_extN(1) = new Vecteur(dim);
Tableau <Mat_pleine* > raideurs_extN(nombre->nbne); raideurs_extN(1) = new Mat_pleine(dim,dim);
for (int i = 2;i<= nombre->nbne;i++)
{ residus_extN(i) = residus_extN(1);
raideurs_extN(i) = raideurs_extN(1);
}
int nbddlA = nombre->nbneA * dim; int nbA = 3; // 3 arêtes
Tableau <Vecteur* > residus_extA(nbA); residus_extA(1) = new Vecteur(nbddlA);
residus_extA(2) = residus_extA(1); residus_extA(3) = residus_extA(1);
Tableau <Mat_pleine* > raideurs_extA(nbA); raideurs_extA(1) = new Mat_pleine(nbddlA,nbddlA);
raideurs_extA(2) = raideurs_extA(1); raideurs_extA(3) = raideurs_extA(1);
Tableau <Vecteur* > residus_extS(1); residus_extS(1) = new Vecteur(nbddl);
Tableau <Mat_pleine* > raideurs_extS(1); raideurs_extS(1) = new Mat_pleine(nbddl,nbddl);
// -- definition de la classe static contenant toute les variables communes aux TriaMemb
TriaMemb::DonnComTria* dodo;
dodo = new DonnComTria
(tri,tab_ddl,tab_ddlErr,tab_Err1Sig11,metri,resEr,raidEr,triEr,triaS,segS
,residu_int,raideur_int,residus_extN,raideurs_extN,residus_extA,raideurs_extA,residus_extS,raideurs_extS
,matmasse,triMas,nombre->nbi,triHourg,NULL,NULL);
// les 2 null de la fin, correspondent à triamatD et triaresD qui ne sont allouées qu'après, via
// la méthode Complete(..
return dodo;
};
// destructions de certaines grandeurs pointées, créées au niveau de l'initialisation
void TriaMemb::Destruction()
{ // tout d'abord l'idée est de détruire certaines grandeurs pointées que pour le dernier élément
if ((unefois->nbelem_in_Prog == 0)&& (unefois->doCoMemb != NULL))
// cas de la destruction du dernier élément
{ TriaMemb::DonnComTria* CoTria = unefois->doCoMemb; // pour simplifier l'écriture
int resErrTaille = CoTria->resErr.Taille();
for (int i=1;i<= resErrTaille;i++)
delete CoTria->resErr(i);
delete CoTria->residus_externeN(1);
delete CoTria->raideurs_externeN(1);
delete CoTria->residus_externeA(1);
delete CoTria->raideurs_externeA(1);
delete CoTria->residus_externeS(1);
delete CoTria->raideurs_externeS(1);
if (CoTria->triaHourg != NULL) delete CoTria->triaHourg;
if (CoTria->triamatD != NULL) delete CoTria->triamatD;
if (CoTria->triaresD != NULL) delete CoTria->triaresD;
}
};
// calcul de la nouvelle épaisseur moyenne finale (sans raideur)
// ramène l'épaisseur moyenne calculée à atdt ou t
// met à jour les épaisseurs aux pti en fonction de l'épaisseur moyenne calculée
const double TriaMemb::CalEpaisseurMoyenne_et_transfert_pti(bool atdt)
{ // .. en bouclant sur les pt d'integ enregistré ..
// -- on récupère et on calcule les jacobiens moyens à 0 et final
double jacobien_moy_fin = 0.; // init
double jacobien_moy_ini = 0.;
// -- de même on récupère et on calcul la trace moyenne de la contrainte
double traceSig_moy = 0.;double traceSig_moy_ini = 0.;
// -- de même on récupère et on calcul le module de compressibilité moyen
double troisK_moy = 0.;
double epaisseur_moy_t = H_moy(TEMPS_t);
double epaisseur_moy_0 = H_moy(TEMPS_0);
for (int i=1;i<= nombre->nbi;i++)
{ // cas de la compressibilité
const double& troisK = 3. * (*lesPtIntegMecaInterne)(i).ModuleCompressibilite_const();
troisK_moy += troisK;
// cas des jacobiens
// const double& jacobien_0 = *(tabSaveDefDon(i)->Meti_00().jacobien_);
if (atdt)
{ const double& jacobien_ini = *(tabSaveDefDon(i)->Meti_t().jacobien_);
jacobien_moy_ini += jacobien_ini;
const double& jacobien_fin = *(tabSaveDefDon(i)->Meti_tdt().jacobien_);
jacobien_moy_fin += jacobien_fin;
// cas de la trace de sigma
const double traceSig = (*lesPtIntegMecaInterne)(i).SigHH_const() && (*(tabSaveDefDon(i)->Meti_tdt().gijBB_));
traceSig_moy += traceSig;
const double traceSig_ini = (*lesPtIntegMecaInterne)(i).SigHH_t_const() && (*(tabSaveDefDon(i)->Meti_t().gijBB_));
traceSig_moy_ini += traceSig_ini;
(*lesPtIntegMecaInterne)(i).Volume_pti() *= (epaisseur_moy_t * jacobien_ini) / jacobien_fin
* troisK / (troisK - traceSig+traceSig_ini); // la pression = - traceSig/3 !!!
}
else
{ const double& jacobien_ini = *(tabSaveDefDon(i)->Meti_00().jacobien_);
jacobien_moy_ini += jacobien_ini;
const double& jacobien_fin = *(tabSaveDefDon(i)->Meti_t().jacobien_);
jacobien_moy_fin += jacobien_fin;
// cas de la trace de sigma
double traceSig = (*lesPtIntegMecaInterne)(i).SigHH_const() && (*(tabSaveDefDon(i)->Meti_t().gijBB_));
traceSig_moy += traceSig;
(*lesPtIntegMecaInterne)(i).Volume_pti() *= (epaisseur_moy_0 * jacobien_ini) / jacobien_fin
* troisK / (troisK - traceSig);
};
};
jacobien_moy_ini /= nombre->nbi;
jacobien_moy_fin /= nombre->nbi;
traceSig_moy_ini /= nombre->nbi;
traceSig_moy /= nombre->nbi;
troisK_moy /= nombre->nbi;
// d'où le calcul de la nouvelle épaisseur en utilisant la relation:
// (V-V_0)/V = trace(sigma)/3 /K_moy
//--- vérification et gestion des cas particuliers ---
bool cas_particulier=false;
{// on suppose un module de compressibilité positif sinon ce n'est pas normal
if (troisK_moy < 0.)
{if (ParaGlob::NiveauImpression()>2)
cout << "\n erreur*** on a trouve une compressibilite moyenne negative = " << troisK_moy/3.
<< "\n TriaMemb::CalEpaisseurMoyenne_et_transfert_pti(...";
// on ne change pas l'épaisseur
cas_particulier = true;
};
// classiquement on suppose que troisK_moy doit-être bien supérieur à traceSig_moy:
// on considère un facteur 10 arbitraire
// si ce n'est pas le cas, on risque d'avoir un calcul d'épaisseur erroné
double delta_traceSig = traceSig_moy-traceSig_moy_ini;
if (Dabs(delta_traceSig) > 10. * Dabs(troisK_moy/3.))
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " le coef de compressibilite moyen = "<<troisK_moy/3.
<< " est par rapport a delta la trace de sigma = "
<< delta_traceSig << " 10 fois inferieur !! ce n'est pas normal a priori "
<< " on continue sans changer l'epaisseur ... "
<< "\n TriaMemb::CalEpaisseurMoyenne_et_vol_pti(...) "
<< endl;
// on ne change pas l'épaisseur
cas_particulier = true;
};
// maintenant on regarde si le module peut conduire à une épaisseur négative
if (delta_traceSig > (troisK_moy/3. - ConstMath::petit))
// dans le cas où delta_traceSig > troisK_moy, cela va donner une épaisseur négative !!
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite moyen = "<<troisK_moy/3.
<< " est inferieur a delta la trace de sigma = "
<< delta_traceSig
<< " ce qui va donner une epaisseur finale negative !! "
<< " on continue sans changer l'epaisseur ... "
<< "\n TriaMemb::CalEpaisseurMoyenne_et_vol_pti(...) "
<< endl;
// on ne change pas l'épaisseur
cas_particulier = true;
};
// maintenant on regarde si le module n'est pas trop petit
// si oui il y a aussi un pb
if ((Dabs(troisK_moy) <= ConstMath::unpeupetit)
&& (Dabs(traceSig_moy) > 10. * Dabs(troisK_moy/3.))
)
// on ne va pas pouvoir peut-être calculer une nouvelle épaisseur
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite moyen = "<<troisK_moy/3.
<< " et delta la trace de sigma = "
<< delta_traceSig
<< " sont de valeurs trop faibles (et un peu etrange) !! "
<< " on continue sans changer l'epaisseur ... "
<< "\n TriaMemb::CalEpaisseurMoyenne_et_vol_pti(...) "
<< endl;
// on ne change pas l'épaisseur
cas_particulier = true;
};
};
// si cas particulier: on ne peut pas calculer, on reste sur les valeurs précédentes
if (cas_particulier)
{if (atdt)
{ // on met à jour les épaisseurs aux pti
for (int i=1;i<= nombre->nbi;i++)
donnee_specif.epais(i).epaisseur_tdt = epaisseur_moy_t;
// puis retour
return epaisseur_moy_t;
}
else
{ // on met à jour les épaisseurs aux pti
for (int i=1;i<= nombre->nbi;i++)
donnee_specif.epais(i).epaisseur_t = epaisseur_moy_t;
// puis retour
return epaisseur_moy_t;
};
}
else // sinon c'est ok
{if (atdt)
{double epaisseur_moy_tdt = (epaisseur_moy_t * jacobien_moy_ini) / jacobien_moy_fin
* troisK_moy / (troisK_moy - traceSig_moy+traceSig_moy_ini);
//epais.epaisseur_tdt = (epais.epaisseur0 * jacobien_moy_0) / jacobien_moy_fin
// * troisK_moy / (troisK_moy + traceSig_moy);
//--debug
//if (num_elt==1)
// { Noeud* noe = tab_noeud(1);
// double R_0 = noe->Coord0().Norme(); double R = noe->Coord2().Norme();
//cout << "\n e0= " << epais.epaisseur_tdt<< " troisK_moy=" << troisK_moy << " traceSig_moy=" << traceSig_moy
// << " J0= " << jacobien_moy_0 << " J= " << jacobien_moy_fin << " R_0 " << R_0 << " R= " << R;
// };
//-- fin debug
// on met à jour les épaisseurs aux pti
for (int i=1;i<= nombre->nbi;i++)
donnee_specif.epais(i).epaisseur_tdt = epaisseur_moy_tdt;
// puis retour
return epaisseur_moy_tdt;
}
else
{epaisseur_moy_t = (epaisseur_moy_0 * jacobien_moy_ini) / jacobien_moy_fin
* troisK_moy / (troisK_moy - traceSig_moy);
// on met à jour les épaisseurs aux pti
for (int i=1;i<= nombre->nbi;i++)
donnee_specif.epais(i).epaisseur_t = epaisseur_moy_t;
// puis retour
return epaisseur_moy_t;
};
};
};
// -- 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
double TriaMemb::Epaisseurs(Enum_dure temps , const Coordonnee& M)
{// on va retourner l'épaisseur au point d'intégration le plus près du point M
int nbi = PtLePlusPres(temps,X1,M);
return H(nbi,temps);
};
// retourne la liste abondée de tous les données particulières interne actuellement utilisées
// par l'élément (actif ou non), sont exclu de cette liste les données particulières des noeuds
// reliées à l'élément
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> TriaMemb::Les_types_particuliers_internes(bool absolue) const
{ // on commence par récupérer la liste général provenant d'ElemMeca
List_io <TypeQuelconque> ret = ElemMeca::Les_types_particuliers_internes(absolue);
// ensuite on va ajouter les données particulières aux sfe
Grandeur_scalaire_double grand_courant; // def d'une grandeur courante
// $$$ cas de l'épaisseur moyenne initiale
TypeQuelconque typQ1(EPAISSEUR_MOY_INITIALE,SIG11,grand_courant);
ret.push_back(typQ1);
// $$$ cas de l'épaisseur moyenne finale
TypeQuelconque typQ2(EPAISSEUR_MOY_FINALE,SIG11,grand_courant);
ret.push_back(typQ2);
// $$$ cas de l'épaisseur initiale
TypeQuelconque typQ3(EPAISSEUR_INITIALE,SIG11,grand_courant);
ret.push_back(typQ3);
// $$$ cas de l'épaisseur finale
TypeQuelconque typQ4(EPAISSEUR_FINALE,SIG11,grand_courant);
ret.push_back(typQ4);
return ret;
};
// récupération de grandeurs particulières au numéro d'ordre = iteg
// celles-ci peuvent être quelconques
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void TriaMemb::Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ,int iteg)
{
// on balaie la liste transmise pour les grandeurs propres
List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
// on commence par appeler la fonction de la classe mére
// il n'y aura pas de calcul des grandeurs inactivées
ElemMeca::Grandeur_particuliere (absolue,liTQ,iteg);
// puis les grandeurs spécifiques
for (il=liTQ.begin();il!=ilfin;il++)
{TypeQuelconque& tipParticu = (*il); // pour simplifier
if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
switch (tipParticu.EnuTypeQuelconque().EnumTQ())
{
// 1) -----cas de l'épaisseur moyenne initiale, ici elle ne dépend pas du point d'intégration
case EPAISSEUR_MOY_INITIALE:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())= H_moy(TEMPS_0);
(*il).Active();
break;
}
// 2) -----cas de l'épaisseur moyenne finale, ici elle ne dépend pas du point d'intégration
case EPAISSEUR_MOY_FINALE: // on inactive la grandeur quelconque
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=H_moy(TEMPS_tdt);
(*il).Active();
break;
}
// 1) -----cas de l'épaisseur moyenne initiale, ici elle dépend du point d'intégration
case EPAISSEUR_INITIALE:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.epais(iteg).epaisseur0;
(*il).Active();
break;
}
// 2) -----cas de l'épaisseur moyenne finale, ici elle dépend du point d'intégration
case EPAISSEUR_FINALE: // on inactive la grandeur quelconque
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.epais(iteg).epaisseur_tdt;
(*il).Active();
break;
}
default: break; // rien sinon
};
};
};