// FICHIER : ElemPoint.cc // CLASSE : ElemPoint // This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-2022 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . //#include "Debug.h" # include using namespace std; //introduces namespace std #include #include "Sortie.h" #include "ElemPoint.h" #include "FrontPointF.h" #include "TypeConsTens.h" #include "Def_Umat.h" #include "ExceptionsLoiComp.h" //---------------------------------------------------------------- // def des donnees commune a tous les elements // la taille n'est pas defini ici car elle depend de la lecture //---------------------------------------------------------------- ElemPoint::DonneeCommune * ElemPoint::doCo_Point = NULL; ElemPoint::UneFois ElemPoint::unefois_Point; ElemPoint::NombresConstruire ElemPoint::nombre_V; ElemPoint::ConstrucElemPoint ElemPoint::construcElemPoint; // constructeur définissant les nombres (de noeud, de point d'integ ..) // utilisé dans la construction des éléments ElemPoint::NombresConstruire::NombresConstruire() { nbne = 1; // le nombre de noeud de l'élément nbiEr = 1;// le nombre de point d'intégration pour le calcul d'erreur nbiMas = 1; // le nombre de point d'intégration pour le calcul de la matrice masse }; // ---- definition du constructeur de la classe conteneur de donnees communes ------------ ElemPoint::DonneeCommune::DonneeCommune (GeomPoint& pteg,DdlElement& tab,DdlElement& tabErr,DdlElement& tab_Err1Sig, Met_ElemPoint& met_point, Tableau & resEr,Mat_pleine& raidEr, GeomPoint& pteEr,Vecteur& residu_int,Mat_pleine& raideur_int, Tableau & residus_extN,Tableau & raideurs_extN, Mat_pleine& mat_masse,GeomPoint& pteMa,UmatAbaqus& umatAbaqusqus,int dim_tenseur,int nbi) : ptpoint(pteg),tab_ddl(tab),tab_ddlErr(tabErr),tab_Err1Sig11(tab_Err1Sig) ,met_ElemPoint(met_point) ,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) ,pteEr(pteEr) ,residu_interne(residu_int),raideur_interne(raideur_int) ,residus_externeN(residus_extN),raideurs_externeN(raideurs_extN) ,matrice_masse(mat_masse) ,pteMas(pteMa) ,umatAbaqus(umatAbaqusqus),inne() { 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 (dim_tenseur); }; int tailledeps = d_epsBB.Taille(); for (int i=1;i<= tailledeps; i++) d_epsBB(i) = NevezTenseurBB (dim_tenseur); int tailledsig = d_sigHH.Taille(); for (int j=1;j<= tailledsig; j++) d_sigHH(j) = NevezTenseurHH (dim_tenseur); // liaisons entre inne et umatAbaqus inne.incre = &umatAbaqus.nb_increment; inne.step = &umatAbaqus.nb_step; inne.nbe = &umatAbaqus.nb_elem; inne.nbpti = &umatAbaqus.nb_pt_integ; inne.temps_tdt = &umatAbaqus.temps_tdt; inne.delta_t = &umatAbaqus.delta_t; inne.nom_loi = &umatAbaqus.nom_materiau; }; ElemPoint::DonneeCommune::DonneeCommune(DonneeCommune& a) : ptpoint(a.ptpoint),tab_ddl(a.tab_ddl),tab_ddlErr(a.tab_ddlErr),tab_Err1Sig11(a.tab_Err1Sig11) ,met_ElemPoint(a.met_ElemPoint),matGeom(a.matGeom),matInit(a.matInit) ,d2_epsBB(a.d2_epsBB),resErr(a.resErr),raidErr(a.raidErr),pteEr(a.pteEr) ,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) ,matrice_masse(a.matrice_masse),pteMas(a.pteMas) ,umatAbaqus(a.umatAbaqus),inne() { 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))); // liaisons entre inne et umatAbaqus inne.incre = &umatAbaqus.nb_increment; inne.step = &umatAbaqus.nb_step; inne.nbe = &umatAbaqus.nb_elem; inne.nbpti = &umatAbaqus.nb_pt_integ; inne.temps_tdt = &umatAbaqus.temps_tdt; inne.delta_t = &umatAbaqus.delta_t; inne.nom_loi = &umatAbaqus.nom_materiau; }; ElemPoint::DonneeCommune::~DonneeCommune() { 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 -+-+-+ ElemPoint::UneFois::UneFois () : // constructeur par défaut doCoMemb(NULL),CalResPrem_t(0),CalResPrem_tdt(0),CalimpPrem(0),dualSortbiel(0) ,CalSMlin_t(0),CalSMlin_tdt(0),CalSMRlin(0) ,CalDynamique(0),CalPt_0_t_tdt(0) ,nbelem_in_Prog(0) {}; ElemPoint::UneFois::~UneFois () { delete doCoMemb; }; // -+-+ fin definition de la classe contenant tous les indicateurs qui sont modifiés une seule fois -+-+-+ // ---------- fin definition de la classe conteneur de donnees communes ------------ // Constructeur par defaut // les tenseurs on par défaut (dimension==-1) la dimension de l'espace // sinon il ont la dimension donnée ElemPoint::ElemPoint (int dimension) : ElemMeca(),nbi(1),nb_appelsCalculUmat(0),lesPtMecaInt() { unefois=&unefois_Point; // le cas d'un vrai ElemPoint if (unefois->nbelem_in_Prog == 0) { unefois->nbelem_in_Prog++; // au premier passage on se contente d'incrémenter } else // sinon on construit {id_interpol=CONSTANT; // donnees de la classe mere id_geom=POINT; Element::Change_TypeProblem(MECA_SOLIDE_DEFORMABLE); //mise à jour du type de pb tab_noeud.Change_taille(nombre_V.nbne); // initialisation par défaut int dim_tenseur = ParaGlob::Dimension(); if (dimension != -1) dim_tenseur = dimension; Init (dim_tenseur); unefois->nbelem_in_Prog++; }; }; // Constructeur fonction d'un numero de maillage et d'identification ElemPoint::ElemPoint (int num_mail,int num_id,int dimension) : ElemMeca(num_mail,num_id,CONSTANT,POINT),nbi(1),nb_appelsCalculUmat(0) ,lesPtMecaInt() {unefois=&unefois_Point; // le cas d'un vrai ElemPoint if (unefois->nbelem_in_Prog == 0) { unefois->nbelem_in_Prog++; // au premier passage on se contente d'incrémenter } else // sinon on construit {tab_noeud.Change_taille(nombre_V.nbne); // initialisation par défaut int dim_tenseur = ParaGlob::Dimension(); if (dimension != -1) dim_tenseur = dimension; unefois->nbelem_in_Prog++; Init (dim_tenseur); Element::Change_TypeProblem(MECA_SOLIDE_DEFORMABLE); //mise à jour du type de pb }; }; //------- pour des classes dérivées ------ // CONSTRUCTEURS : // les tenseurs on par défaut (dimension==-1) la dimension de l'espace // sinon il ont la dimension donnée ElemPoint::ElemPoint (ElemPoint::UneFois& unefoisfois, Enum_geom nouveau_id, int dimension) : ElemMeca(),nbi(1),nb_appelsCalculUmat(0),lesPtMecaInt() { unefois=&unefoisfois; // le cas d'un vrai ElemPoint if (unefois->nbelem_in_Prog == 0) { unefois->nbelem_in_Prog++; // au premier passage on se contente d'incrémenter } else // sinon on construit {id_interpol=CONSTANT; // donnees de la classe mere id_geom=nouveau_id; Element::Change_TypeProblem(MECA_SOLIDE_DEFORMABLE); //mise à jour du type de pb tab_noeud.Change_taille(nombre_V.nbne); // initialisation par défaut int dim_tenseur = ParaGlob::Dimension(); if (dimension != -1) dim_tenseur = dimension; unefois->nbelem_in_Prog++; Init (dim_tenseur); }; }; // Constructeur fonction d'un numero de maillage et d'identification ElemPoint::ElemPoint (ElemPoint::UneFois& unefoisfois, Enum_geom nouveau_id, int num_mail,int num_id,int dimension) : ElemMeca(num_mail,num_id,CONSTANT,nouveau_id),nbi(1),nb_appelsCalculUmat(0) ,lesPtMecaInt() {unefois=&unefoisfois; // le cas d'un vrai ElemPoint if (unefois->nbelem_in_Prog == 0) { unefois->nbelem_in_Prog++; // au premier passage on se contente d'incrémenter } else // sinon on construit {tab_noeud.Change_taille(nombre_V.nbne); // initialisation par défaut int dim_tenseur = ParaGlob::Dimension(); if (dimension != -1) dim_tenseur = dimension; unefois=&unefoisfois; // le cas d'un vrai ElemPoint unefois->nbelem_in_Prog++; Init (dim_tenseur); Element::Change_TypeProblem(MECA_SOLIDE_DEFORMABLE); //mise à jour du type de pb }; }; ElemPoint::ElemPoint (const ElemPoint& a) : ElemMeca (a),nbi(a.nbi),nb_appelsCalculUmat(0) ,lesPtMecaInt(a.lesPtMecaInt) // Constructeur de copie // a priori si on utilise le constructeur de copie, donc il y a déjà un élément // par contre a priori on ne doit pas faire une copie du premier élément {unefois= a.unefois; // le cas d'un vrai ElemPoint if (unefois->nbelem_in_Prog == 1) { cout << "\n **** erreur pour l'element ElemPoint, le constructeur de copie ne doit pas etre utilise" << " pour le premier element !! " << endl; Sortie (1); } else {// initialisation unefois = a.unefois; int dim_tenseur=lesPtMecaInt(1).EpsBB()->Dimension(); unefois->nbelem_in_Prog++; Init (dim_tenseur); }; }; ElemPoint::~ElemPoint () // Destructeur { LibereTenseur(); unefois->nbelem_in_Prog--; Destruction(); }; // Lecture des donnees de la classe sur fichier void ElemPoint::LectureDonneesParticulieres (UtilLecture * entreePrinc,Tableau * tabMaillageNoeud) { int nb; tab_noeud.Change_taille(1); int i=1; // on ne continue que si le tableau de noeud passé en paramètre a une taille non nulle if ( (*tabMaillageNoeud).Taille() != 0) {*(entreePrinc->entree) >> nb; if ( ((entreePrinc->entree)->rdstate() == 0) || ((entreePrinc->entree)->eof()) ) // ici il n'y a qu'une seule information à lire, donc dès le début on a // io_state == 1 // 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 != 2) 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 << "ElemPoint::LectureDonneesParticulieres"; Affiche(); Sortie (1); }; // construction du tableau de ddl des noeuds de ElemPoint ConstTabDdl(); }; }; // on associe un noeud à l'élément, remplace le noeud existant, s'il existe déjà void ElemPoint::Associer_noeud (Noeud * noeu) { // on dimensionne le tableau de noeud éventuellement tab_noeud.Change_taille(1); // on réaffecte tab_noeud(1)=noeu; // construction du tableau de ddl des noeuds de ElemPoint 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 & ElemPoint::Point_physique(const Coordonnee& c_int,Coordonnee & co,Enum_dure temps) { ElemPoint::DonneeCommune* doCo = 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; // b) calcul de l'interpolation const Vecteur& phi = doCo->ptpoint.Phi_point(c_int); // c) calcul du point switch (temps) { case TEMPS_0 : co = doCo->met_ElemPoint.PointM_0(tab_noeud,phi); break; case TEMPS_t : co = doCo->met_ElemPoint.PointM_t(tab_noeud,phi); break; case TEMPS_tdt : co = doCo->met_ElemPoint.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 ElemPoint::Point_physique(const Coordonnee& c_int,Tableau & t_co) { ElemPoint::DonneeCommune* doCo = 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; // b) calcul de l'interpolation const Vecteur& phi = doCo->ptpoint.Phi_point(c_int); // c) calcul des point switch (t_co.Taille()) { case 3 : t_co(3) = doCo->met_ElemPoint.PointM_tdt(tab_noeud,phi); case 2 : t_co(2) = doCo->met_ElemPoint.PointM_t(tab_noeud,phi); case 1 : t_co(1) = doCo->met_ElemPoint.PointM_0(tab_noeud,phi); }; }; // Calcul du residu local à t ou tdt en fonction du booleen atdt Vecteur* ElemPoint::CalculResidu (bool atdt,const ParaAlgoControle & pa) { ElemPoint::DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier l'écriture Tableau & d_epsBB = (doCo->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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; } 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; }; // initialisation du résidu residu->Zero(); Vecteur poids =(doCo->ptpoint).TaWi(); // poids d'interpolation = 2 ElemMeca::Cal_explicit ( doCo->tab_ddl,d_epsBB,1,poids,pa,atdt); return residu; }; // Calcul du residu local et de la raideur locale, // pour le schema implicite Element::ResRaid ElemPoint::Calcul_implicit (const ParaAlgoControle & pa) { ElemPoint::DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier l'écriture Tableau & d_epsBB = (doCo->d_epsBB);// " Tableau & d_sigHH = (doCo->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; doCo->met_ElemPoint.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; }; // initialisation du résidu residu->Zero(); // initialisation de la raideur raideur->Zero(); Vecteur poids =(doCo->ptpoint).TaWi(); // --- pour l'instant il n'y a pas de calcul, on retourne les matrices vides // ElemMeca::Cal_implicit // (doCo->tab_ddl, d_epsBB,(doCo->d2_epsBB),d_sigHH,nbi,poids,pa,cald_Dvirtuelle); Element::ResRaid el; el.res = residu; el.raid = raideur; return el; }; // calcul de l'UMat pour abaqus void ElemPoint::CalculUmatAbaqus(ParaAlgoControle & pa) { // -- récupération des variables Umat abaqus UmatAbaqus& umatA = unefois->doCoMemb->umatAbaqus; // pour simplifier // cas du premier passage 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; unefois->doCoMemb->met_ElemPoint.PlusInitVariables(tab) ; }; // -- appel de la loi de comportement int ni=umatA.nb_pt_integ; // num du pt d'integ (pour simplifier) // on change les coordonnées du point associé au premier pti // (a priori ce n'est pas utilisé ici mais on le fait quand même pour le futur) tab_noeud(1)->Change_coord2(umatA.coor_pt); // on change la température au noeud en fonction de ce qui existe à l'umat // car ce sera utilisé pour les grandeurs interpolées aux noeuds if (tab_noeud(1)->Existe_ici(TEMP)) {tab_noeud(1)->Change_val_t(TEMP,umatA.temper_t); tab_noeud(1)->Change_val_tdt(TEMP,umatA.temper_t + umatA.delta_temper); }; // on change le numéro d'intégration pour les calculs d'interpolation c-a-d des acces // aux tableaux phi et dphi : pour le point il n'y a qu'un pti !! def->ChangeNumInteg(1); //ni); // on associe la déformation à la bonne sauvegarde def->Mise_a_jour_data_specif(tabSaveDefDon(ni)); // mise à jour de la métrique avec les infos de umat ((Def_Umat*)def)->Mise_a_jourUmat(umatA); // valeurs aux pt d'integ PtIntegMecaInterne & ptIntegMeca = (*lesPtIntegMecaInterne)(ni); // on regarde si c'est le premier incrément ou pas (d'où le calcul du premier pas) premier_calcul_meca_impli_expli=false; if (umatA.nb_increment <= 1) premier_calcul_meca_impli_expli = true; CompThermoPhysiqueAbstraite::SaveResul* sTP=NULL; // les données spécifique thermo physiques if (loiTP != NULL) {sTP = tabSaveTP(ni);}; // au pt d'integ si elles existes #ifdef MISE_AU_POINT if ( ParaGlob::NiveauImpression() > 5) {cout << "\n ElemPoint::CalculUmatAbaqus(... " << " dilatation= "<< dilatation << flush; }; #endif // on gère les exceptions éventuelles en mettant le bloc sous surveillance try { // appel du comportement Umat loiComp->ComportementUmat(tabSaveDon(ni),*def,ptIntegMeca,pa,sTP,loiTP,dilatation,umatA ,premier_calcul_meca_impli_expli); } catch (ErrNonConvergence_loiDeComportement excep) // cas d'une d'une erreur survenue à cause d'une non convergence pour la résolution // d'une loi de comportement { // l'idée est que dans le cas où il y a un pb avec la loi on signale qu'il faut diminuer le pas de temps ?? // c'est surtout pour une utilisation avec Abaqus umatA.pnewdt = sqrt(2.)/2.; if (ParaGlob::NiveauImpression() >= 1) cout << "\n warning: CalculUmatAbaqus: modification du pas de temps -> du parametre pnewt"; } catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur { ErrSortieFinale toto; throw (toto); } catch ( ... ) { if (ParaGlob::NiveauImpression() >= 1) {cout << "\n warning: exception generee par la loi de comportement sous Umat mais dont la prise en compte " << " n'est pas prevu !, on demande une diminution du pas de temps de 0.5 "; // << " n'est pas prevu !, on ne fait rien et on continue le calcul"; umatA.pnewdt = 0.5; if (ParaGlob::NiveauImpression() >= 4) cout << "\n ElemPoint::CalculUmatAbaqus(.."; }; }; // comptabilisation des appels si c'est le premier point d'intégration if (ni == 1) nb_appelsCalculUmat++; }; // initialisation éventuelle: ajout de point d'intégration si nécessaire // les tenseurs on par défaut (dim_tens==-1) la dimension de l'espace void ElemPoint::InitialisationUmatAbaqus_interne(int dim_tens) { // dans le cas où le nombre de point d'intégration lue est supérieur à celui de l'élément // on agrandi les tableaux (qui sont des tableaux de pointeurs if (unefois->doCoMemb->umatAbaqus.nb_pt_integ > nbi) { int dim_tenseur = ParaGlob::Dimension(); if (dim_tens != -1) dim_tenseur = dim_tens; ChangeNombrePtinteg(unefois->doCoMemb->umatAbaqus.nb_pt_integ,dim_tenseur); }; }; // Calcul de la matrice masse pour l'élément Mat_pleine * ElemPoint::CalculMatriceMasse (Enum_calcul_masse type_calcul_masse) { ElemPoint::DonneeCommune* doCo = 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; doCo->met_ElemPoint.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 = doCo->tab_ddl.NbDdl(); (doCo->matrice_masse).Initialise (nbddl,nbddl,0.); } }; Vecteur poids =(doCo->pteMas).TaWi(); // poids d'intégration = 2 // appel de la routine générale ElemMeca::Cal_Mat_masse (doCo->tab_ddl,type_calcul_masse, nombre_V.nbiMas,(doCo->pteMas).TaPhi(),nombre_V.nbne ,poids); return mat_masse; }; //------- calcul d'erreur, remontée des contraintes ------------------- // 1) calcul du résidu et de la matrice de raideur pour le calcul d'erreur Element::Er_ResRaid ElemPoint::ContrainteAuNoeud_ResRaid() { DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; // appel du programme général ElemMeca:: SigmaAuNoeud_ResRaid(tab_noeud.Taille() ,(doCo->ptpoint).TaPhi() ,(doCo->ptpoint).TaWi() ,doCo-> resErr,doCo->raidErr ,(doCo->pteEr).TaPhi() ,(doCo->pteEr).TaWi()); return (Element::Er_ResRaid( &(doCo-> resErr),&(doCo->raidErr))); }; // 2) remontée aux erreurs aux noeuds Element::Er_ResRaid ElemPoint::ErreurAuNoeud_ResRaid() { DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; // appel du programme général ElemMeca::Cal_ErrAuxNoeuds(tab_noeud.Taille(), (doCo->ptpoint).TaPhi(), (doCo->ptpoint).TaWi(),doCo-> resErr ); return (Element::Er_ResRaid( &(doCo-> resErr),&(doCo->raidErr))); }; // actualisation des ddl et des grandeurs actives de t+dt vers t void ElemPoint::TdtversT() { for (int ni=1;ni<= nbi; ni++) { lesPtMecaInt.TdtversT(); if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TdtversT(); if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TdtversT(); if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TdtversT(); }; ElemMeca::TdtversT_(); // appel de la procédure mère // normalement ça correspond à la convergence, on met à -1 le nombre d'appel // ainsi au premier appel on aura l'itération 0 nb_appelsCalculUmat = -1; }; // actualisation des ddl et des grandeurs actives de t vers tdt void ElemPoint::TversTdt() { for (int ni=1;ni<= nbi; ni++) { lesPtMecaInt.TversTdt(); if (tabSaveDon(ni) != NULL) tabSaveDon(ni)->TversTdt(); if (tabSaveTP(ni) != NULL) tabSaveTP(ni)->TversTdt(); if (tabSaveDefDon(ni) != NULL) tabSaveDefDon(ni)->TversTdt(); }; ElemMeca::TversTdt_(); // appel de la procédure mère }; // calcul de l'erreur sur l'élément. Ce calcul n'est disponible // qu'une fois la remontée aux contraintes effectuées sinon aucune // action. En retour la valeur de l'erreur sur l'élément // type indique le type de calcul d'erreur : void ElemPoint::ErreurElement(int type,double& errElemRelative ,double& numerateur, double& denominateur) { DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; // appel du programme général ElemMeca::Cal_ErrElem(type,errElemRelative,numerateur,denominateur, tab_noeud.Taille(),(doCo->ptpoint).TaPhi(), (doCo->ptpoint).TaWi(), (doCo->pteEr).TaPhi(),(doCo->pteEr).TaWi()); }; //============= 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 ElemPoint::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 de la ElemPoint // car on n'a pas dimensionné les tableaux qui suivent !! switch (cas) { case 1 : // ------- on récupère tout ------------------------- { string toto; int nbi_old = nbi; ent >> toto >> nbi ; // récup du nombre de point d'intégration // construction du tableau de ddl des noeuds de ElemPoint ConstTabDdl(); // des déformations et contraintes éventuelles int dim_tens; ent >> dim_tens; // lecture de l'indicateur pour savoir s'il y a des tenseurs ou pas if (nbi != nbi_old) ChangeNombrePtinteg(nbi,dim_tens); // récupération lesPtMecaInt.Lecture_base_info(ent,cas); break; } case 2 : // ----------- lecture uniquement de se qui varie -------------------- { // récup info // des déformations et contraintes éventuelles int dim_tens;string toto; ent >> toto >> dim_tens; // lecture de l'indicateur pour savoir s'il y a des tenseurs ou pas // récupération lesPtMecaInt.Lecture_base_info(ent, cas); break; } default : { cout << "\nErreur : valeur incorrecte du type de lecture !\n"; cout << "ElemPoint::Lecture_base_info(ofstream& sort,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 ElemPoint::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 de la ElemPoint // sinon on essaie de sauvegarder switch (cas) { case 1 : // ------- on sauvegarde tout ------------------------- {sort << "\n nbpti= " << nbi << " "; sort << lesPtMecaInt.DimTens() << " "; // des tenseurs déformation et contrainte, lesPtMecaInt.Ecriture_base_info(sort,cas); break; } case 2 : // ----------- sauvegarde uniquement de se qui varie -------------------- { // la déformation et la contrainte sort << "\n dim_tenseur: " << lesPtMecaInt.DimTens() << " "; // des tenseurs déformation et contrainte, lesPtMecaInt.Ecriture_base_info(sort,cas); break; } default : { cout << "\nErreur : valeur incorrecte du type d'écriture !\n"; cout << "ElemPoint::Ecriture_base_info(ofstream& sort,int cas)" << " cas= " << cas << endl; Sortie(1); }; }; }; // Calcul de la matrice géométrique et initiale ElemMeca::MatGeomInit ElemPoint::MatricesGeometrique_Et_Initiale (const ParaAlgoControle & pa) { ElemPoint::DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier l'écriture Tableau & d_epsBB = (doCo->d_epsBB);// " Tableau & d_sigHH = (doCo->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; doCo->met_ElemPoint.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; }; // Par simplicité Mat_pleine & matGeom = doCo->matGeom; Mat_pleine & matInit = doCo->matInit; // mise à zéro de la matrice géométrique matGeom.Initialise(); Vecteur poids =(doCo->ptpoint).TaWi(); // poids d'interpolation = 2 ElemMeca::Cal_matGeom_Init (matGeom,matInit,doCo->tab_ddl, d_epsBB, doCo->d2_epsBB,d_sigHH,1,poids,pa,cald_Dvirtuelle); return MatGeomInit(&matGeom,&matInit); } ; // retourne les tableaux de ddl associés aux noeuds, gere par l'element // ce tableau et specifique a l'element const DdlElement & ElemPoint::TableauDdl() const { DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier return doCo->tab_ddl; }; // liberation de la place pointee void ElemPoint::Libere () {Element::Libere (); // liberation de residu et raideur LibereTenseur() ; // liberation des tenseur intermediaires }; // acquisition ou modification d'une loi de comportement void ElemPoint::DefLoi (LoiAbstraiteGeneral * NouvelleLoi) { // verification du type de loi int dim=ParaGlob::Dimension(); // pour l'instant par défaut // non avec les CP on passe en 2D au niveau de la loi, donc a priori on peut avoir plusieurs dimensions // if (NouvelleLoi->Dimension_loi() != dim) // { cout << "\n Erreur, la loi de comportement a utiliser avec des ElemPoints"; // cout << " est de type = " << (NouvelleLoi->Dimension_loi()) << " au lieu de " << dim << "!!! " << endl; // Sortie(1); // }; // cas d'une loi mécanique if (GroupeMecanique(NouvelleLoi->Id_categorie())) {loiComp = (Loi_comp_abstraite *) NouvelleLoi; // initialisation du stockage particulier, ici 1 pt d'integ tabSaveDon(1) = loiComp->New_et_Initialise(); // idem pour le type de déformation mécanique associé tabSaveDefDon(1) = 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, ici 1 pt d'integ tabSaveTP(1) = 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 ElemPoint::TestComplet() { int res = ElemMeca::TestComplet(); // test dans la fonction mere return res; }; // ajout du tableau de ddl des noeuds de ElemPoint void ElemPoint::ConstTabDdl() { Tableau ta(ParaGlob::Dimension()); int posi = Id_nom_ddl("X1") -1; int dim = ParaGlob::Dimension(); for (int i =1; i<= dim; i++) {Ddl inter((Enum_ddl(i+posi)),0.,LIBRE); ta(i) = inter; }; // attribution des ddls aux noeuds tab_noeud(1)->PlusTabDdl(ta); }; // procesure permettant de completer l'element apres // sa creation avec les donnees du bloc transmis // peut etre appeler plusieurs fois Element* ElemPoint::Complete(BlocGen & bloc,LesFonctions_nD* lesFonctionsnD) { // complétion avec bloc return ElemMeca::Complete_ElemMeca(bloc,lesFonctionsnD); }; // lecture de données diverses sur le flot d'entrée void ElemPoint::LectureContraintes(UtilLecture * entreePrinc) { DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; ElemMeca::LectureDesContraintes (true,entreePrinc,lesPtMecaInt.TabSigHH_t()); }; // retour des contraintes en absolu retour true si elle existe sinon false bool ElemPoint::ContraintesAbsolues(Tableau & tabSig) { DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier 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; doCo->met_ElemPoint.PlusInitVariables(tab) ; }; ElemMeca::ContraintesEnAbsolues(true,lesPtMecaInt.TabSigHH_t(),tabSig); return true; }; // affichage dans la sortie transmise, des variables duales "nom" // dans le cas ou nom est vide, affichage de "toute" les variables void ElemPoint::AfficheVarDual(ofstream& sort, Tableau& nom) {// affichage de l'entête de l'element sort << "\n******************************************************************"; sort << "\n Element bielette (2 noeuds 1 point d'integration) "; sort << "\n******************************************************************"; // appel de la procedure de elem meca if (!(unefois->dualSortbiel ) && (unefois->CalimpPrem )) { VarDualSort(sort,nom,1,1); unefois->dualSortbiel += 1; } else if ((unefois->dualSortbiel) && (unefois->CalimpPrem )) VarDualSort(sort,nom,1,11); else if (!(unefois->dualSortbiel ) && (unefois->CalResPrem_tdt )) { VarDualSort(sort,nom,1,2); unefois->dualSortbiel += 1; } else if ((unefois->dualSortbiel ) && (unefois->CalResPrem_tdt )) VarDualSort(sort,nom,1,12); // sinon on ne fait rien }; // recuperation des coordonnées du point de numéro d'ordre iteg pour // la grandeur enu // temps: dit si c'est à 0 ou t ou tdt // si erreur retourne erreur à true Coordonnee ElemPoint::CoordPtInteg(Enum_dure temps,Enum_ddl enu,int iteg,bool& erreur) { // ici les coordonnées du point d'intégration et celles du noeud sont identique // donc on ramène les coordonnées du noeud associé switch (temps) { case TEMPS_0: {return (tab_noeud(1)->Coord0()); break;}; case TEMPS_t: {return (tab_noeud(1)->Coord1()); break;}; case TEMPS_tdt:{ return (tab_noeud(1)->Coord2()); break;}; }; }; // 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 ElemPoint::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->dualSortbiel) && (unefois->CalimpPrem)) { cas=1;unefois->dualSortbiel += 1; } else if ((unefois->dualSortbiel) && (unefois->CalimpPrem)) { cas = 11;} else if (!(unefois->dualSortbiel) && (unefois->CalResPrem_tdt)) { cas=2;unefois->dualSortbiel += 1; } else if ((unefois->dualSortbiel) && (unefois->CalResPrem_tdt)) { cas = 12;} // sinon pour l'instant pb, car il faut définir des variable dans la métrique 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 prevu, unefois->dualSortbiel= " << unefois->dualSortbiel << " unefois->CalimpPrem= " << unefois->CalimpPrem << "\n ElemPoint::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 void ElemPoint::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->dualSortbiel) && (unefois->CalimpPrem)) { cas=1;unefois->dualSortbiel += 1; } else if ((unefois->dualSortbiel) && (unefois->CalimpPrem)) { cas = 11;} else if (!(unefois->dualSortbiel) && (unefois->CalResPrem_tdt)) { cas=2;unefois->dualSortbiel = 1; } else if ((unefois->dualSortbiel) && (unefois->CalResPrem_tdt)) { cas = 12;} // sinon pour l'instant pb, car il faut définir des variable dans la métrique 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->dualSortbiel= " << unefois->dualSortbiel << " unefois->CalimpPrem= " << unefois->CalimpPrem << "\n ElemPoint::ValTensorielle_a_diff_temps(Enum_dure enu_t..."; Sortie(1); }; ElemMeca::Valeurs_Tensorielles(absolue,enu_t,enu,iteg,cas); }; // 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 & ElemPoint::Frontiere(bool force) { int cas = 3; // on veut des 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_point == 0) || force || (ind_front_point == 2)) // { // dimensionnement des tableaux intermediaires // Tableau tab(1); // les noeuds des points frontieres // DdlElement ddelem(1); // les ddlelements des points frontieres // int tail=1; // tabb.Change_taille(tail); // le tableau total de frontières // // // le point //// tab(1) = tab_noeud(1); //// ddelem.Change_un_ddlNoeudElement(1,doCo->tab_ddl(1)); //// if (tabb(1+posi_tab_front_point) == NULL) //// tabb(1+posi_tab_front_point) = new FrontPointF (tab,ddelem); // // mise à jour des indicateurs //// ind_front_point = 1; // } // // return 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 ElemPoint::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 != 1) // { cout << "\n *** erreur, pour les ElemPoints il n'y a qu'une frontieres point ! " // << "\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 la frontière point existe sinon on la 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 // if (ind_front_point==0) // // cas où aucune frontière existe, on crée pour les points // { tabb.Change_taille(1); posi_tab_front_point = 0;}; // // dans les deux autres cas ((ind_front_lin == 0) && (ind_front_point>0)) et // // ((ind_front_lin > 0) && (ind_front_point>0)), les points existant déjà on n'a rien n'a faire // // on définit le point // // premier point //// tab(1) = tab_noeud(1); //// ddelem.Change_un_ddlNoeudElement(1,doCo->tab_ddl(1)); //// if (tabb(1+posi_tab_front_point) == NULL) //// tabb(1+posi_tab_front_point) = new FrontPointF (tab,ddelem); // ind_front_point=1; // mise à jour de l'indicateur // }; // 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) //// ici normalement la fonction ne doit pas être appelée //ElFrontiere* const ElemPoint::Frontiere_lineique(int ,bool ) // { cout << "\n *** erreur, pour les ElemPoints il n'y a pas de frontiere lineique ! " // << "\n Frontiere_lineique(int ,bool force = false)"; // Sortie(1); // return NULL; // }; // //// ramène la frontière surfacique //// éventuellement création des frontieres 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 la fonction ne doit pas être appelée //ElFrontiere* const ElemPoint::Frontiere_surfacique(int ,bool ) // { cout << "\n *** erreur, pour les ElemPoints il n'y a pas de frontiere surface ! " // << "\n Frontiere_surfacique(int ,bool force = false)"; // Sortie(1); // return NULL; // }; // =====>>>> methodes privées appelees par les classes dérivees <<<<===== // fonction d'initialisation servant au niveau du constructeur // dim_tenseur: = dimension des tenseurs void ElemPoint::Init(int dim_tenseur) { // le fait de mettre les pointeurs a null permet // de savoir que l'element n'est pas complet tab_noeud.Change_taille(nombre_V.nbne); for (int i =1;i<= nombre_V.nbne;i++) tab_noeud(i) = NULL; // definition des donnees communes aux ElemPointxxx // a la premiere definition d'une instance if (unefois->doCoMemb == NULL) unefois->doCoMemb = ElemPoint::Def_DonneeCommune(dim_tenseur); // unefois->doCoMemb = doCo ; met = &(unefois->doCoMemb->met_ElemPoint); // met est defini dans elemeca DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier // def pointe sur la deformation specifique a l'element pour le calcul mecanique def = new Def_Umat(*met,tab_noeud,(doCo->ptpoint).TaDphi(),(doCo->ptpoint).TaPhi()); // idem pour la remontee aux contraintes et le calcul d'erreur defEr = new Def_Umat(*met,tab_noeud,(doCo->pteEr).TaDphi(),(doCo->pteEr).TaPhi()); // idem pour la remontee aux contraintes et le calcul d'erreur defMas = new Def_Umat(*met,tab_noeud,(doCo->pteMas).TaDphi(),(doCo->pteMas).TaPhi()); // idem pour le calcul de second membre defArete.Change_taille(1); // 1 arrête utilisée pour le second membre // la déformation sera construite si nécessaire au moment du calcul de second membre defArete(1) = NULL; //dimensionnement des deformations et contraintes lesPtMecaInt.Change_taille_PtIntegMeca(nbi,dim_tenseur); // 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); }; lesPtIntegMecaInterne = &lesPtMecaInt; // association avec le pointeur d'ElemMeca // stockage des donnees particulieres de la loi de comportement au point d'integ tabSaveDon.Change_taille(nbi); tabSaveTP.Change_taille(nbi); 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 = &(doCo->residu_interne); // residu local raideur = &(doCo->raideur_interne); // raideur locale // --- cas de la dynamique ----- mat_masse = &(doCo->matrice_masse); // --- cas des efforts externes concernant les noeuds ------ res_extN = &(doCo->residus_externeN); // pour les résidus et second membres raid_extN= &(doCo->raideurs_externeN);// pour les raideurs }; // fonction privee // dans cette fonction il ne doit y avoir que les données communes !! ElemPoint::DonneeCommune* ElemPoint::Def_DonneeCommune(int dim_tenseur) { int nbn = nombre_V.nbne; // interpollation : element geometrique de base correspondant: 1 pt integ, 1 noeuds GeomPoint pteg ; // degre de liberte int dim = ParaGlob::Dimension(); DdlElement tab_ddl(nbn,dim); int posi = Id_nom_ddl("X1") -1; for (int i =1; i<= dim; i++) for (int j=1; j<= nbn; 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 = 0; // init ParaGlob::NbCompTens (); int nb_vect=0; // init: nb de vecteur de la base switch (dim_tenseur) { case 3: nbcomposante=6;nb_vect=3; break; case 2: nbcomposante=3;nb_vect=2; break; case 1: nbcomposante=1;nb_vect=1; break; default: break; }; DdlElement tab_ddlErr(nbn,nbcomposante); posi = Id_nom_ddl("SIG11") -1; for (int j=1; j<= nbn; 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)); } else // tab_ddlErr (j,1) = Enum_ddl(1+posi); // uniquement SIG11 {tab_ddlErr.Change_Enum(j,1,Enum_ddl(1+posi));}; // uniquement SIG11 }; // egalement pour tab_Err1Sig11, def d'un tableau de un ddl : enum SIG11 // par noeud DdlElement tab_Err1Sig11(nbn,DdlNoeudElement(SIG11)); // toujours pour le calcul d'erreur definition des fonctions d'interpolation // pour le calcul du hession de la fonctionnelle : // 1 points d'integration et 1 noeuds GeomPoint ptegEr ; // pour le calcul de la matrice masse definition des fonctions d'interpolation // 1 points d'integration et 1 noeuds, en particulier pour le calcul de la masse consistante GeomPoint ptegMa ; // 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 , tableau de ddl et la def de variables Met_ElemPoint metri(ParaGlob::Dimension(),nb_vect,tab_ddl,tab,nbn) ; // ---- 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 (nbn); // une composante par noeud Mat_pleine raidEr(nbn,nbn); // 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 // il y a une extrémité a priori Tableau residus_extN(1); residus_extN(1) = new Vecteur(dim); // pas d'arêtes, un noeud Tableau raideurs_extN(1);raideurs_extN(1) = new Mat_pleine(dim,dim); // -- particularités pour la routine Umat pour Abaqus UmatAbaqus umatAbaqus(ParaGlob::Dimension(),dim_tenseur); // definition de la classe static contenant toute les variables communes aux ElemPoints int nbi=1; // par défaut on met un pt d'integ, ensuite il faudra remettre à jour // les données communes si le nb de pt augmente DonneeCommune* doCoco = new DonneeCommune(pteg,tab_ddl,tab_ddlErr,tab_Err1Sig11,metri,resEr,raidEr,ptegEr ,residu_int,raideur_int,residus_extN,raideurs_extN ,matmasse,ptegMa,umatAbaqus,dim_tenseur,nbi); return doCoco; }; // destructions de certaines grandeurs pointées, créées au niveau de l'initialisation void ElemPoint::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)) // if (unefois->unefois->nbelem_in_Prog == 0) // cas de la destruction du dernier élément { ElemPoint::DonneeCommune* doCo = unefois->doCoMemb; // pour simplifier l'écriture int resErrTaille = doCo->resErr.Taille(); for (int i=1;i<= resErrTaille;i++) delete doCo->resErr(i); delete doCo->residus_externeN(1); delete doCo->raideurs_externeN(1); }; }; // changement du nombre de point d'intégration void ElemPoint::ChangeNombrePtinteg(int nevez_nbi, int dim_tens) { // les numéroq int old_nbi = nbi; nbi = nevez_nbi; // stockage des donnees particulieres de la loi de comportement au point d'integ tabSaveDon.Change_taille(nbi); tabSaveTP.Change_taille(nbi); tabSaveDefDon.Change_taille(nbi); // puis les tenseurs internes lesPtMecaInt.Change_taille_PtIntegMeca(nbi,dim_tens); // 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); }; for (int ni = old_nbi+1; ni <= nbi; ni++) { // cas d'une loi mécanique // initialisation du stockage particulier pour le nouveau pt d'integ tabSaveDon(ni) = loiComp->New_et_Initialise(); // idem pour le type de déformation mécanique associé tabSaveDefDon(ni) = def->New_et_Initialise(); // cas éventuelle d'une loi thermo physique if (loiTP != NULL) {// initialisation du stockage particulier, ici 1 pt d'integ tabSaveTP(ni) = loiTP->New_et_Initialise(); }; }; };