// FICHIER : QuadraMemb.cc // CLASSE : QuadraMemb // 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 using namespace std; //introduces namespace std #include #include #include "Sortie.h" #include "QuadraMemb.h" #include "TypeConsTens.h" #include "FrontPointF.h" #include "TypeQuelconqueParticulier.h" // -------------- definition de la classe conteneur de donnees communes ------------ QuadraMemb::DonnComQuad::DonnComQuad (GeomQuadrangle& quad,DdlElement& tab,DdlElement& tabErr,DdlElement& tab_Err1Sig, Met_abstraite& met_gene,Tableau & resEr,Mat_pleine& raidEr, GeomQuadrangle& quadEr,GeomQuadrangle& quadS,GeomSeg& segmS,Vecteur& residu_int,Mat_pleine& raideur_int, Tableau & residus_extN,Tableau & raideurs_extN, Tableau & residus_extA,Tableau & raideurs_extA, Tableau & residus_extS,Tableau & raideurs_extS, Mat_pleine& mat_masse,GeomQuadrangle& quadMas,int nbi,GeomQuadrangle* quadHourg, Mat_pleine* quadmatD,Vecteur* quadresD ) : quadra(quad),tab_ddl(tab),tab_ddlErr(tabErr),tab_Err1Sig11(tab_Err1Sig),met_quadraMemb(met_gene) ,matGeom(tab.NbDdl(),tab.NbDdl()),matInit(tab.NbDdl(),tab.NbDdl()) ,d_epsBB(tab.NbDdl()),d_sigHH(tab.NbDdl()),d2_epsBB(nbi) ,resErr(resEr),raidErr(raidEr),quadraEr(quadEr) ,quadraS(quadS),segS(segmS) ,residu_interne(residu_int),raideur_interne(raideur_int) ,residus_externeN(residus_extN),raideurs_externeN(raideurs_extN) ,residus_externeA(residus_extA),raideurs_externeA(raideurs_extA) ,residus_externeS(residus_extS),raideurs_externeS(raideurs_extS) ,matrice_masse(mat_masse),quadraMas(quadMas),quadraHourg(quadHourg) ,quadramatD(quadmatD),quadraresD(quadresD) { int nbddl = tab.NbDdl(); for (int ni=1;ni<=nbi;ni++) {d2_epsBB(ni).Change_taille(nbddl); for (int i1=1; i1<= nbddl; i1++) for (int i2=1; i2<= nbddl; i2++) d2_epsBB(ni)(i1,i2) = NevezTenseurBB (2); }; int tailledeps = d_epsBB.Taille(); for (int i=1;i<= tailledeps; i++) d_epsBB(i) = NevezTenseurBB (2); int tailledsig = d_sigHH.Taille(); for (int j=1;j<= tailledsig; j++) d_sigHH(j) = NevezTenseurHH (2); }; // Il ne doit exister qu'un exemplaire de la classe, donc au niveau du constructeur de copie les tableaux // de pointeurs pointes sur les mêmes entités que la valeur passée en paramètre QuadraMemb::DonnComQuad::DonnComQuad(DonnComQuad& a) : quadra(a.quadra),tab_ddl(a.tab_ddl),tab_ddlErr(a.tab_ddlErr),tab_Err1Sig11(a.tab_Err1Sig11) ,met_quadraMemb(a.met_quadraMemb),matGeom(a.matGeom),matInit(a.matInit),d2_epsBB(a.d2_epsBB) ,resErr(a.resErr),raidErr(a.raidErr),quadraEr(a.quadraEr),quadraS(a.quadraS),segS(a.segS) ,d_epsBB(a.d_epsBB),d_sigHH(a.d_sigHH) ,residu_interne(a.residu_interne),raideur_interne(a.raideur_interne) ,residus_externeN(a.residus_externeN),raideurs_externeN(a.raideurs_externeN) ,residus_externeA(a.residus_externeA),raideurs_externeA(a.raideurs_externeA) ,residus_externeS(a.residus_externeS),raideurs_externeS(a.raideurs_externeS) ,matrice_masse(a.matrice_masse),quadraMas(a.quadraMas),quadraHourg(a.quadraHourg) ,quadramatD(a.quadramatD),quadraresD(a.quadraresD) { int nbddl = d_sigHH.Taille(); int nbi=d2_epsBB.Taille(); for (int ni=1;ni<=nbi;ni++) for (int i1=1; i1<= nbddl; i1++) for (int i2=1; i2<= nbddl; i2++) d2_epsBB(ni)(i1,i2) = NevezTenseurBB (*(a.d2_epsBB(ni)(i1,i2))); int tailledeps = d_epsBB.Taille(); for (int i=1;i<= tailledeps; i++) d_epsBB(i) = NevezTenseurBB (*(a.d_epsBB(i))); int tailledsig = d_sigHH.Taille(); for (int j=1;j<= tailledsig; j++) d_sigHH(j) = NevezTenseurHH (*(d_sigHH(j))); }; QuadraMemb::DonnComQuad::~DonnComQuad() { int nbddl = tab_ddl.NbDdl(); int nbi=d2_epsBB.Taille(); for (int ni=1;ni<=nbi;ni++) for (int i1=1; i1<= nbddl; i1++) for (int i2=1; i2<= nbddl; i2++) delete d2_epsBB(ni)(i1,i2); int tailledeps = d_epsBB.Taille(); for (int i=1;i<= tailledeps; i++) delete d_epsBB(i); int tailledsig = d_sigHH.Taille(); for (int j=1;j<= tailledsig; j++) delete d_sigHH(j); }; // ---------- fin definition de la classe conteneur de donnees communes ------------ // -+-+ definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+ QuadraMemb::UneFois::UneFois () : // constructeur par défaut doCoMemb(NULL),CalResPrem_t(0),CalResPrem_tdt(0),CalimpPrem(0),dualSortQuad(0) ,CalSMlin_t(0),CalSMlin_tdt(0),CalSMRlin(0) ,CalSMsurf_t(0),CalSMsurf_tdt(0),CalSMRsurf(0) ,CalSMvol_t(0),CalSMvol_tdt(0),CalSMvol(0) ,CalDynamique(0),CalPt_0_t_tdt(0) ,nbelem_in_Prog(0) {}; QuadraMemb::UneFois::~UneFois () { delete doCoMemb; }; // -+-+ fin definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+ // CONSTRUCTEURS : // Constructeur par defaut QuadraMemb::QuadraMemb () : ElemMeca(),lesPtMecaInt(),donnee_specif(),unefois(NULL),nombre(NULL) { lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca }; // Constructeur fonction d'un numero // d'identification , d'identificateur d'interpolation et de geometrie QuadraMemb::QuadraMemb (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt,string info) : ElemMeca(num_mail,num_id,id_interp_elt,id_geom_elt,info),lesPtMecaInt(),donnee_specif() ,unefois(NULL),nombre(NULL) { lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca }; // Constructeur fonction d'un numero de maillage et d'identification, // du tableau de connexite des noeuds, d'identificateur d'interpolation et de geometrie QuadraMemb::QuadraMemb (int num_mail,int num_id,Enum_interpol id_interp_elt,Enum_geom id_geom_elt, const Tableau& tab,string info) : ElemMeca(num_mail,num_id,tab,id_interp_elt,id_geom_elt,info),lesPtMecaInt(),donnee_specif() ,unefois(NULL),nombre(NULL) { lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca }; // Constructeur de copie QuadraMemb::QuadraMemb (const QuadraMemb& QuadraM) : ElemMeca (QuadraM) ,lesPtMecaInt(QuadraM.lesPtMecaInt) ,donnee_specif(QuadraM.donnee_specif),unefois(QuadraM.unefois),nombre(QuadraM.nombre) { lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca // --- cas des différentes puissances et ... --- QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture residu = &(CoQuadra->residu_interne); // residu local raideur = &(CoQuadra->raideur_interne); // raideur locale // --- cas de la dynamique ----- mat_masse = &(CoQuadra->matrice_masse); // --- cas des efforts externes concernant noeuds ------ res_extN = &(CoQuadra->residus_externeN); // pour les résidus et second membres raid_extN= &(CoQuadra->raideurs_externeN);// pour les raideurs // --- cas des efforts externes concernant les aretes ------ res_extA = &(CoQuadra->residus_externeA); // pour les résidus et second membres raid_extA= &(CoQuadra->raideurs_externeA);// pour les raideurs // --- cas des efforts externes concernant les faces ------ res_extS= &(CoQuadra->residus_externeS); // pour les résidus et second membres raid_extS= &(CoQuadra->raideurs_externeS); // pour les raideurs }; // DESTRUCTEUR : QuadraMemb::~QuadraMemb () { /* // on va libérer les déformations d'arrête et de surface qui sont un peu particulières if (defArete.Taille() != 0) if (defArete(1) != NULL) { delete defArete(1); // on remet à null les pointeurs pour un appel correcte du destructeur d'elemMeca for (int ia=1;ia<= 4; ia++) defArete(ia) = NULL; } if (defSurf.Taille() != 0) if (defSurf(1) != NULL) { delete defSurf(1); defSurf(1) = NULL; } */ LibereTenseur(); }; // Lecture des donnees de la classe sur fichier void QuadraMemb::LectureDonneesParticulieres (UtilLecture * entreePrinc,Tableau * tabMaillageNoeud) { int nb; int nbne = nombre-> nbne; tab_noeud.Change_taille(nbne); for (int i=1; i<= nbne; i++) { *(entreePrinc->entree) >> nb; if ((entreePrinc->entree)->rdstate() == 0) // pour mémoire ici on a /* enum io_state { badbit = 1<<0, // -> 1 dans rdstate() eofbit = 1<<1, // -> 2 failbit = 1<<2, // -> 4 goodbit = 0 // -> O };*/ tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale #ifdef ENLINUX else if ((entreePrinc->entree)->fail()) // on a atteind la fin de la ligne et on appelle un nouvel enregistrement { entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement *(entreePrinc->entree) >> nb; tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale } #else /* #ifdef SYSTEM_MAC_OS_X_unix else if ((entreePrinc->entree)->fail()) // on a atteind la fin de la ligne et on appelle un nouvel enregistrement { entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement *(entreePrinc->entree) >> nb; tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture normale } #else */ else if ((entreePrinc->entree)->eof()) // la lecture est bonne mais on a atteind la fin de la ligne { tab_noeud(i) = (*tabMaillageNoeud)(nb); // lecture // si ce n'est pas la fin de la lecture on appelle un nouvel enregistrement if (i != nbne) entreePrinc->NouvelleDonnee(); // lecture d'un nouvelle enregistrement } // #endif #endif else // cas d'une erreur de lecture { cout << "\n erreur de lecture inconnue "; entreePrinc->MessageBuffer("** lecture des données particulières **"); cout << "QuadraMemb::LecDonPart"; Affiche(); Sortie (1); } } // construction du tableau de ddl des noeuds de QuadraMemb ConstTabDdl(); }; // calcul d'un point dans l'élément réel en fonction des coordonnées dans l'élément de référence associé // temps: indique si l'on veut les coordonnées à t = 0, ou t ou tdt // 1) cas où l'on utilise la place passée en argument Coordonnee & QuadraMemb::Point_physique(const Coordonnee& c_int,Coordonnee & co,Enum_dure temps) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // a) on commence par définir les bonnes grandeurs dans la métrique if( !(unefois->CalPt_0_t_tdt )) { unefois->CalPt_0_t_tdt += 1; Tableau tab(3); tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; // b) calcul de l'interpolation const Vecteur& phi = CoQuadra->quadra.Phi_point(c_int); // c) calcul du point switch (temps) { case TEMPS_0 : co = met->PointM_0(tab_noeud,phi); break; case TEMPS_t : co = met->PointM_t(tab_noeud,phi); break; case TEMPS_tdt : co = met->PointM_tdt(tab_noeud,phi); break; } // d) retour return co; }; // 3) cas où l'on veut les coordonnées aux 1, 2 ou trois temps selon la taille du tableau t_co void QuadraMemb::Point_physique(const Coordonnee& c_int,Tableau & t_co) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // a) on commence par définir les bonnes grandeurs dans la métrique if( !(unefois->CalPt_0_t_tdt )) { unefois->CalPt_0_t_tdt += 1; Tableau tab(3); tab(1)=iM0;tab(2)=iMt;tab(3)=iMtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; // b) calcul de l'interpolation const Vecteur& phi = CoQuadra->quadra.Phi_point(c_int); // c) calcul des point switch (t_co.Taille()) { case 3 : t_co(3) = met->PointM_tdt(tab_noeud,phi); case 2 : t_co(2) = met->PointM_t(tab_noeud,phi); case 1 : t_co(1) = met->PointM_0(tab_noeud,phi); } }; // Calcul du residu local à t ou tdt en fonction du booleen atdt Vecteur* QuadraMemb::CalculResidu (bool atdt,const ParaAlgoControle & pa) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture Tableau & d_epsBB = (CoQuadra->d_epsBB);// " // dimensionnement de la metrique if (!atdt) {if( !(unefois->CalResPrem_t )) { unefois->CalResPrem_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; // dans ce premier passage on vérifie l'orientation de l'élément }; } else {if( !(unefois->CalResPrem_tdt )) {unefois->CalResPrem_tdt += 1; Tableau tab(11); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ; tab(10) = igradVBB_tdt;tab(11) = iVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; }; // dimensionnement du residu int nbddl = CoQuadra->tab_ddl.NbDdl(); if ( residu == NULL) residu = new Vecteur(nbddl); // cas du premier passage else for (int i =1; i<= nbddl; i++) // cas des autres passages (*residu)(i) = 0.; // on initialise a zero ElemMeca::Cal_explicit( CoQuadra->tab_ddl,d_epsBB, nombre->nbi,(CoQuadra->quadra).TaWi(),pa,atdt); // maintenant la nouvelle épaisseur est utilisée directement dans ElemMeca::Cal_explicit // et y est également calculée // 19 nov: en fait il ne faut pas prendre en compte l'épaisseur méca: cf. doc théorique // faux: --- modif 15 nov 2017 --- // prise en compte de l'epaisseur : variation ou non en fonction du fait que l'on soit en def ou contrainte plane // on regarde le type de variation d'épaisseur que l'on veut // et que l'on n'a pas une loi rien if (donnee_specif.use_epais_moyenne && (!Loi_rien(loiComp->Id_comport()))) {double epaisseur_moyenne = 0.; switch (loiComp->Comportement_3D_CP_DP_1D()) { case COMP_CONTRAINTES_PLANES : // en contrainte plane on recalcule l'épaisseur {const bool atdt=true;bool erreur = false; epaisseur_moyenne = CalEpaisseurMoyenne_et_transfert_pti(atdt,erreur); // --- debug // #ifdef MISE_AU_POINT // if (erreur ) // { cout << "\n *** debug erreur*** on a trouve une epaisseur moyenne negative = " << epaisseur_moyenne // << "\n QuadraMemb::CalculResidu (.... \n"; // CalEpaisseurMoyenne_et_transfert_pti(atdt,erreur); // ElemMeca::Cal_explicit( CoQuadra->tab_ddl,d_epsBB, // nombre->nbi,(CoQuadra->quadra).TaWi(),pa,atdt); // Sortie(1); // }; // //--- fin debug --- // #endif ////---debug // #ifdef MISE_AU_POINT // if (ParaGlob::NiveauImpression() > 2) // if ( (std::isinf(epaisseur_moyenne)) // || ( std::isnan(epaisseur_moyenne)) ) // { cout << "\n debug ********** attention on a trouve une epaisseur infini ou nan !! = " // <nbi;i++) (*lesPtIntegMecaInterne)(i).Volume_pti() *= epaisseur_moyenne; break; } default : cout << "\nErreur : cas de loi de comportement : " << Nom_comp((loiComp->Id_comport())) << " non prevu pour le calcul le l'epaisseur avec l'element quadrangulaire "; cout << "\n QuadraMemb::CalculResidu (.... \n"; Sortie(1); }; (*residu) *= epaisseur_moyenne; energie_totale *= epaisseur_moyenne; E_Hourglass *= epaisseur_moyenne; // meme si l'énergie d'hourglass est nulle E_elem_bulk_tdt*= epaisseur_moyenne; // idem P_elem_bulk *= epaisseur_moyenne; // idem volume *= epaisseur_moyenne; }; return residu; }; // Calcul du residu local et de la raideur locale, // pour le schema implicite Element::ResRaid QuadraMemb::Calcul_implicit (const ParaAlgoControle & pa) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture Tableau & d_epsBB = (CoQuadra->d_epsBB);// " Tableau & d_sigHH = (CoQuadra->d_sigHH);// " bool cald_Dvirtuelle = false; if (unefois->CalimpPrem == 0) { unefois->CalimpPrem = 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; // on ne calcul la dérivée de la déformation virtuelle qu'une fois // car elle est constante dans le temps et indépendante des coordonnées cald_Dvirtuelle=true; }; // dimensionnement du residu int nbddl = CoQuadra->tab_ddl.NbDdl(); if ( residu == NULL) residu = new Vecteur(nbddl); // cas du premier passage else for (int i =1; i<= nbddl; i++) // cas des autres passages (*residu)(i) = 0.; // on initialise a zero // dimensionnement de la raideur if ( raideur == NULL) raideur = new Mat_pleine(nbddl,nbddl); // cas du premier passage else for (int i =1; i<= nbddl; i++) // cas des autres passages for (int j=1; j<= nbddl; j++) // (*raideur)(i,j) = 0.; // on initialise a zero ElemMeca::Cal_implicit (CoQuadra->tab_ddl,d_epsBB,(CoQuadra->d2_epsBB),d_sigHH, nombre->nbi,(CoQuadra->quadra).TaWi(),pa,cald_Dvirtuelle); // maintenant la nouvelle épaisseur est utilisée directement dans ElemMeca::Cal_explicit // et y est également calculée // 19 nov: en fait il ne faut pas prendre en compte l'épaisseur méca: cf. doc théorique // faux --- modif 15 nov 2017 --- // prise en compte de l'epaisseur : variation ou non en fonction du fait que l'on soit en def ou contrainte plane // on regarde le type de variation d'épaisseur que l'on veut // et que l'on n'a pas une loi rien if (donnee_specif.use_epais_moyenne && (!Loi_rien(loiComp->Id_comport()))) {double epaisseur_moyenne = 0.; switch (loiComp->Comportement_3D_CP_DP_1D()) { case COMP_CONTRAINTES_PLANES : // en contrainte plane on recalcule l'épaisseur {const bool atdt=true;bool erreur = false; epaisseur_moyenne = CalEpaisseurMoyenne_et_transfert_pti(atdt,erreur); break; } case COMP_DEFORMATIONS_PLANES : // en deformation plane, l'épaisseur ne change pas { epaisseur_moyenne = H_moy(TEMPS_0); //donnee_specif.epais.epaisseur0; for (int i=1;i<= nombre->nbi;i++) (*lesPtIntegMecaInterne)(i).Volume_pti() *= epaisseur_moyenne; break; } default : cout << "\nErreur : cas de loi de comportement : " << Nom_comp((loiComp->Id_comport())) << " non prevu pour le calcul le l'epaisseur avec l'element quadrangulaire "; cout << "\n QuadraMemb::Calcul_implicit (.... \n"; Sortie(1); }; (*residu) *= epaisseur_moyenne; //debug //residu->Affiche(); //fin debug (*raideur) *= epaisseur_moyenne; energie_totale *= epaisseur_moyenne; E_Hourglass *= epaisseur_moyenne; // meme si l'énergie d'hourglass est nulle E_elem_bulk_tdt*= epaisseur_moyenne; // idem P_elem_bulk *= epaisseur_moyenne; // idem volume *= epaisseur_moyenne; }; Element::ResRaid el; el.res = residu; el.raid = raideur; return el; }; // Calcul de la matrice masse pour l'élément Mat_pleine * QuadraMemb::CalculMatriceMasse (Enum_calcul_masse type_calcul_masse) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionement de la métrique si nécessaire if (!(unefois->CalDynamique )) { unefois->CalDynamique += 1; Tableau tab(5); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0; tab(4) = igijBB_tdt; tab(5) = igradVmoyBB_t; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; // on vérifie le bon dimensionnement de la matrice if (type_calcul_masse == MASSE_CONSISTANTE) // dans le cas où la masse est consistante il faut la redimensionner { int nbddl = CoQuadra->tab_ddl.NbDdl(); (CoQuadra->matrice_masse).Initialise (nbddl,nbddl,0.); } }; // appel de la routine générale ElemMeca::Cal_Mat_masse (CoQuadra->tab_ddl,type_calcul_masse, nombre->nbiMas,(CoQuadra->quadraMas).TaPhi(),nombre->nbne ,(CoQuadra->quadraMas).TaWi()); // on regarde le type de variation d'épaisseur que l'on veut if (donnee_specif.use_epais_moyenne) (*mat_masse) *= H_moy(TEMPS_0); // (*mat_masse) *= donnee_specif.epais.epaisseur0; // prise en compte de l'épaisseur return mat_masse; }; //============= lecture écriture dans base info ========== // cas donne le niveau de la récupération // = 1 : on récupère tout // = 2 : on récupère uniquement les données variables (supposées comme telles) void QuadraMemb::Lecture_base_info (ifstream& ent,const Tableau * tabMaillageNoeud,const int cas) {// tout d'abord appel de la lecture de la classe elem_meca ElemMeca::Lecture_bas_inf(ent,tabMaillageNoeud,cas); // traitement du cas particulier du quadrangle switch (cas) { case 1 : // ------- on récupère tout ------------------------- { // construction du tableau de ddl des noeuds du triangle ConstTabDdl(); // récup contraintes et déformation lesPtMecaInt.Lecture_base_info(ent,cas); // les données spécifiques // les données spécifiques string nom; ent >> nom; if (nom == "epaisStockeDansElement") {double titi; for (int i=1; i<= nombre->nbi;i++) ent >> nom >> titi >> nom >> donnee_specif.epais(i).epaisseur0 >> nom >> donnee_specif.epais(i).epaisseur_t >> nom >> donnee_specif.epais(i).epaisseur_tdt; }; break; } case 2 : // ----------- lecture uniquement de se qui varie -------------------- { // récup contraintes et déformation lesPtMecaInt.Lecture_base_info(ent,cas); // les données spécifiques string nom;double titi; ent >> nom; // le mot clé for (int i=1; i<= nombre->nbi;i++) {ent >> nom >> titi >> donnee_specif.epais(i).epaisseur_tdt; donnee_specif.epais(i).epaisseur_t = donnee_specif.epais(i).epaisseur_tdt; }; break; } default : { cout << "\nErreur : valeur incorrecte du type de lecture !\n"; cout << "QuadraMemb::Lecture_base_info(ifstream& ent,const " << "Tableau * tabMaillageNoeud,const int cas)" << " cas= " << cas << endl; Sortie(1); } } }; // cas donne le niveau de sauvegarde // = 1 : on sauvegarde tout // = 2 : on sauvegarde uniquement les données variables (supposées comme telles) void QuadraMemb::Ecriture_base_info(ofstream& sort,const int cas) {// tout d'abord appel de l'écriture de la classe elem_meca ElemMeca::Ecriture_bas_inf(sort,cas); // traitement du cas particulier du quadrangle switch (cas) { case 1 : // ------- on sauvegarde tout ------------------------- { // des tenseurs déformation et contrainte, lesPtMecaInt.Ecriture_base_info(sort,cas); // les données spécifiques sort << "\n epaisStockeDansElement "; for (int i=1; i<= nombre->nbi;i++) sort << " pti: "<< i << " epaisseur0= " << donnee_specif.epais(i).epaisseur0 << " epaisseur_t= " << donnee_specif.epais(i).epaisseur_t << " epaisseur_tdt= " << donnee_specif.epais(i).epaisseur_tdt; break; } case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- { // des tenseurs déformation et contrainte, lesPtMecaInt.Ecriture_base_info(sort,cas); sort << "\n epaisseur_tdt= "; for (int i=1; i<= nombre->nbi;i++) sort << " pti: "<< i << " " << donnee_specif.epais(i).epaisseur_tdt; break; } default : { cout << "\nErreur : valeur incorrecte du type d'écriture !\n"; cout << "QuadraMemb::::Ecriture_base_info(ofstream& sort,const int cas)" << " cas= " << cas << endl; Sortie(1); }; } }; // récupération des valeurs au numéro d'ordre = iteg pour // les grandeur enu // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière Tableau QuadraMemb::Valeur_a_diff_temps(bool absolue,Enum_dure enu_t,const List_io& enu,int iteg) { // appel de la procedure de elem meca int cas; if (!(unefois->dualSortQuad ) && (unefois->CalimpPrem )) { cas=1;unefois->dualSortQuad += 1; } else if ((unefois->dualSortQuad) && (unefois->CalimpPrem)) { cas = 11;} else if (!(unefois->dualSortQuad ) && (unefois->CalResPrem_tdt)) { cas=2;unefois->dualSortQuad += 1; } else if ((unefois->dualSortQuad) && (unefois->CalResPrem_tdt)) { cas = 12;} // sinon problème else { cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul" << " pour inialiser les conteneurs des tenseurs resultats "; if (ParaGlob::NiveauImpression() >= 4) cout << "\n cas non prévu, unefois->dualSortQuad= " << unefois->dualSortQuad << " unefois->CalimpPrem= " << unefois->CalimpPrem << "\n QuadraMemb::Valeur_a_diff_temps(Enum_dure enu_t..."; Sortie(1); }; return ElemMeca::Valeur_multi(absolue,enu_t,enu,iteg,cas); }; // récupération des valeurs au numéro d'ordre = iteg pour les grandeurs enu // ici il s'agit de grandeurs tensorielles, le retour s'effectue dans la liste // de conteneurs quelconque associée // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière void QuadraMemb::ValTensorielle_a_diff_temps(bool absolue,Enum_dure enu_t,List_io& enu,int iteg) { // appel de la procedure de elem meca int cas; if (!(unefois->dualSortQuad ) && (unefois->CalimpPrem )) { cas=1;unefois->dualSortQuad += 1; } else if ((unefois->dualSortQuad) && (unefois->CalimpPrem)) { cas = 11;} else if (!(unefois->dualSortQuad ) && (unefois->CalResPrem_tdt)) { cas=2;unefois->dualSortQuad += 1; } else if ((unefois->dualSortQuad) && (unefois->CalResPrem_tdt)) { cas = 12;} // sinon problème else { cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul" << " pour inialiser les conteneurs des tenseurs resultats "; if (ParaGlob::NiveauImpression() >= 4) cout << "\n cas non prévu, unefois->dualSortQuad= " << unefois->dualSortQuad << " unefois->CalimpPrem= " << unefois->CalimpPrem << "\n QuadraMemb::ValTensorielle_a_diff_temps(Enum_dure enu_t..."; Sortie(1); }; return ElemMeca::Valeurs_Tensorielles(absolue,enu_t,enu,iteg,cas); }; //------- calcul d'erreur, remontée des contraintes ------------------- // calcul du résidu et de la matrice de raideur pour le calcul d'erreur Element::Er_ResRaid QuadraMemb::ContrainteAuNoeud_ResRaid() { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if(!( unefois->CalResPrem_t )) {unefois->CalResPrem_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; // appel du programme général int tabn_taille = tab_noeud.Taille(); ElemMeca::SigmaAuNoeud_ResRaid(tabn_taille, (CoQuadra->quadra).TaPhi(), (CoQuadra->quadra).TaWi(), CoQuadra-> resErr,CoQuadra->raidErr, (CoQuadra->quadraEr).TaPhi(), (CoQuadra->quadraEr).TaWi()); // on tient compte de l'épaisseur à t, supposée déjà calculée ou récupérée // on regarde le type de variation d'épaisseur que l'on veut if (donnee_specif.use_epais_moyenne) {int taille_resErr=CoQuadra->resErr.Taille(); double epais_t = H_moy(TEMPS_t); for (int i=1;i<= taille_resErr;i++) (*CoQuadra-> resErr(i)) *= epais_t; CoQuadra->raidErr *= epais_t; }; return (Element::Er_ResRaid( &(CoQuadra-> resErr),&(CoQuadra->raidErr))); } ; // calcul du résidu pour le calcul d'erreur ramenée aux noeuds Element::Er_ResRaid QuadraMemb::ErreurAuNoeud_ResRaid() { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if(!( unefois->CalResPrem_t )) { unefois->CalResPrem_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; // appel du programme général int tabn_taille = tab_noeud.Taille(); ElemMeca::Cal_ErrAuxNoeuds(tabn_taille, (CoQuadra->quadra).TaPhi(),(CoQuadra->quadra).TaWi() ,CoQuadra-> resErr ); // on tient compte de l'épaisseur à t, supposée déjà calculée ou récupérée // on regarde le type de variation d'épaisseur que l'on veut if (donnee_specif.use_epais_moyenne) {int taille_resErr=CoQuadra->resErr.Taille(); double epais_t = H_moy(TEMPS_t); for (int i=1;i<= taille_resErr;i++) (*CoQuadra-> resErr(i)) *= epais_t; CoQuadra->raidErr *= epais_t; }; return (Element::Er_ResRaid( &(CoQuadra-> resErr),&(CoQuadra->raidErr))); } ; // actualisation des ddl et des grandeurs actives de t+dt vers t void QuadraMemb::TdtversT() { lesPtMecaInt.TdtversT(); // contrainte for (int ni=1;ni<= nombre->nbi; ni++) { if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TdtversT(); if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TdtversT(); if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TdtversT(); donnee_specif.epais(ni).epaisseur_t = donnee_specif.epais(ni).epaisseur_tdt; }; //donnee_specif.epais.epaisseur_t = donnee_specif.epais.epaisseur_tdt; ElemMeca::TdtversT_(); // appel de la procédure mère }; // actualisation des ddl et des grandeurs actives de t vers tdt void QuadraMemb::TversTdt() { lesPtMecaInt.TversTdt(); // contrainte for (int ni=1;ni<= nombre->nbi; ni++) { if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TversTdt(); if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TversTdt(); if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TversTdt(); donnee_specif.epais(ni).epaisseur_tdt = donnee_specif.epais(ni).epaisseur_t; }; // donnee_specif.epais.epaisseur_tdt = donnee_specif.epais.epaisseur_t; ElemMeca::TversTdt_(); // appel de la procédure mère }; // calcul de l'erreur sur l'élément. void QuadraMemb::ErreurElement(int type,double& errElemRelative ,double& numerateur, double& denominateur) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if(!( unefois->CalResPrem_t )) { unefois->CalResPrem_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; // appel du programme général ElemMeca::Cal_ErrElem(type,errElemRelative,numerateur,denominateur, tab_noeud.Taille(),(CoQuadra->quadra).TaPhi(), (CoQuadra->quadra).TaWi(), (CoQuadra->quadraEr).TaPhi(),(CoQuadra->quadraEr).TaWi()); } ; // mise à jour de la boite d'encombrement de l'élément, suivant les axes I_a globales // en retour coordonnées du point mini dans retour.Premier() et du point maxi dans .Second() // la méthode est différente de la méthode générale car il faut prendre en compte l'épaisseur de l'élément const DeuxCoordonnees& QuadraMemb::Boite_encombre_element(Enum_dure temps) { int tab_taille= tab_noeud.Taille(); // on commence par calculer la boite d'encombrement pour l'élément médian Element::Boite_encombre_element( temps); // ensuite on augmente sytématiquement dans toutes directions d'une valeur h/2 majorée double hSur2maj = H_moy(TEMPS_tdt) * 0.5 * ParaGlob::param->ParaAlgoControleActifs().Extra_boite_prelocalisation(); // ajout d'un extra dans toutes les directions hSur2maj += ParaGlob::param->ParaAlgoControleActifs().Ajout_extra_boite_prelocalisation(); // mise à jour boite_encombre.Premier().Ajout_meme_valeur(-hSur2maj); // le min boite_encombre.Second().Ajout_meme_valeur(hSur2maj); // le max //cout << "\n boite "; boite_encombre.Premier().Affiche(); boite_encombre.Second().Affiche(); cout << endl; // retour return boite_encombre; }; // cas d'un chargement volumique, // force indique la force volumique appliquée // retourne le second membre résultant // ici on considère l'épaisseur de l'élément pour constituer le volume // -> explicite à t ou tdt en fonction de la variable booléenne atdt Vecteur QuadraMemb::SM_charge_volumique_E (const Coordonnee& force,Fonction_nD* pt_fonct,bool atdt,const ParaAlgoControle & pa,bool sur_volume_finale_) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if(!(unefois->CalSMvol_t )) { unefois->CalSMvol_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };} else {if(!(unefois->CalSMvol_tdt )) { unefois->CalSMvol_tdt += 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };}; // initialisation du résidu residu->Zero(); // appel du programme général d'elemmeca et retour du vecteur second membre if (donnee_specif.use_epais_moyenne) {// retour multiplié par l'épaisseur pour avoir le volume, on considère que l'épaisseur est à jour double epaisseur = H_moy(TEMPS_tdt);//donnee_specif.epais.epaisseur_tdt; if (!atdt) epaisseur = H_moy(TEMPS_t); return (epaisseur * ElemMeca::SM_charge_vol_E (CoQuadra->tab_ddl,(CoQuadra->quadra).TaPhi() ,tab_noeud.Taille(),(CoQuadra->quadra).TaWi(),force,pt_fonct,pa,sur_volume_finale_)); } else // sinon tout ce fait dans ElemMeca return (ElemMeca::SM_charge_vol_E (CoQuadra->tab_ddl,(CoQuadra->quadra).TaPhi() ,tab_noeud.Taille(),(CoQuadra->quadra).TaWi(),force,pt_fonct,pa,sur_volume_finale_)); }; // calcul des seconds membres suivant les chargements // cas d'un chargement volumique, // force indique la force volumique appliquée // retourne le second membre résultant // ici on l'épaisseur de l'élément pour constituer le volume -> implicite, // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_volumique_I (const Coordonnee& force,Fonction_nD* pt_fonct,const ParaAlgoControle & pa,bool sur_volume_finale_) { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // initialisation du résidu residu->Zero(); // initialisation de la raideur raideur->Zero(); // -- définition des constantes de la métrique si nécessaire // en fait on fait appel aux même éléments que pour le calcul implicite if (!(unefois->CalSMvol_tdt)) { unefois->CalSMvol_tdt += 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; // appel du programme général d'elemmeca ElemMeca::SMR_charge_vol_I (CoQuadra->tab_ddl ,(CoQuadra->quadra).TaPhi(),tab_noeud.Taille() ,(CoQuadra->quadra).TaWi(),force,pt_fonct,pa,sur_volume_finale_); // prise en compte de l'epaisseur if (donnee_specif.use_epais_moyenne) {double epaisseur_moyenne = H_moy(TEMPS_t); (*residu) *= epaisseur_moyenne; (*raideur) *= epaisseur_moyenne; }; Element::ResRaid el; el.res = residu; el.raid = raideur; return el; }; // calcul des seconds membres suivant les chargements // cas d'un chargement surfacique, sur les frontières des éléments // force indique la force surfacique appliquée // numface indique le numéro de la face chargée // retourne le second membre résultant // -> explicite à t ou tdt en fonction de la variable booléenne atdt Vecteur QuadraMemb::SM_charge_surfacique_E(const Coordonnee& force,Fonction_nD* pt_fonct ,int ,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément // // récupération de la métrique associée à l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // définition des constantes de la métrique si nécessaire if (!atdt) {if ( !(unefois->CalSMsurf_t )) { unefois->CalSMsurf_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };} else {if ( !(unefois->CalSMsurf_tdt )) { unefois->CalSMsurf_tdt += 1; Tableau tab(11); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ; tab(10) = igradVBB_tdt;tab(11) = iVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (*met,tabb(1)->TabNoeud(),(CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre // 1 pour dire que c'est la première surface externe return ElemMeca::SM_charge_surf_E (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),tab_noeud.Taille() ,(CoQuadra->quadraS).TaWi(),force,pt_fonct,pa); }; // cas d'un chargement surfacique, sur les frontières des éléments // force indique la force surfacique appliquée // numface indique le numéro de la face chargée // retourne le second membre résultant // -> implicite, // pa : permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_surfacique_I (const Coordonnee& force,Fonction_nD* pt_fonct,int ,const ParaAlgoControle & pa) { // initialisation du vecteur résidu et de la raideur // normalement numface = 1 ((*res_extS)(1))->Zero(); ((*raid_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if ( unefois->CalSMRsurf == 0) { unefois->CalSMRsurf = 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; met->PlusInitVariables(tab) ; }; // on définit la déformation a doc si elle n'existe pas déjà // on utilise la même déformation pour toutes les arrêtes. if (defSurf(1) == NULL) defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(), (CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SMR_charge_surf_I (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),(tabb(1)->TabNoeud()).Taille() ,(CoQuadra->quadraS).TaWi(),force,pt_fonct,pa); }; // cas d'un chargement de type pression, sur les frontières des éléments // pression indique la pression appliquée // numface indique le numéro de la face chargée // retourne le second membre résultant // NB: il y a une définition par défaut pour les éléments qui n'ont pas de // surface externe -> message d'erreur d'où le virtuel et non virtuel pur // -> explicite à t ou tdt en fonction de la variable booléenne atdt Vecteur QuadraMemb::SM_charge_pression_E(double pression,Fonction_nD* pt_fonct ,int ,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if ( !(unefois->CalSMsurf_t )) { unefois->CalSMsurf_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };} else {if ( !(unefois->CalSMsurf_tdt )) { unefois->CalSMsurf_tdt += 1; Tableau tab(11); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ; tab(10) = igradVBB_tdt;tab(11) = iVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (*met,tabb(1)->TabNoeud(),(CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre // 1 pour dire que c'est la première surface externe return ElemMeca::SM_charge_pres_E (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),tab_noeud.Taille() ,(CoQuadra->quadraS).TaWi(),pression,pt_fonct,pa); }; // cas d'un chargement de type pression, sur les frontières des éléments // pression indique la pression appliquée // numface indique le numéro de la face chargée // retourne le second membre résultant // NB: il y a une définition par défaut pour les éléments qui n'ont pas de // surface externe -> message d'erreur d'où le virtuel et non virtuel pur // -> implicite, // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_pression_I (double pression,Fonction_nD* pt_fonct,int ,const ParaAlgoControle & pa) { // initialisation du vecteur résidu et de la raideur ((*res_extS)(1))->Zero(); ((*raid_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if ( unefois->CalSMRsurf == 0) { unefois->CalSMRsurf = 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; met->PlusInitVariables(tab) ; }; // on définit la déformation ad hoc si elle n'existe pas déjà // on utilise la même déformation pour toutes les arrêtes. if (defSurf(1) == NULL) defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(), (CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SMR_charge_pres_I (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),(tabb(1)->TabNoeud()).Taille() ,(CoQuadra->quadraS).TaWi(),pression,pt_fonct,pa); }; // cas d'un chargement de type pression unidirectionnelle, sur les frontières des éléments // presUniDir indique le vecteur appliquée // numface indique le numéro de la face chargée: ici 1 // retourne le second membre résultant // -> explicite à t ou tdt en fonction de la variable booleenne atdt Vecteur QuadraMemb::SM_charge_presUniDir_E (const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int ,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if ( !(unefois->CalSMsurf_t )) { unefois->CalSMsurf_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };} else {if ( !(unefois->CalSMsurf_tdt )) { unefois->CalSMsurf_tdt += 1; Tableau tab(11); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ; tab(10) = igradVBB_tdt;tab(11) = iVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (*met,tabb(1)->TabNoeud(),(CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SM_charge_surf_Suiv_E (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),tab_noeud.Taille() ,(CoQuadra->quadraS).TaWi(),presUniDir,pt_fonct,pa,atdt); }; // -> implicite, // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_presUniDir_I (const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int numface,const ParaAlgoControle & pa) { // initialisation du vecteur résidu et de la raideur ((*res_extS)(1))->Zero(); ((*raid_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique, si elle n'existe pas il faut la creer d'ou le true Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if ( unefois->CalSMRsurf == 0) { unefois->CalSMRsurf = 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; met->PlusInitVariables(tab) ; }; // on définit la déformation ad hoc si elle n'existe pas déjà // on utilise la même déformation pour toutes les arrêtes. if (defSurf(1) == NULL) defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(), (CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SMR_charge_surf_Suiv_I (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),(tabb(1)->TabNoeud()).Taille() ,(CoQuadra->quadraS).TaWi(),presUniDir,pt_fonct,pa); }; // cas d'un chargement lineique, sur les arêtes frontières des éléments // force indique la force lineique appliquée // numArete indique le numéro de l'arête chargée // retourne le second membre résultant // -> explicite à t ou tdt en fonction de la variable booléenne atdt Vecteur QuadraMemb::SM_charge_lineique_E (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les quadrangles // du même type Met_abstraite * meta= elf->Metrique(); QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // définition des constantes de la métrique si nécessaire if (!atdt) {if( !(unefois->CalSMlin_t )) { unefois->CalSMlin_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; meta->PlusInitVariables(tab) ; };} else {if( !(unefois->CalSMlin_tdt )) { unefois->CalSMlin_tdt += 1; Tableau tab(8); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = igradVBB_tdt; meta->PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (defArete(numArete) == NULL) defArete(numArete) = new Deformation(*meta,elf->TabNoeud(), (CoQuadra->segS).TaDphi(),(CoQuadra->segS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SM_charge_line_E (elf->DdlElem(),numArete ,(CoQuadra->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoQuadra->segS).TaWi(),force,pt_fonct,pa); }; // cas d'un chargement lineique, sur les aretes frontières des éléments // force indique la force lineique appliquée // numarete indique le numéro de l'arete chargée // retourne le second membre résultant // -> implicite, // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_lineique_I (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) { // initialisation du vecteur résidu et de la raideur ((*res_extA)(numArete))->Zero(); ((*raid_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les quadrangles // du même type Met_abstraite * meta= elf->Metrique(); QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if( !(unefois->CalSMRlin )) { unefois->CalSMRlin += 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; meta->PlusInitVariables(tab) ; }; // on définit la déformation a doc si elle n'existe pas déjà if (defArete(numArete) == NULL) defArete(numArete) = new Deformation(*meta,elf->TabNoeud(), (CoQuadra->segS).TaDphi(),(CoQuadra->segS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SMR_charge_line_I (elf->DdlElem(),numArete ,(CoQuadra->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoQuadra->segS).TaWi(),force,pt_fonct,pa); }; // cas d'un chargement lineique suiveuse, sur les aretes frontières des éléments 2D (uniquement) // force indique la force lineique appliquée // numarete indique le numéro de l'arete chargée // retourne le second membre résultant // -> explicite à t ou tdt en fonction de la variable booléenne atdt Vecteur QuadraMemb::SM_charge_lineique_Suiv_E (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les quadrangles // du même type Met_abstraite * meta= elf->Metrique(); QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // définition des constantes de la métrique si nécessaire if (!atdt) {if( !(unefois->CalSMlin_t )) { unefois->CalSMlin_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; meta->PlusInitVariables(tab) ; };} else {if( !(unefois->CalSMlin_tdt )) { unefois->CalSMlin_tdt += 1; Tableau tab(8); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = igradVBB_tdt; meta->PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (defArete(numArete) == NULL) defArete(numArete) = new Deformation(*meta,elf->TabNoeud(), (CoQuadra->segS).TaDphi(),(CoQuadra->segS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SM_charge_line_Suiv_E (elf->DdlElem(),numArete ,(CoQuadra->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoQuadra->segS).TaWi(),force,pt_fonct,pa); }; // cas d'un chargement lineique suiveuse, sur les aretes frontières des éléments 2D (uniquement) // force indique la force lineique appliquée // numarete indique le numéro de l'arete chargée // retourne le second membre résultant -> implicite, // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_lineique_Suiv_I (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) { // initialisation du vecteur résidu et de la raideur ((*res_extA)(numArete))->Zero(); ((*raid_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les quadrangles // du même type Met_abstraite * meta= elf->Metrique(); QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if( !(unefois->CalSMRlin )) { unefois->CalSMRlin += 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; meta->PlusInitVariables(tab) ; }; // on définit la déformation a doc si elle n'existe pas déjà if (defArete(numArete) == NULL) defArete(numArete) = new Deformation(*meta,elf->TabNoeud(), (CoQuadra->segS).TaDphi(),(CoQuadra->segS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SMR_charge_line_Suiv_I (elf->DdlElem(),numArete ,(CoQuadra->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoQuadra->segS).TaWi(),force,pt_fonct,pa); }; // cas d'un chargement de type pression hydrostatique, sur les frontières des éléments // la charge dépend de la hauteur à la surface libre du liquide déterminée par un point // et une direction normale à la surface libre: // nSurf : le numéro de la surface externe // poidvol: indique le poids volumique du liquide // M_liquide : un point de la surface libre // dir_normal_liquide : direction normale à la surface libre // retourne le second membre résultant // calcul à l'instant tdt ou t en fonction de la variable atdt // retourne le second membre résultant // NB: il y a une définition par défaut pour les éléments qui n'ont pas de // surface externe -> message d'erreur d'où le virtuel et non virtuel pur // -> explicite à t ou à tdt en fonction de la variable booléenne atdt Vecteur QuadraMemb::SM_charge_hydrostatique_E(const Coordonnee& dir_normal_liquide,const double& poidvol ,int ,const Coordonnee& M_liquide,bool atdt ,const ParaAlgoControle & pa ,bool sans_limitation) { // initialisation du vecteur résidu ((*res_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément // // récupération de la métrique associée à l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // définition des constantes de la métrique si nécessaire if (!atdt) {if ( !(unefois->CalSMsurf_t )) { unefois->CalSMsurf_t += 1; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };} else {if ( !(unefois->CalSMsurf_tdt )) { unefois->CalSMsurf_tdt += 1; Tableau tab(11); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ; tab(10) = igradVBB_tdt;tab(11) = iVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (*met,tabb(1)->TabNoeud(),(CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SM_charge_hydro_E (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),(tabb(1)->TabNoeud()).Taille() ,(CoQuadra->quadraS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa,atdt); }; // cas d'un chargement de type pression hydrostatique, sur les frontières des éléments // la charge dépend de la hauteur à la surface libre du liquide déterminée par un point // et une direction normale à la surface libre: // nSurf : le numéro de la surface externe // poidvol: indique le poids volumique du liquide // M_liquide : un point de la surface libre // dir_normal_liquide : direction normale à la surface libre // retourne le second membre résultant // calcul à l'instant tdt ou t en fonction de la variable atdt // retourne le second membre résultant // NB: il y a une définition par défaut pour les éléments qui n'ont pas de // surface externe -> message d'erreur d'où le virtuel et non virtuel pur // -> implicite, // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_hydrostatique_I (const Coordonnee& dir_normal_liquide,const double& poidvol ,int ,const Coordonnee& M_liquide ,const ParaAlgoControle & pa ,bool sans_limitation) { // initialisation du vecteur résidu et de la raideur ((*res_extS)(1))->Zero(); ((*raid_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if ( unefois->CalSMRsurf == 0) { unefois->CalSMRsurf = 1; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; CoQuadra->met_quadraMemb.PlusInitVariables(tab) ; }; // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation(*met,tabb(1)->TabNoeud(), (CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); // appel du programme général d'elemmeca et retour du vecteur second membre return ElemMeca::SMR_charge_hydro_I (tabb(1)->DdlElem(),1 ,(CoQuadra->quadraS).TaPhi(),(tabb(1)->TabNoeud()).Taille() ,(CoQuadra->quadraS).TaWi(),dir_normal_liquide,poidvol,M_liquide,sans_limitation,pa); }; // cas d'un chargement surfacique hydro-dynamique, // Il y a trois forces: une suivant la direction de la vitesse: de type traînée aerodynamique // Fn = poids_volu * fn(V) * S * (normale*u) * u, u étant le vecteur directeur de V (donc unitaire) // une suivant la direction normale à la vitesse de type portance // Ft = poids_volu * ft(V) * S * (normale*u) * w, w unitaire, normal à V, et dans le plan n et V // une suivant la vitesse tangente de type frottement visqueux // T = to(Vt) * S * ut, Vt étant la vitesse tangentielle et ut étant le vecteur directeur de Vt // coef_mul: est un coefficient multiplicateur global (de tout) // retourne le second membre résultant // // -> explicite à t ou à tdt en fonction de la variable booléenne atdt Vecteur QuadraMemb::SM_charge_hydrodynamique_E( Courbe1D* frot_fluid,const double& poidvol , Courbe1D* coef_aero_n,int numface,const double& coef_mul , Courbe1D* coef_aero_t,bool atdt ,const ParaAlgoControle & pa) { int dime = ParaGlob::Dimension(); QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture Met_abstraite * meta; ElemGeomC0* elemGeom; // définit dans le choix suivant // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les quadrangles // du même type if (dime == 3) // il s'agit de surface // initialisation du vecteur résidu et de la raideur pour la surface {((*res_extS)(numface))->Zero(); ((*raid_extS)(numface))->Zero(); Frontiere_surfacique(numface,true);// on récupère ou on crée la frontière surfacique meta= tabb(numface)->Metrique(); elemGeom = &(CoQuadra->quadraS); // récup de l'élément géométrique } else // dime 2: il s'agit de ligne // initialisation du vecteur résidu et de la raideur pour une arrête {((*res_extA)(numface))->Zero(); ((*raid_extA)(numface))->Zero(); ElFrontiere* elf = Frontiere_lineique(numface,true);// on récupère ou on crée la frontière lineique meta= elf->Metrique(); elemGeom = &(CoQuadra->segS); // récup de l'élément géométrique }; // dimensionnement de la metrique // définition des constantes de la métrique si nécessaire if (!atdt) {if (((dime == 3)&& !(unefois->CalSMsurf_t)) || ((dime == 2)&& !(unefois->CalSMlin_t))) { if (dime == 3) {unefois->CalSMsurf_t += 1;} else {unefois->CalSMlin_t += 1;}; Tableau tab(10); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igijBB_0;tab(4) = igijBB_t; tab(5) = igijHH_t; tab(6) = id_giB_t; tab(7) = id_gijBB_t ; tab(8) = id_gijBB_t ;tab(9) = igradVBB_t; tab(10) = iVt; meta->PlusInitVariables(tab) ; };} else {if (((dime == 3)&& !(unefois->CalSMsurf_tdt )) || ((dime == 2)&& !(unefois->CalSMlin_tdt ))) { if (dime == 3) {unefois->CalSMsurf_tdt += 1;} else {unefois->CalSMlin_tdt += 1;}; Tableau tab(11); tab(1) = igiB_0; tab(2) = igiB_tdt; tab(3) = igijBB_0;tab(4) = igijBB_tdt; tab(5) = igijHH_tdt; tab(6) = id_giB_tdt; tab(7) = id_gijBB_tdt ; tab(8) = id_gijBB_t ;tab(9) = id_gijBB_tdt ; tab(10) = igradVBB_tdt;tab(11) = iVtdt; meta->PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (dime == 3) { if (defSurf(numface) == NULL) defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(), (CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); } else { if (defArete(numface) == NULL) defArete(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(), (CoQuadra->segS).TaDphi(),(CoQuadra->segS).TaPhi()); }; // appel du programme général d'ElemMeca et retour du vecteur second membre return ElemMeca::SM_charge_hydrodyn_E (poidvol,elemGeom->TaPhi(),(tabb(numface)->TabNoeud()).Taille() ,frot_fluid,elemGeom->TaWi() ,coef_aero_n,numface,coef_mul,coef_aero_t,pa,atdt); }; // -> implicite, // pa: permet de déterminer si oui ou non on calcul la contribution à la raideur // retourne le second membre et la matrice de raideur correspondant Element::ResRaid QuadraMemb::SMR_charge_hydrodynamique_I( Courbe1D* frot_fluid,const double& poidvol , Courbe1D* coef_aero_n,int numface,const double& coef_mul , Courbe1D* coef_aero_t ,const ParaAlgoControle & pa) { int dime = ParaGlob::Dimension(); QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture Met_abstraite * meta; ElemGeomC0* elemGeom; // définit dans le choix suivant // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les quadrangles // du même type if (dime == 3) // il s'agit de surface // initialisation du vecteur résidu et de la raideur pour la surface {((*res_extS)(numface))->Zero(); ((*raid_extS)(numface))->Zero(); Frontiere_surfacique(numface,true);// on récupère ou on crée la frontière surfacique meta= tabb(numface)->Metrique(); elemGeom = &(CoQuadra->quadraS); // récup de l'élément géométrique } else // dime 2: il s'agit de ligne // initialisation du vecteur résidu et de la raideur pour une arrête {((*res_extA)(numface))->Zero(); ((*raid_extA)(numface))->Zero(); ElFrontiere* elf = Frontiere_lineique(numface,true);// on récupère ou on crée la frontière lineique meta= tabb(posi_tab_front_lin + numface)->Metrique(); elemGeom = &(CoQuadra->segS); // récup de l'élément géométrique }; // dimensionnement de la metrique // définition des constantes de la métrique si nécessaire if (((dime == 3)&& !(unefois->CalSMRsurf )) || ((dime == 2)&& !(unefois->CalSMRlin ))) { if (dime == 3) {unefois->CalSMRsurf += 1;} else {unefois->CalSMRlin += 1;}; Tableau tab(20); tab(1) = igiB_0; tab(2) = igiB_t; tab(3) = igiB_tdt; tab(4) = igijBB_0; tab(5) = igijBB_t;tab(6) = igijBB_tdt; tab(7) = igijHH_tdt; tab(8) = id_giB_tdt; tab(9) = id_gijBB_tdt ;tab(10) = igiH_tdt;tab(11) = id_giH_tdt; tab(12) = id_gijHH_tdt;tab(13) = id_jacobien_tdt;tab(14) = id2_gijBB_tdt; tab(15) = id_gijBB_t ;tab(16) = id_gijBB_tdt ;tab(17) = idMtdt ; tab(18) = igradVBB_tdt; tab(19) = iVtdt; tab(20) = idVtdt; meta->PlusInitVariables(tab) ; }; // on définit la déformation a doc si elle n'existe pas déjà if (dime == 3) { if (defSurf(numface) == NULL) defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(), (CoQuadra->quadraS).TaDphi(),(CoQuadra->quadraS).TaPhi()); } else { if (defArete(numface) == NULL) defArete(numface) = new Deformation(*meta,tabb(numface)->TabNoeud(), (CoQuadra->segS).TaDphi(),(CoQuadra->segS).TaPhi()); }; // appel du programme général d'ElemMeca et retour du vecteur second membre return ElemMeca::SM_charge_hydrodyn_I (poidvol,elemGeom->TaPhi(),(tabb(numface)->TabNoeud()).Taille() ,frot_fluid,elemGeom->TaWi(),tabb(numface)->DdlElem() ,coef_aero_n,numface,coef_mul ,coef_aero_t,pa); }; // Calcul des frontieres de l'element // creation des elements frontieres et retour du tableau de ces elements // la création n'a lieu qu'au premier appel // ou lorsque l'on force le paramètre force a true // dans ce dernier cas seul les frontière effacées sont recréée Tableau const & QuadraMemb::Frontiere(bool force) { // en 3D on veut des faces et des lignes int cas = 0; // init if ((ParaGlob::Dimension()==3)&& (!ParaGlob::AxiSymetrie())) {cas = 4;} else if (ParaGlob::Dimension()==2) {cas = 2;}; // = 0 -> on veut toutes les frontières // = 1 -> on veut uniquement les surfaces // = 2 -> on veut uniquement les lignes // = 3 -> on veut uniquement les points // = 4 -> on veut les surfaces + les lignes // = 5 -> on veut les surfaces + les points // = 6 -> on veut les lignes + les points return Frontiere_elemeca(cas,force); // {// le calcul et la création ne sont effectués qu'au premier appel // // ou lorsque l'on veut forcer une recréation // if (((ind_front_lin == 0) && (ind_front_surf == 0) && (ind_front_point == 0)) // || force ) //// if ((ind_front_lin == 0) || force || (ind_front_lin == 2)) // {QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // ElemGeomC0 & el = (CoQuadra->quadra); // DdlElement & tdd = CoQuadra->tab_ddl; // // dimensionnement des tableaux intermediaires // Tableau tab(nombre->nbneA); // les noeuds des segments frontieres // DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres // // int tail; // if ((ParaGlob::Dimension() == 2) && (ind_front_surf == 0)) // tail = 4; // quatre cotes et pas de surface // else if (ParaGlob::Dimension() == 2) // cas avec la surface en 2D // tail = 5; // quatre cotes et la facette elle meme // else if (ParaGlob::Dimension() == 3) // tail = 5; // quatre cotes et la facette elle meme // #ifdef MISE_AU_POINT // else // { cout << "\n erreur de dimension dans Quad, dim = " << ParaGlob::Dimension(); // cout << "\n alors que l'on doit avoir 2 ou 3 !! " << endl; // Sortie (1); // } // #endif // // if ((ind_front_point > 0) && (ind_front_lin == 0) && (ind_front_surf == 0)) // // cas où les frontières points existent seule // { int tail_p = nombre->nbne; // le nombre de noeuds // int taille_f = tail + tail_p; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_p;i++) // { tabb(i+tail) = tabb(i); // tabb(i) = NULL; // } // posi_tab_front_point=tail; // } // else if ((ind_front_point > 0) && (ind_front_lin == 0) && (ind_front_surf > 0)) // // cas où les frontières points existent et surface et pas de ligne // { int tail_p = nombre->nbne; // le nombre de noeuds // int taille_f = tail + tail_p + 1; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_p;i++) // transfert pour les noeuds // { tabb(i+tail) = tabb(i+1);tabb(i+1) = NULL;} // posi_tab_front_point=tail; // // pour la surface, c'est la première, elle y reste // } // else if ((ind_front_point > 0) && (ind_front_lin > 0) && (ind_front_surf = 0)) // // cas où les frontières points existent et ligen et pas de surface // { int tail_af = nombre->nbne+el.NonS().Taille(); // nombre d'arête + noeud // int taille_f = tail + tail_af; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_af;i++) // transfert pour les noeuds // { tabb(i+tail) = tabb(i);tabb(i) = NULL;} // posi_tab_front_point +=tail; // posi_tab_front_lin +=tail; // } // else // { // cas où il n'y a pas de frontières points // if (ind_front_surf == 0) // dimensionnement éventuelle // tabb.Change_taille(tail); // le tableau total de frontières // }; // // // positionnement du début des lignes // posi_tab_front_lin = 0; // par défaut // // création éventuelle de la surface // if (tail == 5) // {if (tabb(1) == NULL) // { int nbnoe = el.Nonf()(1).Taille(); // nb noeud de la face // Tableau tab(nbnoe); // les noeuds des faces frontieres // DdlElement ddelem(nombre->nbne); // les ddlelements des noeuds frontieres // for (int i=1;i<= nbnoe;i++) // { tab(i) = tab_noeud(el.Nonf()(1)(i)); // ddelem.Change_un_ddlNoeudElement(i,tdd(el.Nonf()(1)(i))); // // ddelem(i) = tdd(el.Nonf()(1)(i)); // } // tabb(1) = new_frontiere_surf(tab,ddelem); // // mise à jour de l'indicateur de création de face // ind_front_surf = 1; // } // // mise à jour du début des lignes // posi_tab_front_lin = 1; // }; // // création éventuelle des lignes // for (int nlign=1;nlign<=4;nlign++) // if (tabb(posi_tab_front_lin+nlign) == NULL) // { int nbnoe = el.NonS()(nlign).Taille(); // nb noeud de l'arête // Tableau tab(nbnoe); // les noeuds de l'arête frontiere // DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres // for (int i=1;i<= nbnoe;i++) // { tab(i) = tab_noeud(el.NonS()(nlign)(i)); // ddelem.Change_un_ddlNoeudElement(i,tdd(el.NonS()(nlign)(i))); // // ddelem(i) = tdd(el.NonS()(nlign)(i)); // } // tabb(posi_tab_front_lin+nlign) = new_frontiere_lin(tab,ddelem); // } // // mise à jour de l'indicateur // ind_front_lin = 1; // } // // retour du tableau // return (Tableau &) tabb; }; //// ramène la frontière point //// éventuellement création des frontieres points de l'element et stockage dans l'element //// si c'est la première fois sinon il y a seulement retour de l'elements //// a moins que le paramètre force est mis a true //// dans ce dernier cas la frontière effacéee est recréée //// num indique le numéro du point à créer (numérotation EF) //ElFrontiere* const QuadraMemb::Frontiere_points(int num,bool force) // { // le calcul et la création ne sont effectués qu'au premier appel // // ou lorsque l'on veut forcer une recréation // #ifdef MISE_AU_POINT // if ((num > nombre->nbne)||(num <=0)) // { cout << "\n *** erreur, le noeud demande pour frontiere: " << num << " esten dehors de la numeration de l'element ! " // << "\n Frontiere_points(int num,bool force)"; // Sortie(1); // } // #endif // // if ((ind_front_point == 0) || force || (ind_front_point == 2)) // {Tableau tab(1); // les noeuds des points frontieres // DdlElement ddelem(1); // les ddlelements des points frontieres // // on regarde si les frontières points existent sinon on les crée // if (ind_front_point == 1) // return (ElFrontiere*)tabb(posi_tab_front_point+num); // else if ( ind_front_point == 2) // // cas où certaines frontières existent // if (tabb(posi_tab_front_point+num) != NULL) // return (ElFrontiere*)tabb(posi_tab_front_point+num); // // dans tous les autres cas on construit la frontière point // // on commence par dimensionner le tableau de frontière, comme les frontières points sont // // les dernières, il suffit de les ajouter, d'où on redimentionne le tableau mais on ne créra // // que la frontière adoc // // def de la taille // int taille_actuelle = tabb.Taille(); // if ((ind_front_point == 0) && ((ind_front_lin > 0) || (ind_front_surf > 0))) // // cas où les frontières lignes ou surfaces existent, mais pas les points // { int tail_p = nombre->nbne; // le nombre de noeuds // int taille_f = taille_actuelle + tail_p; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_p;i++) // { tabb(i+taille_actuelle) = tabb(i);tabb(i) = NULL;}; // posi_tab_front_point +=taille_actuelle; // if (ind_front_lin > 0) posi_tab_front_lin += taille_actuelle; // } // else if (ind_front_point == 0) // // cas où aucune frontière n'existe // {tabb.Change_taille(nombre->nbne);}; // // dans les autres cas, les frontières points exitent donc pas à dimensionner // // on définit tous les points par simplicité // for (int i=1;i<=nombre->nbne;i++) // {tab(1) = tab_noeud(i);ddelem.Change_un_ddlNoeudElement(1,unefois->doCoMemb->tab_ddl(i)); // if (tabb(i+posi_tab_front_point) == NULL) // tabb(i+posi_tab_front_point) = new FrontPointF (tab,ddelem); // }; // }; // return (ElFrontiere*)tabb(num+posi_tab_front_point); // }; // //// ramène la frontière linéique //// éventuellement création des frontieres linéique de l'element et stockage dans l'element //// si c'est la première fois et en 3D sinon il y a seulement retour de l'elements //// a moins que le paramètre force est mis a true //// dans ce dernier cas la frontière effacéee est recréée //// num indique le numéro de l'arête à créer (numérotation EF) //ElFrontiere* const QuadraMemb::Frontiere_lineique(int num,bool force) // { // le calcul et la création ne sont effectués qu'au premier appel // // ou lorsque l'on veut forcer une recréation // // on regarde si les frontières linéiques existent sinon on les crée // if (ind_front_lin == 1) // return (ElFrontiere*)tabb(posi_tab_front_lin+num); // else if ( ind_front_lin == 2) // // cas où certaines frontières existent // if (tabb(posi_tab_front_lin+num) != NULL) // return (ElFrontiere*)tabb(posi_tab_front_lin+num); // // dans tous les autres cas on reconstruit les frontières // Frontiere(force); // return (ElFrontiere*)tabb(posi_tab_front_lin+num); // }; // //// ramène la frontière surfacique //// éventuellement création de la frontiere surfacique de l'element et stockage dans l'element //// si c'est la première fois sinon il y a seulement retour de l'elements //// a moins que le paramètre force est mis a true //// dans ce dernier cas la frontière effacéee est recréée //// num indique le numéro de la surface à créer (numérotation EF) ici normalement uniquement 1 possible //ElFrontiere* const QuadraMemb::Frontiere_surfacique(int ,bool force) // { // le calcul et la création ne sont effectués qu'au premier appel // // ou lorsque l'on veut forcer une recréation // if ((ind_front_surf == 0) || force || (ind_front_surf == 2)) // { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture // ElemGeomC0 & el = (CoQuadra->quadra); // DdlElement & tdd = CoQuadra->tab_ddl; // int taille = tabb.Taille(); // la taille initiales des frontières // int tail_s = 1; // nombre de faces // int tail_a = el.NonS().Taille(); // nombre d'arête // posi_tab_front_lin = 1; // init indice de début d'arrête dans tabb // // dimensionnement du tableau de frontières ligne si nécessaire // // def de la taille // if ((ind_front_point > 0) && (ind_front_lin == 0) && (ind_front_surf == 0)) // // cas où les frontières points existent seule // { int tail_p = nombre->nbne; // le nombre de noeuds // int taille_f = tail_s + tail_p; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_p;i++) // { tabb(i+tail_s) = tabb(i);tabb(i) = NULL;}; // posi_tab_front_point=tail_s; // } // else if ((ind_front_point > 0) && (ind_front_lin > 0) && (ind_front_surf == 0)) // // cas où les frontières points existent et ligne et pas de surface // { int tail_af = nombre->nbne+el.NonS().Taille(); // nombre d'arête + noeud // int taille_f = tail_s + tail_af; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_af;i++) // transfert pour les noeuds // { tabb(i+tail_s) = tabb(i);tabb(i) = NULL;} // posi_tab_front_point +=tail_s; // posi_tab_front_lin +=tail_s; // } // else if ((ind_front_point == 0) && (ind_front_lin > 0) && (ind_front_surf == 0)) // // cas où les frontières ligne existent seule // { int tail_a = el.NonS().Taille(); // nombre d'arête // int taille_f = tail_s + tail_a; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_a;i++) // transfert pour les noeuds // { tabb(i+tail_s) = tabb(i);tabb(i) = NULL;} // posi_tab_front_point +=tail_s; // posi_tab_front_lin +=tail_s; // } // else if (ind_front_surf == 0) // cas autre, où la frontière surface n'existe pas // // et qu'il n'y a pas de ligne ni de point // tabb.Change_taille(tail_s); // le tableau total de frontières // // création éventuelle de la face // if (tabb(1) == NULL) // { int nbnoe = nombre->nbne; // nb noeud de la surface // Tableau tab(nbnoe); // les noeuds de la surface // DdlElement ddelem(nbnoe); // les ddlelements des noeuds frontieres // for (int i=1;i<= nbnoe;i++) // { tab(i) = tab_noeud(el.Nonf()(1)(i)); // ddelem.Change_un_ddlNoeudElement(i,tdd(el.Nonf()(1)(i))); // // ddelem(i) = tdd(el.Nonf()(1)(i)); // } // tabb(1) = new_frontiere_surf(tab,ddelem); // } // // mise à jour de l'indicateur // ind_front_surf = 1; // } // return (ElFrontiere*)tabb(1); // }; // liberation de la place pointee void QuadraMemb::Libere () {Element::Libere (); // liberation de residu et raideur LibereTenseur() ; // liberation des tenseur intermediaires }; // acquisition ou modification d'une loi de comportement void QuadraMemb::DefLoi (LoiAbstraiteGeneral * NouvelleLoi) { // verification du type de loi if ((NouvelleLoi->Dimension_loi() != 2) && (NouvelleLoi->Dimension_loi() != 4)) { cout << "\n Erreur, la loi de comportement a utiliser avec des QuadraMembs"; cout << " doit etre de type 2D, \n ici elle est de type = " << (NouvelleLoi->Dimension_loi()) << "D !!! " << endl; Sortie(1); } // cas d'une loi mécanique if (GroupeMecanique(NouvelleLoi->Id_categorie())) {loiComp = (Loi_comp_abstraite *) NouvelleLoi; // initialisation du stockage particulier, ici en fonction du nb de pt d'integ int imaxi = tabSaveDon.Taille(); for (int i=1;i<= imaxi;i++) tabSaveDon(i) = loiComp->New_et_Initialise(); // idem pour le type de déformation mécanique associé int iDefmax = tabSaveDefDon.Taille(); for (int i=1;i<= iDefmax;i++) tabSaveDefDon(i) = def->New_et_Initialise(); // définition du type de déformation associé à la loi loiComp->Def_type_deformation(*def); // on active les données particulières nécessaires au fonctionnement de la loi de comp loiComp->Activation_donnees(tab_noeud,dilatation,lesPtMecaInt); }; // cas d'une loi thermo physique if (GroupeThermique(NouvelleLoi->Id_categorie())) {loiTP = (CompThermoPhysiqueAbstraite *) NouvelleLoi; // initialisation du stockage particulier thermo physique, int imax = tabSaveTP.Taille(); for (int i=1;i<= imax;i++) tabSaveTP(i) = loiTP->New_et_Initialise(); // on active les données particulières nécessaires au fonctionnement de la loi de comp loiTP->Activation_donnees(tab_noeud); }; // cas d'une loi de frottement if (GroupeFrottement(NouvelleLoi->Id_categorie())) loiFrot = (CompFrotAbstraite *) NouvelleLoi; }; // test si l'element est complet int QuadraMemb::TestComplet() { int res = ElemMeca::TestComplet(); // test dans la fonction mere bool pas_epaisseur = false; if(donnee_specif.epais.Taille() == 0) pas_epaisseur=true; if (!pas_epaisseur) if (donnee_specif.epais(1).epaisseur0 == epaisseur_defaut) pas_epaisseur = true; if (pas_epaisseur) { cout << "\n l\'epaisseur de l\'element triangulaire n\'est pas defini \n"; res = 0; }; if ( tab_noeud(1) == NULL) { cout << "\n les noeuds de l\'element quadrangulaire ne sont pas defini \n"; res = 0; } else { int testi =1; int posi = Id_nom_ddl("X1") -1; int dim = ParaGlob::Dimension(); int jmaxi = tab_noeud.Taille(); for (int i =1; i<= dim; i++) for (int j=1;j<=jmaxi;j++) if(!(tab_noeud(j)->Existe_ici(Enum_ddl(posi+i)))) testi = 0; if(testi == 0) { cout << "\n les ddls Xi des noeuds de la facette ne sont pas defini \n"; cout << " \n utilisez QuadraMemb::ConstTabDdl() pour completer " ; res = 0; } } return res; }; // procedure permettant de completer l'element apres // sa creation avec les donnees du bloc transmis // ici il s'agit de l'epaisseur Element* QuadraMemb::Complete(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD) { // complétion avec bloc if (bloc.Nom(1) == "epaisseurs") { // deux cas suivant que l'épaisseur est un réel ou que c'est une fonction nD donnee_specif.epais.Change_taille(nombre->nbi); if (bloc.Nom(2) == "_") // cas fixe {double epaiss = bloc.Val(1); for (int i=1; i<= nombre->nbi;i++) donnee_specif.epais(i).epaisseur_tdt = donnee_specif.epais(i).epaisseur_t = donnee_specif.epais(i).epaisseur0 = epaiss; } else // cas fct nD, on va calculer l'épaisseur pour chaque pti { // on récupère la fct nD Fonction_nD* fctnD_epais=NULL; if (lesFonctionsnD->Existe(bloc.Nom(2))) {fctnD_epais= lesFonctionsnD->Trouve(bloc.Nom(2));} else // sinon c'est un problème { cout << "\n *** erreur dans la definition de l'epaisseur via la fonction nD " << bloc.Nom(2) << ", a priori cette fonction n'est pas disponible!! " << "\n QuadraMemb::Complete(...)"; Sortie(1); }; // on vérifie qu'en retour la fonction ramène un seule scalaire if (fctnD_epais->NbComposante() != 1) { cout << "\n *** erreur dans la definition de l'epaisseur via la fonction nD " << bloc.Nom(2) << ", la fonction ramene " << fctnD_epais->NbComposante() << " composantes !! au lieu d'une seule valeur !" << "\n QuadraMemb::Complete(...)"; Sortie(1); }; // pour l'instant on n'accepte qu'une dépendance aux coordonnées initiales du point // d'intégration et par ailleurs à des grandeurs globales if (fctnD_epais->Depend_M0() < 0) {// on va boucler sur les pti for (int ni=1; ni<= nombre->nbi;ni++) {// on récupère les coordonnées du pti bool erreur = false; Coordonnee M = CoordPtInteg(TEMPS_0,X1,ni,erreur); if (erreur) { cout << "\n *** erreur dans le calcul des coordonnees du point d'integration " << ni << ", on ne peut pas initialiser l'epaisseur " << "\n QuadraMemb::Complete(...)"; Sortie(1); } else // sinon c'est ok { Tableau tab_M(1,M); Tableau & tava = fctnD_epais->Val_FnD_Evoluee(NULL,&tab_M,NULL); // pour simplifier donnee_specif.epais(ni).epaisseur_tdt = donnee_specif.epais(ni).epaisseur_t = donnee_specif.epais(ni).epaisseur0 = tava(1); }; }; } else { cout << "\n *** erreur dans le calcul de l'epaisseur via la fonction nD " << bloc.Nom(2) << ", cette fonction ne depend pas seulement des coordonnees initiales ! " << "\n QuadraMemb::Complete(...)"; Sortie(1); }; // // on commence par récupérer les conteneurs des grandeurs à fournir // List_io & li_enu_scal = fctnD_epais->Li_enu_etendu_scalaire(); // List_io & li_quelc = fctnD_epais->Li_equi_Quel_evolue(); // bool absolue = true; // on se place systématiquement en absolu // int cas = 1; // il faut vérifier // for (int ni=1; ni<= nombre->nbi;ni++) // { // on va utiliser la méhode Valeur_multi pour les grandeurs strictement scalaire // Tableau val_ddl_enum(ElemMeca::Valeur_multi(absolue,TEMPS_tdt,li_enu_scal,ni,cas)); // // on utilise la méthode des grandeurs évoluées pour les Coordonnees et Tenseur // Valeurs_Tensorielles(absolue, TEMPS_tdt,li_quelc,ni,cas); // // calcul de la valeur et retour dans tab_ret // Tableau & tab_ret = fctnD_epais->Valeur_FnD_Evoluee // (&val_ddl_enum,&li_enu_scal,&li_quelc,NULL,NULL); // donnee_specif.epais(ni).epaisseur_tdt = donnee_specif.epais(ni).epaisseur_t // = donnee_specif.epais(ni).epaisseur0 = tab_ret(1); // }; }; return this; } // cas de la définition d'une stabilisation transversale pour membrane ou biel else if (bloc.Nom(1) == "stabilisation_transvers_membrane_biel_") {// l'objectif ici est d'allouer la raideur et résidu local spécifique à l'élément int nbddl = (*residu).Taille(); if (unefois->doCoMemb->quadramatD == NULL) unefois->doCoMemb->quadramatD = new Mat_pleine(nbddl,nbddl); if (unefois->doCoMemb->quadraresD == NULL) unefois->doCoMemb->quadraresD = new Vecteur(nbddl); // on renseigne les pointeurs d'ElemeMeca ElemMeca::matD = unefois->doCoMemb->quadramatD; ElemMeca::resD = unefois->doCoMemb->quadraresD; // ensuite les autres informations sont gérées par ElemMeca return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD); } else return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD); }; // Compléter pour la mise en place de la gestion de l'hourglass Element* QuadraMemb::Complet_Hourglass(LoiAbstraiteGeneral * loiHourglass, const BlocGen & bloc) { // on initialise le traitement de l'hourglass string str_precision; // string vide indique que l'on veut utiliser un élément normal // dans le cas où il s'agit d'élément Quadratique il faut utiliser 9 pti par défaut if (id_interpol == QUADRATIQUE) str_precision = "_cm9pti"; ElemMeca::Init_hourglass_comp(*(unefois->doCoMemb->quadraHourg),str_precision,loiHourglass,bloc); // dans le cas où l'hourglass a été activé mais que l'élément n'a pas // de traitement particulier associé, alors on désactive l'hourglass if ( ((type_stabHourglass == STABHOURGLASS_PAR_COMPORTEMENT) || (type_stabHourglass == STABHOURGLASS_PAR_COMPORTEMENT_REDUIT)) &&(unefois->doCoMemb->quadraHourg == NULL)) type_stabHourglass = STABHOURGLASS_NON_DEFINIE; return this; }; // ajout du tableau de ddl des noeuds de Quad void QuadraMemb::ConstTabDdl() { int dim = ParaGlob::Dimension(); Tableau ta(dim); int posi = Id_nom_ddl("X1") -1; for (int i =1; i<= dim; i++) {Ddl inter((Enum_ddl(i+posi)),0.,LIBRE); ta(i) = inter; } // attribution des ddls aux noeuds for (int ne=1; ne<= nombre->nbne; ne++) tab_noeud(ne)->PlusTabDdl(ta); }; // =====>>>> methodes privées appelees par les classes dérivees <<<<===== // fonction d'initialisation servant dans les classes derivant // au niveau du constructeur QuadraMemb::DonnComQuad* QuadraMemb::Init (Donnee_specif donnee_spec,bool sans_init_noeud) { // bien que la grandeur donnee_specif est défini dans la classe generique // le fait de le passer en paramètre permet de tout initialiser dans Init // et ceci soit avec les valeurs par défaut soit avec les bonnes valeurs donnee_specif =donnee_spec; // le fait de mettre les pointeurs a null permet // de savoir que l'element n'est pas complet // dans le cas d'un constructeur avec tableau de noeud, il ne faut pas mettre // les pointeurs à nuls d'où le test if (!sans_init_noeud) for (int i =1;i<= nombre->nbne;i++) tab_noeud(i) = NULL; // definition des donnees communes aux QuadraMembxxx // a la premiere definition d'une instance if (unefois->doCoMemb == NULL) unefois->doCoMemb = QuadraMemb::Def_DonneeCommune(); QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture met = &(CoQuadra->met_quadraMemb); // met est defini dans elemeca // def pointe sur la deformation specifique a l'element def = new Deformation(*met,tab_noeud,(CoQuadra->quadra).TaDphi(),(CoQuadra->quadra).TaPhi()); // idem pour la remonte aux contraintes et le calcul d'erreur defEr = new Deformation(*met,tab_noeud,(CoQuadra->quadraEr).TaDphi(),(CoQuadra->quadraEr).TaPhi()); // idem pour les calculs relatifs à la matrice de masse defMas = new Deformation(*met,tab_noeud,(CoQuadra->quadraMas).TaDphi(),(CoQuadra->quadraMas).TaPhi()); // idem pour le calcul de second membre defSurf.Change_taille(1); // une seule surface pour le second membre defSurf(1) = NULL; // la déformation sera construite si nécessaire au moment du calcul de // second membre // idem pour le calcul de second membre defArete.Change_taille(4); // 4 arrêtes utilisées pour le second membre // la déformation sera construite si nécessaire au moment du calcul de second membre for (int ia=1;ia<=4;ia++) defArete(ia) = NULL; //dimensionnement des deformations et contraintes etc.. int dimtens = 2; lesPtMecaInt.Change_taille_PtIntegMeca(nombre->nbi,dimtens); // attribution des numéros de référencement dans le conteneur for (int ni = 1; ni<= nombre->nbi; ni++) {lesPtMecaInt(ni).Change_Nb_mail(this->num_maillage); lesPtMecaInt(ni).Change_Nb_ele(this->num_elt); lesPtMecaInt(ni).Change_Nb_pti(ni); }; // stockage des donnees particulieres de la loi de comportement mécanique au point d'integ tabSaveDon.Change_taille(nombre->nbi); // stockage des donnees particulieres de la loi de comportement thermo physique au point d'integ tabSaveTP.Change_taille(nombre->nbi); // stockage des donnees particulieres de la déformation mécanique au point d'integ tabSaveDefDon.Change_taille(nombre->nbi); tab_energ.Change_taille(nombre->nbi); tab_energ_t.Change_taille(nombre->nbi); // initialisation des pointeurs définis dans la classe Element concernant les résidus et // raideur // --- cas de la puissance interne --- residu = &(CoQuadra->residu_interne); // residu local raideur = &(CoQuadra->raideur_interne); // raideur locale // --- cas de la dynamique ----- mat_masse = &(CoQuadra->matrice_masse); // --- cas des efforts externes concernant les points ------ res_extN = &(CoQuadra->residus_externeN); // pour les résidus et second membres raid_extN= &(CoQuadra->raideurs_externeN);// pour les raideurs // --- cas des efforts externes concernant les aretes ------ res_extA = &(CoQuadra->residus_externeA); // pour les résidus et second membres raid_extA= &(CoQuadra->raideurs_externeA);// pour les raideurs // --- cas des efforts externes concernant les faces ------ res_extS= &(CoQuadra->residus_externeS); // pour les résidus et second membres raid_extS= &(CoQuadra->raideurs_externeS); // pour les raideurs return CoQuadra; }; // fonction permettant le calcul de CoQuadra QuadraMemb::DonnComQuad* QuadraMemb::Def_DonneeCommune () { // interpolation GeomQuadrangle quad(nombre->nbi,nombre->nbne); // degre de liberte int dim = ParaGlob::Dimension(); // cas des ddl éléments primaires DdlElement tab_ddl(nombre->nbne,dim); int posi = Id_nom_ddl("X1") -1; for (int i =1; i<= dim; i++) for (int j=1; j<= nombre->nbne; j++) // tab_ddl (j,i) = Enum_ddl(i+posi); tab_ddl.Change_Enum(j,i,Enum_ddl(i+posi)); // cas des ddl éléments secondaires pour le calcul d'erreur // def du nombre de composantes du tenseur de contrainte en absolu int nbcomposante = ParaGlob::NbCompTens (); DdlElement tab_ddlErr(nombre->nbne,nbcomposante); posi = Id_nom_ddl("SIG11") -1; // uniquement deux cas a considéré 3 ou 6 composantes for (int j=1; j<= nombre->nbne; j++) {// on definit le nombre de composante de sigma en absolu if (nbcomposante == 3) // dans l'énumération les composantes ne sont pas a suivre {//tab_ddlErr (j,1) = Enum_ddl(1+posi); // cas de SIG11 //tab_ddlErr (j,2) = Enum_ddl(2+posi); // cas de SIG22 //tab_ddlErr (j,3) = Enum_ddl(4+posi); // cas de SIG12 tab_ddlErr.Change_Enum(j,1,Enum_ddl(1+posi)); // cas de SIG11 tab_ddlErr.Change_Enum(j,2,Enum_ddl(2+posi)); // cas de SIG22 tab_ddlErr.Change_Enum(j,3,Enum_ddl(4+posi)); // cas de SIG12 } else if (nbcomposante == 6) // les composantes sont a suivre dans l'enumération for (int i= 1;i<= nbcomposante; i++) // tab_ddlErr (j,i) = Enum_ddl(i+posi); tab_ddlErr.Change_Enum(j,i,Enum_ddl(i+posi)); // uniquement SIG11 } // egalement pour tab_Err1Sig11, def d'un tableau de un ddl : enum SIG11 // par noeud DdlElement tab_Err1Sig11(nombre->nbne,DdlNoeudElement(SIG11)); // toujours pour le calcul d'erreur definition des fonctions d'interpolation // pour le calcul du hession de la fonctionnelle GeomQuadrangle quadEr(nombre->nbiEr,nombre->nbne); // pour le calcul relatifs à la matrice masse GeomQuadrangle quadMas(nombre->nbiMas,nombre->nbne); // pour le calcul relatifs à la stabilisation d'hourglass GeomQuadrangle* quadHourg = NULL; if (nombre->nbiHour > 0) quadHourg = new GeomQuadrangle(nombre->nbiHour,nombre->nbne); // pour le calcul des seconds membres GeomQuadrangle quadraS(nombre->nbiS,nombre->nbne); GeomSeg segS(nombre->nbiA,nombre->nbneA); //def metrique //on definit les variables a priori toujours utiles Tableau tab(24); tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt ; tab(4) = igiB_0; tab(5) = igiB_t; tab(6) = igiB_tdt; tab(7) = igiH_0; tab(8) = igiH_t; tab(9) = igiH_tdt ; tab(10)= igijBB_0; tab(11)= igijBB_t; tab(12)= igijBB_tdt; tab(13)= igijHH_0; tab(14)= igijHH_t; tab(15)= igijHH_tdt ; tab(16)= id_gijBB_tdt; tab(17)= id_giH_tdt; tab(18)= id_gijHH_tdt; tab(19)= idMtdt ; tab(20)= id_jacobien_tdt;tab(21)= id2_gijBB_tdt; tab(22)= igradVBB_tdt; tab(23) = iVtdt; tab(24)= idVtdt; // dim du pb , nb de vecteur de la base = 2 ici, tableau de ddl et la def de variables Met_abstraite metri(ParaGlob::Dimension(),2,tab_ddl,tab,nombre->nbne) ; // ---- cas du calcul d'erreur sur sigma ou epsilon // les tenseurs sont exprimees en absolu donc nombre de composante fonction // de la dimension absolue Tableau resEr(nbcomposante); for (int i=1; i<= nbcomposante; i++) resEr(i)=new Vecteur (nombre->nbne); Mat_pleine raidEr(nombre->nbne,nombre->nbne); // la raideur pour l'erreur // dimensionnement des différents résidus et raideurs pour le calcul mécanique int nbddl = tab_ddl.NbDdl(); Vecteur residu_int(nbddl); Mat_pleine raideur_int(nbddl,nbddl); // cas de la dynamique Mat_pleine matmasse(1,nbddl); // a priori on dimensionne en diagonale // cas des noeuds Tableau residus_extN(nombre->nbne); residus_extN(1) = new Vecteur(dim); Tableau raideurs_extN(nombre->nbne); raideurs_extN(1) = new Mat_pleine(dim,dim); for (int i = 2;i<= nombre->nbne;i++) { residus_extN(i) = residus_extN(1); raideurs_extN(i) = raideurs_extN(1); }; int nbddlA = nombre->nbneA * dim; int nbA = 4; // 4 arêtes Tableau residus_extA(nbA); residus_extA(1) = new Vecteur(nbddlA); residus_extA(2) = residus_extA(1); residus_extA(3) = residus_extA(1); residus_extA(4) = residus_extA(1); Tableau raideurs_extA(nbA); raideurs_extA(1) = new Mat_pleine(nbddlA,nbddlA); raideurs_extA(2) = raideurs_extA(1); raideurs_extA(3) = raideurs_extA(1); raideurs_extA(4) = raideurs_extA(1); Tableau residus_extS(1); residus_extS(1) = new Vecteur(nbddl); Tableau raideurs_extS(1); raideurs_extS(1) = new Mat_pleine(nbddl,nbddl); // definition de la classe static contenant toute les variables communes aux QuadraMemb QuadraMemb::DonnComQuad* dodo; dodo = new DonnComQuad(quad,tab_ddl,tab_ddlErr,tab_Err1Sig11,metri,resEr,raidEr,quadEr,quadraS,segS ,residu_int,raideur_int,residus_extN,raideurs_extN,residus_extA,raideurs_extA,residus_extS,raideurs_extS ,matmasse,quadMas,nombre->nbi,quadHourg,NULL,NULL); // les 2 null de la fin, correspondent à quadramatD et quadraresD qui ne sont allouées qu'après, via // la méthode Complete(.. return dodo; }; // destructions de certaines grandeurs pointées, créées au niveau de l'initialisation void QuadraMemb::Destruction() { // tout d'abord l'idée est de détruire certaines grandeurs pointées que pour le dernier élément if ((unefois->nbelem_in_Prog == 0)&& (unefois->doCoMemb != NULL)) // cas de la destruction du dernier élément { QuadraMemb::DonnComQuad* CoQuadra = unefois->doCoMemb; // pour simplifier l'écriture int resErrTaille = CoQuadra->resErr.Taille(); for (int i=1;i<= resErrTaille;i++) delete CoQuadra->resErr(i); delete CoQuadra->residus_externeN(1); delete CoQuadra->raideurs_externeN(1); delete CoQuadra->residus_externeA(1); delete CoQuadra->raideurs_externeA(1); delete CoQuadra->residus_externeS(1); delete CoQuadra->raideurs_externeS(1); if (CoQuadra->quadraHourg != NULL) delete CoQuadra->quadraHourg; if (CoQuadra->quadramatD != NULL) delete CoQuadra->quadramatD; if (CoQuadra->quadraresD != NULL) delete CoQuadra->quadraresD; } }; // calcul de la nouvelle épaisseur moyenne finale (sans raideur) // ramène l'épaisseur moyenne calculée à atdt ou t // met à jour les épaisseurs aux pti en fonction de l'épaisseur moyenne calculée // erreur = true en retour -> une erreur que l'on exploite en debug const double QuadraMemb::CalEpaisseurMoyenne_et_transfert_pti(bool atdt,bool& erreur) { // .. en bouclant sur les pt d'integ enregistré .. // -- on récupère et on calcule les jacobiens moyens à 0 et final double jacobien_moy_fin = 0.; // init double jacobien_moy_ini = 0.; // -- de même on récupère et on calcul la trace moyenne de la contrainte double traceSig_moy = 0.;double traceSig_moy_ini = 0.; // -- de même on récupère et on calcul le module de compressibilité moyen double troisK_moy = 0.; double epaisseur_moy_t = H_moy(TEMPS_t); double epaisseur_moy_0 = H_moy(TEMPS_0); for (int i=1;i<= nombre->nbi;i++) { // cas de la compressibilité const double& troisK = 3. * (*lesPtIntegMecaInterne)(i).ModuleCompressibilite_const(); troisK_moy += troisK; // cas des jacobiens // const double& jacobien_0 = *(tabSaveDefDon(i)->Meti_00().jacobien_); if (atdt) { const double& jacobien_ini = *(tabSaveDefDon(i)->Meti_t().jacobien_); jacobien_moy_ini += jacobien_ini; const double& jacobien_fin = *(tabSaveDefDon(i)->Meti_tdt().jacobien_); jacobien_moy_fin += jacobien_fin; // cas de la trace de sigma //*** la ligne suivante est fausse car on est en 2D, or cette ligne n'est valable qu'en 3D !!!!! // const double traceSig = (*lesPtIntegMecaInterne)(i).SigHH_const() && (*(tabSaveDefDon(i)->Meti_tdt().gijBB_)); const double traceSig = ((*lesPtIntegMecaInterne)(i).SigHH_const() * (*(tabSaveDefDon(i)->Meti_tdt().gijBB_))).Trace(); traceSig_moy += traceSig; // const double traceSig_ini = (*lesPtIntegMecaInterne)(i).SigHH_t_const() && (*(tabSaveDefDon(i)->Meti_t().gijBB_)); const double traceSig_ini = ((*lesPtIntegMecaInterne)(i).SigHH_t_const() * (*(tabSaveDefDon(i)->Meti_t().gijBB_))).Trace(); traceSig_moy_ini += traceSig_ini; (*lesPtIntegMecaInterne)(i).Volume_pti() *= (epaisseur_moy_t * jacobien_ini) / jacobien_fin * troisK / (troisK - traceSig+traceSig_ini); ////--debug //cout << "\n debug QuadraMemb::CalEpaisseurMoyenne_et_vol_pti "; //if (num_elt==1) // { cout << setprecision(10) << "\n jacobien_ini= " << jacobien_ini << "\n jacobien_fin= " << jacobien_fin // << "\n jacobien_moy_ini= " << jacobien_moy_ini << "\n jacobien_moy_fin= " << jacobien_moy_fin // << " traceSig= "<< traceSig << " " ; // }; ////-- fin debug } else { const double& jacobien_ini = *(tabSaveDefDon(i)->Meti_00().jacobien_); jacobien_moy_ini += jacobien_ini; const double& jacobien_fin = *(tabSaveDefDon(i)->Meti_t().jacobien_); jacobien_moy_fin += jacobien_fin; // cas de la trace de sigma //*** la ligne suivante est fausse car on est en 2D, or cette ligne n'est valable qu'en 3D !!!!! // const double traceSig = (*lesPtIntegMecaInterne)(i).SigHH_const() && (*(tabSaveDefDon(i)->Meti_tdt().gijBB_)); const double traceSig = ((*lesPtIntegMecaInterne)(i).SigHH_const() * (*(tabSaveDefDon(i)->Meti_tdt().gijBB_))).Trace(); // double traceSig = (*lesPtIntegMecaInterne)(i).SigHH_const() && (*(tabSaveDefDon(i)->Meti_t().gijBB_)); traceSig_moy += traceSig; (*lesPtIntegMecaInterne)(i).Volume_pti() *= (epaisseur_moy_0 * jacobien_ini) / jacobien_fin * troisK / (troisK - traceSig); }; }; jacobien_moy_ini /= nombre->nbi; jacobien_moy_fin /= nombre->nbi; traceSig_moy_ini /= nombre->nbi; traceSig_moy /= nombre->nbi; troisK_moy /= nombre->nbi; // d'où le calcul de la nouvelle épaisseur en utilisant la relation: // (V-V_0)/V = trace(sigma)/3 /K_moy //--- vérification et gestion des cas particuliers --- erreur=false; {// on suppose un module de compressibilité positif sinon ce n'est pas normal if (troisK_moy < 0.) {if (ParaGlob::NiveauImpression()>2) cout << "\n erreur*** on a trouve une compressibilite moyenne negative = " << troisK_moy/3. << "\n QuadraMemb::CalEpaisseurMoyenne_et_transfert_pti(..."; // on ne change pas l'épaisseur erreur = true; }; double delta_traceSig = traceSig_moy-traceSig_moy_ini; // classiquement on suppose que troisK_moy doit-être bien supérieur à traceSig_moy: // on considère un facteur 10 arbitraire // si ce n'est pas le cas, on risque d'avoir un calcul d'épaisseur erroné if ( Dabs(delta_traceSig) > 10. * Dabs(troisK_moy/3.)) {if (ParaGlob::NiveauImpression()>2) cout << "\n *** pb dans le calcul de la nouvelle epaisseur: " << " le coef de compressibilite moyen = "< (troisK_moy/3. - ConstMath::petit)) // dans le cas où delta_traceSig > troisK_moy, cela va donner une épaisseur négative !! {if (ParaGlob::NiveauImpression()>2) cout << "\n *** pb dans le calcul de la nouvelle epaisseur: " << " coef de compressibilite moyen = "< 10. * Dabs(troisK_moy/3.)) ) // on ne va pas pouvoir peut-être calculer une nouvelle épaisseur {if (ParaGlob::NiveauImpression()>2) cout << "\n *** pb dans le calcul de la nouvelle epaisseur: " << " coef de compressibilite moyen = "<nbi;i++) donnee_specif.epais(i).epaisseur_tdt = epaisseur_moy_t; // puis retour return epaisseur_moy_t; } else { // on met à jour les épaisseurs aux pti for (int i=1;i<= nombre->nbi;i++) donnee_specif.epais(i).epaisseur_t = epaisseur_moy_t; // puis retour return epaisseur_moy_t; }; } else // sinon c'est ok {if (atdt) {double epaisseur_moy_tdt = (epaisseur_moy_t * jacobien_moy_ini) / jacobien_moy_fin * troisK_moy / (troisK_moy - traceSig_moy+traceSig_moy_ini); //epais.epaisseur_tdt = (epais.epaisseur0 * jacobien_moy_0) / jacobien_moy_fin // * troisK_moy / (troisK_moy + traceSig_moy); //--debug //if (num_elt==1) // { Noeud* noe = tab_noeud(1); // double R_0 = noe->Coord0().Norme(); double R = noe->Coord2().Norme(); //cout << "\n e0= " << epais.epaisseur_tdt<< " troisK_moy=" << troisK_moy << " traceSig_moy=" << traceSig_moy // << " J0= " << jacobien_moy_0 << " J= " << jacobien_moy_fin << " R_0 " << R_0 << " R= " << R; // }; //-- fin debug ////--debug //cout << "\n debug QuadraMemb::CalEpaisseurMoyenne_et_vol_pti "; //if (num_elt==1) // { Noeud* noe = tab_noeud(3); // double R_0 = noe->Coord0().Norme(); double R = noe->Coord2().Norme(); // double R_t = noe->Coord1().Norme(); // cout << setprecision(10) << "\n h_t= " << epais.epaisseur_t << " h_tdt= " << epais.epaisseur_tdt // << " troisK_moy=" << troisK_moy << " traceSig_moy_t=" << traceSig_moy_ini << " traceSig_moy_tdt=" << traceSig_moy // << " Jt= " << jacobien_moy_ini << " J= " << jacobien_moy_fin // << "\n XYZ_0= " << noe->Coord0() << " XYZ= " << noe->Coord2() << " " ; // Noeud* noe1 = tab_noeud(4); // cout << "\n (2) XYZ_0= " << noe1->Coord0() << " XYZ= " << noe1->Coord2() << " " ; // }; ////-- fin debug // on met à jour les épaisseurs aux pti for (int i=1;i<= nombre->nbi;i++) donnee_specif.epais(i).epaisseur_tdt = epaisseur_moy_tdt; // puis retour return epaisseur_moy_tdt; } else {epaisseur_moy_t = (epaisseur_moy_0 * jacobien_moy_ini) / jacobien_moy_fin * troisK_moy / (troisK_moy - traceSig_moy); // on met à jour les épaisseurs aux pti for (int i=1;i<= nombre->nbi;i++) donnee_specif.epais(i).epaisseur_t = epaisseur_moy_t; // puis retour return epaisseur_moy_t; }; }; }; // retourne la liste abondée de tous les données particulières interne actuellement utilisées // par l'élément (actif ou non), sont exclu de cette liste les données particulières des noeuds // reliées à l'élément // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière List_io QuadraMemb::Les_types_particuliers_internes(bool absolue) const { // on commence par récupérer la liste général provenant d'ElemMeca List_io ret = ElemMeca::Les_types_particuliers_internes(absolue); // ensuite on va ajouter les données particulières aux sfe Grandeur_scalaire_double grand_courant; // def d'une grandeur courante // $$$ cas de l'épaisseur moyenne initiale TypeQuelconque typQ1(EPAISSEUR_MOY_INITIALE,SIG11,grand_courant); ret.push_back(typQ1); // $$$ cas de l'épaisseur moyenne finale TypeQuelconque typQ2(EPAISSEUR_MOY_FINALE,SIG11,grand_courant); ret.push_back(typQ2); // $$$ cas de l'épaisseur initiale TypeQuelconque typQ3(EPAISSEUR_INITIALE,SIG11,grand_courant); ret.push_back(typQ3); // $$$ cas de l'épaisseur finale TypeQuelconque typQ4(EPAISSEUR_FINALE,SIG11,grand_courant); ret.push_back(typQ4); return ret; }; // récupération de grandeurs particulières au numéro d'ordre = iteg // celles-ci peuvent être quelconques // en retour liTQ est modifié et contiend les infos sur les grandeurs particulières // absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière void QuadraMemb::Grandeur_particuliere (bool absolue,List_io& liTQ,int iteg) { // on balaie la liste transmise pour les grandeurs propres List_io::iterator il,ilfin = liTQ.end(); // on commence par appeler la fonction de la classe m่re // il n'y aura pas de calcul des grandeurs inactivées ElemMeca::Grandeur_particuliere (absolue,liTQ,iteg); // puis les grandeurs spécifiques for (il=liTQ.begin();il!=ilfin;il++) {TypeQuelconque& tipParticu = (*il); // pour simplifier if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur switch (tipParticu.EnuTypeQuelconque().EnumTQ()) { // 1) -----cas de l'épaisseur moyenne initiale, ici elle ne dépend pas du point d'intégration case EPAISSEUR_MOY_INITIALE: { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())= H_moy(TEMPS_0); (*il).Active(); break; } // 2) -----cas de l'épaisseur moyenne finale, ici elle ne dépend pas du point d'intégration case EPAISSEUR_MOY_FINALE: // on inactive la grandeur quelconque { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=H_moy(TEMPS_tdt); (*il).Active(); break; } // 1) -----cas de l'épaisseur moyenne initiale, ici elle dépend du point d'intégration case EPAISSEUR_INITIALE: { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.epais(iteg).epaisseur0; (*il).Active(); break; } // 2) -----cas de l'épaisseur moyenne finale, ici elle dépend du point d'intégration case EPAISSEUR_FINALE: // on inactive la grandeur quelconque { *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.epais(iteg).epaisseur_tdt; (*il).Active(); break; } default: break; // rien pour le cas défaut }; }; };