// FICHIER : SfeMembT.cc // CLASSE : SfeMembT // 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-2021 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . # include using namespace std; //introduces namespace std #include #include "Sortie.h" #include "MathUtil.h" #include "SfeMembT.h" #include "TypeConsTens.h" #include "FrontPointF.h" #include "Loi_Umat.h" #include "ExceptionsElemMeca.h" // 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 SfeMembT::SM_charge_volumique_E (const Coordonnee& force,Fonction_nD* pt_fonct,bool atdt,const ParaAlgoControle & pa,bool sur_volume_finale_) { SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // on se sert d'un calcul surfacique, en partant du principe que la force de volume est identique dans toute l'épaisseur // seule la géométrie peut changer, dans l'épaisseur, on n'en tiend pas compte // 1-- on calcul sur la surface ----- // initialisation du vecteur résidu de surface, que l'on va utiliser comme variable intermédiaire de stockage // définition du vecteur de retour // initialisation du résidu residu->Zero(); Vecteur& SM = *residu; // 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 // dimensionnement de la metrique if (!atdt) {if ( unefois->CalSMsurf_t == 0) { 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; CoSfe->met_SfeMembT.PlusInitVariables(tab) ; }; } else {if ( unefois->CalSMsurf_tdt == 0) { 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; CoSfe->met_SfeMembT.PlusInitVariables(tab) ; }; }; // la déformation surfacique defSurf(1), est définit par défaut, sauf si elle a été supprimée // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->TaPhi()); Deformation & defS = *defSurf(1); // pour simplifier l'écriture bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde // donc il faut calculer tous les éléments de la métrique // on boucle sur les pt d'integ de l'élément centrale for (int ni=1; ni <= nombre->nbis;ni++) { const Tableau & taphi = CoSfe->eleCentre->TaPhi(); // pour simplifier const Vecteur& poids = CoSfe->eleCentre->TaWi(); // pour simplifier defS.ChangeNumInteg(ni); // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul // que pour un calcul primaire en explicit mais pour un calcul autre que mécanique double jacobien; if (atdt) { const Met_abstraite::Expli_t_tdt& ex = defS.Cal_explicit_tdt(premier_calcul); if (sur_volume_finale_) {jacobien = (*ex.jacobien_tdt);} else {jacobien = (*ex.jacobien_0);}; } else { const Met_abstraite::Expli& ex = defS.Cal_explicit_t(premier_calcul); if (sur_volume_finale_) {jacobien = (*ex.jacobien_t);} else {jacobien = (*ex.jacobien_0);}; }; // récup de l'épaisseur double epais_courant = 0.; if (donnee_specif.epais != NULL) // multiplié par l'épaisseur pour avoir le volume dans le cas d'élément 2D { if (atdt) { epais_courant = donnee_specif.epais->epaisseur_tdt;} else { epais_courant = donnee_specif.epais->epaisseur_t;}; } else { if (atdt) { epais_courant = defSurf(1)->DonneeInterpoleeScalaire(EPAIS,TEMPS_tdt);} else { epais_courant = defSurf(1)->DonneeInterpoleeScalaire(EPAIS,TEMPS_t);}; }; // calcul de la contribution: il faut tenir compte que l'on peut avoir un ddl d'épaisseur // or ici on ne considère que la contribution relativement au ddl de déplacement primaire // par contre pour chaque DdlNoeudElement on commence par les ddl de déplacement des noeuds int dimf = force.Dimension(); int decal_x =0; // décalage for (int ne =1; ne<= nombre->nbnce; ne++) {for (int i=1;i<= dimf;i++) SM(i+decal_x) += taphi(ni)(ne)* force(i) * (poids(ni) * jacobien * epais_courant); decal_x += CoSfe->tab_ddl.NbDdl(ne); } }; // liberation des tenseurs intermediaires LibereTenseur(); // retour du second membre return SM; }; // 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 SfeMembT::SMR_charge_volumique_I (const Coordonnee& force,Fonction_nD* pt_fonct,const ParaAlgoControle & pa,bool sur_volume_finale_) { residu->Zero(); // initialisation du résidu raideur->Zero(); // initialisation de la raideur Vecteur& SM = *residu; Mat_pleine & KM = *raideur; // on se sert d'un calcul surfacique, en partant du principe que la force de volume est identique dans toute l'épaisseur // seule la géométrie peut changer, dans l'épaisseur, on n'en tiend pas compte // on récupère ou on crée la frontière surfacique Frontiere_surfacique(1,true); SfeMembT::DonnComSfe* CoSfe = 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; CoSfe->met_surf_cent.PlusInitVariables(tab) ; }; // la déformation surfacique defSurf(1), est définit par défaut, sauf si elle a été supprimée // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->TaPhi()); // controle bool avec_raid = pa.Var_charge_externe(); // // dans le cas où la variation sur la raideur est demandé on s'assure que la variation // // du jacobien est bien effective sinon on l'impose, par contre on ne tient pas compte de la variation // // des épaisseurs même si c'est un ddl (car on suppose qu'a priori cela n'a pas d'importance (?) ) // ParaAlgoControle pa_nevez(pa); // if (!pa_nevez.Var_jacobien()) pa_nevez.Modif_Var_jacobien(true); // la déformation surfacique est définit par défaut Deformation & defS = *defSurf(1); // pour simplifier l'écriture bool premier_calcul=true; // contrairement à la déformation, pas de sauvegarde // donc il faut calculer tous les éléments de la métrique // on boucle sur les pt d'integ de l'élément centrale for (int ni=1; ni <= nombre->nbis;ni++) { const Tableau & taphi = CoSfe->eleCentre->TaPhi(); // pour simplifier const Vecteur& poids = CoSfe->eleCentre->TaWi(); // pour simplifier defS.ChangeNumInteg(ni); // calcul des éléments de la métrique, entre autre le jacobien, on utilise le même calcul // que pour un calcul primaire en implicit const Met_abstraite::Impli& ex = defS.Cal_implicit(premier_calcul); // récup de l'épaisseur double epais_courant = 0.; if (donnee_specif.epais != NULL) { epais_courant = donnee_specif.epais->epaisseur_tdt;} else { epais_courant = defSurf(1)->DonneeInterpoleeScalaire(EPAIS,TEMPS_tdt);}; // on regarde si éventuellement on voudrait calculer sur le volume initial double jacobien=0.; if (sur_volume_finale_) {jacobien = (*ex.jacobien_tdt);} else {jacobien = (*ex.jacobien_0);}; // on boucle sur les degrés de liberté: a priori ne dépend que des ddl de déplacement des noeuds (choix pour l'instant) int decal_x =0; // décalage int dimf = force.Dimension(); int nbddl = (*ex.d_jacobien_tdt).Taille(); // NB: il s'agit ici de la métrique de la surface donc qui ne contient que les ddl de déplacement des noeuds, pas l'épaisseur par ex for (int ne =1; ne<= nombre->nbnce; ne++) {for (int i=1;i<= dimf;i++) { SM(i+decal_x) += taphi(ni)(ne)* force(i) * (poids(ni) * jacobien * epais_courant); // dans le cas avec_raideur on calcul la contribution à la raideur, if (avec_raid&& sur_volume_finale_) for (int j =1; j<= nbddl; j++) {KM(i+decal_x,j) += taphi(ni)(ne)* force(i) * (poids(ni) * (*ex.d_jacobien_tdt)(j)) * epais_courant; }; }; decal_x += CoSfe->tab_ddl.NbDdl(ne); }; } // liberation des tenseurs intermediaires LibereTenseur(); 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 SfeMembT::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 SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if ( unefois->CalSMsurf_t == 0) { 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; CoSfe->met_SfeMembT.PlusInitVariables(tab) ; };} else {if ( unefois->CalSMsurf_tdt == 0) { 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; CoSfe->met_SfeMembT.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 (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->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 ,CoSfe->eleS->TaPhi(),nombre->nbnce //tab_noeud.Taille() ,CoSfe->eleS->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 SfeMembT::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); SfeMembT::DonnComSfe* CoSfe = 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; CoSfe->met_surf_cent.PlusInitVariables(tab) ; }; // la déformation surfacique defSurf(1), est définit par défaut, sauf si elle a été supprimée // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->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 ,CoSfe->eleS->TaPhi(),nombre->nbnce ,CoSfe->eleS->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 SfeMembT::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 SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if ( unefois->CalSMsurf_t == 0) { 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; CoSfe->met_SfeMembT.PlusInitVariables(tab) ; };} else {if ( unefois->CalSMsurf_tdt == 0) { 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; CoSfe->met_SfeMembT.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 (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->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 ,CoSfe->eleS->TaPhi(),nombre->nbnce //tab_noeud.Taille() ,CoSfe->eleS->TaWi(),pression,pt_fonct,pa); }; // cas d'un chargement de type pression, sur les frontières des éléments (type surface) // 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 SfeMembT::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); SfeMembT::DonnComSfe* CoSfe = 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; CoSfe->met_surf_cent.PlusInitVariables(tab) ; }; // la déformation surfacique defSurf(1), est définit par défaut, sauf si elle a été supprimée // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->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 ,CoSfe->eleS->TaPhi(),(tabb(1)->TabNoeud()).Taille() ,CoSfe->eleS->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 SfeMembT::SM_charge_presUniDir_E (const Coordonnee& presUniDir,Fonction_nD* pt_fonct,int ,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extS)(1))->Zero(); // on récupère ou on crée la frontière surfacique Frontiere_surfacique(1,true); // on pourrait utiliser la métrique des éléments de frontière // avec l'instance déformation dédiée pour // mais on utilise celle de l'élément SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if ( unefois->CalSMsurf_t == 0) { 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; CoSfe->met_SfeMembT.PlusInitVariables(tab) ; };} else {if ( unefois->CalSMsurf_tdt == 0) { 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; CoSfe->met_SfeMembT.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 (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->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 ,CoSfe->eleS->TaPhi(),nombre->nbnce ,CoSfe->eleS->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 SfeMembT::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); SfeMembT::DonnComSfe* CoSfe = 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; CoSfe->met_surf_cent.PlusInitVariables(tab) ; }; // la déformation surfacique defSurf(1), est définit par défaut, sauf si elle a été supprimée // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(1) == NULL) defSurf(1) = new Deformation (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->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 ,CoSfe->eleS->TaPhi(),nombre->nbnce ,CoSfe->eleS->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 SfeMembT::SM_charge_lineique_E (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les triangles // du même type Met_abstraite * meta= elf->Metrique(); SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if( unefois->CalSMlin_t == 0) { unefois->CalSMlin_t = 1; Tableau tab(8); 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) = igradVBB_t; meta->PlusInitVariables(tab) ; };} else {if( unefois->CalSMlin_tdt == 0) { 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(), (CoSfe->segS).TaDphi(),(CoSfe->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 ,(CoSfe->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoSfe->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 SfeMembT::SMR_charge_lineique_I (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) { // initialisation du vecteur résidu et de la raideur ((*res_extA)(numArete))->Zero(); ((*raid_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les triangles // du même type Met_abstraite * meta= elf->Metrique(); SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if( !(unefois->CalSMRlin )) { unefois->CalSMRlin += 1; Tableau tab(15); 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) = 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(), (CoSfe->segS).TaDphi(),(CoSfe->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 ,(CoSfe->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoSfe->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 SfeMembT::SM_charge_lineique_Suiv_E (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,bool atdt,const ParaAlgoControle & pa) { // initialisation du vecteur résidu ((*res_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les triangles // du même type Met_abstraite * meta= elf->Metrique(); SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if( unefois->CalSMlin_t == 0) { unefois->CalSMlin_t = 1; Tableau tab(8); 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) = igradVBB_t; meta->PlusInitVariables(tab) ; };} else {if( unefois->CalSMlin_tdt == 0) { 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(), (CoSfe->segS).TaDphi(),(CoSfe->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 ,(CoSfe->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoSfe->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 SfeMembT::SMR_charge_lineique_Suiv_I (const Coordonnee& force,Fonction_nD* pt_fonct,int numArete,const ParaAlgoControle & pa) { // initialisation du vecteur résidu et de la raideur ((*res_extA)(numArete))->Zero(); ((*raid_extA)(numArete))->Zero(); // on récupère ou on crée la frontière arrête ElFrontiere* elf = Frontiere_lineique(numArete,true); // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour // récupération de la métrique associée à l'élément qui est commune a tous les triangles // du même type Met_abstraite * meta= elf->Metrique(); SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if( !(unefois->CalSMRlin )) { unefois->CalSMRlin += 1; Tableau tab(15); 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) = 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(), (CoSfe->segS).TaDphi(),(CoSfe->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 ,(CoSfe->segS).TaPhi(),(elf->TabNoeud()).Taille() ,(CoSfe->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 SfeMembT::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 SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // dimensionnement de la metrique if (!atdt) {if ( unefois->CalSMsurf_t == 0) { 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; CoSfe->met_SfeMembT.PlusInitVariables(tab) ; };} else {if ( unefois->CalSMsurf_tdt == 0) { 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; CoSfe->met_SfeMembT.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 (CoSfe->met_surf_cent,tabb(1)->TabNoeud(),CoSfe->eleS->TaDphi(),CoSfe->eleS->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_hydro_E (tabb(1)->DdlElem(),1 ,CoSfe->eleS->TaPhi(),nombre->nbnce ,CoSfe->eleS->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 SfeMembT::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 // 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); SfeMembT::DonnComSfe* CoSfe = 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; CoSfe->met_surf_cent.PlusInitVariables(tab) ; }; // la déformation surfacique defSurf(1), est définit par défaut, sauf si elle a été supprimée // on définit la déformation a doc si elle n'existe pas déjà return ElemMeca::SMR_charge_hydro_I (tabb(1)->DdlElem(),1 ,CoSfe->eleS->TaPhi(),nombre->nbnce ,CoSfe->eleS->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 SfeMembT::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) { SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour Met_abstraite * meta = tabb(numface)->Metrique(); ElemGeomC0* elemGeom = CoSfe->eleS; // 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 // dimensionnement de la metrique // définition des constantes de la métrique si nécessaire if (!atdt) {if (unefois->CalSMsurf_t == 0) { 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; meta->PlusInitVariables(tab) ; };} else {if (unefois->CalSMsurf_tdt == 0) { 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; meta->PlusInitVariables(tab) ; };}; // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(numface) == NULL) defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud() ,CoSfe->eleS->TaDphi(),CoSfe->eleS->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 SfeMembT::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) { SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // on utilise la métrique des éléments de frontière // avec l'instance déformation dédiée pour Met_abstraite * meta = tabb(numface)->Metrique(); ElemGeomC0* elemGeom = CoSfe->eleS; // 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 // dimensionnement de la metrique // définition des constantes de la métrique si nécessaire 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; meta->PlusInitVariables(tab) ; }; // on définit la déformation a doc si elle n'existe pas déjà if (defSurf(numface) == NULL) defSurf(numface) = new Deformation(*meta,tabb(numface)->TabNoeud() ,CoSfe->eleS->TaDphi(),CoSfe->eleS->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); }; // ramène le nombre de points d'intégration correspondant à un type énuméré int SfeMembT::NbPtInteg(Enum_ddl ddl) const { Enum_ddl enu = PremierDdlFamille(ddl); switch (enu) { case X1 : case SIG11 : case EPS11 : case DEPS11 : return (nombre->nbie * nombre->nbis); break; case ERREUR : return (nombre->nbieEr * nombre->nbisEr); break; default : {cout << "\n cas non prévu ou non encore implanté: ddl= " << Nom_ddl(ddl) << "\n SfeMembT::NbPtInteg(Enum_ddl ddl) " ; Sortie(1); }; } return (nombre->nbie * nombre->nbis); // pour taire le compilo }; // 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 & SfeMembT::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)) // {SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // ElemGeomC0 & el = *(CoSfe->eleCentre); // DdlElement & tdd = CoSfe->tab_ddl; // int tail_fa = el.NbFe(); // nombre de faces, normalement = 1 // // dimensionnement des tableaux intermediaires // Tableau tab(nombre->nbneA); // les noeuds des segments frontieres // DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres // // // ici la dimension ne peut-être qu'égale à 3 // int tail_ar = el.NbSe(); // le nombre d'arêtes (de l'élément central) // int tail = tail_fa + tail_ar; // les cotés et la face centrale: normalement NbFe()=1 // // 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->nbnce; // le nombre de noeuds de l'élément central // int taille_f = tail_fa + tail_ar + 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; // posi_tab_front_lin=tail_fa; // } // 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->nbnce; // le nombre de noeuds de l'élément central // 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 ligne et pas de surface // { int tail_af = nombre->nbnce+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 // }; // // // création de la surface // if (tabb(1) == NULL) // { int nbnoe = nombre->nbnce; // nb noeud de la face centrale // Tableau tab(nbnoe); // les noeuds des faces frontieres // 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 de création de face // ind_front_surf = 1; // }; // // positionnement du début des lignes // posi_tab_front_lin = 1; // dans tous les cas, comme on vient de créer la surface, la ligne vient après // // création éventuelle des lignes // for (int nlign=1;nlign<=tail_ar;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))); // }; // 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 SfeMembT::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->nbnce)||(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->nbnce; // le nombre de noeuds de l'élément central // 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->nbnce);}; // // 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->nbnce;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 SfeMembT::Frontiere_lineique(int num,bool force) //{ // le calcul et la création ne sont effectués qu'au premier appel // // ou lorsque l'on veut forcer une recréation // // on regarde si les frontières linéiques existent sinon on les crée // if (!force) // {if (ind_front_lin == 1) // {return (ElFrontiere*)tabb(posi_tab_front_lin+num);} // else if ( ind_front_lin == 2) // // cas où certaines frontières existent // {if (tabb(posi_tab_front_lin+num) != NULL) // return (ElFrontiere*)tabb(posi_tab_front_lin+num); // }; // } // else // cas où on veut forcer une nouvelle création // { if (ind_front_lin != 0) // if (tabb(posi_tab_front_lin+num) != NULL) // {delete tabb(posi_tab_front_lin+num); //on commence par supprimer // tabb(posi_tab_front_lin+num)=NULL; // // on supprime également éventuellement la déformation associée pour un calcul d'arête // if (defArete.Taille() != 0) // {delete defArete(num);defArete(num)=NULL;}; // if (ind_front_lin == 1) // ind_front_lin = 2; // on indique // }; // }; // // arrivée ici cela veut dire que la frontière ligne n'existe pas // // on l'a reconstruit // // // le calcul et la création ne sont effectués qu'au premier appel // // ou lorsque l'on veut forcer une recréation // if ((ind_front_lin == 0) || force || (ind_front_lin == 2)) // {SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // ElemGeomC0 & el = *(CoSfe->eleCentre); // DdlElement & tdd = CoSfe->tab_ddl; // int tail_fa = el.NbFe(); // nombre de faces, normalement = 1 // // dimensionnement des tableaux intermediaires // Tableau tab(nombre->nbneA); // les noeuds des segments frontieres // DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres // // // ici la dimension ne peut-être qu'égale à 3 // int tail_ar = el.NbSe(); // le nombre d'arêtes (de l'élément central) // int tail = tail_fa + tail_ar; // les cotés et la face centrale: normalement NbFe()=1 // // // dimensionnement du tableau de frontières ligne si nécessaire // if (ind_front_lin == 0) // {if ((ind_front_point > 0) && (ind_front_surf == 0)) // // cas où les frontières points existent seule // { int tail_p = nombre->nbnce; // le nombre de noeuds de l'élément central // int taille_f = tail_fa + tail_ar + 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; // posi_tab_front_lin=tail_fa; // } // else if ((ind_front_point > 0) && (ind_front_surf > 0)) // // cas où les frontières points existent et surface et pas de ligne // { int tail_p = nombre->nbnce; // le nombre de noeuds de l'élément central // 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 // { // cas où il n'y a pas de frontières points // if (ind_front_surf == 0) // cas où il n'y a pas la surface // {tabb.Change_taille(tail_ar,NULL); // on n'a pas de ligne, pas de point et pas de surface // posi_tab_front_lin = 0;} // on peut tout mettre à NULL // else {tabb.Change_taille(tail_ar+tail_fa); // cas où les surfaces existent // for (int i=1;i<=tail_ar;i++) // tabb(i+tail_fa)=NULL; // posi_tab_front_lin = 1;}; // }; // }; // // // création de la ligne éventuellement // if ((tabb(posi_tab_front_lin+num) == NULL) || force) // { int nbnoe = el.NonS()(num).Taille(); // nb noeud de l'arête // Tableau tab(nbnoe); // les noeuds de l'arête frontiere // DdlElement ddelem(nombre->nbneA); // les ddlelements des noeuds frontieres // for (int i=1;i<= nbnoe;i++) // { tab(i) = tab_noeud(el.NonS()(num)(i)); // ddelem.Change_un_ddlNoeudElement(i,tdd(el.NonS()(num)(i))); // }; // tabb(posi_tab_front_lin+num) = new_frontiere_lin(tab,ddelem); // ind_front_lin = 1; // a priori // for (int nlign=1;nlign<=3;nlign++) // if (tabb(posi_tab_front_lin+nlign) == NULL) // { ind_front_lin = 2; break;}; // }; // }; // // maintenant normalement la frontière est créé on la ramène // return (ElFrontiere*)tabb(posi_tab_front_lin+num); //}; //// ramène la frontière surfacique //// éventuellement création de la frontiere surfacique de l'element et stockage dans l'element //// si c'est la première fois sinon il y a seulement retour de l'elements //// a moins que le paramètre force est mis a true //// dans ce dernier cas la frontière effacéee est recréée //// num indique le numéro de la surface à créer (numérotation EF) ici normalement uniquement 1 possible //ElFrontiere* const SfeMembT::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)) // { SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // ElemGeomC0 & el = *(CoSfe->eleCentre); // DdlElement & tdd = CoSfe->tab_ddlXi_C; //// int taille = tabb.Taille(); // la taille initiales des frontières // int tail_fa = 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->nbnce; // le nombre de noeuds // int taille_f = tail_fa + tail_p; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_p;i++) // { tabb(i+tail_fa) = tabb(i);tabb(i) = NULL;}; // posi_tab_front_point=tail_fa; // } // 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->nbnce+el.NonS().Taille(); // nombre d'arête + noeud // int taille_f = tail_fa + tail_af; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_af;i++) // transfert pour les noeuds // { tabb(i+tail_fa) = tabb(i);tabb(i) = NULL;} // posi_tab_front_point +=tail_fa; // posi_tab_front_lin +=tail_fa; // } // 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_fa + tail_a; // tabb.Change_taille(taille_f); // for (int i=1;i<= tail_a;i++) // transfert pour les noeuds // { tabb(i+tail_fa) = tabb(i);tabb(i) = NULL;} // posi_tab_front_point +=tail_fa; // posi_tab_front_lin +=tail_fa; // } // 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_fa); // le tableau total de frontières // // création éventuelle de la face // if (tabb(1) == NULL) // { int nbnoe = nombre->nbnce; // nb noeud de la surface centrale // Tableau tab(nbnoe); // les noeuds de la surface centrale // 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 SfeMembT::Libere () {Element::Libere (); // liberation de residu et raideur LibereTenseur() ; // liberation des tenseur intermediaires }; // acquisition ou modification d'une loi de comportement void SfeMembT::DefLoi (LoiAbstraiteGeneral * NouvelleLoi) { // verification du type de loi if (donnee_specif.epais != NULL) // cas d'un élément 2D {if ((NouvelleLoi->Dimension_loi() != 2) && (NouvelleLoi->Dimension_loi() != 4)) { cout << "\n Erreur, la loi de comportement a utiliser avec des SfeMembTs 2D "; cout << " doit etre de type 2D, \n ici elle est de type = " << (NouvelleLoi->Dimension_loi()) << "D !!! " << endl; Sortie(1); } } else // cas 3D ou quelconque {if ((NouvelleLoi->Dimension_loi() != 3) && (NouvelleLoi->Dimension_loi() != 4)) { cout << "\n Erreur, la loi de comportement a utiliser avec des SfeMembTs 3D "; cout << " doit etre de type 3D, \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; }; // définition de conditions limites pouvant affecter l'élément // on peut ainsi soit mettre une nouvelle condition, soit changer une ancienne condition // en cours de calcul, la condition peut changer // cas de plusieurs arêtes, la dimension des tableaux = le nombre d'arêtes // si arTypeCL(i) == RIEN_TYPE_CL, la condition est supprimée, et vpla(i) n'est pas utilisé void SfeMembT::DefCondLim(const Tableau & arTypeCL,const Tableau & vpla ) { // on commence par créer les tableaux locaux si besoin est if (areteTypeCL == (&(unefois->doCoMemb->tabType_rienCL))) { // si ça ne pointe pas sur la valeur par défaut, alors c'est qu'il y a // des CL particulières, on les crée donc à l'identique areteTypeCL = new Tableau (3,RIEN_TYPE_CL); vplan = new Tableau (3); }; // affectation (*areteTypeCL) = arTypeCL; int taille = areteTypeCL->Taille(); #ifdef MISE_AU_POINT if ((taille != 3) && (taille != 0)) { cout << "\n *** erreur dans la definition des conditions limites dans un element sfe, " << " le tableau doit etre de taille nulle ou =3 et ici la taille = " << taille; Affiche(1); Sortie(1); }; #endif if (taille == 3) {(*vplan) = vpla; // on affecte aussi les vecteurs de directions de tangente imposée #ifdef MISE_AU_POINT // on vérifie la taille if (vplan->Taille() != 3) { cout << "\n erreur dans la definition des conditions limites dans un element sfe, " << "la taille du tableau vplan doit etre =3 et ici la taille = " << vplan->Taille(); Affiche(1); Sortie(1); }; for (int i=1; i<= 3; i++) { if ((*areteTypeCL)(i)!=TANGENTE_CL) { cout << "\n erreur dans la definition des conditions limites dans un element sfe, " << "elle ne peuvent etre que de type de tangente imposée alors qu'ici " << " elle sont de type " << NomTypeCL((*areteTypeCL)(i)); Affiche(1); Sortie(1); }; }; #endif }; // on renseigne maintenant la déformation ((DeformationSfe1*) def)->RenseigneCondLim(*areteTypeCL,*vplan ); }; // définition de conditions limites pouvant affecter l'élément // on peut ainsi soit mettre une nouvelle condition, soit changer une ancienne condition // en cours de calcul, la condition peut changer // cas d'une seule arête, nb_ar = le numéro de l'arete // si arTypeCL == RIEN_TYPE_CL, la condition est supprimée, et vpla n'est pas utilisé void SfeMembT::DefCondLim(const EnuTypeCL & arTypeCL,const Coordonnee3& vpla,const int& nb_ar) { // on commence par créer les tableaux locaux si besoin est if (areteTypeCL == (&(unefois->doCoMemb->tabType_rienCL))) { // si ça ne pointe pas sur la valeur par défaut, alors c'est qu'il y a // des CL particulières, on les crée donc à l'identique areteTypeCL = new Tableau (3,RIEN_TYPE_CL); vplan = new Tableau (3); }; // affectation if (arTypeCL == RIEN_TYPE_CL) // cas où l'on veut par exemple annuler une condition existante {(*areteTypeCL)(nb_ar)=RIEN_TYPE_CL; // on laisse le vecteur condition telle qu'il est, de toute façon on ne s'en sert pas } else // cas où l'on met une nouvelle condition {(*areteTypeCL)(nb_ar)=arTypeCL; (*vplan)(nb_ar)=vpla; }; #ifdef MISE_AU_POINT // on vérifie la taille { if (arTypeCL!=TANGENTE_CL) { cout << "\n erreur dans la definition des conditions limites dans un element sfe, " << "elle ne peuvent etre que de type de tangente imposée alors qu'ici " << " elle sont de type " << NomTypeCL(arTypeCL); Affiche(1); Sortie(1); }; }; #endif // on renseigne maintenant la déformation ((DeformationSfe1*) def)->RenseigneCondLim(*areteTypeCL,*vplan ); }; // test si l'element est complet int SfeMembT::TestComplet() { int res = ElemMeca::TestComplet(); // test dans la fonction mere if (donnee_specif.epais != NULL) // test valide uniquement pour des éléments 2D if (( donnee_specif.epais->epaisseur0 == epaisseur_defaut) || ( donnee_specif.epais->epaisseur_t == epaisseur_defaut) || ( donnee_specif.epais->epaisseur_tdt == epaisseur_defaut)) { cout << "\n l\'epaisseur de l\'element Sfe n\'est pas defini \n"; res = 0; }; if ( tab_noeud(1) == NULL) { cout << "\n les noeuds de l\'element Sfe ne sont pas defini \n"; res = 0; } else { int testi =1; int posi = Id_nom_ddl("X1") -1; int dim = ParaGlob::Dimension(); int jmax = tab_noeud.Taille(); for (int i =1; i<= dim; i++) for (int j=1;j<=jmax;j++) if(!(tab_noeud(j)->Existe_ici(Enum_ddl(posi+i)))) testi = 0; // dans le cas où les épaisseurs sont stockées aux noeuds if (donnee_specif.epais == NULL) for (int j=1;j<=jmax;j++) if(!(tab_noeud(j)->Existe_ici(EPAIS))) testi = 0; if(testi == 0) { cout << "\n les ddls Xi des noeuds de la facette ne sont pas defini \n"; cout << " \n utilisez SfeMembT::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 et de la masse volumique Element* SfeMembT::Complete(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD) { // complétion avec bloc if (bloc.Nom(1) == "epaisseurs") {if (donnee_specif.epais != NULL) { donnee_specif.epais->epaisseur0 = donnee_specif.epais->epaisseur_t =donnee_specif.epais->epaisseur_tdt = bloc.Val(1); return this; } else { cout << "\n erreur: l'element SFE utilise une epaisseur definie aux noeuds " << " et non a l'element !!!!! "; Element::Affiche(1); Sortie(1); return this; // pour taire le compilo }; } // 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->sfematD == NULL) unefois->doCoMemb->sfematD = new Mat_pleine(nbddl,nbddl); if (unefois->doCoMemb->sferesD == NULL) unefois->doCoMemb->sferesD = new Vecteur(nbddl); // on renseigne les pointeurs d'ElemeMeca ElemMeca::matD = unefois->doCoMemb->sfematD; ElemMeca::resD = unefois->doCoMemb->sferesD; // on définie le tableau: noeud_a_prendre_en_compte if (unefois->doCoMemb->noeud_a_prendre_en_compte == NULL) {unefois->doCoMemb->noeud_a_prendre_en_compte = new Tableau (nombre->nbnte);} else {unefois->doCoMemb->noeud_a_prendre_en_compte->Change_taille(nombre->nbnte);}; // on prend en compte les noeuds centraux autres que sommet for (int i=1;i<=3;i++ ) (*unefois->doCoMemb->noeud_a_prendre_en_compte)(i)=0; for (int i=1;i<=nombre->nbnce;i++ ) (*unefois->doCoMemb->noeud_a_prendre_en_compte)(i)=1; // on ne prend pas en compte les noeuds externes for (int i=nombre->nbnce+1;i<=nombre->nbnte;i++ ) (*unefois->doCoMemb->noeud_a_prendre_en_compte)(i)=0; // ensuite les autres informations sont gérées par ElemMeca return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD); } else { return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD);}; }; // ajout du tableau de ddl des noeuds void SfeMembT::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->nbnte; ne++) {tab_noeud(ne)->PlusTabDdl(ta); // dans le cas où les épaisseurs sont stockées aux noeuds // on ajoute si besoin est l'épaisseur pour les noeuds du centre if ((donnee_specif.epais == NULL) && (ne <= nombre->nbnce)) {if (!(tab_noeud(ne)->Existe_ici(EPAIS))) {Ddl inter(EPAIS,0.,LIBRE); tab_noeud(ne)->PlusDdl(inter);} else {tab_noeud(ne)->Met_en_service(EPAIS);}; }; }; }; // =====>>>> methodes privées appelees par les classes dérivees <<<<===== // fonction d'initialisation servant dans les classes derivant // au niveau du constructeur // nbis : nb de pt d'integ de surface,nbie : nb de pt d'integ d'epaisseur // nbiSur : point d'intégration pour les forces de surfaces extérieures SfeMembT::DonnComSfe* SfeMembT::Init (ElemGeomC0* eleCentre,ElemGeomC0* eleEr,ElemGeomC0* eleS,ElemGeomC0* eleMas ,int type_calcul_jacobien,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->nbnte;i++) tab_noeud(i) = NULL; // definition des donnees communes aux SfeMembTxxx // a la premiere definition d'une instance bool epaisAuNoeud = (donnee_spec.epais == NULL); if (unefois->doCoMemb == NULL) unefois->doCoMemb = SfeMembT::Def_DonneeCommune(epaisAuNoeud,eleCentre,eleEr,eleS,eleMas); SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture met = &(CoSfe->met_SfeMembT); // met est defini dans elemeca // def de la manière dont le jacobien est calculé (ex: plat ou courbe) CoSfe->met_SfeMembT.ChangeTypeCalculJacobien(type_calcul_jacobien); // ajout de l'interpolation dans l'epaisseur aux tableaux globaux // def pointe sur la deformation specifique a l'element def = new DeformationSfe1(*met,tab_noeud,CoSfe->eleCentre->TaDphi(),CoSfe->eleCentre->TaPhi() ,(CoSfe->segment).TaDphi(),(CoSfe->segment).TaPhi()); // on met les conditions limites par défaut ((DeformationSfe1*) def)->RenseigneCondLim(CoSfe->tabType_rienCL,CoSfe->vplan_rien ); // on met à jour les pointeurs sur les infos par défaut areteTypeCL = (&(unefois->doCoMemb->tabType_rienCL)); vplan = (&(unefois->doCoMemb->vplan_rien)); // idem pour la remonte aux contraintes et le calcul d'erreur defEr = new Deformation(*met,tab_noeud,CoSfe->eleEr->TaDphi(),CoSfe->eleEr->TaPhi()); // idem pour les calculs relatifs à la matrice de masse defMas = new Deformation(*met,tab_noeud,CoSfe->eleMas->TaDphi(),CoSfe->eleMas->TaPhi()); // idem pour la déformation pour la surface, relative au force répartie // pour le calcul de second membre defSurf.Change_taille(1); // une seule surface pour le second membre defSurf(1) = new Deformation(CoSfe->met_surf_cent,t_N_centre, CoSfe->eleS->TaDphi(),CoSfe->eleS->TaPhi()); // pour le calcul de second membre int nb_arrete = CoSfe->eleCentre->NbSe(); // le nombre d'arêtes defArete.Change_taille(nb_arrete); // 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<=nb_arrete;ia++) defArete(ia) = NULL; //dimensionnement des deformations et contraintes int nbi = nombre->nbis * nombre->nbie; //dimensionnement des deformations et contraintes etc.. int dimtens = 2; if (epaisAuNoeud) dimtens = 3; lesPtMecaInt.Change_taille_PtIntegMeca(nbi,dimtens); // attribution des numéros de référencement dans le conteneur for (int ni = 1; ni<= 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(nbi); // stockage des donnees particulieres de la loi de comportement thermo physique au point d'integ tabSaveTP.Change_taille(nbi); // stockage des donnees particulieres de la déformation mécanique au point d'integ tabSaveDefDon.Change_taille(nbi); tab_energ.Change_taille(nbi); tab_energ_t.Change_taille(nbi); // initialisation des pointeurs définis dans la classe Element concernant les résidus et // raideur // --- cas de la puissance interne --- residu = &(CoSfe->residu_interne); // residu local raideur = &(CoSfe->raideur_interne); // raideur locale // --- cas de la dynamique ----- mat_masse = &(CoSfe->matrice_masse); // --- cas des efforts externes concernant les points ------ res_extN = &(CoSfe->residus_externeN); // pour les résidus et second membres raid_extN= &(CoSfe->raideurs_externeN);// pour les raideurs // --- cas des efforts externes concernant les aretes ------ res_extA = &(CoSfe->residus_externeA); // pour les résidus et second membres raid_extA= &(CoSfe->raideurs_externeA);// pour les raideurs // --- cas des efforts externes concernant les faces ------ res_extS= &(CoSfe->residus_externeS); // pour les résidus et second membres raid_extS= &(CoSfe->raideurs_externeS); // pour les raideurs return CoSfe; }; // fonction permettant le calcul de CoSfe // epaisAuNoeud indique si oui ou non l'épaisseur est définit aux noeuds SfeMembT::DonnComSfe* SfeMembT::Def_DonneeCommune (bool epaisAuNoeud,ElemGeomC0* eleCentre ,ElemGeomC0* eleEr,ElemGeomC0* eleS,ElemGeomC0* eleMas) { SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture // interpollation Enum_type_pt_integ type_pti=PTI_GAUSS; // dans le cas d'un nombre impair > 2, on utilise des points de Gauss lobatto if(nombre->nbie > 2) { if (nombre->nbie % 2 == 1) type_pti=PTI_GAUSS_LOBATTO; }; GeomSeg seg(nombre->nbie,2,type_pti); // interpolation dans l'épaisseur // degre de liberte int dim = 3; int nb_epais=0; if (epaisAuNoeud) nb_epais = 1; // --- def du tableau de ddl pour l'élément, il est ici possible que les noeuds n'aient // pas tous le même nombre de ddl actif (pour le centre xi+epai, pour les autres uniquement xi) Tableau mddl(nombre->nbnte); //contient le nb de ddl actif par noeud for (int ne = 1;ne<= nombre->nbnce;ne++) mddl(ne)=dim+nb_epais; for (int ne=nombre->nbnce+1;ne<=nombre->nbnte;ne++) mddl(ne)=dim; DdlElement tab_ddl(nombre->nbnte,mddl); // on le remplit int posi = Id_nom_ddl("X1") -1; for (int i =1; i<= dim; i++) for (int j=1; j<= nombre->nbnte; j++) // tab_ddl (j,i) = Enum_ddl(i+posi); tab_ddl.Change_Enum(j,i,Enum_ddl(i+posi)); // pour l'épaisseur éventuellement if (epaisAuNoeud) for (int j=1; j<= nombre->nbnce; j++) tab_ddl.Change_Enum(j,dim+nb_epais,EPAIS); // on définit le tableau de correspondance entre la numérotation des ddl dans la métrique et // celui dans tab_ddl. Pour la métrique, on a d'abord tous les ddl de xi, puis à la fin // les ddl d'épaisseurs éventuel. Dans tab_ddl, on a pour chaque noeud central ddlxi puis epais // et pour les ddl externes que les xi int nbddl = tab_ddl.NbDdl(); int nbddl_xi = tab_ddl.NbDdl_famille(X1); Tableau nMetVTab_ddl(nbddl); if (!epaisAuNoeud) // cas sans ddl d'épaisseur {for (int i=1;i<=nbddl;i++) nMetVTab_ddl(i)=i;} else // cas avec des ddl d'épaisseur {int iddl=1; // d'abord les xi du centre for (int ne = 1;ne <= nombre->nbnce; ne++) for (int i=1;i<=dim;i++,iddl++) nMetVTab_ddl(iddl) = i + (ne-1) * (dim+1); // puis les xi des noeuds externes int decalxi = nombre->nbnce*(dim+1); // le total de ddl xi du centre pour tab_ddl int nddcentreXi = nombre->nbnce*dim; // le total de ddl xi du centre pour metsfe int restexi = nbddl_xi - nddcentreXi; for (int ddi = 1;ddi<=restexi;ddi++,iddl++) nMetVTab_ddl(iddl) = ddi + decalxi; // puis les épaisseurs for (int iep=1;iep<= nombre->nbnce;iep++,iddl++) nMetVTab_ddl(iddl) = iep * (dim+1); }; // 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->nbnce,nbcomposante); posi = Id_nom_ddl("SIG11") -1; // uniquement deux cas a considéré 3 ou 6 composantes for (int j=1; j<= nombre->nbnce; j++) {// on definit le nombre de composante de sigma en absolu if (nbcomposante == 3) // dans l'énumération les composantes ne sont pas a suivre {//tab_ddlErr (j,1) = Enum_ddl(1+posi); // cas de SIG11 //tab_ddlErr (j,2) = Enum_ddl(2+posi); // cas de SIG22 //tab_ddlErr (j,3) = Enum_ddl(4+posi); // cas de SIG12 tab_ddlErr.Change_Enum(j,1,Enum_ddl(1+posi)); // cas de SIG11 tab_ddlErr.Change_Enum(j,2,Enum_ddl(2+posi)); // cas de SIG22 tab_ddlErr.Change_Enum(j,3,Enum_ddl(4+posi)); // cas de SIG12 } else if (nbcomposante == 6) // les composantes sont a suivre dans l'enumération for (int i= 1;i<= nbcomposante; i++) // tab_ddlErr (j,i) = Enum_ddl(i+posi); tab_ddlErr.Change_Enum(j,i,Enum_ddl(i+posi)); }; // egalement pour tab_Err1Sig11, def d'un tableau de un ddl : enum SIG11 // par noeud DdlElement tab_Err1Sig11(nombre->nbnce,DdlNoeudElement(SIG11)); // toujours pour le calcul d'erreur definition des fonctions d'interpolation // pour le calcul du hession de la fonctionnelle GeomSeg segEr(nombre->nbieEr); // pour les calculs relatifs à la matrice masse GeomSeg segMas(nombre->nbieMas); // pour le calcul des seconds membres GeomSeg segS(nombre->nbiA,nombre->nbneA); // --- def metrique // on definit les variables a priori toujours utiles Tableau tab(27); 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; tab(25)= id_giB_t; tab(26)= id_giH_t; tab(27)= id_giB_tdt; // tableau de ddl et la def de variables // def du nombre de vecteur de la métrique pour l'élément SFE, donc choix entre tenseur 2x2 ou 3x3 int nbvec = 2; // choix par défaut if (epaisAuNoeud) nbvec = 3; Met_Sfe1 metri(tab_ddl,nbvec,tab,id_interpol,nombre->nbnce) ; // --- def de la métrique de surface qui est utile en particulier pour calculer les forces externes --- // !! on n'utilise que la facette centrale et les ddl xi uniquement !! // en effet: on part du principe que cette métrique et la def associée ne seront relatives qu'aux ddl de déplacement // en particulier on ne tiend pas compte d'un ddl d'épaisseur éventuel: par exemple on estime que la // variation des efforts dus à une pression, ne dépend pas des ddl d'épaisseur (s'ils existent) // == on reconstruit un DdlElement relatif aux xi uniquement // --- def du tableau de ddl pour l'élément, il est ici possible que les noeuds n'aient // pas tous le même nombre de ddl actif (pour le centre xi+epai, pour les autres uniquement xi) Tableau mddl_C(nombre->nbnce); //contient le nb de ddl xi par noeud for (int ne = 1;ne<= nombre->nbnce;ne++) mddl_C(ne)=dim; DdlElement tab_ddlXi_C(nombre->nbnce,mddl_C); // on le remplit posi = Id_nom_ddl("X1") -1; for (int i =1; i<= dim; i++) for (int j=1; j<= nombre->nbnce; j++) tab_ddlXi_C.Change_Enum(j,i,Enum_ddl(i+posi)); // == maintenant on s'occupe de définir la métrique int nbvec_surf = 2; // nombre de vecteur de la surface médiane Met_abstraite met_centrale(dim,nbvec_surf,tab_ddlXi_C,tab,nombre->nbnce); // ---- 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->nbnce); Mat_pleine raidEr(nombre->nbnce,nombre->nbnce); // la raideur pour l'erreur // dimensionnement des différents résidus et raideurs pour le calcul mécanique 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 //*** pour l'instant , le dimensionnement pour les noeuds et pour les arêtes n'est pas correcte dans le cas // où il y a un ddl d'épaisseur au noeuds (voir face interne comme exemple correcte) Tableau residus_extN(nombre->nbnce); residus_extN(1) = new Vecteur(dim); Tableau raideurs_extN(nombre->nbnce); raideurs_extN(1) = new Mat_pleine(dim,dim); for (int i = 2;i<= nombre->nbnce;i++) { residus_extN(i) = residus_extN(1); raideurs_extN(i) = raideurs_extN(1); } // cas des arêtes int nbddlA = nombre->nbneA * dim; int nbA = 3; // 3 arêtes internes Tableau residus_extA(nbA); residus_extA(1) = new Vecteur(nbddlA); residus_extA(2) = residus_extA(1); residus_extA(3) = 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); // cas de la face interne int nbddlS = nombre->nbnce * dim; // ddl pour la face Vecteur * res_extS_inter=NULL; Mat_pleine * raid_extS_inter=NULL; // grandeurs intermédiaires if (epaisAuNoeud) {// on définit les tableaux inter, de dimensionnement classique pour pouvoir // utiliser les méthodes classiques d'ElemMeca res_extS_inter = new Vecteur(nbddlS); raid_extS_inter = new Mat_pleine(nbddlS,nbddlS); // puis on prend en compte le ddl d'épaisseur nbddlS += nombre->nbnce; // on ajoute l'épaisseur }; Tableau residus_extS(1); residus_extS(1) = new Vecteur(nbddlS); Tableau raideurs_extS(1); raideurs_extS(1) = new Mat_pleine(nbddlS,nbddlS); // définition des conditions limites par défaut Tableau tabType_rienCL(3); tabType_rienCL(1)=RIEN_TYPE_CL;tabType_rienCL(2)=RIEN_TYPE_CL; tabType_rienCL(3)=RIEN_TYPE_CL; Tableau vplan_rien(3); // initialisé à 0. par défaut // definition de la classe static contenant toute les variables communes aux SfeMembT SfeMembT::DonnComSfe* dodo; dodo = new DonnComSfe (eleCentre,seg,tab_ddl,tab_ddlErr,tab_Err1Sig11,tab_ddlXi_C,metri,resEr,raidEr,eleEr,segEr,eleS,segS ,residu_int,raideur_int,residus_extN,raideurs_extN,residus_extA,raideurs_extA,residus_extS,raideurs_extS ,matmasse,eleMas,segMas,nombre->nbis * nombre->nbie,tabType_rienCL,vplan_rien,nMetVTab_ddl,met_centrale); return dodo; }; // destructions de certaines grandeurs pointées, créées au niveau de l'initialisation void SfeMembT::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 { SfeMembT::DonnComSfe* CoSfe = unefois->doCoMemb; // pour simplifier l'écriture int resErrTaille = CoSfe->resErr.Taille(); for (int i=1;i<= resErrTaille;i++) delete CoSfe->resErr(i); delete CoSfe->residus_externeN(1); delete CoSfe->raideurs_externeN(1); delete CoSfe->residus_externeA(1); delete CoSfe->raideurs_externeA(1); delete CoSfe->residus_externeS(1); delete CoSfe->raideurs_externeS(1); // suppression des éléments géométriques de référence delete CoSfe->eleCentre; delete CoSfe->eleEr; delete CoSfe->eleS; delete CoSfe->eleMas; }; // enfin il faut certaine fois supprimer les conditions limites tant que unefois existe // comme unefois pointe sur un membre statique de la classe dérivée, si on attend d'arriver dans // le destructeur de SfeMembT il n'existe plus à ce moment là donc erreur if (areteTypeCL != (&(unefois->doCoMemb->tabType_rienCL))) // si ça ne pointe pas sur la valeur par défaut, alors c'est qu'il y a // des CL particulières, on les supprime { delete areteTypeCL; delete vplan;}; };