// 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) . // // 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 . // // For more information, please consult: . //#include "Debug.h" # include using namespace std; //introduces namespace std #include #include #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 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 (ifstream& 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 (ofstream& 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 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 "< :" << "\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(ifstream& 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(ofstream& 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 & 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 & d_giB_tdt,BaseH& giH_tdt,Tableau & d_giH_tdt ,TenseurBB & epsBB_tdt,Tableau & d_epsBB ,TenseurBB & delta_epsBB_,TenseurBB & gijBB_tdt,TenseurHH & gijHH_tdt ,Tableau & d_gijBB_tdt ,Tableau & d_gijHH_tdt,double& jacobien_0,double& jacobien ,Vecteur& d_jacobien_tdt,TenseurHH& sigHH_tdt,Tableau & 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 : "< 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 : "< 5) {cout << "\n sigHH dans g_i :" < 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 };