Herezh_dev/Elements/Mecanique/ElemMeca3.cc

3049 lines
174 KiB
C++
Raw Permalink Normal View History

// 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.
//
2023-05-03 17:23:49 +02:00
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
//#include "Debug.h"
#include "ElemMeca.h"
#include <iomanip>
#include "ConstMath.h"
#include "Util.h"
#include "CharUtil.h"
#include "Coordonnee2.h"
#include "Coordonnee3.h"
#include "TypeConsTens.h"
#include "TypeQuelconqueParticulier.h"
// retourne la liste de tous les types de ddl interne actuellement utilisés
// par l'élément (actif ou non), sont exclu de cette liste les ddl des noeuds
// reliés à l'élément (ddl implique grandeur uniquement scalaire !)
// par contre sont inclus les ddl venant de l'élément, qui sont représenté directement aux noeuds
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <Ddl_enum_etendu> ElemMeca::Les_type_de_ddl_internes(bool absolue) const
{ List_io <Ddl_enum_etendu> ret;
switch (this->Dim_sig_eps())
{ case 1 :
{ret.push_back(SIG11); ret.push_back(EPS11);ret.push_back(DEPS11);
ret.push_back(string("Green-Lagrange11"));ret.push_back(string("Almansi11"));ret.push_back(string("logarithmique11"));
ret.push_back(string("Cauchy_local11"));
ret.push_back(string("Almansi_local11"));
ret.push_back(string("Def_principaleI"));ret.push_back(string("Sigma_principaleI"));
ret.push_back(string("Vit_principaleI"));ret.push_back(string("Delta_def11"));
if (dilatation)
{ret.push_back(string("Almansi_totale11"));ret.push_back(string("Green_Lagrange_totale11"));
ret.push_back(string("logarithmique_totale11"));};
break;
}
case 2 :
{ret.push_back(SIG11); ret.push_back(SIG22);
ret.push_back(SIG12); ret.push_back(EPS11);
ret.push_back(EPS22); ret.push_back(EPS12);
ret.push_back(DEPS11);ret.push_back(DEPS22);ret.push_back(DEPS12);
ret.push_back(string("Green-Lagrange11")); ret.push_back(string("Green-Lagrange22"));
ret.push_back(string("Green-Lagrange12")); ret.push_back(string("Almansi11"));
ret.push_back(string("Almansi22")); ret.push_back(string("Almansi12"));
ret.push_back(string("logarithmique11")); ret.push_back(string("logarithmique22"));
ret.push_back(string("logarithmique12"));
ret.push_back(string("Cauchy_local11")); ret.push_back(string("Cauchy_local22"));
ret.push_back(string("Cauchy_local12"));
ret.push_back(string("Almansi_local11"));
ret.push_back(string("Almansi_local22")); ret.push_back(string("Almansi_local12"));
ret.push_back(string("Def_principaleI"));ret.push_back(string("Def_principaleII"));
ret.push_back(string("Sigma_principaleI"));ret.push_back(string("Sigma_principaleII"));
ret.push_back(string("Vit_principaleI"));ret.push_back(string("Vit_principaleII"));
ret.push_back(string("Delta_def11"));ret.push_back(string("Delta_def22"));ret.push_back(string("Delta_def12"));
if (dilatation)
{ret.push_back(string("Almansi_totale11"));ret.push_back(string("Almansi_totale12"));ret.push_back(string("Almansi_totale22"));
ret.push_back(string("Green_Lagrange_totale11"));ret.push_back(string("Green_Lagrange_totale12"));
ret.push_back(string("Green_Lagrange_totale22"));
ret.push_back(string("logarithmique_totale11"));ret.push_back(string("logarithmique_totale12"));
ret.push_back(string("logarithmique_totale22"));
};
break;
}
case 3 :
{ret.push_back(SIG11); ret.push_back(SIG22);
ret.push_back(SIG33); ret.push_back(SIG12);
ret.push_back(SIG23); ret.push_back(SIG13);
ret.push_back(EPS11); ret.push_back(EPS22);
ret.push_back(EPS33); ret.push_back(EPS12);
ret.push_back(EPS23); ret.push_back(EPS13);
ret.push_back(DEPS11); ret.push_back(DEPS22);
ret.push_back(DEPS33); ret.push_back(DEPS12);
ret.push_back(DEPS23); ret.push_back(DEPS13);
ret.push_back(string("Green-Lagrange11")); ret.push_back(string("Green-Lagrange22"));
ret.push_back(string("Green-Lagrange33")); ret.push_back(string("Green-Lagrange12"));
ret.push_back(string("Green-Lagrange23")); ret.push_back(string("Green-Lagrange13"));
ret.push_back(string("Almansi11")); ret.push_back(string("Almansi22"));
ret.push_back(string("Almansi33")); ret.push_back(string("Almansi12"));
ret.push_back(string("Almansi23")); ret.push_back(string("Almansi13"));
ret.push_back(string("logarithmique11")); ret.push_back(string("logarithmique22"));
ret.push_back(string("logarithmique33")); ret.push_back(string("logarithmique12"));
ret.push_back(string("logarithmique23")); ret.push_back(string("logarithmique13"));
ret.push_back(string("Cauchy_local11")); ret.push_back(string("Cauchy_local22"));
ret.push_back(string("Cauchy_local33")); ret.push_back(string("Cauchy_local12"));
ret.push_back(string("Cauchy_local23")); ret.push_back(string("Cauchy_local13"));
ret.push_back(string("Almansi_local11")); ret.push_back(string("Almansi_local22"));
ret.push_back(string("Almansi_local33")); ret.push_back(string("Almansi_local12"));
ret.push_back(string("Almansi_local23")); ret.push_back(string("Almansi_local13"));
ret.push_back(string("Def_principaleI"));ret.push_back(string("Def_principaleII"));
ret.push_back(string("Def_principaleIII"));
ret.push_back(string("Sigma_principaleI"));ret.push_back(string("Sigma_principaleII"));
ret.push_back(string("Sigma_principaleIII"));
ret.push_back(string("Vit_principaleI"));ret.push_back(string("Vit_principaleII"));ret.push_back(string("Vit_principaleIII"));
ret.push_back(string("Delta_def11"));ret.push_back(string("Delta_def22"));ret.push_back(string("Delta_def33"));
ret.push_back(string("Delta_def12"));ret.push_back(string("Delta_def13"));ret.push_back(string("Delta_def23"));
if (dilatation)
{ret.push_back(string("Almansi_totale11"));ret.push_back(string("Almansi_totale22"));
ret.push_back(string("Almansi_totale33"));ret.push_back(string("Almansi_totale12"));
ret.push_back(string("Almansi_totale23"));ret.push_back(string("Almansi_totale13"));
ret.push_back(string("Green_Lagrange_totale11"));ret.push_back(string("Green_Lagrange_totale22"));
ret.push_back(string("Green_Lagrange_totale33"));ret.push_back(string("Green_Lagrange_totale12"));
ret.push_back(string("Green_Lagrange_totale23"));ret.push_back(string("Green_Lagrange_totale13"));
ret.push_back(string("logarithmique_totale11"));ret.push_back(string("logarithmique_totale22"));
ret.push_back(string("logarithmique_totale33"));ret.push_back(string("logarithmique_totale12"));
ret.push_back(string("logarithmique_totale23"));ret.push_back(string("logarithmique_totale13"));
};
ret.push_back(string("Spherique_eps"));ret.push_back(string("Q_eps"));ret.push_back(string("Cos3phi_eps"));
ret.push_back(string("Spherique_sig"));ret.push_back(string("Q_sig"));ret.push_back(string("Cos3phi_sig"));
break;
}
};
// cas de mises et tresca
ret.push_back(string("contrainte_mises"));
ret.push_back(string("contrainte_tresca"));
// déformation duale de mises = sqrt(2/3 * eps_barre:eps_barre)
ret.push_back(string("def_duale_mises"));
// déformation cumulée: int_0^t sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. ))
ret.push_back(string("def_equivalente"));
// déformation duale de mises maxi
ret.push_back(string("def_duale_mises_maxi"));
// vitesse de déformation équivalente
ret.push_back(string("vitesse_def_equivalente"));
// cas de l'existence de l'erreur
if (sigErreur != NULL) ret.push_back(ERREUR);
// cas de la plasticité classique
string nom_comport(loiComp->Nom_comport());
if ((strstr(nom_comport.c_str(),"PRANDTL_REUSS")!=NULL))
ret.push_back(string("def_plastique_cumulee"));
// cas des énergies locales
ret.push_back(string("energie_elastique"));
ret.push_back(string("dissipation_plastique"));
ret.push_back(string("dissipation_visqueuse"));
// cas des coordonnées du points
switch (ParaGlob::Dimension())
{case 3: ret.push_back(X3);
case 2: ret.push_back(X2);
case 1: ret.push_back(X1);
};
// cas des pressions éventuellement exercées sur les faces de l'élément
// modif 15 juin 2019: on sort systématiquement même s'il n'y a pas de pression enregistrée
// car la pression peut ne pas être active au début puis ensuite elle devient active
// et ret sert pour autoriser la sortie par la suite dans les résultats
// de plus au moment de la sortie, lesChargeExtSurEle sera testé et si c'est non nul ce sera ok
// si c'est nul, ce sera by passé
// if (lesChargeExtSurEle != NULL)
// if (lesChargeExtSurEle->LesPressionsExternes() != NULL)
ret.push_back(string("pression_ext"));
// dans le cas d'un élément 2D, dans un espace 3D, on peut récupérer la normale
if ((Type_geom_generique(this->Id_geometrie()) == SURFACE )
&& (ParaGlob::Dimension() == 3))
{ret.push_back(string("N_surf_1"));ret.push_back(string("N_surf_2"));ret.push_back(string("N_surf_3"));
ret.push_back(string("N_surf_1_t0"));ret.push_back(string("N_surf_2_t0"));ret.push_back(string("N_surf_3_t0"));
};
// retour
return ret;
};
// retourne la liste abondée de tous les données particulières interne actuellement utilisés
// par l'élément (actif ou non), sont exclu de cette liste les données particulières des noeuds
// reliés à l'élément
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_types_particuliers_internes(bool absolue) const
{ List_io <TypeQuelconque> ret;
// on s'intéresse au information stockée au niveau des points d'intégration
// 1° récupéreration les grandeurs
// a) cas des grandeurs liées à la déformation
def->ListeGrandeurs_particulieres(absolue,ret);
// b) cas des grandeurs liées à la loi de comportement mécanique
loiComp->ListeGrandeurs_particulieres(absolue,ret);
// c) cas des grandeurs liées à la loi de comportement thermo-physique
if (loiTP != NULL) loiTP->ListeGrandeurs_particulieres(absolue,ret);
// d) cas des infos stockés aux points d'intégration, donc par l'élément
Grandeur_scalaire_double grand_courant; // def d'une grandeur courante
Tableau <double> tab_1(1);
Tab_Grandeur_scalaire_double tab_grand_courant(tab_1);
// def d'un type quelconque représentatif à chaque grandeur
// a priori ces grandeurs sont défini aux points d'intégration
// $$$ cas de MODULE_COMPRESSIBILITE_TOTAL: intègre toutes les sous_lois par exemple
TypeQuelconque typQ1(MODULE_COMPRESSIBILITE_TOTAL,SIG11,grand_courant);
ret.push_back(typQ1);
// $$$ cas de MODULE_CISAILLEMENT_TOTAL: intègre toutes les sous_lois par exemple
TypeQuelconque typQ2(MODULE_CISAILLEMENT_TOTAL,SIG11,grand_courant);
ret.push_back(typQ2);
// e) cas des infos stockés à l'élément
// $$$ cas du volume total :
TypeQuelconque typQ3(VOLUME_ELEMENT,SIG11,grand_courant);
ret.push_back(typQ3);
// $$$ cas du volume élémentaire associé au pti
TypeQuelconque typQ34(VOLUME_PTI,SIG11,grand_courant);
ret.push_back(typQ34);
// $$$ cas éventuel d'intégrale de volume: INTEG_SUR_VOLUME
if (integ_vol_typeQuel != NULL)
{int nb_integration = integ_vol_typeQuel->Taille();
// on va créer un conteneur particulier pour chaque intégrale
Tableau <TypeQuelconque> & tab_integ = *integ_vol_typeQuel; //_t; // pour simplifier
for (int i=1; i<= nb_integration;i++)
{ TypeQuelconque& tbinteg = tab_integ(i); // pour simplifier
EnuTypeQuelParticulier type_interne =
tbinteg.Const_Grandeur_pointee()->Type_enumGrandeurParticuliere();
const TypeQuelconque_enum_etendu& enuTQetendu = tbinteg.EnuTypeQuelconque();
{switch (type_interne)
{case PARTICULIER_DDL_ETENDU:
{ Grandeur_Ddl_etendu& gin
= *((Grandeur_Ddl_etendu*) tbinteg.Grandeur_pointee()); // pour simplifier
// // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
// // -- on crée le nom de référence
// string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
// +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
// TypeQuelconque_enum_etendu tqnevez =
// TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
// (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
// // on enregistre pour la gestion future
// (*enu_integ_vol_TQ)(i)=tqnevez;
// on crée un exemplaire de conteneur pointé
Grandeur_Ddl_etendu inter(gin);
// création du type conteneur
TypeQuelconque typQ91((*enu_integ_vol_TQ)(i),tbinteg.Enum(),inter);
ret.push_back(typQ91);
break;
};
case PARTICULIER_VECTEUR_NOMMER:
{ Grandeur_Vecteur_Nommer& gin
= *((Grandeur_Vecteur_Nommer*) tbinteg.Grandeur_pointee()); // pour simplifier
// // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
// // -- on crée le nom de référence
// string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
// +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
// TypeQuelconque_enum_etendu tqnevez =
// TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
// (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
// // on enregistre pour la gestion future
// (*enu_integ_vol_TQ)(i)=tqnevez;
//// //----- debug
//// cout << "\n ElemMeca::Les_types_particuliers_internes( "
//// << "\n (*enu_integ_vol_TQ)("<<i<<")=" <<(*enu_integ_vol_TQ)(i);
//// //----- fin debug
// on crée un exemplaire de conteneur pointé
Grandeur_Vecteur_Nommer inter(gin);
// création du type conteneur
TypeQuelconque typQ91((*enu_integ_vol_TQ)(i),tbinteg.Enum(),inter);
ret.push_back(typQ91);
break;
}
default: // pas d'intégrale ad hoc dispo ici pour la demande
break;
};
};
};
};
// $$$ cas éventuel d'intégrale de volume et en temps: INTEG_SUR_VOLUME_ET_TEMPS
if (integ_vol_t_typeQuel != NULL)
{int nb_integration = integ_vol_t_typeQuel->Taille();
// on va créer un conteneur particulier pour chaque intégrale
Tableau <TypeQuelconque> & tab_integ = *integ_vol_t_typeQuel; //_t; // pour simplifier
for (int i=1; i<= nb_integration;i++)
{TypeQuelconque& tbinteg = tab_integ(i); // pour simplifier
EnuTypeQuelParticulier type_interne =
tbinteg.Const_Grandeur_pointee()->Type_enumGrandeurParticuliere();
const TypeQuelconque_enum_etendu& enuTQetendu = tbinteg.EnuTypeQuelconque();
{switch (type_interne)
{case PARTICULIER_DDL_ETENDU:
{ Grandeur_Ddl_etendu& gin
= *((Grandeur_Ddl_etendu*) tbinteg.Grandeur_pointee()); // pour simplifier
// // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
// // -- on crée le nom de référence
// string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
// +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
// TypeQuelconque_enum_etendu tqnevez =
// TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
// (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
// // on enregistre pour la gestion future
// (*enu_integ_vol_t_TQ)(i)=tqnevez;
// on crée un exemplaire de conteneur pointé
Grandeur_Ddl_etendu inter(gin);
// création du type conteneur
TypeQuelconque typQ91((*enu_integ_vol_t_TQ)(i),tbinteg.Enum(),inter);
ret.push_back(typQ91);
break;
};
case PARTICULIER_VECTEUR_NOMMER:
{ Grandeur_Vecteur_Nommer& gin
= *((Grandeur_Vecteur_Nommer*) tbinteg.Grandeur_pointee()); // pour simplifier
// // on va créer (éventuellement s'il n'existe pas déjà) un nouveau :
// // -- on crée le nom de référence
// string nom(enuTQetendu.NomPlein()+"_"+(*(gin.Nom_ref()))+"_"
// +ChangeEntierSTring((*index_Integ_vol_typeQuel)(i)));
// TypeQuelconque_enum_etendu tqnevez =
// TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
// (INTEG_SUR_VOLUME,nom,tbinteg.EnuTypeGrandeur());
// // on enregistre pour la gestion future
// (*enu_integ_vol_t_TQ)(i)=tqnevez;
// on crée un exemplaire de conteneur pointé
Grandeur_Vecteur_Nommer inter(gin);
// création du type conteneur
TypeQuelconque typQ91((*enu_integ_vol_t_TQ)(i),tbinteg.Enum(),inter);
ret.push_back(typQ91);
break;
}
default: // pas d'intégrale ad hoc dispo ici pour la demande
break;
};
};
};
};
// $$$ cas de l'énergie d'hourglasse :
TypeQuelconque typQ31(ENERGIE_HOURGLASS,SIG11,grand_courant);
ret.push_back(typQ31);
// $$$ cas de la puissance bulk :
TypeQuelconque typQ32(PUISSANCE_BULK,SIG11,grand_courant);
ret.push_back(typQ32);
// $$$ cas de l'énergie bulk :
TypeQuelconque typQ33(ENERGIE_BULK,SIG11,grand_courant);
ret.push_back(typQ33);
// $$$ cas de l'énergie de stabilisation membrane ou biel :
TypeQuelconque typQ330(ENERGIE_STABMEMB_BIEL,SIG11,grand_courant);
ret.push_back(typQ330);
// $$$ cas de la force de stabilisation membrane ou biel :
TypeQuelconque typQ331(FORCE_STABMEMB_BIEL,SIG11,grand_courant);
ret.push_back(typQ331);
// $$$ cas du temps cpu relativement à la loi de comp :
TypeQuelconque typQ35(TEMPS_CPU_LOI_COMP,SIG11,grand_courant);
ret.push_back(typQ35);
// $$$ cas du temps cpu relativement à la métrique :
TypeQuelconque typQ36(TEMPS_CPU_METRIQUE,SIG11,grand_courant);
ret.push_back(typQ36);
// $$$ cas des numéros
Grandeur_scalaire_entier entier_courant;
TypeQuelconque typQ37(NUM_ELEMENT,SIG11,entier_courant);
ret.push_back(typQ37);
TypeQuelconque typQ38(NUM_MAIL_ELEM,SIG11,entier_courant);
ret.push_back(typQ38);
TypeQuelconque typQ39(NUM_PTI,SIG11,entier_courant);
ret.push_back(typQ39);
// f) cas des infos calculable à la demande sur l'élément
// $$$ cas des volumes entre les plans et l'élément dans le cas ou l'élément des de surface
// et que le calcul est 3D :
if ((ParaGlob::Dimension()==3)&&(Type_geom_generique(id_geom)==SURFACE))
{Grandeur_coordonnee grandCoordonnee(3); // un type courant
TypeQuelconque typQ4(VOL_ELEM_AVEC_PLAN_REF,SIG11,grandCoordonnee);
ret.push_back(typQ4);
};
// liberation des tenseurs intermediaires
LibereTenseur();
return ret;
};
// retourne la liste des grandeurs évoluées interne actuellement utilisés
// par l'élément, c'est-à-dire directement sous forme de vecteur, tenseurs ....
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_type_evolues_internes(bool absolue) const
{ List_io <TypeQuelconque> liTQ;
// // def de la dimension des tenseurs
// // il y a deux pb a gérer: 1) le fait que la dimension absolue peut-être différente de la dimension des tenseurs
// // 2) le fait que l'on veut une sortie dans une base ad hoc ou pas
// int dim = lesPtIntegMecaInterne->DimTens();int dim_sortie_tenseur = dim;
// // dans le cas ou l'on veut une sortie en base absolue, il faut que dim_sortie_tenseur = la dimension de la base absolue
// int dim_espace = ParaGlob::Dimension();
// if (absolue)
// dim_sortie_tenseur = dim_espace;
// // pour ne faire qu'un seul test ensuite
// bool prevoir_change_dim_tenseur = false;
// if ((absolue) && (dim != dim_sortie_tenseur))
// prevoir_change_dim_tenseur = true;
// def des grandeurs courantes de type tenseur BB
int dim_espace = ParaGlob::Dimension();
int dim_tenseur_sortie = this->Dim_sig_eps(); // la dimension a priori
if (absolue)
dim_tenseur_sortie = dim_espace; // si on sort en absolue, on utilise la dim globale
{TenseurBB* tens = NevezTenseurBB(dim_tenseur_sortie); // un tenseur typique
// maintenant on définit une grandeur typique de type tenseurBB
Grandeur_TenseurBB gtBB(*tens);
// def d'un type quelconque représentatif pour chaque grandeur
{TypeQuelconque typQ(DEFORMATION_COURANTE,EPS11,gtBB);liTQ.push_back(typQ);};
{TypeQuelconque typQ(VITESSE_DEFORMATION_COURANTE,DEPS11,gtBB);liTQ.push_back(typQ);};
{TypeQuelconque typQ(ALMANSI,EPS11,gtBB);liTQ.push_back(typQ);};
{TypeQuelconque typQ(GREEN_LAGRANGE,EPS11,gtBB);liTQ.push_back(typQ);};
{TypeQuelconque typQ(LOGARITHMIQUE,EPS11,gtBB);liTQ.push_back(typQ);};
{TypeQuelconque typQ(DELTA_DEF,EPS11,gtBB);liTQ.push_back(typQ);};
if (dilatation)
{{TypeQuelconque typQ(ALMANSI_TOTAL,EPS11,gtBB);liTQ.push_back(typQ);};
{TypeQuelconque typQ(GREEN_LAGRANGE_TOTAL,EPS11,gtBB);liTQ.push_back(typQ);};
{TypeQuelconque typQ(LOGARITHMIQUE_TOTALE,EPS11,gtBB);liTQ.push_back(typQ);};
};
delete tens; // car on n'en a plus besoin
};
// def des grandeurs courantes de type tenseur HH
{TenseurHH* tens = NevezTenseurHH(dim_tenseur_sortie); // un tenseur typique
// maintenant on définit une grandeur typique de type tenseurHH
Grandeur_TenseurHH gtHH(*tens);
// def d'un type quelconque représentatif pour chaque grandeur
TypeQuelconque typQ(CONTRAINTE_COURANTE,SIG11,gtHH);liTQ.push_back(typQ);
delete tens; // car on n'en a plus besoin
};
// def des grandeurs courantes de type coordonnee
{Coordonnee coor(dim_tenseur_sortie); // un type coordonnee typique
// maintenant on définit une grandeur typique de type Grandeur_coordonnee
Grandeur_coordonnee gt(coor);
// def d'un type quelconque représentatif pour chaque grandeur
{TypeQuelconque typQ(DEF_PRINCIPALES,EPS11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(SIGMA_PRINCIPALES,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(VIT_PRINCIPALES,DEPS11,gt);liTQ.push_back(typQ);};
// pour la position il s'agit de la position du point d'intégration
{TypeQuelconque typQ(POSITION_GEOMETRIQUE,SIG11,gt);liTQ.push_back(typQ);};
}
{Coordonnee coor(dim_espace); // un type coordonnee typique
// maintenant on définit une grandeur typique de type Grandeur_coordonnee
Grandeur_coordonnee gt(coor);
// *** 21 avril 2020: on change la position d'expression: du noeuds au pti
// donc on passe de X1 à SIG11 , mais il s'agit d'un pti spécifique de surface ou de ligne ...
// le chargement de type pression, sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_PRESSION,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force volumique sous forme d'un vecteur charge, exprimée aux pti volume
{TypeQuelconque typQ(VECT_FORCE_VOLUM,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force de direction fixe sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_DIR_FIXE,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force suiveuse sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_SURF_SUIV,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force hydrodynamique sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_HYDRODYNA_Fn,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(VECT_HYDRODYNA_Ft,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(VECT_HYDRODYNA_T,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force linéique sous forme d'un vecteur charge, exprimée aux pti ligne
{TypeQuelconque typQ(VECT_LINE,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force linéique suiveuse sous forme d'un vecteur charge, exprimée aux pti ligne
{TypeQuelconque typQ(VECT_LINE_SUIV,SIG11,gt);liTQ.push_back(typQ);};
// *** fin modif avril 2020
// // les réaction sous forme d'un vecteur charge, exprimée aux noeuds
// {TypeQuelconque typQ(VECT_REAC,X1,gt);liTQ.push_back(typQ);};
};
// def des grandeurs courantes de type scalaires
{// on définit une grandeur typique de type Grandeur_scalaire_double
Grandeur_scalaire_double scd(0.);
// def d'un type quelconque représentatif pour chaque grandeur
{TypeQuelconque typQ(CONTRAINTE_MISES,SIG11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(CONTRAINTE_TRESCA,SIG11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(DEF_DUALE_MISES,EPS11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(DEF_DUALE_MISES_MAXI,EPS11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(DEF_EQUIVALENTE,EPS11,scd);liTQ.push_back(typQ);};
// cas de l'existence de l'erreur
// if (sigErreur != NULL)
{TypeQuelconque typQ(ERREUR_Q,ERREUR,scd);liTQ.push_back(typQ);}
// if (sigErreur_relative != NULL)
{TypeQuelconque typQ(ERREUR_SIG_RELATIVE,ERREUR,scd);liTQ.push_back(typQ);}
// cas de la plasticité classique
string nom_comport(loiComp->Nom_comport());
if ((strstr(nom_comport.c_str(),"PRANDTL_REUSS")!=NULL))
{TypeQuelconque typQ(DEF_PLASTIQUE_CUMULEE,EPS11,scd);liTQ.push_back(typQ);}
// les infos sur la décomposition spherique,polaire des contraintes et déformations
// seulement en 3D
if (ParaGlob::Dimension() == 3)
{{TypeQuelconque typQ(SPHERIQUE_EPS,EPS11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(Q_EPS,EPS11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(COS3PHI_EPS,EPS11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(SPHERIQUE_SIG,SIG11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(Q_SIG,SIG11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(COS3PHI_SIG,SIG11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(SPHERIQUE_DEPS,DEPS11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(Q_DEPS,DEPS11,scd);liTQ.push_back(typQ);};
{TypeQuelconque typQ(COS3PHI_DEPS,DEPS11,scd);liTQ.push_back(typQ);};
};
};
// $$$ cas du repère local ad hoc orthonormé d'expression des tenseurs
{Coordonnee v_rep(dim_espace);
Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
TypeQuelconque typQ6(REPERE_LOCAL_ORTHO,EPS11,grand5);
liTQ.push_back(typQ6);
};
// $$$ cas du repère local dual exprimé dans le repère global
// par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
{Coordonnee v_rep(dim_espace);
Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
TypeQuelconque typQ6(REPERE_LOCAL_H,EPS11,grand5);
liTQ.push_back(typQ6);
};
// $$$ cas du repère local naturel exprimé dans le repère global
// par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
{Coordonnee v_rep(dim_espace);
Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
TypeQuelconque typQ6(REPERE_LOCAL_B,EPS11,grand5);
liTQ.push_back(typQ6);
};
// $$$ cas du repère principal orthonormé du tenseur des contraintes
{Coordonnee v_rep(dim_espace);
Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
TypeQuelconque typQ6(DIRECTIONS_PRINC_SIGMA,SIG11,grand5);
liTQ.push_back(typQ6);
};
// $$$ cas du repère principal orthonormé du tenseur des déformations
{Coordonnee v_rep(dim_espace);
Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
TypeQuelconque typQ6(DIRECTIONS_PRINC_DEF,EPS11,grand5);
liTQ.push_back(typQ6);
};
// $$$ cas du repère principal orthonormé du tenseur des vitesses de déformation
{Coordonnee v_rep(dim_espace);
Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
TypeQuelconque typQ6(DIRECTIONS_PRINC_D,DEPS11,grand5);
liTQ.push_back(typQ6);
};
// dans le cas d'un élément 2D, dans un espace 3D, on peut récupérer la normale
if ((Type_geom_generique(this->Id_geometrie()) == SURFACE )
&& (ParaGlob::Dimension() == 3))
{Grandeur_coordonnee grandCoordonnee(3); // un type courant
TypeQuelconque typQ4(NN_SURF,EPS11,grandCoordonnee);
liTQ.push_back(typQ4);
};
// retour
return liTQ;
};
// retourne la liste de toutes les grandeurs quelconques relatives aux faces de
// l'élément (actif ou non),
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_type_quelconque_de_face(bool absolue) const
{ List_io <TypeQuelconque> liTQ;
// // def de la dimension des tenseurs
// // il y a deux pb a gérer: 1) le fait que la dimension absolue peut-être différente de la dimension des tenseurs
// // 2) le fait que l'on veut une sortie dans une base ad hoc ou pas
// int dim = lesPtIntegMecaInterne->DimTens();int dim_sortie_tenseur = dim;
// // dans le cas ou l'on veut une sortie en base absolue, il faut que dim_sortie_tenseur = la dimension de la base absolue
// int dim_espace = ParaGlob::Dimension();
// if (absolue)
// dim_sortie_tenseur = dim_espace;
// // pour ne faire qu'un seul test ensuite
// bool prevoir_change_dim_tenseur = false;
// if ((absolue) && (dim != dim_sortie_tenseur))
// prevoir_change_dim_tenseur = true;
// def des grandeurs courantes de type tenseur BB
int dim_espace = ParaGlob::Dimension();
int dim_tenseur_sortie = this->Dim_sig_eps(); // la dimension a priori
if (absolue)
dim_tenseur_sortie = dim_espace; // si on sort en absolue, on utilise la dim globale
// def des grandeurs courantes de type coordonnee
{Coordonnee coor(dim_tenseur_sortie); // un type coordonnee typique
// maintenant on définit une grandeur typique de type Grandeur_coordonnee
Grandeur_coordonnee gt(coor);
// pour la position il s'agit de la position du point d'intégration
{TypeQuelconque typQ(POSITION_GEOMETRIQUE,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(POSITION_GEOMETRIQUE_t,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(POSITION_GEOMETRIQUE_t0,SIG11,gt);liTQ.push_back(typQ);};
}
{Coordonnee coor(dim_espace); // un type coordonnee typique
// maintenant on définit une grandeur typique de type Grandeur_coordonnee
Grandeur_coordonnee gt(coor);
// le chargement de type pression, sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_PRESSION,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force de direction fixe sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_DIR_FIXE,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force suiveuse sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_SURF_SUIV,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force hydrodynamique sous forme d'un vecteur charge, exprimée aux pti surface
{TypeQuelconque typQ(VECT_HYDRODYNA_Fn,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(VECT_HYDRODYNA_Ft,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(VECT_HYDRODYNA_T,SIG11,gt);liTQ.push_back(typQ);};
// // les réaction sous forme d'un vecteur charge, exprimée aux noeuds
// {TypeQuelconque typQ(VECT_REAC,X1,gt);liTQ.push_back(typQ);};
};
// def des grandeurs courantes de type scalaires
{// def d'un type quelconque représentatif pour chaque grandeur
// // $$$ cas du repère local ad hoc orthonormé d'expression des tenseurs
// {Coordonnee v_rep(dim_espace);
// Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
// TypeQuelconque typQ6(REPERE_LOCAL_ORTHO,EPS11,grand5);
// liTQ.push_back(typQ6);
// };
//
// // $$$ cas du repère local dual exprimé dans le repère global
// // par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
// {Coordonnee v_rep(dim_espace);
// Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
// TypeQuelconque typQ6(REPERE_LOCAL_H,EPS11,grand5);
// liTQ.push_back(typQ6);
// };
// // $$$ cas du repère local naturel exprimé dans le repère global
// // par défaut, on réserve dim_espace vecteurs, éventuellement certains peuvent être nuls
// {Coordonnee v_rep(dim_espace);
// Tab_Grandeur_Coordonnee grand5(v_rep,dim_espace); // def d'une grandeur courante coordonnée
// TypeQuelconque typQ6(REPERE_LOCAL_B,EPS11,grand5);
// liTQ.push_back(typQ6);
// };
{Grandeur_coordonnee grandCoordonnee(3); // un type courant
TypeQuelconque typQ4(NN_SURF,EPS11,grandCoordonnee);
liTQ.push_back(typQ4);
};
{Grandeur_coordonnee grandCoordonnee(3); // un type courant
TypeQuelconque typQ4(NN_SURF_t,EPS11,grandCoordonnee);
liTQ.push_back(typQ4);
};
{Grandeur_coordonnee grandCoordonnee(3); // un type courant
TypeQuelconque typQ4(NN_SURF_t0,EPS11,grandCoordonnee);
liTQ.push_back(typQ4);
};
};
// $$$ cas des numéros
Grandeur_scalaire_entier entier_courant;
TypeQuelconque typQ37(NUM_ELEMENT,SIG11,entier_courant);
liTQ.push_back(typQ37);
TypeQuelconque typQ38(NUM_MAIL_ELEM,SIG11,entier_courant);
liTQ.push_back(typQ38);
TypeQuelconque typQ39(NUM_FACE,SIG11,entier_courant);
liTQ.push_back(typQ39);
TypeQuelconque typQ40(NUM_PTI,SIG11,entier_courant);
liTQ.push_back(typQ40);
Grandeur_scalaire_double double_courant;
TypeQuelconque typQ41(PRESSION_SCALAIRE,SIG11,double_courant);
liTQ.push_back(typQ41);
// retour
return liTQ;
};
// retourne la liste de toutes les grandeurs quelconques relatives aux arêtes de
// l'élément (actif ou non),
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
List_io <TypeQuelconque> ElemMeca::Les_type_quelconque_de_arete(bool absolue) const
{ List_io <TypeQuelconque> liTQ;
// // def de la dimension des tenseurs
// // il y a deux pb a gérer: 1) le fait que la dimension absolue peut-être différente de la dimension des tenseurs
// // 2) le fait que l'on veut une sortie dans une base ad hoc ou pas
// int dim = lesPtIntegMecaInterne->DimTens();int dim_sortie_tenseur = dim;
// // dans le cas ou l'on veut une sortie en base absolue, il faut que dim_sortie_tenseur = la dimension de la base absolue
// int dim_espace = ParaGlob::Dimension();
// if (absolue)
// dim_sortie_tenseur = dim_espace;
// // pour ne faire qu'un seul test ensuite
// bool prevoir_change_dim_tenseur = false;
// if ((absolue) && (dim != dim_sortie_tenseur))
// prevoir_change_dim_tenseur = true;
// def des grandeurs courantes de type tenseur BB
int dim_espace = ParaGlob::Dimension();
int dim_tenseur_sortie = this->Dim_sig_eps(); // la dimension a priori
if (absolue)
dim_tenseur_sortie = dim_espace; // si on sort en absolue, on utilise la dim globale
// def des grandeurs courantes de type coordonnee
{Coordonnee coor(dim_tenseur_sortie); // un type coordonnee typique
// maintenant on définit une grandeur typique de type Grandeur_coordonnee
Grandeur_coordonnee gt(coor);
// pour la position il s'agit de la position du point d'intégration
{TypeQuelconque typQ(POSITION_GEOMETRIQUE,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(POSITION_GEOMETRIQUE_t,SIG11,gt);liTQ.push_back(typQ);};
{TypeQuelconque typQ(POSITION_GEOMETRIQUE_t0,SIG11,gt);liTQ.push_back(typQ);};
}
{Coordonnee coor(dim_espace); // un type coordonnee typique
// maintenant on définit une grandeur typique de type Grandeur_coordonnee
Grandeur_coordonnee gt(coor);
// le chargement de type force linéique sous forme d'un vecteur charge, exprimée aux pti ligne
{TypeQuelconque typQ(VECT_LINE,SIG11,gt);liTQ.push_back(typQ);};
// le chargement de type force linéique suiveuse sous forme d'un vecteur charge, exprimée aux pti ligne
{TypeQuelconque typQ(VECT_LINE_SUIV,SIG11,gt);liTQ.push_back(typQ);};
};
// $$$ cas des numéros
Grandeur_scalaire_entier entier_courant;
TypeQuelconque typQ37(NUM_ELEMENT,SIG11,entier_courant);
liTQ.push_back(typQ37);
TypeQuelconque typQ38(NUM_MAIL_ELEM,SIG11,entier_courant);
liTQ.push_back(typQ38);
TypeQuelconque typQ39(NUM_ARETE,SIG11,entier_courant);
liTQ.push_back(typQ39);
TypeQuelconque typQ40(NUM_PTI,SIG11,entier_courant);
liTQ.push_back(typQ40);
// retour
return liTQ;
};
// 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 ElemMeca::Grandeur_particuliere(bool absolue,List_io<TypeQuelconque>& liTQ,int iteg)
{ // on s'intéresse au information stockée au niveau des points d'intégration
// pour tenir compte du fait qu'il peut y avoir plusieurs fois la même information, ces dernières sont systématiquement
// stockées dans des tableaux, et on associe à ce tableau un indice qui indique aux méthodes appelées, à quel endroit
// elles doivent écrire les infos. les indices sont stockés dans une liste de même dim que liTQ
list <int> decal(liTQ.size(),0.); // on initi tous les membres à 0
// 0° on initialise les grandeurs à 0 pour éviter d'avoir des valeurs aléatoires
// -- on commence par initialiser les conteneurs car certaines données peuvent ne pas exister
List_io<TypeQuelconque>::iterator iquefin=liTQ.end();
List_io<TypeQuelconque>::iterator ique,ique_deb=liTQ.begin();
for (ique=ique_deb;ique!=iquefin;ique++) (*ique).Grandeur_pointee()->InitParDefaut();
// 1° on change le numéro de point d'intégration courant
def->ChangeNumInteg(iteg);
// 2° on commence par récupérer les grandeurs
// a) cas des grandeurs liées à la déformation
// met à jour les données spécifiques du point considéré
def->Mise_a_jour_data_specif(tabSaveDefDon(iteg));
def->Grandeur_particuliere(absolue,liTQ);
// b) cas des grandeurs liées à la loi de comportement méca
// on commence par indiquer quel saveresult de pti a utiliser
loiComp->IndiquePtIntegMecaInterne(&((*lesPtIntegMecaInterne)(iteg)));
// puis on récupère les grandeurs
loiComp->Grandeur_particuliere(absolue,liTQ,tabSaveDon(iteg),decal);
// pour le débug ----
//cout << "\n debug ElemMeca::Grandeur_particuliere " << liTQ << endl; // débug
// fin pour le débug ----
// c) cas des grandeurs liées à la loi de comportement thermo-physique
if (loiTP != NULL) loiTP->Grandeur_particuliere(absolue,liTQ,tabSaveTP(iteg),decal);
// 3° on change éventuellement de repère (local en global) si nécessaire
// a) définition des grandeurs qui sont indépendante de la boucle qui suit
// dimension des vecteurs de base de la métrique
int dim = met->Dim_vec_base();
// calcul des matrices de passages
Mat_pleine* gamma0=NULL; Mat_pleine* gammat=NULL; Mat_pleine* gammatdt=NULL;
Mat_pleine* beta0=NULL; Mat_pleine* betat=NULL; Mat_pleine* betatdt=NULL;
// const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(gamma0,gammat,gammatdt);
// Mat_pleine beta0(gamma0.Inverse().Transpose());
// Mat_pleine betat(gammat.Inverse().Transpose());
// Mat_pleine betatdt(gammatdt.Inverse().Transpose());
List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
for (il=liTQ.begin();il!=ilfin;il++)
{ TypeQuelconque& tipParticu = (*il); // pour simplifier
// n'intervient que si la grandeur est active:
if ((*il).Activite())
{ // on regarde si c'est une grandeur locale ou pas
if (tipParticu.TypeExpressionGrandeur()==0)
// cas d'une grandeur exprimée dans le repère locale, changement de repère
{ // calcul des matrices de passages, au premier passage
if (gamma0 == NULL)
{ Mat_pleine Aa0(dim,dim),Aat(dim,dim),Aatdt(dim,dim);
const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(absolue,Aa0,Aat,Aatdt);
// a) ----- dans le sens: gi -> Ia
// on a: g^i = A^i_{.a} * I^a ou Ip^a suivant que absolue est true ou false
// si false, cela veut dire que Ip^a est un repère ad hoc
// sinon cela veut dire que c'est le repère absolu donc I_a = I^a
// et g_j = B_j^{.a} * I_a d'où [B_j^{.a}] = [A^i_{.a}]^{-1T}
//
// b) ----- dans le sens: Ia -> gi
// pour les formules de passage de repère il nous faut :
// Ip_a = beta_a^{.j} g_j et Ip^b = gamma^b_{.j} g^j
// on a alors : [beta_a^{.j}] = [Aa^j_{.a}]^T
// et [gamma^b_{.j}] = [beta_a^{.j}]^{-1T} = [Aa^j_{.a}]^{-1}
//
// au final: [beta_a^{.j}] = [Aa^j_{.a}]^T
// [gamma^b_{.j}] = [Aa^j_{.a}]^{-1}
// [B_j^{.a}] = [gamma^b_{.j}]^T
gamma0 = new Mat_pleine(Aa0.Inverse());
gammat = new Mat_pleine(Aat.Inverse());
gammatdt = new Mat_pleine(Aatdt.Inverse());
// on détermine également les matrices beta
beta0 = new Mat_pleine(Aa0.Transpose());
betat = new Mat_pleine(Aat.Transpose());
betatdt = new Mat_pleine(Aatdt.Transpose());
//---------- debug
/*
{
cout << "\n debug en 3D ElemMeca::Grandeur_particuliere( ";
cout << "\n -- affichage de la sauvegarde du pti "<<iteg<<" de la loi de comp ---";
tabSaveDon(iteg)->Affiche();
cout << "\n Aatdt: "; Aatdt.Affiche();
cout << "\n betatdt: "; betatdt->Affiche();
cout << "\n gammatdt: "; gammatdt->Affiche();
Tableau <Vecteur > gB_itdt(3),gH_itdt(3);
for (int a=1; a<3;a++)
{ cout << "\n giB_tdt("<<a<<"): "; (*ex.giB_tdt)(a).Affiche();
cout << "\n giH_tdt("<<a<<"): "; (*ex.giH_tdt)(a).Affiche();
gH_itdt(a) = (*ex.giH_tdt)(a).Vect(); // il manque le 3ième
gB_itdt(a) = (*ex.giB_tdt)(a).Vect(); // il manque le 3ième
};
// calcul des g^i à l'aide des A^i_{.a}
for (int a=1; a<4;a++)
{ cout << "\n giH_tdt("<<a<<"): via A^i_{.a} " << Aatdt.Ligne (a);
if (a == 3 )
{gH_itdt(a) = gB_itdt(a) = Aatdt.Ligne(a);}
};
// vérif des relations entre beta et gamma
Mat_pleine AA(*betatdt);
cout << "\n beta * gamma "; ((*gammatdt)* AA).Affiche();
Mat_pleine BB(betatdt->Transpose());
cout << "\n beta^T * gamma "; ((*gammatdt)* BB).Affiche();
// calcul des Ip_a à l'aide de betatdt
for (int a=1; a<4;a++)
{ Vecteur V(3);
for (int j=1;j<4;j++)
V += (*betatdt)(a,j) * gB_itdt(j);
// V += BB(a,j) * gB_itdt(j);
cout << "\n Ip("<<a<<"): via betatdt " << V;
};
// idem calcul des Ip_a à l'aide de gamma
for (int a=1; a<4;a++)
{ Vecteur V(3);
for (int j=1;j<4;j++)
V += (*gammatdt)(a,j) * gH_itdt(j);
cout << "\n Ip("<<a<<"): via gammatdt " << V;
};
};
*/
//----------- fin debug
};
tipParticu.Change_repere(*beta0,*betat,*betatdt,*gamma0,*gammat,*gammatdt);
};
// on utilise la boucle également pour mettre à jour les grandeurs particulières liés à l'élément
// 1) -----cas du module de compressibilité ou de cisaillement totale
switch (tipParticu.EnuTypeQuelconque().EnumTQ())
{case MODULE_COMPRESSIBILITE_TOTAL:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=(*lesPtIntegMecaInterne)(iteg).ModuleCompressibilite();break;}
case MODULE_CISAILLEMENT_TOTAL:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=(*lesPtIntegMecaInterne)(iteg).ModuleCisaillement();break;}
// e) cas des infos stockés à l'élément
case VOLUME_ELEMENT:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=volume;break;}
case VOLUME_PTI:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())
=(*lesPtIntegMecaInterne)(iteg).Volume_pti_const();break;
}
// $$$ cas éventuel d'intégrales de volume: INTEG_SUR_VOLUME
case INTEG_SUR_VOLUME:
// on utilise la valeur actuelle plutôt que la valeur à t, sinon on est en retard d'un incrément
// et par exemple en relaxation dynamique sur un incrément, on ne voit rien car, tant que l'incrément
// n'est pas fini, la valeur à t n'est pas abondée
{if (integ_vol_typeQuel != NULL) // cas où localement il y a une intégrale de définie
{int nb_integration = integ_vol_typeQuel->Taille();//_t->Taille();
Tableau <TypeQuelconque> & tab_integ = *integ_vol_typeQuel; //_t; // pour simplifier
const TypeQuelconque_enum_etendu& type_externe = tipParticu.EnuTypeQuelconque();
// maintenant il faut trouver la locale qui correspond: le plus simple
// mais pas le plus rapide !! est d'itérer
for (int i=1; i<= nb_integration;i++)
{EnuTypeQuelParticulier enuTQP = tipParticu.Grandeur_pointee()->Type_enumGrandeurParticuliere();
// //----- debug
// cout << "\n ElemMeca::Grandeur_particuliere( ";
// cout << "\n type_externe " << type_externe
// << "\n (*enu_integ_vol_TQ)("<<i<<")=" <<(*enu_integ_vol_TQ)(i);
// //----- fin debug
if (type_externe == (*enu_integ_vol_TQ)(i))
{switch (enuTQP)
{case PARTICULIER_DDL_ETENDU:
{ Grandeur_Ddl_etendu& gex
= *((Grandeur_Ddl_etendu*) tipParticu.Grandeur_pointee()); // pour simplifier
Grandeur_Ddl_etendu& gin
= *((Grandeur_Ddl_etendu*) tab_integ(i).Grandeur_pointee()); // pour simplifier
if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
// là on a récupérer la même grandeur
{Ddl_etendu& ddl = *(gex.ConteneurDdl_etendu());// récup du ddl
ddl.Valeur() = gin.ConteneurDdl_etendu()->Valeur();
}
break;
};
case PARTICULIER_VECTEUR_NOMMER:
{ Grandeur_Vecteur_Nommer& gex
= *((Grandeur_Vecteur_Nommer*) tipParticu.Grandeur_pointee()); // pour simplifier
Grandeur_Vecteur_Nommer& gin
= *((Grandeur_Vecteur_Nommer*) tab_integ(i).Grandeur_pointee()); // pour simplifier
if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
// là on a récupérer la même grandeur
{Vecteur& V = gex.ConteneurVecteur();
V = gin.ConteneurVecteur();
// //----- debug
// cout << "\n ElemMeca::Grandeur_particuliere( ";
// V.Affiche();
// //----- fin debug
}
break;
}
default: // pas d'intégrale ad hoc dispo ici pour la demande
break;
};
};
};
};
break;
}
case INTEG_SUR_VOLUME_ET_TEMPS:
{if (integ_vol_t_typeQuel != NULL)//_t != NULL) // cas où localement il y a une intégrale de définie
{int nb_integration = integ_vol_t_typeQuel->Taille(); //_t->Taille();
Tableau <TypeQuelconque> & tab_integ = *integ_vol_t_typeQuel; //_t; // pour simplifier
const TypeQuelconque_enum_etendu& type_externe = tipParticu.EnuTypeQuelconque();
// maintenant il faut trouver la locale qui correspond: le plus simple
// mais pas le plus rapide !! est d'itérer
for (int i=1; i<= nb_integration;i++)
{EnuTypeQuelParticulier enuTQP = tipParticu.Grandeur_pointee()->Type_enumGrandeurParticuliere();
if (type_externe == (*enu_integ_vol_TQ)(i))
{switch (enuTQP)
{case PARTICULIER_DDL_ETENDU:
{ Grandeur_Ddl_etendu& gex
= *((Grandeur_Ddl_etendu*) tipParticu.Grandeur_pointee()); // pour simplifier
Grandeur_Ddl_etendu& gin
= *((Grandeur_Ddl_etendu*) tab_integ(i).Grandeur_pointee()); // pour simplifier
if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
// là on a récupérer la même grandeur
{Ddl_etendu& ddl = *(gex.ConteneurDdl_etendu());// récup du ddl
ddl.Valeur() = gin.ConteneurDdl_etendu()->Valeur();
}
break;
};
case PARTICULIER_VECTEUR_NOMMER:
{ Grandeur_Vecteur_Nommer& gex
= *((Grandeur_Vecteur_Nommer*) tipParticu.Grandeur_pointee()); // pour simplifier
Grandeur_Vecteur_Nommer& gin
= *((Grandeur_Vecteur_Nommer*) tab_integ(i).Grandeur_pointee()); // pour simplifier
if ((*(gex.Nom_ref())) == (*(gin.Nom_ref())))
// là on a récupérer la même grandeur
{Vecteur& V = gex.ConteneurVecteur();
V = gin.ConteneurVecteur();
}
break;
}
default: // pas d'intégrale ad hoc dispo ici pour la demande
break;
};
};
};
};
break;
}
case ENERGIE_HOURGLASS:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Energie_Hourglass();break;}
case PUISSANCE_BULK:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Puissance_Bulk();break;}
case ENERGIE_BULK:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Energie_Bulk();break;}
case ENERGIE_STABMEMB_BIEL:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Energie_StabMembBiel(iteg);break;}
case FORCE_STABMEMB_BIEL:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=ElemMeca::Force_StabMembBiel(iteg);break;}
// d) cas des infos calculable à la demande sur l'élément
case VOL_ELEM_AVEC_PLAN_REF:
{ *((Grandeur_coordonnee*) tipParticu.Grandeur_pointee())=VolumePlan();break;}
// cas des temps d'exécution
case TEMPS_CPU_LOI_COMP:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=
(*lesPtIntegMecaInterne)(iteg).Tps_cpu_loi_comp_const().Temps_CPU_User();break;}
case TEMPS_CPU_METRIQUE:
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=
(*lesPtIntegMecaInterne)(iteg).TpsMetrique_const().Temps_CPU_User();break;}
case NUM_ELEMENT:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_elt; break;}
case NUM_MAIL_ELEM:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_maillage; break;}
case NUM_PTI:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= iteg; break;}
default: ;
};
};
};
// suppression des bases de passages
if (gamma0 != NULL)
{delete gamma0; delete gammat; delete gammatdt; delete beta0; delete betat; delete betatdt;};
// liberation des tenseurs intermediaires
LibereTenseur();
def->Retour_pti_precedant(); // on revient au pti initial
};
// récupération de grandeurs particulières pour une face au numéro d'ordre = iteg
// celles-ci peuvent être quelconques
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void ElemMeca::Grandeur_particuliere_face (bool absolue,List_io<TypeQuelconque>& liTQ,int face, int iteg)
{ // on s'intéresse au information stockée au niveau des points d'intégration
// pour tenir compte du fait qu'il peut y avoir plusieurs fois la même information, ces dernières sont systématiquement
// stockées dans des tableaux, et on associe à ce tableau un indice qui indique aux méthodes appelées, à quel endroit
// elles doivent écrire les infos. les indices sont stockés dans une liste de même dim que liTQ
list <int> decal(liTQ.size(),0.); // on initi tous les membres à 0
// 0° on initialise les grandeurs à 0 pour éviter d'avoir des valeurs aléatoires
// -- on commence par initialiser les conteneurs car certaines données peuvent ne pas exister
List_io<TypeQuelconque>::iterator iquefin=liTQ.end();
List_io<TypeQuelconque>::iterator ique,ique_deb=liTQ.begin();
for (ique=ique_deb;ique!=iquefin;ique++) (*ique).Grandeur_pointee()->InitParDefaut();
// 1° on change le numéro de point d'intégration courant si c'est possible
// on récupère l'élément frontière associée
int num_face = face; // init par défaut
// if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
// {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
// if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
// {num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
// const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
Deformation* definter=NULL; // variable de travail transitoire
if (!(ParaGlob::AxiSymetrie()))
{ definter = defSurf(num_face); } // le cas normal est non axisymétrique
else { definter = defArete(num_face);}; // en axisymétrie, c'est une def d'arête
Deformation * defS = definter; // pour simplifier l'écriture
if (defS != NULL) // cas où la face existe
{ defS->ChangeNumInteg(iteg);
// calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
// que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
Met_abstraite::Expli_t_tdt ex = (defS->Cal_explicit_tdt(true));
// 3° on change éventuellement de repère (local en global) si nécessaire
// a) définition des grandeurs qui sont indépendante de la boucle qui suit
// dimension des vecteurs de base de la métrique
int dim = met->Dim_vec_base();
// calcul des matrices de passages
Mat_pleine* gamma0=NULL; Mat_pleine* gammat=NULL; Mat_pleine* gammatdt=NULL;
Mat_pleine* beta0=NULL; Mat_pleine* betat=NULL; Mat_pleine* betatdt=NULL;
// const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(gamma0,gammat,gammatdt);
// Mat_pleine beta0(gamma0.Inverse().Transpose());
// Mat_pleine betat(gammat.Inverse().Transpose());
// Mat_pleine betatdt(gammatdt.Inverse().Transpose());
List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
for (il=liTQ.begin();il!=ilfin;il++)
{ TypeQuelconque& tipParticu = (*il); // pour simplifier
// n'intervient que si la grandeur est active:
if ((*il).Activite())
{ // on regarde si c'est une grandeur locale ou pas
if (tipParticu.TypeExpressionGrandeur()==0)
// cas d'une grandeur exprimée dans le repère locale, changement de repère
{ // calcul des matrices de passages, au premier passage
if (gamma0 == NULL)
{ Mat_pleine Aa0(dim,dim),Aat(dim,dim),Aatdt(dim,dim);
const Met_abstraite::Info0_t_tdt& ex = defS->Remont0_t_tdt(absolue,Aa0,Aat,Aatdt);
// a) ----- dans le sens: gi -> Ia
// on a: g^i = A^i_{.a} * I^a ou Ip^a suivant que absolue est true ou false
// si false, cela veut dire que Ip^a est un repère ad hoc
// sinon cela veut dire que c'est le repère absolu donc I_a = I^a
// et g_j = B_j^{.a} * I_a d'où [B_j^{.a}] = [A^i_{.a}]^{-1T}
//
// b) ----- dans le sens: Ia -> gi
// pour les formules de passage de repère il nous faut :
// Ip_a = beta_a^{.j} g_j et Ip^b = gamma^b_{.j} g^j
// on a alors : [beta_a^{.j}] = [Aa^j_{.a}]^T
// et [gamma^b_{.j}] = [beta_a^{.j}]^{-1T} = [Aa^j_{.a}]^{-1}
//
// au final: [beta_a^{.j}] = [Aa^j_{.a}]^T
// [gamma^b_{.j}] = [Aa^j_{.a}]^{-1}
// [B_j^{.a}] = [gamma^b_{.j}]^T
gamma0 = new Mat_pleine(Aa0.Inverse());
gammat = new Mat_pleine(Aat.Inverse());
gammatdt = new Mat_pleine(Aatdt.Inverse());
// on détermine également les matrices beta
beta0 = new Mat_pleine(Aa0.Transpose());
betat = new Mat_pleine(Aat.Transpose());
betatdt = new Mat_pleine(Aatdt.Transpose());
};
tipParticu.Change_repere(*beta0,*betat,*betatdt,*gamma0,*gammat,*gammatdt);
};
// on la boucle également pour mettre à jour les grandeurs quelconque liés à la face de l'élément
// 1) -----cas du module de compressibilité ou de cisaillement totale
switch (tipParticu.EnuTypeQuelconque().EnumTQ())
{
case POSITION_GEOMETRIQUE :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
(*gr.ConteneurCoordonnee())= defS->Position_tdt();
break;
}
case POSITION_GEOMETRIQUE_t :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
(*gr.ConteneurCoordonnee())= defS->Position_t();
break;
}
case POSITION_GEOMETRIQUE_t0 :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
(*gr.ConteneurCoordonnee())= defS->Position_0();
break;
}
case VECT_PRESSION:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
if (lesChargeExtSurEle != NULL)
{if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
// on se positionne sur la face
if (lesPressionsExternes(num_face).Taille() != 0)
{ Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(num_face)); // pour simplifier
if (tab_press_appliquee.Taille())
{(*gr.ConteneurCoordonnee())=tab_press_appliquee(iteg).P;
};
};
};
};
break;
}
case VECT_DIR_FIXE:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
if (lesChargeExtSurEle != NULL)
{ if (lesChargeExtSurEle->LesEffortsDirFixe() != NULL) // cas où il existe des valeurs sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesEffortsDirFixe();
// on se positionne sur la face
if (lesForcesExternes(num_face).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(num_face)); // pour simplifier
if (tab_force_appliquee.Taille())
{(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
};
};
};
};
break;
}
case VECT_SURF_SUIV:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
if (lesChargeExtSurEle != NULL)
{ if (lesChargeExtSurEle->LesPressDir() != NULL) // cas où il existe des valeurs sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesPressDir();
// on se positionne sur la num_face
if (lesForcesExternes(num_face).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(num_face)); // pour simplifier
if (tab_force_appliquee.Taille())
{(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
};
};
};
};
break;
}
case VECT_HYDRODYNA_Fn:case VECT_HYDRODYNA_Ft:case VECT_HYDRODYNA_T:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
if (lesChargeExtSurEle != NULL)
{ if (lesChargeExtSurEle->LesHydroDyna() != NULL) // cas où il existe des valeurs sauvegardées
{ Tableau <Tableau <Force_hydroDyna> >& lesForcesExternes = *lesChargeExtSurEle->LesHydroDyna();
// on se positionne sur la face
if (lesForcesExternes(num_face).Taille() != 0)
{ Tableau <Force_hydroDyna>& tab_force_appliquee = (lesForcesExternes(num_face)); // pour simplifier
switch (tipParticu.EnuTypeQuelconque().EnumTQ())
{case VECT_HYDRODYNA_Fn:
(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg).F_n;
break;
case VECT_HYDRODYNA_Ft:
(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg).F_t;
break;
case VECT_HYDRODYNA_T:
(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg).T;
break;
default:
break;
};
};
};
};
break;
}
case NN_SURF:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
// la normale vaut le produit vectoriel des 2 premiers vecteurs
(*gr.ConteneurCoordonnee()) = Util::ProdVec_coorBN( (*ex.giB_tdt)(1), (*ex.giB_tdt)(2));
gr.ConteneurCoordonnee()->Normer(); // que l'on norme
break;
};
case NN_SURF_t:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
// la normale vaut le produit vectoriel des 2 premiers vecteurs
(*gr.ConteneurCoordonnee()) = Util::ProdVec_coorBN( (*ex.giB_t)(1), (*ex.giB_t)(2));
gr.ConteneurCoordonnee()->Normer(); // que l'on norme
break;
};
case NN_SURF_t0:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
// la normale vaut le produit vectoriel des 2 premiers vecteurs
(*gr.ConteneurCoordonnee()) = Util::ProdVec_coorBN( (*ex.giB_0)(1), (*ex.giB_0)(2));
gr.ConteneurCoordonnee()->Normer(); // que l'on norme
break;
};
case NUM_ELEMENT:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_elt; break;}
case NUM_MAIL_ELEM:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_maillage; break;}
case NUM_FACE:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_face; break;}
case NUM_PTI:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= iteg; break;
}
case PRESSION_SCALAIRE:
{// on récupère les infos
Grandeur_scalaire_double& gr= *((Grandeur_scalaire_double*) (tipParticu.Grandeur_pointee()));
if (lesChargeExtSurEle != NULL)
{if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
// on se positionne sur la face
if (lesPressionsExternes(num_face).Taille() != 0)
{ Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(num_face)); // pour simplifier
if (tab_press_appliquee.Taille())
{(*gr.ConteneurDouble())=tab_press_appliquee(iteg).press;
//// --- debug
//cout << "\n debug ElemMeca::Grandeur_particuliere_face ( ";
//cout << "\n pression = "<<
};
};
};
};
break;
}
default: ;
};
};
};
// suppression des bases de passages
if (gamma0 != NULL)
{delete gamma0; delete gammat; delete gammatdt; delete beta0; delete betat; delete betatdt;};
// liberation des tenseurs intermediaires
LibereTenseur();
defS->Retour_pti_precedant(); // on revient au pti initial
};
};
// récupération de grandeurs particulières pour une arête au numéro d'ordre = iteg
// celles-ci peuvent être quelconques
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
void ElemMeca::Grandeur_particuliere_arete (bool absolue,List_io<TypeQuelconque>& liTQ,int arete, int iteg)
{ // on s'intéresse au information stockée au niveau des points d'intégration
// pour tenir compte du fait qu'il peut y avoir plusieurs fois la même information, ces dernières sont systématiquement
// stockées dans des tableaux, et on associe à ce tableau un indice qui indique aux méthodes appelées, à quel endroit
// elles doivent écrire les infos. les indices sont stockés dans une liste de même dim que liTQ
list <int> decal(liTQ.size(),0.); // on initi tous les membres à 0
// 0° on initialise les grandeurs à 0 pour éviter d'avoir des valeurs aléatoires
// -- on commence par initialiser les conteneurs car certaines données peuvent ne pas exister
List_io<TypeQuelconque>::iterator iquefin=liTQ.end();
List_io<TypeQuelconque>::iterator ique,ique_deb=liTQ.begin();
for (ique=ique_deb;ique!=iquefin;ique++) (*ique).Grandeur_pointee()->InitParDefaut();
// 1° on change le numéro de point d'intégration courant si c'est possible
Deformation * defA = defArete(arete); // pour simplifier l'écriture
if (defA != NULL)
{defA->ChangeNumInteg(iteg);
// calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
// que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
Met_abstraite::Expli_t_tdt ex = (defA->Cal_explicit_tdt(true));
// 3° on change éventuellement de repère (local en global) si nécessaire
// a) définition des grandeurs qui sont indépendante de la boucle qui suit
// dimension des vecteurs de base de la métrique
int dim = met->Dim_vec_base();
// calcul des matrices de passages
Mat_pleine* gamma0=NULL; Mat_pleine* gammat=NULL; Mat_pleine* gammatdt=NULL;
Mat_pleine* beta0=NULL; Mat_pleine* betat=NULL; Mat_pleine* betatdt=NULL;
// const Met_abstraite::Info0_t_tdt& ex = def->Remont0_t_tdt(gamma0,gammat,gammatdt);
// Mat_pleine beta0(gamma0.Inverse().Transpose());
// Mat_pleine betat(gammat.Inverse().Transpose());
// Mat_pleine betatdt(gammatdt.Inverse().Transpose());
List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
for (il=liTQ.begin();il!=ilfin;il++)
{ TypeQuelconque& tipParticu = (*il); // pour simplifier
// n'intervient que si la grandeur est active:
if ((*il).Activite())
{ // on regarde si c'est une grandeur locale ou pas
if (tipParticu.TypeExpressionGrandeur()==0)
// cas d'une grandeur exprimée dans le repère locale, changement de repère
{ // calcul des matrices de passages, au premier passage
if (gamma0 == NULL)
{ Mat_pleine Aa0(dim,dim),Aat(dim,dim),Aatdt(dim,dim);
const Met_abstraite::Info0_t_tdt& ex = defA->Remont0_t_tdt(absolue,Aa0,Aat,Aatdt);
// a) ----- dans le sens: gi -> Ia
// on a: g^i = A^i_{.a} * I^a ou Ip^a suivant que absolue est true ou false
// si false, cela veut dire que Ip^a est un repère ad hoc
// sinon cela veut dire que c'est le repère absolu donc I_a = I^a
// et g_j = B_j^{.a} * I_a d'où [B_j^{.a}] = [A^i_{.a}]^{-1T}
//
// b) ----- dans le sens: Ia -> gi
// pour les formules de passage de repère il nous faut :
// Ip_a = beta_a^{.j} g_j et Ip^b = gamma^b_{.j} g^j
// on a alors : [beta_a^{.j}] = [Aa^j_{.a}]^T
// et [gamma^b_{.j}] = [beta_a^{.j}]^{-1T} = [Aa^j_{.a}]^{-1}
//
// au final: [beta_a^{.j}] = [Aa^j_{.a}]^T
// [gamma^b_{.j}] = [Aa^j_{.a}]^{-1}
// [B_j^{.a}] = [gamma^b_{.j}]^T
gamma0 = new Mat_pleine(Aa0.Inverse());
gammat = new Mat_pleine(Aat.Inverse());
gammatdt = new Mat_pleine(Aatdt.Inverse());
// on détermine également les matrices beta
beta0 = new Mat_pleine(Aa0.Transpose());
betat = new Mat_pleine(Aat.Transpose());
betatdt = new Mat_pleine(Aatdt.Transpose());
};
tipParticu.Change_repere(*beta0,*betat,*betatdt,*gamma0,*gammat,*gammatdt);
};
// on la boucle également pour mettre à jour les grandeurs quelconque liés à la arete de l'élément
// 1) -----cas du module de compressibilité ou de cisaillement totale
switch (tipParticu.EnuTypeQuelconque().EnumTQ())
{
case POSITION_GEOMETRIQUE :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
(*gr.ConteneurCoordonnee())= defA->Position_tdt();
break;
}
case POSITION_GEOMETRIQUE_t :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
(*gr.ConteneurCoordonnee())= defA->Position_t();
break;
}
case POSITION_GEOMETRIQUE_t0 :
{Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
(*gr.ConteneurCoordonnee())= defA->Position_0();
break;
}
case VECT_LINE:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
if (lesChargeExtSurEle != NULL)
{ if (lesChargeExtSurEle->LesLineique() != NULL) // cas où il existe des valeurs sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineique();
// on se positionne sur la arete
if (lesForcesExternes(arete).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(arete)); // pour simplifier
if (tab_force_appliquee.Taille())
{(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
};
};
};
};
break;
}
case VECT_LINE_SUIV:
{// on récupère les infos
Grandeur_coordonnee& gr= *((Grandeur_coordonnee*) (tipParticu.Grandeur_pointee()));
if (lesChargeExtSurEle != NULL)
{ if (lesChargeExtSurEle->LesLineiqueSuiveuse() != NULL) // cas où il existe des valeurs sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineiqueSuiveuse();
// on se positionne sur la arete
if (lesForcesExternes(arete).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(arete)); // pour simplifier
if (tab_force_appliquee.Taille())
{(*gr.ConteneurCoordonnee())=tab_force_appliquee(iteg);
};
};
};
};
break;
}
case NUM_ELEMENT:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_elt; break;}
case NUM_MAIL_ELEM:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= num_maillage; break;}
case NUM_ARETE:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= arete; break;}
case NUM_PTI:
{ *((Grandeur_scalaire_entier*) tipParticu.Grandeur_pointee())= iteg; break;
}
default: ;
};
};
};
// suppression des bases de passages
if (gamma0 != NULL)
{delete gamma0; delete gammat; delete gammatdt; delete beta0; delete betat; delete betatdt;};
// liberation des tenseurs intermediaires
LibereTenseur();
defA->Retour_pti_precedant(); // on revient au pti initial
};
};
// --- transfert des grandeurs des points d'intégration aux noeuds
// transfert de ddl des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds, on ne remplace pas)
// les ddl doivent déjà exister aux noeuds sinon erreur
// il doit s'agir du même type de répartition de pt d'integ pour toutes les grandeurs
// tab_val(i)(j) : valeur associée au i ième pt d'integ et au j ième ddl_enum_etendu
void ElemMeca::TransfertAjoutAuNoeuds(const List_io < Ddl_enum_etendu >& lietendu
,const Tableau <Tableau <double> > & tab_val,int cas)
{List_io < Ddl_enum_etendu >::const_iterator ili,ilifin = lietendu.end();
// on récupère l'élément géométrique associé au ddl pur du premier ddl étendu,
ili = lietendu.begin();
Enum_ddl enu = (*ili).Enum();
int indice = 1;
for (ili = lietendu.begin();ili!=ilifin;ili++,indice++)
{ // cas normal courant
// récupération des tableaux d'indiçage pour le calcul aux noeuds
const ElemGeomC0& elemgeom = ElementGeometrie(enu);
// on récupère le nombre de noeud de l'élément géométrique (qui peut-être différent de celui de l'élément
// par ex: element sfe, donc on utilise les noeuds de l'élément géom. On considère que ce sont les premiers
// du tableau des noeuds
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
// calcul des valeurs aux noeuds
// val_au_noeud(i) = somme_(de j=indir(i)(1) à indir(i)(taille(indice(i)) )) {tab(i)(j) * val_pt_integ(j) }
for (int ine=1;ine<=nbn;ine++)
{ Ddl_etendu& de = tab_noeud(ine)->ModifDdl_etendu(*ili);
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
de.Valeur() += contExtra.tab(ine)(indir(j)) * tab_val(indir(j))(indice);
};
};
};
// transfert de type quelconque des points d'intégrations (de tous) aux noeuds d'un éléments (on ajoute aux noeuds,
// on ne remplace pas). Les types quelconques doivent déjà exister.
// un tableau tab_liQ correspondent aux grandeurs quelconque pour tous les pt integ. tab_liQ(i) est associé au pt d'integ i
// Toutes les listes sont identiques au niveau des descripteurs (types...) ce sont uniquement les valeurs numériques
// c-a-dire les valeurs associées à TypeQuelconque::Grandeur qui sont différentes (elles sont associées à chaque pt d'integ)
// liQ_travail: est une liste de travail qui sera utilisée dans le transfert
void ElemMeca::TransfertAjoutAuNoeuds(const Tableau <List_io < TypeQuelconque > >& tab_liQ
,List_io < TypeQuelconque > & liQ_travail,int cas)
{int nb_pt_integ = lesPtIntegMecaInterne->NbPti();
// ---- modif transitoire pour la sortie des coques !!!!
// on s'occupe uniquement de la première couche d'élément
if ((this->PoutrePlaqueCoque() == COQUE)||(this->PoutrePlaqueCoque() == PLAQUE))
nb_pt_integ = this->NbPtIntegSurface(SIG11); // SIG11 arbitraire car c'est les pt d'integ classique
//------- fin modif transitoire --------
if (tab_liQ.Taille() == 0)
return; // cas où on n'a rien à faire
#ifdef MISE_AU_POINT
if (nb_pt_integ != tab_liQ.Taille())
{ cout << "\n erreur de dimension, la taille de tab_liQ= " << tab_liQ.Taille() << " n'est pas egale "
<< " au nombre de pt_d'integ de l'element : " << nb_pt_integ ;
cout << "\n ElemMeca::TransfertAjoutAuNoeuds(... " << endl;
Sortie(1);
}
#endif
//---- pour le debug
//cout << " \n debug ElemMeca::TransfertAjoutAuNoeuds " << tab_liQ << endl;
//--- fin pour le debug
// sinon on a au moins un élément, on récupère la 1ère liste qui nous servira pour les descripteurs
List_io <TypeQuelconque > & liQ_ref = tab_liQ(1); // pour simplifier
List_io < TypeQuelconque >::const_iterator ili_ref,ilifin_ref=liQ_ref.end();
// la liste de travail
List_io < TypeQuelconque >::iterator ili_travail = liQ_travail.begin();
// on définit un tableau d'itérator de dimension = le nb de pt d'integ
static Tableau < List_io < TypeQuelconque >::const_iterator > tab_iterator;
// on le redimentionne si besoin est
tab_iterator.Change_taille(nb_pt_integ);
// on définit ses éléments
for (int ia=1;ia<=nb_pt_integ;ia++)
tab_iterator(ia) = tab_liQ(ia).begin();
// on boucle sur les éléments de la liste de référence
for (ili_ref = liQ_ref.begin();ili_ref != ilifin_ref;ili_ref++,ili_travail++)
{ // on récupère l'élément géométrique associé au ddl pur dont les valeurs sont calculées aux mêmes
// endroits que la grandeur quelconque
Enum_ddl enu = (*ili_ref). Enum();
const ElemGeomC0& elemgeom = ElementGeometrie(enu);
// on récupère le nombre de noeud de l'élément géométrique (qui peut-être différent de celui de l'élément
// par ex: element sfe, donc on utilise les noeuds de l'élément géom. On considère que ce sont les premiers
// du tableau des noeuds
int nbn = elemgeom.Nbne();
// récupération des tableaux d'indiçage pour le calcul aux noeuds
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
// on boucle sur les noeuds, ceci est due à la technique utilisée pour accumuler dans les conteneurs du noeud
for (int ine=1;ine<=nbn;ine++)
{TypeQuelconque& tq = tab_noeud(ine)->ModifGrandeur_quelconque((*ili_ref).EnuTypeQuelconque());
TypeQuelconque::Grandeur & grandeur_au_noeud = *(tq.Grandeur_pointee());
// on récupère une grandeur du même type que les grandeurs à manipuler, ceci pour accumuler
TypeQuelconque::Grandeur & stockage_inter = *((*ili_travail).Grandeur_pointee());
// calcul des valeurs aux noeuds
// val_au_noeud(i) = somme_(de j=indir(i)(1) à indir(i)(taille(indice(i)) )) {tab(i)(j) * val_pt_integ(j) }
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ stockage_inter *= 0.; // met à 0 la grandeur inter
// tab_iterator(j) pointe sur la grandeur quelconque du point d'intégration voulu
stockage_inter = *((*(tab_iterator(indir(j)))).Const_Grandeur_pointee()); // récup de la grandeur pointée
//---- debug
//cout << "\n debug ElemMeca::TransfertAjoutAuNoeuds: stockage_inter 1= " << stockage_inter;
//-- fin debug
stockage_inter *= contExtra.tab(ine)(indir(j)); // * par le coeff
grandeur_au_noeud += stockage_inter; // stockage dans le noeud
//---- debug
//cout << " stockage_inter 2= "<< stockage_inter << " grandeur_au_noeud= " << grandeur_au_noeud;
//if (Dabs(grandeur_au_noeud.GrandeurNumOrdre(2)) > 1.)
// {cout << "\n ***** grandeur_au_noeud.GrandeurNumOrdre(2) = " << grandeur_au_noeud.GrandeurNumOrdre(2)
// << "\n contExtra.tab= "<< contExtra.tab << " contExtra.indir= "<< contExtra.indir;
//
// };
//
//-- fin debug
};
};
// on incrémente les itérators de points d'intégration
for (int ib=1;ib<=nb_pt_integ;ib++)
(tab_iterator(ib))++;
};
};
// accumulation aux noeuds de grandeurs venant des éléments vers leurs noeuds (exemple la pression appliquée)
// autres que celles aux pti classiques, mais directements disponibles
// le contenu du conteneur stockées dans liQ est utilisé en variable intermédiaire
void ElemMeca::Accumul_aux_noeuds(const List_io < Ddl_enum_etendu >& lietendu
,List_io < TypeQuelconque > & liQ,int cas)
{// ... cas des ddl étendu ...
{List_io < Ddl_enum_etendu >::const_iterator ili,ilifin = lietendu.end();
ili = lietendu.begin();
for (ili = lietendu.begin();ili!=ilifin;ili++)
{// on traite en fonctions des cas particuliers
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " *ili = " << *ili << endl;
// fin debug
switch ((*ili).Position()-NbEnum_ddl())
{ case 94 : // cas des pressions externes
{if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
int nb_face = lesPressionsExternes.Taille();
for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
if (lesPressionsExternes(n_face).Taille() != 0)
{ Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(n_face)); // pour simplifier
int t_tail = tab_press_appliquee.Taille();
if (t_tail != 0) // cas où on a une face chargée
{ // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
int num_face = n_face; // init par défaut
if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
{num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
for (int ine=1;ine<=nbn;ine++)
{ Ddl_etendu& de = tab_noe(ine)->ModifDdl_etendu(*ili);
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ de.Valeur() += contExtra.tab(ine)(indir(j)) * tab_press_appliquee(indir(j)).press;
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
} };
};
};
};
break;
}
default :
break;
// sinon on ne fait rien, cela signifie que ce n'est pas un ddl géré par l'élément
};
};
};
// ... cas des grandeurs quelconque ...
// on traite d'abord le cas où on n'a rien à faire
if (liQ.size() == 0)
return;
//---- pour le debug
//cout << " \n debug ElemMeca::TransfertAjoutAuNoeuds " << tab_liQ << endl;
//--- fin pour le debug
{List_io < TypeQuelconque >::const_iterator ili,ilifin=liQ.end();
// on boucle sur les grandeurs de la liste
for (ili = liQ.begin();ili != ilifin;ili++)
{ // on récupère l'énuméré
TypeQuelconque_enum_etendu enutq = (*ili).EnuTypeQuelconque();
switch (enutq.EnumTQ())
{ case VECT_PRESSION:
{ // on récupère les infos pour extrapoler les valeurs
if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->LesPressionsExternes() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Pression_appliquee> >& lesPressionsExternes = *lesChargeExtSurEle->LesPressionsExternes();
int nb_face = lesPressionsExternes.Taille();
for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
if (lesPressionsExternes(n_face).Taille() != 0)
{ Tableau <Pression_appliquee>& tab_press_appliquee = (lesPressionsExternes(n_face)); // pour simplifier
int t_tail = tab_press_appliquee.Taille();
if (t_tail != 0) // cas où on a une face chargée
{ // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
int num_face = n_face; // init par défaut
if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
{num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
for (int ine=1;ine<=nbn;ine++)
{ TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
// récup des coordonnées
Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ coor += contExtra.tab(ine)(indir(j)) * tab_press_appliquee(indir(j)).P;
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
} };
};
};
};
}
break;
case VECT_FORCE_VOLUM:
{ // on récupère les infos pour extrapoler les valeurs
if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->Force_volume() != NULL) // cas où il existe des F volume sauvegardées
{ Tableau <Coordonnee>& force_volume = *lesChargeExtSurEle->Force_volume();
int t_tail = force_volume.Taille();
if (t_tail != 0) // cas où on a des forces volumique
{ // on récupère l'élément géométrique associée
const ElemGeomC0& elemgeom = ElementGeometrie(X1);
// on récupère le nombre de noeud de l'élément géométrique (qui peut-être différent de celui de l'élément
// par ex: element sfe, donc on utilise les noeuds de l'élément géom. On considère que ce sont les premiers
// du tableau des noeuds
int nbn = elemgeom.Nbne();
// récupération des tableaux d'indiçage pour le calcul aux noeuds
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
// on boucle sur les noeuds,
for (int ine=1;ine<=nbn;ine++)
{TypeQuelconque& tq = tab_noeud(ine)->ModifGrandeur_quelconque(enutq);
// récup des coordonnées
Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) tq.Const_Grandeur_pointee());
Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ coor += (contExtra.tab(ine)(indir(j))) * force_volume(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
} };
};
};
}
break;
case VECT_DIR_FIXE:
{ // on récupère les infos pour extrapoler les valeurs
if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->LesEffortsDirFixe() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesEffortsDirFixe();
int nb_face = lesForcesExternes.Taille();
for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
if (lesForcesExternes(n_face).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
int t_tail = tab_force_appliquee.Taille();
if (t_tail != 0) // cas où on a une face chargée
{ // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
int num_face = n_face; // init par défaut
if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
{num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
for (int ine=1;ine<=nbn;ine++)
{ TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
// récup des coordonnées
Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
} };
};
};
};
}
break;
case VECT_SURF_SUIV:
{ // on récupère les infos pour extrapoler les valeurs
if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->LesPressDir() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesPressDir();
int nb_face = lesForcesExternes.Taille();
for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
if (lesForcesExternes(n_face).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
int t_tail = tab_force_appliquee.Taille();
if (t_tail != 0) // cas où on a une face chargée
{ // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
int num_face = n_face; // init par défaut
if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
{num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
for (int ine=1;ine<=nbn;ine++)
{ TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
// récup des coordonnées
Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
} };
};
};
};
}
break;
case VECT_HYDRODYNA_Fn:case VECT_HYDRODYNA_Ft:case VECT_HYDRODYNA_T:
{ // on récupère les infos pour extrapoler les valeurs
if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->LesHydroDyna() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Force_hydroDyna> >& lesForcesExternes = *lesChargeExtSurEle->LesHydroDyna();
int nb_face = lesForcesExternes.Taille();
for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
if (lesForcesExternes(n_face).Taille() != 0)
{ Tableau <Force_hydroDyna>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
int t_tail = tab_force_appliquee.Taille();
if (t_tail != 0) // cas où on a une face chargée
{ // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
int num_face = n_face; // init par défaut
if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
{num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
for (int ine=1;ine<=nbn;ine++)
{ TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
// récup des coordonnées
Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
switch (enutq.EnumTQ())
{case VECT_HYDRODYNA_Fn:
for (int j=1; j<= nbindir; j++)
coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j)).F_n;
break;
case VECT_HYDRODYNA_Ft:
for (int j=1; j<= nbindir; j++)
coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j)).F_t;
break;
case VECT_HYDRODYNA_T:
for (int j=1; j<= nbindir; j++)
coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j)).T;
break;
default:
break;
};
};
};
};
};
}
break;
case VECT_LINE:
{ // on récupère les infos pour extrapoler les valeurs
if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->LesLineique() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineique();
int nb_face = lesForcesExternes.Taille();
for (int n_face=1;n_face<=nb_face;n_face++) // on boucle sur les faces
if (lesForcesExternes(n_face).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_face)); // pour simplifier
int t_tail = tab_force_appliquee.Taille();
if (t_tail != 0) // cas où on a une face chargée
{ // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
int num_face = n_face; // init par défaut
if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les faces
{num_face += posi_tab_front_lin;}; // sont en faites les frontières lignes
const ElemGeomC0 & elemgeom = tabb(num_face)->ElementGeometrique();
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
Tableau <Noeud *>& tab_noe = tabb(num_face)->TabNoeud(); // récup du tableau de noeuds de la frontière
for (int ine=1;ine<=nbn;ine++)
{ TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
// récup des coordonnées
Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
} };
};
};
};
}
break;
case VECT_LINE_SUIV:
{ // on récupère les infos pour extrapoler les valeurs
if (lesChargeExtSurEle != NULL)
if (lesChargeExtSurEle->LesLineiqueSuiveuse() != NULL) // cas où il existe des pressions sauvegardées
{ Tableau <Tableau <Coordonnee> >& lesForcesExternes = *lesChargeExtSurEle->LesLineiqueSuiveuse();
int nb_ligne = lesForcesExternes.Taille();
for (int n_ligne=1;n_ligne<=nb_ligne;n_ligne++) // on boucle sur les lignes
if (lesForcesExternes(n_ligne).Taille() != 0)
{ Tableau <Coordonnee>& tab_force_appliquee = (lesForcesExternes(n_ligne)); // pour simplifier
int t_tail = tab_force_appliquee.Taille();
if (t_tail != 0) // cas où on a une ligne chargée
{ // on récupère l'élément frontière associée (on considère qu'il y en a forcément 1)
int num_ligne = n_ligne; // init par défaut
if(ParaGlob::AxiSymetrie()) // dans le cas d'éléments axysymétriques, les lignes
{num_ligne += posi_tab_front_point;} // sont en faites les frontières points
else {num_ligne += posi_tab_front_lin;}; // sinon c'est des lignes
const ElemGeomC0 & elemgeom = tabb(num_ligne)->ElementGeometrique();
int nbn = elemgeom.Nbne();
const ElemGeomC0::ConteneurExtrapolation & contExtra = elemgeom.ExtrapolationNoeud(cas);
Tableau <Noeud *>& tab_noe = tabb(num_ligne)->TabNoeud(); // récup du tableau de noeuds de la frontière
for (int ine=1;ine<=nbn;ine++)
{ TypeQuelconque& de = tab_noe(ine)->ModifGrandeur_quelconque(enutq);
// récup des coordonnées
Grandeur_coordonnee* gr_coor = ((Grandeur_coordonnee*) de.Const_Grandeur_pointee());
Coordonnee& coor = *(gr_coor->ConteneurCoordonnee());
Tableau <int>& indir = contExtra.indir(ine); // pour simplifier
int nbindir = indir.Taille();
for (int j=1; j<= nbindir; j++)
{ coor += contExtra.tab(ine)(indir(j)) * tab_force_appliquee(indir(j));
//debug
//cout << "\n debug ElemMeca::Accumul_aux_noeuds"
// << " de.Valeur() = " << de.Valeur() << endl;
// fin debug
} };
};
};
};
}
break;
// case VECT_REAC:
// // là on ne fait rien car la grandeur est directement à construire via les noeuds
// // et ceci est fait dans la routine:
// // lesMaillages->PassageInterneDansNoeud_composantes_vers_vectorielles()
// break;
default:
// VECT_PRESSION pour l'instant il n'y a aucune grandeur a priori qui est disponible directement
// donc message d'erreur
cout << "\n cas de grandeur actuellement non traité "
<< "\n pas de grandeur " << (*ili).EnuTypeQuelconque().NomPlein()
<< " dans l'element "
<< "\n ou cas non implante pour l'instant"
<< "\n ElemMeca::Accumul_aux_noeuds(....";
};
};
};
};
// procedure permettant de completer l'element, en ce qui concerne les variables gérés
// par ElemMeca, apres sa creation avec les donnees du bloc transmis
// peut etre appeler plusieurs fois
Element* ElemMeca::Complete_ElemMeca(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD)
2023-05-03 17:23:49 +02:00
{ // avant toute chose, une complétion hors bloc, concernant la stabilisation
if (pt_StabMembBiel != NULL) // ne sert qu'après un démarrage initial sur un base_info
// donc dans la pratique ne sert pas souvent, mais existe pour que
// ElemMeca::StabMembBiel::Lecture_bas_inf soit correcte
pt_StabMembBiel->Complete_StabMembBiel(lesFonctionsnD);
// cas de la masse volumique
if (bloc.Nom(1) == "masse_volumique")
{ masse_volumique = bloc.Val(1);
return this;
}
// cas de données thermique
else if (bloc.Nom(1) == "dilatation_thermique")
{ if (bloc.Val(1) == 1) {dilatation=1;} else {dilatation = 0;};
return this;
};
// cas de la définition d'une intégrale sur le volume
// on prévoit une intégrale via les pti, on utilise donc le ddl EPS11 pour la position
// (*index_Integ_vol_typeQuel)(ii) contient alors le numéro de l'intégrale qui a été
// demandé par l'utilisateur = le numéro d'apparition dans le .info
// idem pour (*index_Integ_vol_t_typeQuel)(ii)
if (bloc.Nom(1) == "integrale_sur_volume_")
{ if (bloc.Nom(2) == "un_ddl_etendu_")
{ // il s'agit d'une intégrale d'un ddl étendu de nom: bloc.Nom(3)
Ddl_etendu ddl(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc
Grandeur_Ddl_etendu grand_courant(ddl,bloc.Nom(4));// le conteneur ad hoc
TypeQuelconque typQ(INTEG_SUR_VOLUME,EPS11,grand_courant);
// on garde en mémoire le TypeQuelconque_enum_etendu associé
// -- on crée le nom de référence
// string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_"
// +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_");
// on regarde si l'identificateur existe déjà, sinon on le crée
if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(INTEG_SUR_VOLUME,nom,typQ.EnuTypeGrandeur());
// puis récupération
TypeQuelconque_enum_etendu tqnevez =
TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);
if (integ_vol_typeQuel == NULL)
{// ici rien n'existe, donc on crée sans se poser des questions
int taille = 1;
integ_vol_typeQuel = new Tableau <TypeQuelconque>(1);
integ_vol_typeQuel_t = new Tableau <TypeQuelconque>(1);
(*integ_vol_typeQuel)(1) = typQ;(*integ_vol_typeQuel_t)(1) = typQ;
index_Integ_vol_typeQuel = new Tableau <int>(1);
(*index_Integ_vol_typeQuel)(1) = (int) bloc.Val(1);
enu_integ_vol_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
(*enu_integ_vol_TQ)(1)=tqnevez;
}
else
{// sinon, deux cas suivant que la grandeur a déjà été enregistrée
// suite à un restart par exemple , ou au contraire en n'existe pas encore
// on utilise l'identificateur pour repérer l'intégrale
int indic = enu_integ_vol_TQ->Contient(tqnevez);
if (!indic)
{// cas où l'intégrale n'existe pas déjà
int taille = integ_vol_typeQuel->Taille()+1;
integ_vol_typeQuel->Change_taille(taille);
integ_vol_typeQuel_t->Change_taille(taille);
(*integ_vol_typeQuel)(taille) = typQ;
(*integ_vol_typeQuel_t)(taille) = typQ;
index_Integ_vol_typeQuel->Change_taille(taille);
(*index_Integ_vol_typeQuel)(taille) = (int) bloc.Val(1);
enu_integ_vol_TQ->Change_taille(taille);
(*enu_integ_vol_TQ)(taille)=tqnevez;
}
else // sinon les conteneurs existent déjà
// il faut juste mettre à jour l'index
{ (*index_Integ_vol_typeQuel)(indic) = (int) bloc.Val(1);
} ;
};
}
else if (bloc.Nom(2) == "une_fonction_nD_")
{ // il s'agit d'une intégrale d'une fonction nD de nom: bloc.Nom(3)
// on récupère le pointeur de fonction correspondant:
Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3));
int nb_composante = fct->NbComposante();
Grandeur_Vecteur_Nommer grand_courant(bloc.Nom(3),nb_composante,fct);
TypeQuelconque typQ(INTEG_SUR_VOLUME,EPS11,grand_courant);
// on garde en mémoire le TypeQuelconque_enum_etendu associé
// -- on crée le nom de référence
// string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_"
// +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
string nom(NomTypeQuelconque(INTEG_SUR_VOLUME)+"_"+bloc.Nom(4)+"_");
// on regarde si l'identificateur existe déjà, sinon on le crée
if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(INTEG_SUR_VOLUME,nom,typQ.EnuTypeGrandeur());
// puis récupération
TypeQuelconque_enum_etendu tqnevez =
TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);
if (integ_vol_typeQuel == NULL)
{ // ici rien n'existe, donc on crée sans se poser des questions
int taille = 1;
integ_vol_typeQuel = new Tableau <TypeQuelconque>(1);
integ_vol_typeQuel_t = new Tableau <TypeQuelconque>(1);
(*integ_vol_typeQuel)(1) = typQ;(*integ_vol_typeQuel_t)(1) = typQ;
index_Integ_vol_typeQuel = new Tableau <int>(1);
(*index_Integ_vol_typeQuel)(1) = (int) bloc.Val(1);
enu_integ_vol_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
(*enu_integ_vol_TQ)(1)=tqnevez;
}
else
{// sinon, deux cas suivant que la grandeur a déjà été enregistrée
// suite à un restart par exemple , ou au contraire en n'existe pas encore
// on utilise l'identificateur pour repérer l'intégrale
int indic = enu_integ_vol_TQ->Contient(tqnevez);
if (!indic)
{// cas où l'intégrale n'existe pas déjà
int taille = integ_vol_typeQuel->Taille()+1;
integ_vol_typeQuel->Change_taille(taille);
integ_vol_typeQuel_t->Change_taille(taille);
(*integ_vol_typeQuel)(taille) = typQ;
(*integ_vol_typeQuel_t)(taille) = typQ;
index_Integ_vol_typeQuel->Change_taille(taille);
(*index_Integ_vol_typeQuel)(taille) = (int) bloc.Val(1);
enu_integ_vol_TQ->Change_taille(taille);
(*enu_integ_vol_TQ)(taille)=tqnevez;
}
else // sinon les conteneurs existent déjà
// il faut juste mettre à jour l'index
{ (*index_Integ_vol_typeQuel)(indic) = (int) bloc.Val(1);
} ;
};
};
return this;
}
// cas de la définition d'une intégrale sur le volume et le temps
else if (bloc.Nom(1) == "integrale_sur_vol_et_temps_")
{ if (bloc.Nom(2) == "un_ddl_etendu_")
{ // il s'agit d'une intégrale d'un ddl étendu de nom: bloc.Nom(3)
Ddl_etendu ddl(Ddl_enum_etendu(bloc.Nom(3))) ;// on crée un ddl ad hoc
Grandeur_Ddl_etendu grand_courant(ddl,bloc.Nom(4));// le conteneur ad hoc
TypeQuelconque typQ(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant);
// on garde en mémoire le TypeQuelconque_enum_etendu associé
// -- on crée le nom de référence
// string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_"
// +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_");
// on regarde si l'identificateur existe déjà, sinon on le crée
if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(INTEG_SUR_VOLUME_ET_TEMPS,nom,typQ.EnuTypeGrandeur());
// puis récupération
TypeQuelconque_enum_etendu tqnevez =
TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);
if (integ_vol_t_typeQuel == NULL)
{// ici rien n'existe, donc on crée sans se poser des questions
int taille = 1;
integ_vol_t_typeQuel = new Tableau <TypeQuelconque>(1);
integ_vol_t_typeQuel_t = new Tableau <TypeQuelconque>(1);
(*integ_vol_t_typeQuel)(1) = typQ;(*integ_vol_t_typeQuel_t)(1) = typQ;
index_Integ_vol_t_typeQuel = new Tableau <int>(1);
(*index_Integ_vol_t_typeQuel)(1) = (int) bloc.Val(1);
enu_integ_vol_t_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
(*enu_integ_vol_t_TQ)(1)=tqnevez;
}
else
{// sinon, deux cas suivant que la grandeur a déjà été enregistrée
// suite à un restart par exemple , ou au contraire en n'existe pas encore
// on utilise l'identificateur pour repérer l'intégrale
int indic = enu_integ_vol_t_TQ->Contient(tqnevez);
if (!indic)
{int taille = integ_vol_t_typeQuel->Taille()+1;
integ_vol_t_typeQuel->Change_taille(taille);
integ_vol_t_typeQuel_t->Change_taille(taille);
(*integ_vol_t_typeQuel)(taille) = typQ;
(*integ_vol_t_typeQuel_t)(taille) = typQ;
index_Integ_vol_t_typeQuel->Change_taille(taille);
(*index_Integ_vol_t_typeQuel)(taille) = (int) bloc.Val(1);
enu_integ_vol_t_TQ->Change_taille(taille);
(*enu_integ_vol_t_TQ)(taille)=tqnevez;
}
else // sinon les conteneurs existent déjà
// il faut juste mettre à jour l'index
{ (*index_Integ_vol_t_typeQuel)(indic) = (int) bloc.Val(1);
} ;
};
}
else if (bloc.Nom(2) == "une_fonction_nD_")
{ // il s'agit d'une intégrale d'une fonction nD de nom: bloc.Nom(3)
// on récupère le pointeur de fonction correspondant:
Fonction_nD * fct = lesFonctionsnD->Trouve(bloc.Nom(3));
int nb_composante = fct->NbComposante();
Grandeur_Vecteur_Nommer grand_courant(bloc.Nom(3),nb_composante,fct);
TypeQuelconque typQ(INTEG_SUR_VOLUME_ET_TEMPS,EPS11,grand_courant);
// on garde en mémoire le TypeQuelconque_enum_etendu associé
// -- on crée le nom de référence
// string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_"
// +ChangeEntierSTring(bloc.Val(1)));
// modif le 29 janvier 2018 version >= 6.827, on ne met plus le chiffre du rang
// de l'intégrale à la fin, car le rang peu changer après un restart par exemple
// du coup c'est une complexité qui n'apporte pas d'info sup, car la rang est stocké dans l'index
string nom(NomTypeQuelconque(INTEG_SUR_VOLUME_ET_TEMPS)+"_"+bloc.Nom(4)+"_");
if (!TypeQuelconque_enum_etendu::VerifExistence(nom))
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
(INTEG_SUR_VOLUME_ET_TEMPS,nom,typQ.EnuTypeGrandeur());
// puis récupération
TypeQuelconque_enum_etendu tqnevez =
TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(nom);
if (integ_vol_t_typeQuel == NULL)
{// ici rien n'existe, donc on crée sans se poser des questions
int taille = 1;
integ_vol_t_typeQuel = new Tableau <TypeQuelconque>(1);
integ_vol_t_typeQuel_t = new Tableau <TypeQuelconque>(1);
(*integ_vol_t_typeQuel)(1) = typQ;(*integ_vol_t_typeQuel_t)(1) = typQ;
index_Integ_vol_t_typeQuel = new Tableau <int>(1);
(*index_Integ_vol_t_typeQuel)(1) = (int) bloc.Val(1);
enu_integ_vol_t_TQ = new Tableau <TypeQuelconque_enum_etendu>(1);
(*enu_integ_vol_t_TQ)(1)=tqnevez;
}
else
{// sinon, deux cas suivant que la grandeur a déjà été enregistrée
// suite à un restart par exemple , ou au contraire en n'existe pas encore
// on utilise l'identificateur pour repérer l'intégrale
int indic = enu_integ_vol_t_TQ->Contient(tqnevez);
if (!indic)
{int taille = integ_vol_t_typeQuel->Taille()+1;
integ_vol_t_typeQuel->Change_taille(taille);
integ_vol_t_typeQuel_t->Change_taille(taille);
(*integ_vol_t_typeQuel)(taille) = typQ;
(*integ_vol_t_typeQuel_t)(taille) = typQ;
index_Integ_vol_t_typeQuel->Change_taille(taille);
(*index_Integ_vol_t_typeQuel)(taille) = (int) bloc.Val(1);
enu_integ_vol_t_TQ->Change_taille(taille);
(*enu_integ_vol_t_TQ)(taille)=tqnevez;
}
else // sinon les conteneurs existent déjà
// il faut juste mettre à jour l'index
{ (*index_Integ_vol_t_typeQuel)(indic) = (int) bloc.Val(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_")
{// on vérifie qu'il s'agit d'une géométrie membrane ou biel
Enum_type_geom enu_type_geom = Type_geom_generique(this->Id_geometrie());
if ((enu_type_geom != LIGNE) && (enu_type_geom != SURFACE))
{cout << "\n **** erreur, la stabilisation n'est pas prevue pour ce type d'element: ";
this->Affiche(1);
Sortie(1);
};
// maintenant on va allouer le conteneur d'infos
// pour savoir comment dimensionner le stockage
// il faut prendre en compte le type de stabilisation
Enum_StabMembraneBiel enu_stab = Id_Enum_StabMembraneBiel(bloc.Nom(2));
int taille_stockage = 0; // init
if (!Contient_Normale_au_noeud(enu_stab))
// cas d'un stockage aux pti
{ // détermination de la taille en fonction du type d'élément
// ** non car finalement on ne prend que les pti de surface
// Enum_type_geom enu_type_geom = Type_geom_generique(this->Id_geometrie());
// switch (enu_type_geom)
// { case SURFACE:
// taille_stockage = NbPtIntegSurface(X1) * NbPtIntegEpaiss(X1);
// break;
// default:
// cout << "\n *** actuellement seule les elements de surface peuvent etre stabilise ** revoir la mise en donnees ...";
// Sortie(1);
// };
taille_stockage = this->ElementGeometrique().Nbi();
}
else // sinon c'est un stockage aux noeuds
{ taille_stockage = tab_noeud.Taille();};
pt_StabMembBiel = new StabMembBiel(taille_stockage);
// définition du type de stabilisation
if (Type_Enum_StabMembraneBiel_existe(bloc.Nom(2)))
{pt_StabMembBiel->Type_stabMembrane()= Id_Enum_StabMembraneBiel(bloc.Nom(2));}
else
{cout << "\n *** erreur en mise en place de la stabilisation de membrane et/ou biel: "
<< " le type de stabilisation "<<bloc.Nom(2)<<" n'existe pas ! ";
cout << "\n ElemMeca::Complete_ElemMeca(..."<<endl; this->Affiche(1);
Sortie(1);
};
// choix entre valeur numérique ou une fonction nD
if (bloc.Nom(3) == "une_valeur_numerique_")
{// dans ce cas la valeur numémrique est en string
pt_StabMembBiel->Valgamma() = ChangeReel(bloc.Nom(4));
}
else if (bloc.Nom(3) == "une_fonction_nD_")
{// il s'agit d'une fonction nD: récupération de la fonction
pt_StabMembBiel->Change_pt_fct_gamma(lesFonctionsnD->Trouve(bloc.Nom(4)));
2023-05-03 17:23:49 +02:00
// non modif 8 mai 2022 // pour l'instant seules les variables globales sont autorisées:
// if (pt_StabMembBiel->Pt_fct_gamma()->Nom_variables().Taille() == 0)
// // cas où il n'y a que des variables globales
{// on vérifie qu'en retour on a un scalaire
2023-05-03 17:23:49 +02:00
// Tableau <double> & tava = pt_StabMembBiel->Pt_fct_gamma()->Valeur_pour_variables_globales(); // pour simplifier
if (pt_StabMembBiel->Pt_fct_gamma()->NbComposante() != 1)
{cout << "\n *** erreur en mise en place de la stabilisation de membrane et/ou biel : "
2023-05-03 17:23:49 +02:00
// << " la fonction nD avec grandeur(s) globale(s) ne renvoie pas un scalaire ! ";
<< " la fonction nD " << bloc.Nom(4) << " ne renvoie pas un unique scalaire ! ";
cout << "\n element: "; this->Affiche(1);
cout << "\n fonction nD : "; pt_StabMembBiel->Pt_fct_gamma()->Affiche();
Sortie(1);
}
}
2023-05-03 17:23:49 +02:00
// else
// {cout << "\n *** erreur en mise en place de la stabilisation: "
// << " la fonction nD ne doit utiliser que des variables globales ! ";
// cout << "\n element: "; this->Affiche(1);
// cout << "\n fonction nD : "; pt_StabMembBiel->Pt_fct_gamma()->Affiche();
// Sortie(1);
// };
}
else
{cout << "\n **** erreur, en mise en place de la stabilisation: "
<< " le mot cle: "<< bloc.Nom(3) << "n'est pas exploitable ";
if (ParaGlob::NiveauImpression() > 2)
cout << "\n ElemMeca::Complete_ElemMeca(..";
Sortie(1);
};
// on regarde s'il y a des infos sur les limites
int nb_info = (bloc.DimNom()-4)/2; // nombre de couples
// on passe en revue les noms s'ils existent, > 4
// on va de 2 en 2
for (int i=1;i<= nb_info;i++)
2023-05-03 17:23:49 +02:00
{if (bloc.Nom(3+i*2) == "affichage_stabilisation_")
{pt_StabMembBiel->Change_affichage_stabilisation(ChangeEntier(bloc.Nom(4+i*2)));}
else if (bloc.Nom(3+i*2) == "gestion_maxi_mini_")
{pt_StabMembBiel->Change_gestion_maxi_mini(bool(ChangeEntier(bloc.Nom(4+i*2))));}
else if (bloc.Nom(3+i*2) == "beta_")
{pt_StabMembBiel->Change_beta(ChangeReel(bloc.Nom(4+i*2)));}
else if (bloc.Nom(3+i*2) == "f_mini_")
{pt_StabMembBiel->Change_f_mini(ChangeReel(bloc.Nom(4+i*2)));}
else if (bloc.Nom(3+i*2) == "d_maxi_")
{pt_StabMembBiel->Change_d_maxi(ChangeReel(bloc.Nom(4+i*2)));}
2023-05-03 17:23:49 +02:00
else if (bloc.Nom(3+i*2) == "specifique_explicite_")
{if (bloc.Nom(4+i*2) == "inactive_stabilisation_")
pt_StabMembBiel->change_activite_en_explicite(false);
else if (bloc.Nom(4+i*2) == "active_stabilisation_")
pt_StabMembBiel->change_activite_en_explicite(true);
}
else if (bloc.Nom(3+i*2) == "ponderation_f_stab_t_")
{// il s'agit d'une fonction nD: récupération de la fonction
pt_StabMembBiel->Change_pt_fct_ponder_Ft(lesFonctionsnD->Trouve(bloc.Nom(4+i*2)));
// on vérifie que c'est bien une fonction scalaire
if (pt_StabMembBiel->Pt_fct_ponder_Ft()->NbComposante() != 1)
{cout << "\n *** erreur en mise en place de la stabilisation de membrane et/ou biel : "
<< " la fonction nD " << bloc.Nom(4+i*2) << " n'est pas scalaire ";
cout << "\n element: "; this->Affiche(1);
cout << "\n fonction nD : "; pt_StabMembBiel->Pt_fct_ponder_Ft()->Affiche();
Sortie(1);
};
}
};
return this;
}
// cas de la définition d'un repère d'anisotropie
else if (bloc.Nom(1) == "repere_anisotropie_")
{// pour l'instant le repère d'anisotropie est éventuellement
// utilisable par la loi de comportement
// 1) tout d'abord on doit définir le repère au niveau de chaque point d'intégration
// définition d'un repère d'anisotropie à un point d'intégration
// ici on ne fait que définir les conteneurs, la définition exacte des repères
// ne se fera que pendant l'initialisation de l'algo et/ou pendant le calcul
int nb_pti = lesPtIntegMecaInterne->NbPti();
int dim = ParaGlob::Dimension();
Coordonnee u(dim);
Tableau <Coordonnee> tab_coor(dim,u);
for (int ni=1;ni<= nb_pti;ni++)
{// passage des infos
if (tabSaveDon(ni) != NULL)
tabSaveDon(ni)->Complete_SaveResul(bloc,tab_coor,loiComp);
};
return this;
}
// sinon rien
else
{ return NULL;};
};
// calcul de la contrainte modifiée en fonction du bulk viscosity
// ramène l'énergie par unité de volume, dépensée par le bulk
DeuxDoubles ElemMeca::ModifContrainteBulk(Enum_dure temps,const TenseurHH& gijHH,TenseurHH & sigHH
,const TenseurBB & DepsBB,TenseurHH & sigbulkHH )
{ DeuxDoubles ener_bulk_volumique; // pour le retour
// on calcul la trace du tenseur de vitesse de déformation
TenseurBH* DepsBH = NevezTenseurBH(DepsBB.Dimension());
(*DepsBH) = DepsBB * gijHH;
double IDeps = DepsBH->Trace();
// on intervient que si la trace est négative dans le cas où bulk_viscosity != 2
// ou dans tous les cas si == 2
if ((bulk_viscosity == 2) || (IDeps < 0.))
{ // calcul d'une longueur caractéristique de l'élément
// cout << "\n c_carreBulk" << c_carreBulk << " c_traceBulk" << c_traceBulk << endl;
2023-05-03 17:23:49 +02:00
double lon=this->LongueurGeometrique_mini(1); // cas 1 pour l'instant
// on calcul la célérité
double cc = sqrt(ElemMeca::Calcul_maxi_E_qui(temps)/masse_volumique);
// calcul de la pression
//-- double q = masse_volumique * lon * ( c_carreBulk * lon * IDeps*IDeps + c_traceBulk * cc * IDeps );
//-- modification car il y a une erreur / à la théorique concernant le signe de c_carreBulk
double q = masse_volumique * lon * ( c_carreBulk * lon * IDeps*IDeps - c_traceBulk * cc * IDeps );
// calcul de la modification du tenseur sigHH
//-- sigHH += q * gijHH;
sigbulkHH = (-q) * gijHH;
//--- debug
//cout << "\n sigbulkHH= " << sigbulkHH(1,1) << " sigHH= " << sigHH(1,1)
// << " lon="<<lon<<" cc="<< cc<<" q="<<q << " IDeps= " << IDeps << endl;
//--- fin debug
sigHH += sigbulkHH;
// -- on calcul également l'énergie par unité de volume non réversible visqueuse dépensée
// on considère que la contrainte du bulk demeure constante sur l'incrément de temps
// recup de l'incrément de temps
double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
ener_bulk_volumique.un = -q*IDeps*deltat;
ener_bulk_volumique.deux = -q*IDeps;
}
else
{ sigbulkHH.Inita(0.);}; // dans le cas où le bulk n'est pas activé on le met à 0
delete DepsBH;
LibereTenseur();
return ener_bulk_volumique;
};
// récupération de la base locales au noeud noe, pour le temps: temps
const BaseB & ElemMeca::Gib_elemeca(Enum_dure temps, const Noeud * noe)
{ int nb_noeud = tab_noeud.Taille(); // nombre de noeud de l'élément local
// on fait une rotation sur les noeuds de l'élément
int num=1;
for (num=1;num<= nb_noeud;num++)
{ if (noe == tab_noeud(num)) break; }
// récupération des coordonnées locales du noeud
ElemGeomC0& elem_geom = ElementGeometrique(); // recup de l'élément géométrique correspondant
// récup de la référence des coordonnées locales du noeud num
const Coordonnee & coo = elem_geom.PtelemRef()(num);
// calcul de la dérivée des fonctions au point
2023-05-03 17:23:49 +02:00
const Mat_pleine& ddphi = elem_geom.Dphi_point(coo);
const Vecteur& pphi = elem_geom.Phi_point(coo);
// en fonction du temps on calcul la base naturelle
switch (temps)
{ case TEMPS_0: return (met->BaseNat_0(tab_noeud,ddphi,pphi)); break;
case TEMPS_t: return (met->BaseNat_t(tab_noeud,ddphi,pphi)); break;
case TEMPS_tdt: return (met->BaseNat_tdt(tab_noeud,ddphi,pphi)); break;
};
// pour faire taire le compilateur
cout << "\n erreur, on ne devrait jamais passer ici"
<< "\n ElemMeca::Gib_elemeca(...";
Sortie(1);
BaseB *toto = new BaseB(0);
return (*toto);
};
// calcul du mini du module d'young équivalent pour tous les points d'intégrations
double ElemMeca::Calcul_mini_E_qui(Enum_dure temps)
{ double mini = 0.; // init
int ni;
for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
{ def->ChangeNumInteg(ni);def->Mise_a_jour_data_specif(tabSaveDefDon(ni));
// si l'on a une thermo-dépendance il faut s'assurer que la température est mise à jour
loiComp->Mise_a_jour_temperature(temps,*def);
// indique également à la loi quelle valeur de saveResult il faut se référer
double E_equi = loiComp->Module_young_equivalent(temps,*def,tabSaveDon(ni));
if (E_equi < mini) mini = E_equi;
}
return mini;
};
// calcul du maxi du module d'young équivalent pour tous les points d'intégrations
double ElemMeca::Calcul_maxi_E_qui(Enum_dure temps)
{ double maxi = 0.; // init
int ni;
for (def->PremierPtInteg(), ni = 1;def->DernierPtInteg();def->NevezPtInteg(),ni++)
{ def->ChangeNumInteg(ni);def->Mise_a_jour_data_specif(tabSaveDefDon(ni));
// si l'on a une thermo-dépendance il faut s'assurer que la température est mise à jour
loiComp->Mise_a_jour_temperature(temps,*def);
double E_equi = loiComp->Module_young_equivalent(temps,*def,tabSaveDon(ni));
if (E_equi > maxi) maxi = E_equi;
}
return maxi;
};
// cas d'un chargement aero-hydrodynamique, sur les frontières de l'élément
// Il y a trois forces: une suivant la direction de la vitesse: de type traînée aerodynamique
// Fn = poids_volu * fn(V) * S * (normale*u) * u, u étant le vecteur directeur de V (donc unitaire)
// une suivant la direction normale à la vitesse de type portance
// Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire, normal à V, et dans le plan n et V
// une suivant la vitesse tangente de type frottement visqueux
// T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
// retourne le second membre résultant
// calcul à l'instant tdt ou t en fonction de la variable atdt
// coef_mul: est un coefficient multiplicateur global (de tout)
Vecteur& ElemMeca::SM_charge_hydrodyn_E (const double& poidvol,const Tableau <Vecteur>& taphi,int nbne
,Courbe1D* frot_fluid,const Vecteur& poids
,Courbe1D* coef_aero_n,int numfront,const double& coef_mul
,Courbe1D* coef_aero_t,const ParaAlgoControle & ,bool atdt)
{
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
// *** dans l'ensemble du sp on utilise des vecteurs et on gére directement la variance
// *** sinon c'est intractable et long
// remarque: l'initialisation du résidu n'est pas fait ici, mais dans les routines appelants
Vecteur* SM_r;
int dime = ParaGlob::Dimension();
bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
// donc il faut calculer tous les éléments de la métrique
switch (dime)
{case 3: // cas de la dimension 3
{ // définition du vecteur de retour
Vecteur& SM = *((*res_extS)(numfront));SM_r=&SM;
// dans le cas ou le poid volumique est nul, on retourne sans calcul
if (Dabs(poidvol) < ConstMath::trespetit) return SM;
int ni; // compteur globale de point d'integration
Deformation & defS = *defSurf(numfront); // pour simplifier l'écriture
// éventuellement dimensionnement de la sauvegarde
if (lesChargeExtSurEle == NULL)
lesChargeExtSurEle = new LesChargeExtSurElement;
if (lesChargeExtSurEle->LesHydroDyna() == NULL)
{if(ParaGlob::AxiSymetrie())
{lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());}
else
{lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbFe());}
};
Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
if (tab_hydrodyna.Taille() != defS.Phi1_Taille())
tab_hydrodyna.Change_taille(defS.Phi1_Taille());
for (defS.PremierPtInteg(), ni = 1;defS.DernierPtInteg();defS.NevezPtInteg(),ni++)
{ // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
// que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
Met_abstraite::Expli ex;
if (atdt) {ex = (defS.Cal_explicit_tdt(premier_calcul)).Tdt_dans_t(); }
else {ex = defS.Cal_explicit_t(premier_calcul); };
// détermination de la normale à la surface qui vaut le produit vectoriel des 2 premiers vecteurs
// conversion explicite en coordonnées sans variance
Coordonnee normale = Util::ProdVec_coorBN( (*ex.giB_t)(1), (*ex.giB_t)(2));
// cout << "\n normale avant normalisation";
// normale.Affiche();
normale.Normer(); // on norme la normale
// cout << "\n normale après normalisation";
// normale.Affiche(); Sortie(1);
// récupération de la vitesse
const Coordonnee* Vp;
if (atdt) {Vp = &(defS.VitesseM_tdt());}
else {Vp = &(defS.VitesseM_t());};
const Coordonnee& V = *Vp; double nV = V.Norme();
// dans le cas où la vitesse est trop faible, le résidu est nul
if (nV < ConstMath::trespetit) return SM;
Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
double nVt = Vt.Norme(); // norme de la vitesse tangente
if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
Coordonnee w(3);
if (coef_aero_t != NULL)
{w = Util::ProdVec_coor(u,Util::ProdVec_coor( u, normale));
// si w est non nulle on le norme
double norme_w = w.Norme();
if (norme_w > ConstMath::trespetit) {w /= norme_w;};
};
Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
// calcul du résidu
int ix=1; int dimf = 3; // ne fonctionne qu'en dim 3
// cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
double coef_frot_fluid=0.;
if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_t);
Fsauve.T += frot_fluid->Valeur(nVt) * Vt;};
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
double coef_n=0.;
if (coef_aero_n != NULL)
{ coef_n += poidvol * coef_aero_n->Valeur(nV) * poids(ni) * (*ex.jacobien_t) * cos_directeur;
Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;};
// cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
double coef_t=0.;
if (coef_aero_t != NULL)
{ coef_t += poidvol * coef_aero_t->Valeur(nV) * poids(ni) * (*ex.jacobien_t) * cos_directeur;
Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
for (int ne =1; ne<= nbne; ne++)
for (int i=1;i<= dimf;i++,ix++)
{ SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));};
} // fin boucle sur les points d'intégrations
break;
}; // fin du cas de la dimension 3
case 2: // cas de la dimension 2
{ // définition du vecteur de retour
Vecteur& SM = *((*res_extA)(numfront));SM_r=&SM;
// dans le cas ou le poid volumique est nul, on retourne sans calcul
if (Dabs(poidvol) < ConstMath::trespetit) return SM;
int ni; // compteur globale de point d'integration
Deformation & defA = *defArete(numfront); // pour simplifier l'écriture
// éventuellement dimensionnement de la sauvegarde
if (lesChargeExtSurEle == NULL)
lesChargeExtSurEle = new LesChargeExtSurElement;
if (lesChargeExtSurEle->LesHydroDyna() == NULL)
lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());
Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
if (tab_hydrodyna.Taille() != defA.Phi1_Taille())
tab_hydrodyna.Change_taille(defA.Phi1_Taille());
for (defA.PremierPtInteg(), ni = 1;defA.DernierPtInteg();defA.NevezPtInteg(),ni++)
{ // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
// que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
Met_abstraite::Expli ex;
if (atdt) {ex = (defA.Cal_explicit_tdt(premier_calcul)).Tdt_dans_t(); }
else {ex = defA.Cal_explicit_t(premier_calcul); };
// détermination de la normale à la surface qui vaut le vecteur perpendiculaire au g1
// dans le sens directe
Coordonnee normale; normale(1) = - (*ex.giB_t)(1)(2); normale(2) = (*ex.giB_t)(1)(1);
normale.Normer(); // on norme la normale
// récupération de la vitesse
const Coordonnee* Vp;
if (atdt) {Vp = &(defA.VitesseM_tdt());}
else {Vp = &(defA.VitesseM_t());};
const Coordonnee& V = *Vp; double nV = V.Norme();
// dans le cas où la vitesse est trop faible, le résidu est nul
if (nV < ConstMath::trespetit) return SM;
Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
double nVt = Vt.Norme(); // norme de la vitesse tangente
if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
Coordonnee w(dime); // comme on est en 2D w ce calcul directement avec les composantes de u
if (coef_aero_t != NULL) {w(1) = -u(2); w(2)=u(1);};
Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
// calcul du résidu
int ix=1;
// cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
double coef_frot_fluid=0.;
if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_t);
Fsauve.T+=frot_fluid->Valeur(nVt) * Vt;};
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
double coef_n=0.;
if (coef_aero_n != NULL)
{ coef_n += poidvol * coef_aero_n->Valeur(nV) * poids(ni) * (*ex.jacobien_t) * cos_directeur;
Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;};
// cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
double coef_t=0.;
if (coef_aero_t != NULL)
{ coef_t += poidvol * coef_aero_t->Valeur(nV) * poids(ni) * (*ex.jacobien_t) * cos_directeur;
Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
for (int ne =1; ne<= nbne; ne++)
for (int i=1;i<= dime;i++,ix++)
{ SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));};
} // fin boucle sur les points d'intégrations
} // fin boucle sur les points d'intégrations
break;
case 1: // cas de la dimension 1
{ // définition du vecteur de retour
Vecteur& SM = *((*res_extN)(numfront));SM_r=&SM;
// dans le cas ou le poid volumique est nul, on retourne sans calcul
if (Dabs(poidvol) < ConstMath::trespetit) return SM;
// il n'y a pas plusieurs point d'intégration
// en 1D il ne peut y avoir que deux extrémités, la première à une normale = -1 , la seconde 1
Coordonnee normale(1); if (numfront == 1) {normale(1)=-1.;} else {normale(1)=1.;};
// éventuellement dimensionnement de la sauvegarde
if (lesChargeExtSurEle == NULL)
lesChargeExtSurEle = new LesChargeExtSurElement;
if (lesChargeExtSurEle->LesHydroDyna() == NULL)
lesChargeExtSurEle->LesHydroDyna_Change_taille(2); // car deux extrémités au plus
Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
if (tab_hydrodyna.Taille() != 1)
tab_hydrodyna.Change_taille(1); // un seul point d'intégration en un point !
// récupération de la vitesse
const Coordonnee* Vp;
Noeud* noe = (tabb(posi_tab_front_point+numfront)->TabNoeud())(1); // on récupére tout d'abord le noeud fontière
if (atdt) {Vp = &(def->VitesseM_tdt(noe));} // on utilise la déformation générale, qui convient pour un noeud
else {Vp = &(def->VitesseM_t(noe));};
const Coordonnee& V = *Vp; double nV = V.Norme();
// dans le cas où la vitesse est trop faible, le résidu est nul
if (nV < ConstMath::trespetit) return SM;
// dans le cas 1D il n'y a qu'un effort de trainée (car pas de vitesse tangente)
Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
// inutile double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
Force_hydroDyna& Fsauve = tab_hydrodyna(1); // pour simplifier la sauvegarde
// calcul du résidu
int ix=1; int dimf = dime;
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
double coef_n=0.;
if (coef_aero_n != NULL) // le poids(1) contiend la section, et il n'y a pas de jacobien, cos directeur = 1
{ coef_n += poidvol * coef_aero_n->Valeur(nV) * poids(1) ;
Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) ) * u ;};
for (int ne =1; ne<= nbne; ne++) // il n'y qu'un point d'intégration le noeud lui-même
for (int i=1;i<= dimf;i++,ix++)
{ SM(ix) += taphi(1)(ne) * coef_mul * ( coef_n * u(i) );};
break;
}; // fin du cas de la dimension 1 */
}; //-- fin du switch sur la dimension
// retour du second membre
return *SM_r;
};
// idem SM_charge_hydrodyn_E mais -> implicite,
// pa: permet de déterminer si oui ou non on calcul la contribution à la raideur
// retourne le second membre et la matrice de raideur correspondant
// coef_mul: est un coefficient multiplicateur global (de tout)
Element::ResRaid ElemMeca::SM_charge_hydrodyn_I (const double& poidvol,const Tableau <Vecteur>& taphi,int nbne
,Courbe1D* frot_fluid,const Vecteur& poids,DdlElement & ddls
,Courbe1D* coef_aero_n,int numfront,const double& coef_mul
,Courbe1D* coef_aero_t,const ParaAlgoControle & pa)
{
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
//****************** attention voir w non normé pour les dimensions 2 et 1 ****************
// *** dans l'ensemble du sp on utilise des vecteurs et on gére directement la variance
// *** sinon c'est intractable et long
// remarque: l'initialisation du résidu n'est pas fait ici, mais dans les routines appelants
Element::ResRaid el;
int nbddl = ddls.NbDdl();
bool avec_raid = pa.Var_charge_externe(); // controle
// // dans le cas où la variation sur la raideur est demandé on s'assure que la variation
// // du jacobien est bien effective sinon on l'impose
// ParaAlgoControle pa_nevez(pa);
// if (!pa_nevez.Var_jacobien()) pa_nevez.Modif_Var_jacobien(true);
int dime = ParaGlob::Dimension();
bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde
// donc il faut calculer tous les éléments de la métrique
switch (dime)
{case 3: // cas de la dimension 3
{ // dans le cas ou le poid volumique est nul, on retourne sans calcul
if (Dabs(poidvol) < ConstMath::trespetit)
{ el.res = (*res_extS)(numfront); el.raid = (*raid_extS)(numfront);
return el;
};
Vecteur& SM = (*((*res_extS)(numfront))); // pour simplifier
Mat_pleine & KM = (*((*raid_extS)(numfront))); // " " "
el.res = (*res_extS)(numfront); el.raid = (*raid_extS)(numfront); // pour le retour
int ni; // compteur globale de point d'integration
Deformation & defS = *defSurf(numfront); // pour simplifier l'écriture
// éventuellement dimensionnement de la sauvegarde
if (lesChargeExtSurEle == NULL)
lesChargeExtSurEle = new LesChargeExtSurElement;
if (lesChargeExtSurEle->LesHydroDyna() == NULL)
{if(ParaGlob::AxiSymetrie())
{lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());}
else
{lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbFe());}
};
Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
if (tab_hydrodyna.Taille() != defS.Phi1_Taille())
tab_hydrodyna.Change_taille(defS.Phi1_Taille());
for (defS.PremierPtInteg(), ni = 1;defS.DernierPtInteg();defS.NevezPtInteg(),ni++)
{ // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
// que pour un calcul primaire en implicit mais pour un calcul autre que mécanique
const Met_abstraite::Impli& ex = defS.Cal_implicit(premier_calcul);
// détermination de la normale à la surface qui vaut le produit vectoriel des 2 premiers vecteurs
Coordonnee normale = Util::ProdVec_coorBN( (*ex.giB_tdt)(1), (*ex.giB_tdt)(2));
normale.Normer(); // on norme la normale
// récupération de la vitesse
const Coordonnee V = defS.VitesseM_tdt(); double nV = V.Norme();
// dans le cas où la vitesse est trop faible, le résidu est nul
if (nV < ConstMath::trespetit) return el;
Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
double nVt = Vt.Norme(); // norme de la vitesse tangente
if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
Coordonnee w(3);double norme_w=0.;
Coordonnee vecNul(3); // un vecteur nul pour l'initialisation
if (coef_aero_t != NULL)
{w = Util::ProdVec_coor(u,Util::ProdVec_coor( u, normale));
// si w est non nulle on le norme
norme_w = w.Norme();
if (norme_w > ConstMath::trespetit) {w /= norme_w;};
};
// calcul éventuel des variations
static Tableau <Coordonnee> D_Vt,D_u,D_w,D_w_non_normer;
static Tableau <double> D_coef_frot_fluid,D_coef_n,D_coef_t;
if (avec_raid)
{ // calcul de la variation de la normale
// 1) variation du produit vectoriel
Tableau <Coordonnee > D_pasnormale =
Util::VarProdVect_coor((*ex.giB_tdt)(1).Coor(),(*ex.giB_tdt)(2).Coor(),(*ex.d_giB_tdt));
// 2) de la normale
Tableau <Coordonnee> D_normale = Util::VarUnVect_coor(normale,D_pasnormale,normale.Norme());
// récupération de la variation de vitesse
bool ddl_vitesse;
const Tableau <Coordonnee> D_V = defS.Der_VitesseM_tdt(ddl_vitesse);
D_Vt.Change_taille(nbddl); // calcul de la variation de la vitesse tangente
for (int ii=1;ii<=nbddl;ii++)
{D_Vt(ii)=D_V(ii) - (D_V(ii) * normale + V * D_normale(ii)) * normale
- (V*normale) * D_normale(ii);};
// variation de u
D_u.Change_taille(nbddl); D_u = Util::VarUnVect_coor( V, D_V,nV);
// variation de la norme de V
Tableau <double> D_nV = Util::VarNorme(D_V,V,nV);
// variation de w s'il a une norme différente de 0
D_w.Change_taille(nbddl,vecNul); // !! init obligatoire car peut ne pas rentrer dans les if qui suivent
if (norme_w > ConstMath::trespetit)
{if (coef_aero_t != NULL)
{ D_w_non_normer.Change_taille(nbddl);
// tout d'abord la variation du produit vectoriel
Coordonnee k = Util::ProdVec_coor( u, normale);
Tableau <Coordonnee> D_k = Util::VarProdVect_coor(u,normale,D_u,D_normale);
D_w_non_normer=Util::VarProdVect_coor(u,k,D_u,D_k);
D_w = Util::VarUnVect_coor(w,D_w_non_normer,norme_w);
}
};
// variation des coefficients
// cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
D_coef_frot_fluid.Change_taille(nbddl);
if (frot_fluid != NULL)
{ Courbe1D::ValDer valder = frot_fluid->Valeur_Et_derivee(nVt);
for (int i=1;i<=nbddl;i++)
D_coef_frot_fluid(i) = valder.derivee * D_nV(i) * poids(ni) * (*ex.jacobien_tdt)
+ valder.valeur * poids(ni) * (*ex.d_jacobien_tdt)(i);
};
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
D_coef_n.Change_taille(nbddl);
if (coef_aero_n != NULL)
{ Courbe1D::ValDer valder = coef_aero_n->Valeur_Et_derivee(nV);
for (int i=1;i<=nbddl;i++)
D_coef_n(i) = poidvol * poids(ni) * (
valder.derivee * D_nV(i) * (*ex.jacobien_tdt) * cos_directeur
+ valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur
+ valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
);
};
// cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
D_coef_t.Change_taille(nbddl);
if (coef_aero_t != NULL)
{ Courbe1D::ValDer valder = coef_aero_t->Valeur_Et_derivee(nV);
for (int i=1;i<=nbddl;i++)
D_coef_t(i) = poidvol * poids(ni) * (
valder.derivee * D_nV(i) * (*ex.jacobien_tdt) * cos_directeur
+ valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur
+ valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
);
};
}; //-- fin du if (avec_raid)
Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
// calcul du résidu
int ix=1; int dimf = 3; // ne fonctionne qu'en dim 3
// cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
double coef_frot_fluid=0.;
if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_tdt);
Fsauve.T += frot_fluid->Valeur(nVt) * Vt;};
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
double coef_n=0.;
if (coef_aero_n != NULL)
{ coef_n += poidvol * coef_aero_n->Valeur(nV) * poids(ni) * (*ex.jacobien_tdt) * cos_directeur;
Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;};
// cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
double coef_t=0.;
if (coef_aero_t != NULL)
{ coef_t += poidvol * coef_aero_t->Valeur(nV) * poids(ni) * (*ex.jacobien_tdt) * cos_directeur;
Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
for (int ne =1; ne<= nbne; ne++)
for (int i=1;i<= dimf;i++,ix++)
{ SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));
if (avec_raid)
{for (int j =1; j<= nbddl; j++)
{ //cout << "\n taphi(ni)(ne)= " << taphi(ni)(ne) << endl;
//cout << "\n D_coef_frot_fluid(j) " << D_coef_frot_fluid(j) << endl;
//cout << "\n Vt(i) " << Vt(i) << endl;
//cout << "\n D_Vt(j)(i) " << D_Vt(j)(i) << endl;
//cout << "\n D_coef_n(j) " << D_coef_n(j) << endl;
//cout << "\n u(i) " << u(i) << endl;
//cout << "\n D_u(j)(i) " << D_u(j)(i) << endl;
//cout << "\n D_coef_t(j) " << D_coef_t(j) << endl;
//cout << "\n w(i) " << w(i) << endl;
//cout << "\n D_w(j)(i) " << D_w(j)(i) << endl;
KM(ix,j) -= taphi(ni)(ne) * coef_mul *(
D_coef_frot_fluid(j) * Vt(i) + coef_frot_fluid * D_Vt(j)(i)
+ D_coef_n(j) * u(i) + coef_n * D_u(j)(i)
+ D_coef_t(j) * w(i) + coef_t * D_w(j)(i)
);
};
};
};
} // fin boucle sur les points d'intégrations
break;
}; // fin du cas de la dimension 3
case 2: // cas de la dimension 2
{ // dans le cas ou le poid volumique est nul, on retourne sans calcul
if (Dabs(poidvol) < ConstMath::trespetit)
{ el.res = (*res_extS)(numfront); el.raid = (*raid_extS)(numfront);
return el;
};
Vecteur& SM = (*((*res_extA)(numfront))); // pour simplifier
Mat_pleine & KM = (*((*raid_extA)(numfront))); // " " "
el.res = (*res_extA)(numfront); el.raid = (*raid_extA)(numfront); // pour le retour
int ni; // compteur globale de point d'integration
Deformation & defA = *defArete(numfront); // pour simplifier l'écriture
// éventuellement dimensionnement de la sauvegarde
if (lesChargeExtSurEle == NULL)
lesChargeExtSurEle = new LesChargeExtSurElement;
if (lesChargeExtSurEle->LesHydroDyna() == NULL)
lesChargeExtSurEle->LesHydroDyna_Change_taille(ElementGeometrique().NbSe());
Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
if (tab_hydrodyna.Taille() != defA.Phi1_Taille())
tab_hydrodyna.Change_taille(defA.Phi1_Taille());
for (defA.PremierPtInteg(), ni = 1;defA.DernierPtInteg();defA.NevezPtInteg(),ni++)
{ // -- calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul
// que pour un calcul primaire en explicit mais pour un calcul autre que mécanique
const Met_abstraite::Impli& ex = defA.Cal_implicit(premier_calcul);
// détermination de la normale à la surface qui vaut le vecteur perpendiculaire au g1
// dans le sens directe
Coordonnee normale; normale(1) = -(*ex.giB_tdt)(1)(2); normale(2) = (*ex.giB_tdt)(1)(1);
normale.Normer(); // on norme la normale
// récupération de la vitesse
const Coordonnee V = defA.VitesseM_tdt(); double nV = V.Norme();
// dans le cas où la vitesse est trop faible, le résidu est nul
if (nV < ConstMath::trespetit) return el;
Coordonnee Vt=V-(V*normale)*normale;// calcul de la vitesse tangente
double nVt = Vt.Norme(); // norme de la vitesse tangente
if (nVt < ConstMath::trespetit) { nVt=0.;Vt.Zero();} else {Vt /= nVt;}; // on norme la vitesse tangente
Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
double cos_directeur = u * normale; // permet de calculer surface normale à la vitesse
Coordonnee w(dime); // comme on est en 2D, w ce calcul directement avec les composantes de u
if (coef_aero_t != NULL) {w(1) = -u(2); w(2)=u(1);};
// calcul éventuel des variations
static Tableau <Coordonnee> D_Vt,D_u,D_w;
static Tableau <double> D_coef_frot_fluid,D_coef_n,D_coef_t;
if (avec_raid)
{ // calcul de la variation de la normale
// 1) variation du produit vectoriel
Tableau <Coordonnee > D_pasnormale(nbddl);
for (int i=1;i<=nbddl;i++)
{D_pasnormale(i)(1) = -(*ex.d_giB_tdt)(i)(1)(2); D_pasnormale(i)(2) = (*ex.d_giB_tdt)(i)(1)(1);};
// 2) de la normale
Tableau <Coordonnee> D_normale = Util::VarUnVect_coor(normale,D_pasnormale,normale.Norme());
// récupération de la variation de vitesse
bool ddl_vitesse;
const Tableau <Coordonnee> D_V = defA.Der_VitesseM_tdt(ddl_vitesse);
D_Vt.Change_taille(nbddl); // calcul de la variation de la vitesse tangente
for (int ii=1;ii<=nbddl;ii++)
{D_Vt(ii)=D_V(ii) - (D_V(ii) * normale + V * D_normale(ii)) * normale
- (V*normale) * D_normale(ii);};
// variation de u
D_u.Change_taille(nbddl); D_u = Util::VarUnVect_coor( V, D_V,nV);
// variation de la norme de V
Tableau <double> D_nV = Util::VarNorme(D_V,V,nV);
// variation de w
D_w.Change_taille(nbddl);
if (coef_aero_t != NULL)
{ for (int i=1;i<=nbddl;i++) {D_w(i)(1)=-D_u(i)(2);D_w(i)(2)=D_u(i)(1);};
}
// variation des coefficients
// cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
D_coef_frot_fluid.Change_taille(nbddl);
if (frot_fluid != NULL)
{ Courbe1D::ValDer valder = frot_fluid->Valeur_Et_derivee(nVt);
for (int i=1;i<=nbddl;i++)
D_coef_frot_fluid(i) = valder.derivee * D_nV(i) * poids(ni) * (*ex.jacobien_tdt)
+ valder.valeur * poids(ni) * (*ex.d_jacobien_tdt)(i);
};
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
D_coef_n.Change_taille(nbddl);
if (coef_aero_n != NULL)
{ Courbe1D::ValDer valder = coef_aero_n->Valeur_Et_derivee(nV);
for (int i=1;i<=nbddl;i++)
D_coef_n(i) = poidvol * poids(ni) * (
valder.derivee * D_nV(i) * (*ex.jacobien_tdt) * cos_directeur
+ valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur
+ valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
);
};
// cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
D_coef_t.Change_taille(nbddl);
if (coef_aero_t != NULL)
{ Courbe1D::ValDer valder = coef_aero_t->Valeur_Et_derivee(nV);
for (int i=1;i<=nbddl;i++)
D_coef_t(i) = poidvol * poids(ni) * (
valder.derivee * D_nV(i) * (*ex.jacobien_tdt) * cos_directeur
+ valder.valeur * (*ex.d_jacobien_tdt)(i) * cos_directeur
+ valder.valeur * (*ex.jacobien_tdt) * (D_u(i) * normale + u * D_normale(i))
);
};
}; //-- fin du if (avec_raid)
Force_hydroDyna& Fsauve = tab_hydrodyna(ni); // pour simplifier la sauvegarde
// calcul du résidu
int ix=1;
// cas de T: T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt
double coef_frot_fluid=0.;
if (frot_fluid != NULL) { coef_frot_fluid += frot_fluid->Valeur(nVt) * poids(ni) * (*ex.jacobien_tdt);
Fsauve.T+=frot_fluid->Valeur(nVt) * Vt;};
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
double coef_n=0.;
if (coef_aero_n != NULL)
{ coef_n += poidvol * coef_aero_n->Valeur(nV) * poids(ni) * (*ex.jacobien_tdt) * cos_directeur;
Fsauve.F_n += (poidvol * coef_aero_n->Valeur(nV) * cos_directeur) * u ;};
// cas de Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire suivant la normal à V
double coef_t=0.;
if (coef_aero_t != NULL)
{ coef_t += poidvol * coef_aero_t->Valeur(nV) * poids(ni) * (*ex.jacobien_tdt) * cos_directeur;
Fsauve.F_t += (poidvol * coef_aero_t->Valeur(nV) * cos_directeur) * w ;};
for (int ne =1; ne<= nbne; ne++)
for (int i=1;i<= dime;i++,ix++)
{ SM(ix) += taphi(ni)(ne) * coef_mul * (coef_frot_fluid * Vt(i) + coef_n * u(i) + coef_t * w(i));
if (avec_raid)
{for (int j =1; j<= nbddl; j++)
{KM(ix,j) -= taphi(ni)(ne) * coef_mul * (
D_coef_frot_fluid(j) * Vt(i) + coef_frot_fluid * D_Vt(j)(i)
+ D_coef_n(j) * u(i) + coef_n * D_u(j)(i)
+ D_coef_t(j) * w(i) + coef_t * D_w(j)(i)
);
};
};
};
} // fin boucle sur les points d'intégrations
break;
};
case 1: // cas de la dimension 1
{ // dans le cas ou le poid volumique est nul, on retourne sans calcul
if (Dabs(poidvol) < ConstMath::trespetit)
{ Element::ResRaid el;
el.res = (*res_extN)(numfront);
el.raid = (*raid_extN)(numfront);
return el;
};
Vecteur& SM = (*((*res_extN)(numfront))); // pour simplifier
Mat_pleine & KM = (*((*raid_extN)(numfront))); // " " "
el.res = (*res_extN)(numfront); el.raid = (*raid_extN)(numfront); // pour le retour
// il n'y a pas plusieurs point d'intégration
// en 1D il ne peut y avoir que deux extrémités, la première à une normale = -1 , la seconde 1
Coordonnee normale(1); if (numfront == 1) {normale(1)=-1.;} else {normale(1)=1.;};
// éventuellement dimensionnement de la sauvegarde
if (lesChargeExtSurEle == NULL)
lesChargeExtSurEle = new LesChargeExtSurElement;
if (lesChargeExtSurEle->LesHydroDyna() == NULL)
lesChargeExtSurEle->LesHydroDyna_Change_taille(2); // car deux extrémités au plus
Tableau <Force_hydroDyna>& tab_hydrodyna= (*lesChargeExtSurEle->LesHydroDyna())(numfront); // pour simplifier
if (tab_hydrodyna.Taille() != 1)
tab_hydrodyna.Change_taille(1); // un seul point d'intégration en un point !
// récupération de la vitesse
Noeud* noe = (tabb(posi_tab_front_point+numfront)->TabNoeud())(1); // on récupére tout d'abord le noeud fontière
const Coordonnee& V = def->VitesseM_tdt(noe); double nV = V.Norme();
// dans le cas où la vitesse est trop faible, le résidu est nul
if (nV < ConstMath::trespetit) return el;
// dans le cas 1D il n'y a qu'un effort de trainée (car pas de vitesse tangente)
Coordonnee u= V / nV; // on norme la vitesse, car ensuite on n'a besoin que de la direction unitaire de la vitesse
// u en fait = 1 ou -1 d'où variation = 0
// calcul éventuel des variations
static Tableau <double> D_coef_n;
if (avec_raid)
{ // calcul de la variation de la normale
// récupération de la variation de vitesse
bool ddl_vitesse;
const Tableau <Coordonnee> D_V = def->Der_VitesseM_tdt(ddl_vitesse,noe);
// variation de la norme de V
Tableau <double> D_nV = Util::VarNorme(D_V,V,nV);
// variation des coefficients
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
D_coef_n.Change_taille(nbddl);
if (coef_aero_n != NULL)
{ Courbe1D::ValDer valder = coef_aero_n->Valeur_Et_derivee(nV);
for (int i=1;i<=nbddl;i++)
D_coef_n(i) = poidvol * poids(1) * valder.derivee * D_nV(i);
};
}; //-- fin du if (avec_raid)
Force_hydroDyna& Fsauve = tab_hydrodyna(1); // pour simplifier la sauvegarde
// calcul du résidu
int ix=1; int dimf = dime;
// cas de Fn = poids_volu * fn(V) * S * (normale*u) * u, u unitaire suivant V
double coef_n=0.;
if (coef_aero_n != NULL) // le poids(1) contiend la section, et il n'y a pas de jacobien, cos directeur = 1
{ coef_n += poidvol * coef_mul * coef_aero_n->Valeur(nV) * poids(1) ;
Fsauve.F_n = (poidvol * coef_aero_n->Valeur(nV) ) * u ;};
for (int ne =1; ne<= nbne; ne++) // il n'y qu'un point d'intégration le noeud lui-même
for (int i=1;i<= dimf;i++,ix++)
{ SM(ix) += taphi(1)(ne) * ( coef_n * u(i) );
if (avec_raid)
{for (int j =1; j<= nbddl; j++)
{KM(ix,j) -= taphi(1)(ne) * coef_mul * (D_coef_n(j) * u(i));};
};
};
break;
}; // fin du cas de la dimension 1 */
}; //-- fin du switch sur la dimension
// retour
return el;
};