Herezh_dev/comportement/loi_Umat/Loi_Umat.cc

1226 lines
60 KiB
C++

// FICHIER : Loi_Umat.cp
// CLASSE : Loi_Umat
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-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 <iostream>
using namespace std; //introduces namespace std
#include <math.h>
#include <stdlib.h>
#include "Sortie.h"
#include "TypeConsTens.h"
#include "ConstMath.h"
#include "MathUtil.h"
#include "CharUtil.h"
#include "Util.h"
#include "Loi_Umat.h"
// ------------------fonctions interne template ------------
// multiplication de tenseur par des bases
template <class T1,class T2,class Base2,class Base1>
T1 & produit_1_pourLoiUmat(T1 & A,T2& Nous, const Base2 & gi2, const Base1 & gi1)
{ int dim = abs(A.Dimension());
int dimint = abs(Nous.Dimension());
for (int i=1;i<= dim; i++)
for (int j=1; j<= dim; j++)
{ A.Coor(i,j) = 0.;
for (int al=1; al<= dimint; al++)
for (int be=1; be<= dimint; be++)
A.Coor(i,j) += Nous(al,be)* (gi1.Coordo(al)(i)*gi2.Coordo(be)(j)+gi2.Coordo(al)(i)*gi1.Coordo(be)(j));
}
return A;
};
//==================== cas de la class de sauvegarde SaveResul ===================
// constructeur par défaut
Loi_Umat::SaveResul_Loi_Umat::SaveResul_Loi_Umat() :
save_pour_loi_ext(NULL),hsurh0(ConstMath::tresgrand),h_tsurh0(ConstMath::tresgrand)
{};
// constructeur de copie
Loi_Umat::SaveResul_Loi_Umat::SaveResul_Loi_Umat(const Loi_Umat::SaveResul_Loi_Umat& sav ):
save_pour_loi_ext(sav.save_pour_loi_ext),hsurh0(sav.hsurh0),h_tsurh0(sav.h_tsurh0)
{};
// affectation
Loi_comp_abstraite::SaveResul &
Loi_Umat::SaveResul_Loi_Umat::operator = ( const Loi_comp_abstraite::SaveResul & a)
{ Loi_Umat::SaveResul_Loi_Umat& sav = *((Loi_Umat::SaveResul_Loi_Umat*) &a);
// on affecte si non dimensionné, sinon on crée à l'identique
if (sav.save_pour_loi_ext != NULL)
{ if (save_pour_loi_ext == NULL)
{save_pour_loi_ext = sav.save_pour_loi_ext->Nevez_SaveResul();}
else
{(*save_pour_loi_ext) = *(sav.save_pour_loi_ext);};
};
hsurh0 = sav.hsurh0; h_tsurh0 = sav.h_tsurh0;
return *this;
};
//============= lecture écriture dans base info ==========
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void Loi_Umat::SaveResul_Loi_Umat::Lecture_base_info (istream& ent,const int cas)
{ // ici toutes les données sont toujours a priori variables
// ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
string toto; ent >> toto;
int titi=0.;
ent >> titi;
if (titi == 1 )
ent >> toto >> hsurh0; h_tsurh0 = hsurh0;
#ifdef MISE_AU_POINT
if (toto != "S_R_LoiUmat")
{ cout << "\n erreur en lecture du conteneur pour la loi Umat"
<< " \n Loi_Umat::SaveResul_Loi_Umat::Lecture_base_info(..";
Sortie(1);
}
#endif
if (save_pour_loi_ext!=NULL)
{save_pour_loi_ext->Lecture_base_info(ent,cas);};
};
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Loi_Umat::SaveResul_Loi_Umat::Ecriture_base_info (ostream& sort,const int cas)
{ // ici toutes les données sont toujours a priori variables
// ou en tout cas pour les méthodes appelées, elles sont gérées par le paramètre: cas
sort << "\n S_R_LoiUmat ";
if (hsurh0 != ConstMath::tresgrand )
sort << "\n 1 " << "CP:hsurh0= " << h_tsurh0;
else sort << "\n 0 ";
if (save_pour_loi_ext!=NULL)
{save_pour_loi_ext->Ecriture_base_info(sort,cas);};
};
// mise à jour des informations transitoires en définitif s'il y a convergence
// par exemple (pour la plasticité par exemple)
void Loi_Umat::SaveResul_Loi_Umat::TdtversT()
{ if (save_pour_loi_ext!=NULL)
save_pour_loi_ext->TdtversT();
// CP par défaut: car c'est aussi rapide que le test (sans doute ?)
h_tsurh0 = hsurh0;
};
void Loi_Umat::SaveResul_Loi_Umat::TversTdt()
{ if (save_pour_loi_ext!=NULL)
save_pour_loi_ext->TversTdt();
// CP par défaut: car c'est aussi rapide que le test (sans doute ?)
hsurh0 = h_tsurh0;
};
//==================== fin du cas de la class de sauvegarde SaveResul ============
Loi_Umat::Loi_Umat (Enum_comp enu) : // Constructeur par defaut
Loi_comp_abstraite(enu,CAT_MECANIQUE,0)
,nom_de_la_loi("_")
,umatAbaqus(ParaGlob::Dimension(),Loi_Umat::Choix_dim(enu))
,loi_ext(NULL)
,utilisation_umat_interne(NULL)
,umat_met3D(),umat_met2D(),umat_met1D()
,d_sigma_deps_2D(),d_sigma_deps_1D()
,gabBB_tdt(NULL),gabHH_tdt(NULL),gabBB_t(NULL),gabHH_t(NULL)
,gixB_0(),gixB_t(),gixB_tdt(),gixH_0(),gixH_t(),gixH_tdt()
// des pointeurs nulles pour les grandeurs qui actuellement ne servent pas
,ggaB_0null(NULL),ggaB_tnull(NULL),ggaH_0null(NULL)
,ggradVmoyBB_tnull(NULL),ggradVmoyBB_tdtnull(NULL),ggradVBB_tdtnull(NULL)
// --//\\-- grandeurs particulières pour le cas contraintes planes
// -- conteneur des métriques
,umat_cont_3D(NULL)
,umat_cont_2D(NULL)
,Ip2_B(ParaGlob::Dimension(),2) // pour définir la base 2D locale dans l'espace de travail
// -- les variables pointées dans les conteneurs, et leur pointeur associé éventuellement
,giB_0_3D(),giH_0_3D(),giB_t_3D(),giH_t_3D(),giB_tdt_3D(),giH_tdt_3D()
,gijBB_0_3D(),gijHH_0_3D(),gijBB_t_3D(),gijHH_t_3D()
,gijBB_tdt_3D(),gijHH_tdt_3D()
,gradVmoyBB_t_3D(),gradVmoyBB_tdt_3D(),gradVBB_tdt_3D()
,gradVmoyBB_t_3D_P(NULL),gradVmoyBB_tdt_3D_P(NULL),gradVBB_tdt_3D_P(NULL)
,jacobien_tdt_3D(0.),jacobien_0_3D(0.)
// idem en 2D
,Ip3B_0_3D(),Ip3H_0_3D() // ne fait pas partie de umat_cont_2D
,giB_0_2D(ParaGlob::Dimension(),2),giH_0_2D(ParaGlob::Dimension(),2)
,giB_t_2D(ParaGlob::Dimension(),2),giH_t_2D(ParaGlob::Dimension(),2)
,giB_tdt_2D(ParaGlob::Dimension(),2),giH_tdt_2D(ParaGlob::Dimension(),2)
,gijBB_0_2D(),gijHH_0_2D(),gijBB_t_2D(),gijHH_t_2D()
,gijBB_tdt_2D(),gijHH_tdt_2D()
,gradVmoyBB_t_2D(),gradVmoyBB_tdt_2D(),gradVBB_tdt_2D()
,gradVmoyBB_t_2D_P(NULL),gradVmoyBB_tdt_2D_P(NULL),gradVBB_tdt_2D_P(NULL)
,jacobien_tdt_2D(0.),jacobien_0_2D(0.)
// --//\\-- fin grandeurs particulières pour le cas contraintes planes
{ // définition de la métrique umat
int dim_base=3;
int nbvec_base_3D=3;
DdlElement tabddl; // init par défaut -> pas de ddl élément
int nb_noeud_interpol=0; // par de noeud, on n'a pas a s'en servir normalement
umat_met3D.Dim_NbVec(dim_base,nbvec_base_3D,tabddl,nb_noeud_interpol);
int nbvec_base_2D=2;//dim_base=2;
umat_met2D.Dim_NbVec(dim_base,nbvec_base_2D,tabddl,nb_noeud_interpol);
int nbvec_base_1D=1;//dim_base=1;
umat_met1D.Dim_NbVec(dim_base,nbvec_base_1D,tabddl,nb_noeud_interpol);
// on definit les variables a priori toujours utiles
Tableau<Enum_variable_metrique> tab(13);
tab(1)=igiB_0;tab(2)=igiB_t;tab(3)=igiB_tdt;
tab(4)=igiH_0;tab(5)=igiH_t;tab(6)=igiH_tdt ;
tab(7)=igijBB_0;tab(8)=igijBB_t;tab(9)=igijBB_tdt;
tab(10)=igijHH_0;tab(11)=igijHH_t;tab(12)=igijHH_tdt ;
tab(13)=igradVmoyBB_t;
umat_met3D.PlusInitVariables(tab) ;
umat_met2D.PlusInitVariables(tab) ;
umat_met1D.PlusInitVariables(tab) ;
// --//\\-- grandeurs particulières pour le cas contraintes planes
umat_cont_3D = new Met_abstraite::Umat_cont // constructeur normal
(&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
,&gijBB_tdt_3D,&gijHH_tdt_3D
,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
// idem 2D
umat_cont_2D = new Met_abstraite::Umat_cont // constructeur normal
(&giB_0_2D,&giH_0_2D,&giB_t_2D,&giH_t_2D,&giB_tdt_2D,&giH_tdt_2D
,&gijBB_0_2D,&gijHH_0_2D,&gijBB_t_2D,&gijHH_t_2D
,&gijBB_tdt_2D,&gijHH_tdt_2D
,gradVmoyBB_t_2D_P,gradVmoyBB_tdt_2D_P,gradVBB_tdt_2D_P // pas affecté par défaut
,&jacobien_tdt_2D,&jacobien_t_2D,&jacobien_0_2D);
// --//\\-- fin grandeurs particulières pour le cas contraintes planes
};
// Constructeur de copie
Loi_Umat::Loi_Umat (const Loi_Umat& loi) :
Loi_comp_abstraite(loi)
,nom_de_la_loi(loi.nom_de_la_loi),umatAbaqus(loi.umatAbaqus)
,loi_ext(loi.loi_ext),utilisation_umat_interne(loi.utilisation_umat_interne)
,umat_met3D(loi.umat_met3D),umat_met2D(loi.umat_met2D),umat_met1D(loi.umat_met1D)
,d_sigma_deps_2D(loi.d_sigma_deps_2D),d_sigma_deps_1D(loi.d_sigma_deps_1D)
,gabBB_tdt(NULL),gabHH_tdt(NULL),gabBB_t(NULL),gabHH_t(NULL)
,gixB_0(),gixB_t(),gixB_tdt(),gixH_0(),gixH_t(),gixH_tdt()
// -- conteneur des métriques: ce sont des pointeurs, pour l'instant on ne les affecte pas
,umat_cont_3D(NULL)
,umat_cont_2D(loi.umat_cont_2D) // umat_cont_2D avec uniquement des pointeurs
,Ip2_B(loi.Ip2_B) // pour définir la base 2D locale dans l'espace travail
// -- les variables pointées dans les conteneurs
,giB_0_3D(loi.giB_0_3D),giH_0_3D(loi.giH_0_3D),giB_t_3D(loi.giB_t_3D),giH_t_3D(loi.giH_t_3D)
,giB_tdt_3D(loi.giB_tdt_3D)
,gijBB_0_3D(loi.gijBB_0_3D),gijHH_0_3D(loi.gijHH_0_3D)
,gijBB_t_3D(loi.gijBB_t_3D),gijHH_t_3D(loi.gijHH_t_3D),gijBB_tdt_3D(loi.gijBB_tdt_3D)
,gijHH_tdt_3D(loi.gijHH_tdt_3D),gradVmoyBB_t_3D(loi.gradVmoyBB_t_3D)
,gradVmoyBB_tdt_3D(loi.gradVmoyBB_tdt_3D),gradVBB_tdt_3D(loi.gradVBB_tdt_3D)
,jacobien_0_3D(loi.jacobien_0_3D)
// idem en 2D
,Ip3B_0_3D(loi.Ip3B_0_3D),Ip3H_0_3D(loi.Ip3H_0_3D) // ne fait pas partie de umat_cont_2D
,giB_0_2D(loi.giB_0_2D),giH_0_2D(loi.giH_0_2D),giB_t_2D(loi.giB_t_2D),giH_t_2D(loi.giH_t_2D)
,giB_tdt_2D(loi.giB_tdt_2D)
,gijBB_0_2D(loi.gijBB_0_2D),gijHH_0_2D(loi.gijHH_0_2D)
,gijBB_t_2D(loi.gijBB_t_2D),gijHH_t_2D(loi.gijHH_t_2D),gijBB_tdt_2D(loi.gijBB_tdt_2D)
,gijHH_tdt_2D(loi.gijHH_tdt_2D),gradVmoyBB_t_2D(loi.gradVmoyBB_t_2D)
,gradVmoyBB_tdt_2D(loi.gradVmoyBB_tdt_2D),gradVBB_tdt_2D(loi.gradVBB_tdt_2D)
,jacobien_0_2D(loi.jacobien_0_2D)
{ gabBB_tdt=NevezTenseurBB(*loi.gabBB_tdt);gabHH_tdt=NevezTenseurHH(*loi.gabHH_tdt);
gabBB_t=NevezTenseurBB(*loi.gabBB_t);gabHH_t=NevezTenseurHH(*loi.gabHH_t);
// association des pointeurs de grandeurs si nécessaire
if (loi.gradVmoyBB_t_3D_P != NULL) {gradVmoyBB_t_3D_P = &gradVmoyBB_t_3D;};
if (loi.gradVmoyBB_tdt_3D_P != NULL) {gradVmoyBB_tdt_3D_P = &gradVmoyBB_tdt_3D;};
if (loi.gradVBB_tdt_3D_P != NULL) {gradVBB_tdt_3D_P = &gradVBB_tdt_3D;};
umat_cont_3D = new Met_abstraite::Umat_cont // constructeur normal
(&giB_0_3D,&giH_0_3D,&giB_t_3D,&giH_t_3D,&giB_tdt_3D,&giH_tdt_3D
,&gijBB_0_3D,&gijHH_0_3D,&gijBB_t_3D,&gijHH_t_3D
,&gijBB_tdt_3D,&gijHH_tdt_3D
,gradVmoyBB_t_3D_P,gradVmoyBB_tdt_3D_P,gradVBB_tdt_3D_P // pas affecté par défaut
,&jacobien_tdt_3D,&jacobien_t_3D,&jacobien_0_3D);
// idem 2D
umat_cont_2D = new Met_abstraite::Umat_cont // constructeur normal
(&giB_0_2D,&giH_0_2D,&giB_t_2D,&giH_t_2D,&giB_tdt_2D,&giH_tdt_2D
,&gijBB_0_2D,&gijHH_0_2D,&gijBB_t_2D,&gijHH_t_2D
,&gijBB_tdt_2D,&gijHH_tdt_2D
,gradVmoyBB_t_2D_P,gradVmoyBB_tdt_2D_P,gradVBB_tdt_2D_P // pas affecté par défaut
,&jacobien_tdt_2D,&jacobien_t_2D,&jacobien_0_2D);
};
Loi_Umat::~Loi_Umat ()
// Destructeur
{ if (gabBB_tdt != NULL) delete gabBB_tdt;
if (gabHH_tdt != NULL) delete gabHH_tdt;
if (gabBB_t != NULL) delete gabBB_t;
if (gabHH_t != NULL) delete gabHH_t;
// les conteneurs de pointeurs:
delete umat_cont_3D;
delete umat_cont_2D;
// pour les grandeurs de base, pas de new, donc pas de delete
};
// def d'une instance de données spécifiques, et initialisation
Loi_comp_abstraite::SaveResul * Loi_Umat::New_et_Initialise()
{ Loi_comp_abstraite::SaveResul* sav = new SaveResul_Loi_Umat();
// dans le cas ou la loi est interne on stocke ses infos égalements
if (utilisation_umat_interne)
{ SaveResul_Loi_Umat* sv = (SaveResul_Loi_Umat*) sav;
sv->save_pour_loi_ext = ((Loi_comp_abstraite*)loi_ext)->New_et_Initialise();
};
return sav;
};
// fonction de travail
int Loi_Umat::Choix_dim(Enum_comp enu)
{if(enu == LOI_VIA_UMAT_CP)
return 2;
else
return 3;
};
// Lecture des donnees de la classe sur fichier
void Loi_Umat::LectureDonneesParticulieres (UtilLecture * entreePrinc,LesCourbes1D&
,LesFonctions_nD& lesFonctionsnD)
{ // lecture du nom de la loi
string toto;
*(entreePrinc->entree) >> toto >> nom_de_la_loi;
if (toto != "nom_de_la_loi=")
{ cout << "\n erreur en lecture du nom de la loi, on aurait du lire le mot cle nom_de_la_loi="
<< " suivi du nom de la loi ";
entreePrinc->MessageBuffer("**erreur1: Loi_Umat::LectureDonneesParticulieres(... **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
// lecture de la catégorie
string categorie;
*(entreePrinc->entree) >> toto >> categorie;
if (toto != "categorie=")
{ cout << "\n erreur en lecture du nom de la loi, on aurait du lire le mot cle categorie="
<< " suivi du nom de la categorie ";
entreePrinc->MessageBuffer("**erreur2: Loi_Umat::LectureDonneesParticulieres(... **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
// on met à jour la catégorie de la loi
Enum_categorie_loi_comp cat = Id_nom_categorie_loi_comp(categorie.c_str());
ChangeCategorie(cat);
if (cat==CAT_THERMO_MECANIQUE) {thermo_dependant=true;}
else {thermo_dependant=false;};
// lecture de la dimension
string dimension;
*(entreePrinc->entree) >> toto >> dimension;
if (toto != "dim_loi=")
{ cout << "\n erreur en lecture du nom de la loi, on aurait du lire le mot cle dim_loi="
<< " suivi de la dimension: 1D ou 2D ou 3D ";
entreePrinc->MessageBuffer("**erreur3: Loi_Umat::LectureDonneesParticulieres(... **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
// on met à jour la dimension de la loi
if ((dimension== "1D") || (dimension=="1")) {Change_dimension(1); }
else if ((dimension == "2D") || (dimension=="2")) {Change_dimension(2); }
else if ((dimension == "3D") || (dimension=="3")) {Change_dimension(3); }
else
{ cout << "\n erreur en lecture de la dimension de la loi geree par umat"
<< " on devrait lire 1 ou 2 ou 3 ou 1D ou 2D ou 3D";
entreePrinc->MessageBuffer("**erreur4: Loi_Umat::LectureDonneesParticulieres(... **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
string nom_class_methode("Loi_Umat::LectureDonneesParticulieres");
// lecture de la ligne qui suit
entreePrinc->NouvelleDonnee();
*(entreePrinc->entree) >> toto;
if (toto != "fin_loi_Umat")
{ if (toto == "nom_pipe_envoi=")
{// lecture du nom du pipe d'envoi
string nom_pipe_envoi; *(entreePrinc->entree) >> nom_pipe_envoi;
umatAbaqus.Change_nom_pipe_envoi(nom_pipe_envoi);
*(entreePrinc->entree) >> toto;
// on regarde si éventuellement il y a le pipe de reception
if(toto == "nom_pipe_reception=")
{ string nom_pipe_reception; *(entreePrinc->entree) >> nom_pipe_reception;
umatAbaqus.Change_nom_pipe_reception(nom_pipe_reception);
}
else
{ cout << "\n erreur en lecture du nom du pipe de reception, on aurait du lire le mot "
<< " cle nom_pipe_reception=, suivi du nom du pipe ";
entreePrinc->MessageBuffer("**erreur5: Loi_Umat::LectureDonneesParticulieres(... **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
entreePrinc->NouvelleDonnee();// préparation du flot
if(strstr(entreePrinc->tablcar,"permet_affichage_")!=0)
{// on lit le niveau de commentaire
string nom; *(entreePrinc->entree) >> nom;
Lecture_permet_affichage(entreePrinc,lesFonctionsnD);
// string mot_cle("permet_affichage_");
// entreePrinc->Lecture_un_parametre_int(0,nom_class_methode
// ,0, 10,mot_cle,permet_affichage);
entreePrinc->NouvelleDonnee();// préparation du flot
};
}
else if (toto == "utilisation_umat_interne")
{// cas d'une umat interne
utilisation_umat_interne=true;
entreePrinc->NouvelleDonnee();// préparation du flot
if(strstr(entreePrinc->tablcar,"permet_affichage_")!=0)
{// on lit le niveau de commentaire
string nom; *(entreePrinc->entree) >> nom;
Lecture_permet_affichage(entreePrinc,lesFonctionsnD);
// string mot_cle("permet_affichage_");
// entreePrinc->Lecture_un_parametre_int(0,nom_class_methode
// ,0, 10,mot_cle,permet_affichage);
entreePrinc->NouvelleDonnee();// préparation du flot
};
if(strstr(entreePrinc->tablcar,"fin_loi_Umat")==0)
{ cout << "\n erreur en lecture de la fin de la loi on devrait avoir le mot cle fin_loi_Umat "
<< " soit le mot cle : permet_affichage_ ";
entreePrinc->MessageBuffer("**erreur6: Loi_Umat::LectureDonneesParticulieres(... **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
}
else
{ cout << "\n erreur en lecture de la fin de la loi on devrait soit avoir le mot cle fin_loi_Umat "
<< " ou alors les noms des pipes d'envoi et de reception (cf doc) ";
entreePrinc->MessageBuffer("**erreur7: Loi_Umat::LectureDonneesParticulieres(... **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie(1);
};
};
// appel au niveau de la classe mère
Loi_comp_abstraite::Lecture_type_deformation_et_niveau_commentaire
(*entreePrinc,lesFonctionsnD);
};
// affichage de la loi
void Loi_Umat::Affiche() const
{ cout << "\n loi de comportement Umat "<<dim<<"D : "<< nom_de_la_loi << " ";
if(thermo_dependant) {cout << " thermodependante ";};
cout << " categorie " << Nom_categorie_loi_comp(categorie_loi_comp) << " ";
Loi_comp_abstraite::Affiche_don_classe_abstraite();
};
// affichage et definition interactive des commandes particulières à chaques lois
void Loi_Umat::Info_commande_LoisDeComp(UtilLecture& entreePrinc)
{ ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
cout << "\n definition standart (rep o) ou exemples exhaustifs (rep n'importe quoi) ? ";
string rep = "_"; // procédure de lecture avec prise en charge d'un retour chariot
rep = lect_return_defaut(true,"o");
sort << "\n# ----------------------------------------------------------"
<< "\n# | exemple de loi de comportement defini en Umat |"
<< "\n# | via un processus qui dialogue avec herezh++ |"
<< "\n# ----------------------------------------------------------"
<< "\n nom_de_la_loi= acier categorie= CAT_MECANIQUE dim_loi= 3 "
<< "\n nom_pipe_envoi= pipe_envoi nom_pipe_reception= pipe_reception "
<< "\n fin_loi_Umat " << endl ;
if ((rep != "o") && (rep != "O" ) && (rep != "0") )
{ sort << "\n ....................................................................................."
<< "\n# NB: en contrainte plane, la loi se nomme LOI_VIA_UMAT_CP et il faut utiliser : dim_loi= 2 "
<< "\n# - le nom de la loi, peut permettre le choix entre plusieurs Umat "
<< "\n# - les differentes categorie sont: "
<< "\n# CAT_MECANIQUE pour une loi utilisable pour un calcul mecanique "
<< "\n# CAT_THERMO_MECANIQUE pour une loi utilisable pour un calcul thermo-mecanique "
<< "\n# CAT_THERMO_PHYSIQUE pour une loi thermo-physique "
<< "\n# - dim_loi peut etre: "
// << "\n# 1D : permet la traction - compression "
<< "\n# 2D : 2D contraintes planes ou deformations planes"
<< "\n# 3D : 3D classique (sans particularite) "
<< "\n# - la ligne suivante est facultative (par contre si elle existe elle doit etre complete)"
<< "\n# nom_pipe_envoi= suivi du nom du pipe d'envoi (par defaut = Umat_reception_Hz "
<< "\n# nom_pipe_reception= suivi du nom du pipe de recepetion (par defaut= Umat_envoi_Hz "
<< "\n# - a la place des nom de pipe il est possible de mettre le mot cle: utilisation_umat_interne "
<< "\n# dans ce cas il n'est pas fait appel au pipe, on travail directement avec une loi interne "
<< "\n# defini dans le fichier .info d'entree d'herezh "
<< "\n# permet_affichage_ <un entier> :"
<< "\n# - mot cle fin_loi_Umat "
<< "\n# - ensuite il est possible de definir le type de deformation a utiliser "
<< "\n# comme pour tous les autres lois "
<< "\n#:....................................................................................."
<< endl;
};
// appel de la classe mère
Loi_comp_abstraite::Info_commande_don_LoisDeComp(entreePrinc);
};
// test si la loi est complete
int Loi_Umat::TestComplet()
{ // appel de la fonction mère
return LoiAbstraiteGeneral::TestComplet();
};
//----- lecture écriture de restart -----
// cas donne le niveau de la récupération
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void Loi_Umat::Lecture_base_info_loi(istream& ent,const int cas,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
,LesFonctions_nD& lesFonctionsnD)
{ string toto,nom;
if (cas == 1)
{ ent >> toto >> thermo_dependant;
};
// cas de la structure UmatAbaqus
umatAbaqus.Lecture_base_info(ent,cas);
// appel de la classe mère
Loi_comp_abstraite::Lecture_don_base_info(ent,cas,lesRef,lesCourbes1D,lesFonctionsnD);
};
// cas donne le niveau de sauvegarde
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Loi_Umat::Ecriture_base_info_loi(ostream& sort,const int cas)
{ if (cas == 1)
{ sort << " " << Nom_comp(this->Id_comport()) << " " << thermo_dependant;
};
// cas de la structure UmatAbaqus
umatAbaqus.Ecriture_base_info(sort,cas);
// appel de la classe mère
Loi_comp_abstraite::Ecriture_don_base_info(sort,cas);
};
// calcul d'un module d'young équivalent à la loi pour un chargement nul
double Loi_Umat::Module_young_equivalent(Enum_dure temps,const Deformation & def,SaveResul * )
{ if (thermo_dependant)
{temperature_tdt = def.DonneeInterpoleeScalaire(TEMP,temps);
temperature_t = def.DonneeInterpoleeScalaire(TEMP,TEMPS_t);
};
// comme on ne connait la loi, on fait un appel standart avec une déformation donnée
// on en déduit le module d'young
// .. définition de jeux de données adoc
umatAbaqus.Init_un();
// *** on impose une déformation de traction et de cisaillement arbitraire ******
double dep=0.001;// une valeur arbitraire
(*(umatAbaqus.eps_meca)).Coor(1,1)=(*(umatAbaqus.delta_eps_meca)).Coor(1,1)=dep;
(*(umatAbaqus.eps_meca)).Coor(1,2)=(*(umatAbaqus.delta_eps_meca)).Coor(1,2)=dep;
(*(umatAbaqus.eps_meca)).Coor(2,1)=(*(umatAbaqus.delta_eps_meca)).Coor(2,1)=dep;
umatAbaqus.temper_t= temperature_t;
umatAbaqus.delta_temper=temperature_tdt-temperature_t;
BaseH giH(3);
double jacobien_0,jacobien =1.;
EnergieMeca energ,energ_t; // variables intermédiaires, ne sert pas vraiment ici
double module_compressibilite=0.; double module_cisaillement=0. ;
// construction de la métrique umat associée:
// ici on considére que la base de référence actuelle est orthonormée
// ainsi: gijBB_tdt -> gabBB = identitée, idem en HH
// pour gijBB_0 et gijHH_0, on utilise la déformation arbitraire proposée
// a faire *******************
// (*gabBB_0) = (*gabBB_t) = IdBB3 - 2. * (*(umatAbaqus.eps_meca));
// (*gabHH_0) = (*gabHH_t) = gabBB_0->Monte2Indices();
// mise à jour du conteneur de la métrique umat
// umat_met3D.Mise_a_jour_grandeur(&gixB_0,&gixH_0,&gixB_t,&gixH_t,&gixB_tdt,&gixH_tdt
// ,IdBB,IdHH,gabBB_t,gabHH_t,gabBB_tdt,gabHH_tdt
// ,ggradVmoyBB_tnull,ggradVmoyBB_tdtnull,ggradVBB_tdtnull
// ,&jacobien,&jacobien_0);
// appel d'un calcul Umat
bool en_base_orthonormee = true; // les tenseurs sont en orthonormee a priori
Calcul_dsigma_deps (en_base_orthonormee, *(umatAbaqus.t_sigma),*(umatAbaqus.delta_eps_meca)
,(*(umatAbaqus.eps_meca)),(*(umatAbaqus.delta_eps_meca)),jacobien_0,jacobien
,*(umatAbaqus.t_sigma),*(umatAbaqus.d_sigma_deps),energ,energ_t
,module_compressibilite,module_cisaillement,umat_met3D.Conteneur_Umat()) ;
// calcul approché du E
// a) calcul du coefficient de compressibilité
Tenseur3HH& sig= *((Tenseur3HH*) umatAbaqus.t_sigma);
Tenseur3BB& eps= *((Tenseur3BB*) umatAbaqus.eps_meca);
double Isig= sig(1,1)+sig(2,2)+sig(3,3);
double Ieps= dep; //eps(1,1)+eps(2,2)+eps(3,3);
double Kc=(Isig)/(Ieps);
// b) calcul du coefficient de cisaillement moyen
double mu= sig(1,2)/dep;
// c) calcul de E approchée
double E=(3*Kc*mu)/(2*Kc+mu);
LibereTenseur();
LibereTenseurQ();
return E;
};
// ========== codage des METHODES VIRTUELLES protegees:================
// calcul des contraintes a t+dt
void Loi_Umat::Calcul_SigmaHH (TenseurHH& ,TenseurBB& ,DdlElement & tab_ddl,
TenseurBB & ,TenseurHH & ,BaseB& ,BaseH& ,TenseurBB& epsBB_,
TenseurBB& ,TenseurBB& ,
TenseurHH & ,Tableau <TenseurBB *>& d_gijBB_,double& ,double& ,
TenseurHH &
,EnergieMeca & ,const EnergieMeca &
,double& ,double&
,const Met_abstraite::Expli_t_tdt& )
{
#ifdef MISE_AU_POINT
if (epsBB_.Dimension() != 3)
{ cout << "\nErreur : la dimension devrait etre 3 !\n";
cout << " Loi_Umat::Calcul_SigmaHH\n";
Sortie(1);
};
if (tab_ddl.NbDdl() != d_gijBB_.Taille())
{ cout << "\nErreur : le nb de ddl est != de la taille de d_gijBB_ !\n";
cout << " Loi_Umat::Calcul_SigmaHH\n";
Sortie(1);
};
#endif
cout << "\n pour l'instant le calcul en explicit n' implantees en Umat interne"
<< "\n Loi_Umat::Calcul_SigmaHH (.... ";
Sortie(1);
};
// calcul des contraintes a t+dt et de ses variations
void Loi_Umat::Calcul_DsigmaHH_tdt (TenseurHH& sigHH_t_,TenseurBB& DepsBB_,DdlElement & tab_ddl
,BaseB& giB_t,TenseurBB & gijBB_t,TenseurHH & gijHH_t
,BaseB& giB_tdt,Tableau <BaseB> & d_giB_tdt,BaseH& giH_tdt,Tableau <BaseH> & d_giH_tdt
,TenseurBB & epsBB_tdt,Tableau <TenseurBB *>& d_epsBB
,TenseurBB & delta_epsBB_,TenseurBB & gijBB_tdt,TenseurHH & gijHH_tdt
,Tableau <TenseurBB *>& d_gijBB_tdt
,Tableau <TenseurHH *>& d_gijHH_tdt,double& jacobien_0,double& jacobien
,Vecteur& d_jacobien_tdt,TenseurHH& sigHH_tdt,Tableau <TenseurHH *>& d_sigHH
,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double& module_cisaillement
,const Met_abstraite::Impli& ex)
{
#ifdef MISE_AU_POINT
if (tab_ddl.NbDdl() != d_gijBB_tdt.Taille())
{ cout << "\nErreur : le nb de ddl est != de la taille de d_gijBB_tdt !\n";
cout << " Loi_Umat::Calcul_DsigmaHH_tdt\n";
Sortie(1);
};
#endif
// en fonction de la dimension on modifie les tenseurs de passage dans l'umat
switch (abs(epsBB_tdt.Dimension()))
{ case 2: // cas de tenseur en 2 dimension
{ const Tenseur2BB & epsBB = *((Tenseur2BB*) &epsBB_tdt); // passage explicite en dim 2
const Tenseur2BB & delta_epsBB = *((Tenseur2BB*) &delta_epsBB_); // passage en dim 2
const Tenseur2BB & DepsBB = *((Tenseur2BB*) &DepsBB_); // passage en dim 2
const Tenseur2HH & gijHH = *((Tenseur2HH*) &gijHH_tdt); // " " " "
Tenseur2HH & sigHH = *((Tenseur2HH*) &sigHH_tdt); // " " " "
Tenseur2HH & sigHH_t = *((Tenseur2HH*) &sigHH_t_); // " " " "
// on définit des tenseurs intermédiaires pour la contrainte et la déformation
Tenseur2BB eps_orthoBB(epsBB),delta_eps_orthoBB(delta_epsBB);
Tenseur2HH sig_orthoHH(sigHH_t);
Tenseur2BB D_orthoBB(DepsBB);
//la loi en dimension 2 doit s'exprimer dans un repère orthonormé de dimension 2
// on va utiliser une méthode particulière de la déformation associé
#ifdef MISE_AU_POINT
// vérif que le pointeur est ok
if (def_en_cours == NULL)
{ cout << "\nErreur : la deformation en cours n'est pas utilisable "
<< " on ne peut pas continuere ! !\n" ;
cout << " Loi_Umat::Calcul_DsigmaHH_tdt\n";
Sortie(1);
};
#endif
// détermination d'une bases particulière orthonormée pour représenter les tenseurs
// on est en contrainte plane ou déformation plane, la géométrie interpolée est de type 2D
// et on considère que la normale suivant laquelle la contrainte ou la déformation 33 est nulle
// est normale à la géométrie 2D, d'où l'utilisation d'une méthode ad hoc de la déformation en cours
// en sortie on a une matrice de passage, qui permet de passer de la base curviligne
// à cette base particulière que l'on va appeler IPa
// Le choix qui est fait est de calculer le passage gH(alpha) -> IP^beta ,
// c-a-d Aa(alpha,beta) = les coordonnées de gH(alpha) dans la base IP^beta,
// ou encore: la ligne alpha de Aa = les coordonnées locales de gH(alpha)
// NB: si on a besoin du passage de gB(alpha) on utilise la matrice
// inverse transposée de Aa
Mat_pleine Aa(2,2); // matrice de passage
bool absolue = false; // on utilise un repère locale ad hoc
def_en_cours->BasePassage(absolue,(*ex.giB_0),(*ex.giH_0),Aa);
// pour le changement de repère: la nouvelle base doit-être tel que
// gp^i = gamma^i_{.j} * g^j et gp_i = beta_i^{.j} g_j
// ici gp^i = Ip^i d'où [gamma] = [Aa]^{-1T} et [beta] = [Aa]^T
Mat_pleine gamma(Aa.Inverse().Transpose());
Mat_pleine beta(Aa.Transpose());
// on passe ensuite les tenseurs dans la base locale orthonormée
eps_orthoBB.ChBase(beta);
delta_eps_orthoBB.ChBase(beta);
D_orthoBB.ChBase(beta);
sig_orthoHH.ChBase(gamma);
sigHH.ChBase(gamma); // normalement ne sert à rien car est un résultat
// maintenant on va calculer l'équivalent local des bases à 0
ex.giB_0->ChangeBase_curviligne(Aa,giB_0_2D,giH_0_2D,Ip3B_0_3D);
// giB_0_2D et giH_0_2D contiennent les coordonnées des gi initiaux dans la nouvelle
// base ortho: mais il s'agit toujours des gi relatifs aux theta i de départ
// Ip3B_0_3D contient les coordonnées de la base ortho 2D + 1D (normal aux 2 premiers)
// , exprimées dans le repère 3D
// on doit avoir Ip3H_0_3D = Ip3B_0_3D mais comme la variance n'est pas la même il faut les
// affecter en passant outre la variance
Ip3H_0_3D.Affectation_trans_variance(Ip3B_0_3D);
// on change de base: pour exprimer les bases précédentes mais maintenant dans le nouveau
// repère Ip3B_0_3D
ex.giB_t->Change_repere(Ip3H_0_3D,giB_t_2D);
ex.giB_tdt->Change_repere(Ip3H_0_3D,giB_tdt_2D);
ex.giH_t->Change_repere(Ip3B_0_3D,giH_t_2D);
ex.giH_tdt->Change_repere(Ip3B_0_3D,giH_tdt_2D);
// donc maintenant umat_cont_2D contient via ses pointeurs les nouvelles bases
#ifdef MISE_AU_POINT
if (Permet_affichage() > 5)
{cout << "\n\n Loi_Umat::Calcul_DsigmaHH_tdt (.. ";
cout << "\n gamma= "; Aa.Affiche();
cout << " base ex.giB_0:" << (*ex.giB_0);
cout << "\n base Ip : "<<Ip3B_0_3D;
cout << "\n base ex.giB_t:" << (*ex.giB_t);
cout << "\n dans Ip:" << giB_t_2D;
cout << "\n base ex.giB_tdt:" << (*ex.giB_tdt);
cout << "\n dans ip:" << giB_tdt_2D;
cout << "\n def epsBB: "<<epsBB;
cout << "\n def eps_orthoBB: "<< eps_orthoBB;
}
#endif
// maintenant on peut construire le reste de la métrique
const Met_abstraite::Umat_cont& umat_cont = umat_met2D.Construction_Umat(*umat_cont_2D);
#ifdef MISE_AU_POINT
if (Permet_affichage() > 5)
{cout << "\n base gip_B_t:" << (*umat_cont.giB_t);
cout << "\n base gip_B_tdt:" << (*umat_cont.giB_tdt);
};
#endif
bool en_base_orthonormee=true; // ici les tenseurs sont en orthonormee a priori
// c'est-à-dire dans un repère orthonormée, la direction 3 correspond à la direction
// pour laquelle sig^33 = 0
// appel de la procedure umat
Calcul_dsigma_deps (en_base_orthonormee, sig_orthoHH,D_orthoBB
,eps_orthoBB,delta_eps_orthoBB,jacobien_0,jacobien
,sigHH,d_sigma_deps_2D,energ,energ_t
,module_compressibilite,module_cisaillement,umat_cont);
#ifdef MISE_AU_POINT
if (Permet_affichage() > 5)
{cout << "\n contrainte sigHH dans Ip_a : "<<sigHH;
cout << "\n d_sigma_deps_2D dans Ip_a :" << d_sigma_deps_2D;
};
#endif
// la contrainte résultat : est tel qu'elle représente les composantes
// du tenseur contrainte dans le repère non orthonormée \hat I'_a
// les composantes de \hat I'_a dans I'_a sont giB_tdt_2D
// on a par définition: \hat I'_al = gamma(be,al) * \hat g_be
// la matrice gamma est utilisée sous forme de sa transposée
// maintenant on veut le tenseur des contraintes dans la base \hat g_be
// donc la relation \hat I'_al = gamma(be,al) * \hat g_be la relation de changement
// de base de l'ancienne base \hat I'_al à la nouvelle voulue \hat g_be
// avec comme matrice de changement: transposée (gamma)
sigHH.ChBase(gamma.Transpose(),true);
#ifdef MISE_AU_POINT
if (Permet_affichage() > 5)
{cout << "\n sigHH dans g_i :" <<sigHH;
};
#endif
// calcul de l'opérateur tangent / ddl
int nbddl = d_gijBB_tdt.Taille();
// ---- première solution --- on travail dans le repère local
int cas_resoudre = 1;
if (cas_resoudre==1)
{// on ramène l'opérateur tangent dans le repère local
Tenseur2HHHH d_sigma_depsHHHH; // init
// en sortie de Calcul_dsigma_deps, d_sigma_deps_2D est relatif à l'opérateur tangent
// dans le repère
// giH_tdt_2D
// ---- rappel du changement de repère pour le 4ième ordre ----
// changement des composantes du tenseur, retour donc dans la même variance
// en argument : A -> une reference sur le tenseur résultat qui a la même dimension
// retour d'une reference sur A
// A = A^{ijkl) g_i rond g_j rond g_k rond g_l = A'^{efgh) gp_i rond gpp_j rond g_k rond gp_l
// g_i = beta_i^j gp_j --> A'^{efgh) = A^{ijkl) beta_i^e beta_j^f beta_k^g beta_l^h
// TenseurHHHH & ChangeBase(TenseurHHHH & A,const BaseB & gi) const;
// pour simplifier on définit un nouveau repère qui va nous servir pour le
// changement de base, ceci à partir de la relation
// \hat I'_al = gamma(be,al) * \hat g_be
// gammaB est construit à partir de la matrice gamma transposée
BaseB gammaB(2,2);
gammaB.CoordoB(1)(1) = gamma(1,1);gammaB.CoordoB(1)(2) = gamma(2,1);
gammaB.CoordoB(2)(1) = gamma(1,2);gammaB.CoordoB(2)(2) = gamma(2,2);
// on change de repère
d_sigma_deps_2D.ChangeBase(d_sigma_depsHHHH,gammaB);
#ifdef MISE_AU_POINT
if (Permet_affichage() > 5)
{cout << "\n d_sigma_deps_2D: dans g_i" << d_sigma_deps_2D;
};
#endif
for (int i = 1; i<= nbddl; i++)
{ Tenseur2HH & dsigHH = *((Tenseur2HH*) (d_sigHH(i))); // passage en dim 2
const Tenseur2BB & depsBB = *((Tenseur2BB *) (d_epsBB(i))); // "
dsigHH = d_sigma_depsHHHH && depsBB;
};
};
// l'autre cas, voir 3D n'est pas d'actualité pour l'instant
break;
}
case 3: // cas en 3 dimension
{ const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_); // passage en dim 3
const Tenseur3BB & DepsBB = *((Tenseur3BB*) &DepsBB_); // passage en dim 3
const Tenseur3HH & gijHH = *((Tenseur3HH*) &gijHH_tdt); // " " " "
Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_tdt); // " " " "
Tenseur3HH & sigHH_t = *((Tenseur3HH*) &sigHH_t_); // " " " "
// on définit des tenseurs intermédiaires pour la contrainte et la déformation
Tenseur3BB epsAA,delta_epsAA; Tenseur3HH sigAA;
// cout << "\n epsBB " << epsBB;
// calcul de la déformation et de l'accroissement dans le repère orthonormee
epsBB.BaseAbsolue(epsAA,giH_tdt);
// cout << "\n epsAA "; (umatAbaqus.eps_meca)->Ecriture(cout);
// int toto; cout << "\n une lettre ? "; cin >> toto;
delta_epsBB.BaseAbsolue(delta_epsAA,giH_tdt);
// calcul de la vitesse de déformation dans le repère orthonormee
Tenseur3BB D_abs_epsBB;
DepsBB.BaseAbsolue(D_abs_epsBB,giH_tdt);
// calcul de la contrainte initiale dans le repère orthonormee
sigHH_t.BaseAbsolue(sigAA,giB_tdt);
#ifdef MISE_AU_POINT
if (Permet_affichage() > 5)
{cout << "\n\n Loi_Umat::Calcul_DsigmaHH_tdt (.. ";
cout << "\n eps en absolu :";epsAA.Ecriture(cout);
cout << "\n Deps en absolu :";D_abs_epsBB.Ecriture(cout);
cout << "\n delta_eps en absolu :";delta_epsAA.Ecriture(cout);
cout << "\n sig_t en absolu :";sigAA.Ecriture(cout);
}
#endif
// construction de la métrique umat associée à la métrique actuelle,
// c'est-à-dire construction de la métrique correspondant aux coordonnées initiales
// considérées comme paramétrage matériel
const Met_abstraite::Umat_cont& umat_cont = umat_met3D.Construction_Umat(ex);
bool en_base_orthonormee=true; // ici les tenseurs sont en orthonormee a priori
// appel de la procedure umat
Calcul_dsigma_deps (en_base_orthonormee, sigAA,D_abs_epsBB
,epsAA,delta_epsAA,jacobien_0,jacobien
,*(umatAbaqus.t_sigma),*(umatAbaqus.d_sigma_deps),energ,energ_t
,module_compressibilite,module_cisaillement,umat_cont);
// passage de la contrainte dans la base locale HH
Tenseur3HH & sigabHH_tdt = *((Tenseur3HH*) (umatAbaqus.t_sigma)); // // passage en dim 3 explicite
sigabHH_tdt.Baselocale(sigHH,*(ex.giH_tdt));
// calcul de l'opérateur tangent / ddl
int nbddl = d_gijBB_tdt.Taille();
Tenseur3HHHH & d_sigma_deps = *((Tenseur3HHHH *) umatAbaqus.d_sigma_deps);
// ---- première solution --- on travail dans le repère local
int cas_resoudre = 1;
if (cas_resoudre==1)
{// on ramène l'opérateur tangent dans le repère local
Tenseur3HHHH d_sigma_depsHHHH;
d_sigma_deps.Baselocale(d_sigma_depsHHHH,*(ex.giH_tdt));
for (int i = 1; i<= nbddl; i++)
{ Tenseur3HH & dsigHH = *((Tenseur3HH*) (d_sigHH(i))); // passage en dim 3
const Tenseur3BB & depsBB = *((Tenseur3BB *) (d_epsBB(i))); // "
dsigHH = d_sigma_depsHHHH && depsBB;
};
}
else // ---- cas on travail dans le repère global ---- (ne fonctionne pas !!)
{
Tenseur3BB depsAA; Tenseur3BB dep1AA,dep2AA;
Tenseur3HH dsigAA; Tenseur3HH dsig1AA;
// on rajoute l'effet de la déformation
// terme sigma.D + D.sigma
d_sigma_deps += 2*Tenseur3HHHH::Prod_tensoriel_barre(sigabHH_tdt,IdHH3);
for (int i = 1; i<= nbddl; i++)
{ Tenseur3HH & dsigHH = *((Tenseur3HH*) (d_sigHH(i))); // passage en dim 3
const Tenseur3BB & d_gijBB = *((Tenseur3BB*)(d_gijBB_tdt(i))); // passage en dim 3
const Tenseur3HH & dgijHH = *((Tenseur3HH*)(d_gijHH_tdt(i))) ; // pour simplifier l'ecriture
const Tenseur3BB & depsBB = *((Tenseur3BB *) (d_epsBB(i))); // "
// tout d'abord variation de la déformation en orthonormee
depsBB.BaseAbsolue(depsAA,*(ex.giH_tdt)); // 1) prise en compte de la variation de depsBB
// 2) puis on tiens compte de la variation des gamma_a^i qui servent au changement de base
// de la base locale à la base orthonormee
depsAA += produit_1_pourLoiUmat(dep1AA,epsBB,(*(ex.d_giH_tdt))(i),*(ex.giH_tdt));
// dérivée de sigma^ab / d_ddl
dsigAA = d_sigma_deps && depsAA;
// dérivée de sigma^ij / d_ddl
dsigAA.Baselocale(dsigHH,*(ex.giH_tdt)); // 1) prise en compte de la variation de dsigAA
// 2) puis prise en compte de la variation des gamma_a^i qui servent au changement de base
// du global au locale (c'est-à-dire l'opération inverse que pour la déformation) mais dans
// les deux cas c'est les gamma_a^i qui servent !
// a priori ces les termes -W.sigma + sigma.W ?????
dsigHH += produit_1_pourLoiUmat(dsig1AA,sigabHH_tdt,(*(ex.d_giH_tdt))(i),*(ex.giH_tdt));
};
};
break;
}
default:
{cout << "\n pour l'instant seules les lois 3D sont implantees en Umat interne"
<< "\n Loi_Umat::Calcul_DsigmaHH_tdt (.... ";
Sortie(1);
}
};
// on libère les tenseurs intermédiaires
LibereTenseur();
LibereTenseurQ();
};
// calcul des contraintes et ses variations par rapport aux déformations a t+dt
// en_base_orthonormee: le tenseur de contrainte en entrée est en orthonormee
// le tenseur de déformation et son incrémentsont également en orthonormees
// si = false: les bases transmises sont utilisées
// ex: contient les éléments de métrique relativement au paramétrage matériel = X_(0)^a
void Loi_Umat::Calcul_dsigma_deps (bool en_base_orthonormee, TenseurHH & sigHH_t_,TenseurBB& DepsBB
,TenseurBB & epsBB_tdt,TenseurBB & delta_epsBB_,double& jacobien_0,double& jacobien
,TenseurHH& sigHH_tdt,TenseurHHHH& d_sigma_deps
,EnergieMeca & energ,const EnergieMeca & energ_t,double& module_compressibilite,double& module_cisaillement
,const Met_abstraite::Umat_cont& ex)
{
// si l'on est dans une utilisation interne de l'umat on appel
// directement la loi interne
if (utilisation_umat_interne)
{ // il faut passer les informations à la loi interne
((Loi_comp_abstraite*)loi_ext)->saveResul = ((SaveResul_Loi_Umat*) saveResul)->save_pour_loi_ext;
RepercuteChangeTemperature(TEMPS_tdt);
((Loi_comp_abstraite*)loi_ext)->Calcul_dsigma_deps (en_base_orthonormee, sigHH_t_,DepsBB,epsBB_tdt
,delta_epsBB_,jacobien_0,jacobien,sigHH_tdt
,d_sigma_deps,energ,energ_t,module_compressibilite,module_cisaillement,ex
);
// on met à jour la variation d'épaisseur constatée
Loi_Umat::SaveResul_Loi_Umat& sav = *((Loi_Umat::SaveResul_Loi_Umat*) &saveResul);
sav.h_tsurh0 = ((Loi_comp_abstraite*)loi_ext)->HsurH0(((Loi_comp_abstraite*)loi_ext)->saveResul);
return;
};
// sinon on dialogue via les pipes d'où le remplissage du conteneur UmatAbaqus
// const Tenseur3BB & epsBB = *((Tenseur3BB*) &epsBB_tdt); // passage en dim 3
// const Tenseur3BB & delta_epsBB = *((Tenseur3BB*) &delta_epsBB_); // passage en dim 3
// Tenseur3HH & sigHH = *((Tenseur3HH*) &sigHH_tdt); // " " " "
// Tenseur3HH & sigHH_t = *((Tenseur3HH*) &sigHH_t_); // " " " "
SaveResul_Loi_Umat & save_resul = *((SaveResul_Loi_Umat*) saveResul);
// .. définition de jeux de données adoc
// si on a des tenseurs à 2 dimensions, on considère que l'on est en CP par défaut
int dim_reel_tens = 3 ; // init par défaut: nb sigii
int nb_reel_tau_ij = 3 ; // idem
if (ex.giB_t->NbVecteur() == 2 )
{dim_reel_tens = 2; nb_reel_tau_ij=1; };
umatAbaqus.Init_un(dim_reel_tens,nb_reel_tau_ij);
// on renseigne la position du pti
// on devrait pouvoir le récupérer de l'appel venant de loi_comp_abstraite
// mais c'est pas simple donc je recalcule
umatAbaqus.coor_pt = def_en_cours->Position_tdt();
// umatAbaqus.Init_un();
// init de la déformation et de l'accroissement
// la dimension des tenseurs passés en paramètre, peut-être 2 ou 3
// non // par contre dans l'umatAbaqus on est toujours en 3D
// on fait donc une affectation trans dimension
bool plusZero = true; // on ajoute des zéros par défaut
// (umatAbaqus.eps_meca)->Affectation_trans_dimension(epsBB_tdt,plusZero);
*(umatAbaqus.eps_meca) = epsBB_tdt;
// (umatAbaqus.delta_eps_meca)->Affectation_trans_dimension(delta_epsBB_,plusZero);
*(umatAbaqus.delta_eps_meca) = delta_epsBB_;
// init de la contrainte initiale
// (umatAbaqus.t_sigma)->Affectation_trans_dimension(sigHH_t_,plusZero);
*(umatAbaqus.t_sigma)=sigHH_t_;
// récup des températures
umatAbaqus.temper_t=temperature_t; // température initiale
umatAbaqus.delta_temper=temperature_tdt-temperature_t; // variation de température
// récup des temps
const VariablesTemps& v_temps = ParaGlob::Variables_de_temps();
umatAbaqus.temps_tdt = v_temps.TempsCourant();
umatAbaqus.delta_t = v_temps.IncreTempsCourant();
umatAbaqus.temps_t = umatAbaqus.temps_tdt-umatAbaqus.delta_t;
// init des énergies
umatAbaqus.energie_elastique=energ_t.EnergieElastique();
umatAbaqus.dissipation_plastique=energ_t.DissipationPlastique();
umatAbaqus.dissipation_visqueuse=energ_t.DissipationVisqueuse();
// init des gradients
// les bases dans l'umatAbaqus ont toujours 3 vecteurs, mais
// ex peut en avoir que 2 : cas CP par exemple
int nb_vecteur = (ex.giB_t)->NbVecteur();
bool pas_Zero_base=false; // on ne veut pas changer le 3ième vecteur
// qui a été initialisé normalement correctement avec umatAbaqus.Init_un();
// umatAbaqus.giB_t.Affectation_partielle(nb_vecteur, *(ex.giB_t),pas_Zero_base);
umatAbaqus.giB_t = *(ex.giB_t);
// umatAbaqus.giB_tdt.Affectation_partielle(nb_vecteur, *(ex.giB_tdt),pas_Zero_base);
umatAbaqus.giB_tdt = *(ex.giB_tdt);
// si on est en tenseur 2D et en dimension 3 il faut définir les normales
if ((ex.giB_t->NbVecteur() == 2 )&& (ParaGlob::Dimension()==3))
{ umatAbaqus.N_t = Util::ProdVec_coorB( (*ex.giB_t)(1), (*ex.giB_t)(2));
umatAbaqus.N_tdt = Util::ProdVec_coorB( (*ex.giB_tdt)(1), (*ex.giB_tdt)(2));
};
// coordonnées du point, longueur caractéristique, les indices
if (umatAbaqus.nb_increment==1)
umatAbaqus.nom_materiau = nom_de_la_loi;
// le nombre d'itération est sytématiquement laissé à 1
// idem pour le nb de plis le np de pt d'integ dans le plis
// la longueur caractéristique est mise à 1. par défaut
// appel des routines Umat
umatAbaqus.EcritureDonneesPourUmat(utilisation_umat_interne,Permet_affichage());
umatAbaqus.LectureResultatUmat(utilisation_umat_interne,Permet_affichage());
// on met à jour la variation d'épaisseur constatée
Loi_Umat::SaveResul_Loi_Umat& sav = *((Loi_Umat::SaveResul_Loi_Umat*) &saveResul);
sav.hsurh0 = umatAbaqus.N_tdt.Norme();
// ------ retour des résultats
// les énergies
energ.ChangeEnergieElastique(umatAbaqus.energie_elastique);
energ.ChangeDissipationPlastique(umatAbaqus.dissipation_plastique);
energ.ChangeDissipationVisqueuse(umatAbaqus.dissipation_visqueuse);
// les contraintes
// les contraintes de l'umatAbaqus sont toujours en 3D,
// par contre l'utilisation interne peut-être en 2D: par exemple en CP
// sigHH_tdt.Affectation_trans_dimension(*(umatAbaqus.t_sigma),plusZero);
sigHH_tdt = *(umatAbaqus.t_sigma);
// l'opérateur tangent
// d_sigma_deps.Affectation_trans_dimension(*(umatAbaqus.d_sigma_deps),plusZero);
d_sigma_deps=*(umatAbaqus.d_sigma_deps);
// il faut maintenant calculer les modules de compressibilité et de cisaillement
Calcul_compressibilite_cisaillement(ex,module_compressibilite,module_cisaillement);
// on libère les tenseurs intermédiaires
LibereTenseur();
LibereTenseurQ();
};
// fonction interne utilisée par les classes dérivées de Loi_comp_abstraite
// pour répercuter les modifications de la température
// ici utiliser pour modifier la température des lois élémentaires
// l'Enum_dure: indique quel est la température courante : 0 t ou tdt
void Loi_Umat::RepercuteChangeTemperature(Enum_dure temps)
{ // la répercution n'est licite que s'il y a une loi interne
if (loi_ext != NULL)
{// pour l'instant on se place dans le cas d'une Loi_comp_abstraite
Loi_comp_abstraite * lois_interne = (Loi_comp_abstraite*) loi_ext;
lois_interne->temperature_0 = this->temperature_0;
lois_interne->temperature_t = this->temperature_t;
lois_interne->temperature_tdt = this->temperature_tdt;
lois_interne->dilatation=dilatation;
lois_interne->RepercuteChangeTemperature(temps);
// on répercute également les déformations thermiques, qui ne sont utilisées
// telles quelles que pour certaines lois: ex: loi hyper-élastique
if (dilatation)
{// a- dimensionnement des tenseurs intermédiaires
int dim_tens = epsBB_therm->Dimension();
// -- cas de la déformation
if (lois_interne->epsBB_therm == NULL) { lois_interne->epsBB_therm = NevezTenseurBB(dim_tens);}
else if (lois_interne->epsBB_therm->Dimension() != dim_tens)
{ delete lois_interne->epsBB_therm;lois_interne->epsBB_therm = NevezTenseurBB(dim_tens);};
// -- cas de la vitesse de déformation
if (lois_interne->DepsBB_therm == NULL) { lois_interne->DepsBB_therm = NevezTenseurBB(dim_tens);}
else if (lois_interne->DepsBB_therm->Dimension() != dim_tens)
{ delete lois_interne->DepsBB_therm;lois_interne->DepsBB_totale = NevezTenseurBB(dim_tens);};
// b- affectation des tenseurs
(*lois_interne->epsBB_therm)=(*epsBB_therm);
(*lois_interne->DepsBB_therm)=(*DepsBB_therm);
};
switch (temps)
{ case TEMPS_0:
{lois_interne->temperature = &lois_interne->temperature_0;
break;
}
case TEMPS_t:
{lois_interne->temperature = &lois_interne->temperature_t;
break;
}
case TEMPS_tdt:
{lois_interne->temperature = &lois_interne->temperature_tdt;
break;
}
default:
{ cout << "\n erreur, cas de temps non prevu !! "
<< "\n LoiContraintesPlanes::RepercuteChangeTemperature(...";
Sortie(1);
};
};
};
};
// passage des grandeurs métriques de l'ordre 2 à 3
void Loi_Umat::Passage_metrique_ordre2_vers_3(const Met_abstraite::Umat_cont& ex)
{// on s'occupe du redimensionnement éventuel
// la partie dépendant des vitesses: entre accolades pour pouvoir fermer
{if (ex.gradVmoyBB_t != NULL) {umat_cont_3D->gradVmoyBB_t= gradVmoyBB_t_3D_P = &gradVmoyBB_t_3D;};
if (ex.gradVmoyBB_tdt != NULL) {umat_cont_3D->gradVmoyBB_tdt=gradVmoyBB_tdt_3D_P = &gradVmoyBB_tdt_3D;};
if (ex.gradVBB_tdt != NULL) {umat_cont_3D->gradVBB_tdt=gradVBB_tdt_3D_P = &gradVBB_tdt_3D;};
}; // fin de la partie dédiée à la vitesse
// on commence par recopier les grandeurs de l'ordre 2 à 3
bool plusZero = true; // on complète avec des 0 dans un premier temps
int type_recopie=0; // = 0 -> on transfert les grandeurs à 0, t et tdt
umat_cont_3D->Passage_de_Ordre2_vers_Ordre3(ex,plusZero,type_recopie);
// maintenant on s'occupe de mettre à jour les grandeurs manquantes
// - les bases naturelles: le vecteur normal est normé et est identique pour les bases naturelles et duales
giB_0_3D.CoordoB(3) = (Util::ProdVec_coorB(giB_0_3D(1),giB_0_3D(2))).Normer();
giH_0_3D.CoordoH(3) = giB_0_3D(3).Bas_haut();
giB_t_3D.CoordoB(3) = (Util::ProdVec_coorB(giB_t_3D(1),giB_t_3D(2))).Normer();
giH_t_3D.CoordoH(3) = giB_t_3D(3).Bas_haut();
// cas particulier du vecteur tdt
giB_tdt_3D.CoordoB(3) = (Util::ProdVec_coorB(giB_tdt_3D(1),giB_tdt_3D(2))); // calcul du vecteur normal non normé
double norme_N_tdt = giB_tdt_3D(3).Norme(); // calcul de la norme qui nous servira pour les variations
giB_tdt_3D.CoordoB(3) /= norme_N_tdt;
giH_tdt_3D.CoordoH(3) = giB_tdt_3D(3).Bas_haut();
// - les tenseurs métriques: au début 1 pour la direction 3
gijBB_0_3D.Coor(3,3)=gijHH_0_3D.Coor(3,3)=gijBB_t_3D.Coor(3,3)=gijHH_t_3D.Coor(3,3)=gijBB_tdt_3D.Coor(3,3)=gijHH_tdt_3D.Coor(3,3)=1.;
};
// calcul des modules de compressibilité et de cisaillement
// en fonction des résultats de l'umat
void Loi_Umat::Calcul_compressibilite_cisaillement(const Met_abstraite::Umat_cont& ex
,double & module_compressibilite,double & module_cisaillement)
{
switch (umatAbaqus.t_sigma->Dimension())
{case 3:
{Tenseur3HB sigHB = (*umatAbaqus.t_sigma) * (*ex.gijBB_tdt);
// cas du module de compressibilité
double trace_sig_sur_trois = 1./3. * sigHB.Trace();
double log_V = log((*ex.jacobien_tdt));
module_compressibilite = trace_sig_sur_trois / log_V;
// cas du module de cisaillement
double Qsig = sigHB.II();
Tenseur3HB epsHB = (*ex.gijHH_tdt) * (*umatAbaqus.eps_meca) ;
double deux_Qeps = 2.*epsHB.II();
module_cisaillement = Qsig / deux_Qeps;
break;
}
case 2: // en CP
{if ((umatAbaqus.dim_tens == 2) && (umatAbaqus.nb_tau_ij == 1))
{Tenseur2HB sigHB = (*umatAbaqus.t_sigma) * (*ex.gijBB_tdt);
// cas du module de compressibilité
// la contrainte 33 = 0
double trace_sig_sur_trois = 1./3. * sigHB.Trace();
// on démarre d'une base ortho donc le jacobien initial par principe = 1
double V = Dabs((*ex.jacobien_tdt)); // cas de la surface
// il faut maintenant introduire la surface
// la normale en 3 = 1 initialement
double var_3 = umatAbaqus.N_tdt.Norme();
V *= var_3;
double log_V = log(V);
// pour éviter une division de 0/0 on régularise
module_compressibilite = Dabs(trace_sig_sur_trois / (log_V+DSigne(log_V)*ConstMath::petit));
// cas du module de cisaillement
double Qsig = sigHB.II();
// il faut que l'on reconstruise un tenseur 3D avec la déformation d'épaisseur
Tenseur3HB epsHB; double eps_33=0;double delta_eps_33 = 0.;
double var_3_t = umatAbaqus.N_t.Norme();
epsHB.Affectation_trans_dimension((*ex.gijHH_tdt) * (*umatAbaqus.eps_meca),true);
// N_tdt = la nouvelle normale, compte tenu de la variation d'épaisseur
// et on part de N_0 qui est normé, d'où on considère que ||N_tdt|| = h/h0
switch (type_de_deformation)
{case DEFORMATION_STANDART : case DEFORMATION_POUTRE_PLAQUE_STANDART :
// cas d'une déformation d'Almansi
{ // epsBB33 = 1/2 * (1. - (h0/h)^2), en orthonormee
// dans le repère local: epsBB33 = 1/2 * (h^2 - 1.), or h0=1. donc : epsBB33 = 1/2 * ((h/h0)^2 - 1.)
eps_33 = 0.5 * (var_3 * var_3 - 1.);
delta_eps_33 = 0.5 * (var_3 * var_3 - var_3_t * var_3_t);
};
break;
case DEFORMATION_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEFORMATION_CUMU_LOGARITHMIQUE :
// cas d'une def logarithmique ou une approximation
{ eps_33 = log(var_3);
delta_eps_33 = log(var_3) - log(var_3_t);
};
break;
default :
cout << "\nErreur : type de deformation qui n'est pas actuellement pris en compte, type= "
<< Nom_type_deformation(type_de_deformation);
cout << "\n Loi_Umat::Calcul_compressibilite_cisaillement(.. \n";
Sortie(1);
};
// le vecteur normal est normal à g_i à tous les temps (on considère que l'on reste dans le plan principal
// du coup g^{33} = h0^2/h^2 ce qui permet de calculer eps^3_3
epsHB.Coor(3,3)=eps_33 /(var_3*var_3);
double deux_Qeps = 2.*epsHB.II();
// pour éviter une division de 0/0 on régularise
module_cisaillement = Qsig / (deux_Qeps+ConstMath::petit);;
}
else
{ cout << "\n ** erreur, ce cas n'est pas encore pris en compte: "
<< " tenseur d'ordre 2 et situation non en contrainte plane !";
cout << "\n Loi_Umat::Calcul_compressibilite_cisaillement(.. \n";
Sortie(1);
};
break;
}
default:
cout << "\n ** erreur, ce cas n'est pas encore pris en compte: ";
cout << "\n Loi_Umat::Calcul_compressibilite_cisaillement(.. \n";
Sortie(1);
break;
};
#ifdef MISE_AU_POINT
if (Permet_affichage() > 4)
{cout << "\n module_compressibilite= " << module_compressibilite;
cout << "\n module_cisaillement= " << module_cisaillement;
};
#endif
};