// 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 "Algori.h" #include "MatBand.h" #include "Assemblage.h" #include "ElemMeca.h" // ------ fait partie de la classe Algori ----------- // initialisation du calcul de la remontée des contraintes aux noeuds // initialisation valable également dans le cas où aucun calcul n'a précédé ce calcul void Algori::InitRemontSigma(LesMaillages * lesMail,LesReferences* lesRef, DiversStockage* ,Charge* , LesCondLim* lesCondLim,LesContacts* ,Resultats* ) {//mise en place des coordonnées à t, qui sont nécessaire pour calculer les éléments // géométriques sur une pièce déformée, même si les ddl sont autres que les déplacements // dans le cas où les coordonnées existent déjà, il n'y a aucune modification lesMail->Insert_coord1(); // l'idée ici est d'initialiser la gestion d'un nouveau groupe de ddl // ==== 1 - on commence par inactiver les ddl qui sont en cours lesMail->Inactive_ddl(); // ==== 2 - on définit un nouveau groupe de ddl avec la gestion rapide associé // introduction des ddl de contraintes (s'ils n'existent pas déjà sinon aucune action) lesMail->Plus_ddl_Sigma(); ////--- debug //cout << "\n debug Algori::InitRemontSigma "; //lesMail->Noeud_LesMaille(1,1).Affiche(1); //cout << endl; ////--- fin debug // mise a zero des ddl actifs et on laisse les ddl à t+dt // mais il faut d'abord activer les ddl sigma lesMail->Active_ddl_Sigma(); // le deuxième paramètre de ZeroDdl est false pour indiquer que les coordonnées à t // ne sont pas à initialiser aux valeurs à t = 0, ceci permet par exemple de travailler // sur une structure déformée si elle a été calculée auparavant lesMail->ZeroDdl(true,false); // mise à jour de tous les ddl actifs sauf de déplacement // ==== 3 - def de l'assemblage pour tous les ddl de type sigma nbddl_sigeps = lesMail->NbTotalDdlActifs(); // nb total de ddl de sigma // on définit un nouveau cas de second membre // à travers la définition d'une instance de la classe assemblage // si elle existe déjà on l'utilise directement if (cas_ass_sig == NULL) // cas où les conteneurs sont à créer { cas_ass_sig = new Nb_assemb(lesMail->InitNouveauCasAssemblage(1)); Ass_sig = new Assemblage(*cas_ass_sig); } // mise a jour des pointeurs d'assemblage lesMail->MiseAJourPointeurAssemblage(Ass_sig->Nb_cas_assemb()); // ==== 4 - def de l'assemblage pour tous les ddl de type sigma11 uniquement (c-a-d le premier ddl) // on rend actif le premier ddl mécanique, en fait on se servira des //autres qui sont supposé être à la suite mais pour éviter d'avoir une //grosse matrice de raideur le second membre est décomposé en plusieurs //SM, chacun relatif à "un" ddl de contrainte lesMail->Inactive_ddl_Sigma(); lesMail->Active_premier_ddl_Sigma(); // récup du nombre de composantes du tenseur de contrainte en absolu int nbcomposante = ParaGlob::NbCompTens (); nbddl_sigeps11 = lesMail->NbTotalDdlActifs(SIG11) / nbcomposante; // nb total de ddl de sigma11 // on définit un nouveau cas de second membre // à travers la définition d'une instance de la classe assemblage // si elle existe déjà on l'utilise directement if (cas_ass_sig11 == NULL) // cas où les conteneurs sont à créer { cas_ass_sig11 = new Nb_assemb(lesMail->InitNouveauCasAssemblage(1)); Ass_sig11 = new Assemblage(*cas_ass_sig11); } // mise a jour des pointeurs d'assemblage lesMail->MiseAJourPointeurAssemblage(Ass_sig11->Nb_cas_assemb()); // ==== 5 - définition de la matrice pour la résolution du problème de minimisation // dans le cas où c'est déjà fait on ne change rien if (mat_glob_sigeps == NULL) //on est obligé de faire une petite manipe avec un tableau, car l'appel à changé { Tableau < Mat_abstraite*> tab_inter(1); tab_inter(1)=NULL; Choix_matriciel(nbddl_sigeps11,tab_inter,lesMail,lesRef ,Ass_sig11->Nb_cas_assemb(),lesCondLim); mat_glob_sigeps = tab_inter(1); }; // choix de la résolution mat_glob_sigeps->Change_Choix_resolution(pa.Type_resolution(),pa.Type_preconditionnement()); // def du tableau de seconds membres globaux avec initialisation à zéro if (vglob_sigeps == NULL) vglob_sigeps = new Tableau (nbcomposante,Vecteur(nbddl_sigeps11)); // définition du vecteur global de tous les ddl de sigma if (vglobal_sigeps == NULL) vglobal_sigeps = new Vecteur(nbcomposante*nbddl_sigeps11); }; // initialisation du calcul de la remontée des déformations aux noeuds // initialisation valable également dans le cas où aucun calcul n'a précédé ce calcul void Algori::InitRemontEps(LesMaillages * ,LesReferences* , DiversStockage* ,Charge* , LesCondLim* ,LesContacts* ,Resultats* ) {// pour l'instant rien }; // initialisation du calcul d'erreur aux éléments // initialisation valable également dans le cas où aucun calcul n'a précédé ce calcul void Algori::InitErreur(LesMaillages * lesMail,LesReferences* , DiversStockage* ,Charge* , LesCondLim* ,LesContacts* ,Resultats* ) {// pour la remontée des valeurs aux noeuds // l'idée ici est d'initialiser la gestion d'un nouveau groupe de ddl // ==== 1 - on commence par inactiver les ddl qui sont en cours lesMail->Inactive_ddl(); // ==== 2 - on définit un nouveau groupe de ddl avec la gestion rapide associé // introduction des ddl d'erreur (s'ils n'existent pas déjà sinon aucune action) lesMail->Plus_ddl_Erreur(); // activation des ddl Erreur lesMail->Active_ddl_Erreur(); // mise a zero des ddl actifs et on laisse les ddl à t+dt // le deuxième paramètre de ZeroDdl est false pour indiquer que les coordonnées à t // ne sont pas à initialiser aux valeurs à t = 0, ceci permet par exemple de travailler // sur une structure déformée si elle a été calculée auparavant lesMail->ZeroDdl(true,false); // mise à jour de tous les ddl actifs sauf de déplacement // ==== 3 - def de l'assemblage pour tous les ddl de type erreur nbddl_err= lesMail->NbTotalDdlActifs(); // nb total de ddl d'erreur // on définit un nouveau cas de second membre // à travers la définition d'une instance de la classe assemblage // si elle existe déjà on l'utilise directement if (cas_ass_err == NULL) // cas où les conteneurs sont à créer { cas_ass_err = new Nb_assemb(lesMail->InitNouveauCasAssemblage(1)); Ass_err = new Assemblage(*cas_ass_err); } // mise a jour des pointeurs d'assemblage lesMail->MiseAJourPointeurAssemblage(Ass_err->Nb_cas_assemb()); // ==== 4 - définition de la matrice pour la résolution du problème de minimisation // dans le cas où c'est déjà fait on ne change rien // ici contrairement au cas des contraintes où des déformations, on considère qu'il y a déjà eu // la remonté des contraintes, qui est obligatoire pour calculer l'erreur aux éléments qui elle est // obligatoire pour calculer l'erreur aux noeuds => on utilise la même matrice de raideur if (mat_glob_sigeps == NULL) { cout << "\n erreur la remontee des contraintes n'a pas ete faite, on ne peut pas continuer" << "\n Algori::InitErreur(..."; Sortie(1); }; // def du tableau du second membre global avec initialisation à zéro // on utilise la place de celui utilisé pour sigma if (vglob_sigeps == NULL) { cout << "\n erreur la remontee des contraintes n'a pas ete faite, on ne peut pas continuer" << "\n Algori::InitErreur(..."; Sortie(1); }; }; // calcul de la remontée des contraintes aux noeuds void Algori::RemontSigma(LesMaillages * lesMail) { // affichage if (ParaGlob::NiveauImpression() >= 2 ) cout << "\n=================================================================" << "\n REMONTEE DES CONTRAINTES AUX NOEUDS " << "\n=================================================================\n"; lesMail->Inactive_ddl(); // inactive les ddl en cours // mise a zero des ddl actifs et on laisse les ddl à t+dt // mais il faut d'abord activer les ddl sigma lesMail->Active_ddl_Sigma(); // le deuxième paramètre de ZeroDdl est false pour indiquer que les coordonnées à t // ne sont pas à initialiser aux valeurs à t = 0, ceci permet par exemple de travailler // sur une structure déformée si elle a été calculée auparavant lesMail->ZeroDdl(true,false); // on rend actif le premier ddl mécanique, en fait on se servira des //autres qui sont supposé être à la suite mais pour éviter d'avoir une //grosse matrice de raideur le second membre est décomposé en plusieurs //SM, chacun relatif à "un" ddl de contrainte lesMail->Inactive_ddl_Sigma(); lesMail->Active_premier_ddl_Sigma(); // def du nombre de composantes du tenseur de contrainte en absolu int nbcomposante = ParaGlob::NbCompTens (); // pour simplifier Mat_abstraite& matglob = *mat_glob_sigeps; mat_glob_sigeps->Initialise(0.); Tableau & vglob = *vglob_sigeps; Vecteur& vglobal = *vglobal_sigeps; vglobal_sigeps->Zero(); // ----- Calcul de la raideur et des seconds membres Tableau * sol; // pointeur du vecteur solution // boucle sur les elements int nbMaillage = lesMail->NbMaillage(); for (int nbMail =1; nbMail<= nbMaillage; nbMail++) {int nbelement = lesMail->Nombre_element(nbMail); for (int ne=1; ne<= nbelement;ne++) { // calcul du résidu et de la matrice de raideur pour le calcul d'erreur ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element Element::Er_ResRaid resu = el.ContrainteAuNoeud_ResRaid(); Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el // création du tableau d'un ddl SIG11, pour chaque noeud concerné des // élément traité const DdlElement& TabDdl = el.Tableau_de_Sig1() ; // assemblage de la raideur Ass_sig11->AssembMatSym (matglob,*(resu.raidErr),TabDdl,taN); // de la raideur // assemblage des seconds membres Ass_sig11->AssemSM (vglob,*(resu.resErr),TabDdl,taN); // du second membre // cout << "numéro =" << ne << endl; // (resu.res)->Affiche(); // (resu.raid)->Affiche(); // assemblage }; }; // affichage éventuelle de la matrice de raideur et du second membre if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage de la matrice de raideur pour le calcul d'erreur "; matglob.Affichage_ecran(entete); entete = " affichage du second membre nb= "; int nbsm = vglob.Taille(); for (int i=1;i<=nbsm;i++) vglob(i).Affichage_ecran(entete + ChangeEntierSTring(i) +" "); }; //------------- resolution ----------------- // matglob.Affiche1(1,6,1,1,6,1); // for (int i=1;i<= vglob.Taille();i++) // vglob(i).Affiche(); // vglobal.Affiche(); // cout << "\n entree une lettre"; int toto; cin >> toto; // ici sol en fait = vecglob qui est ecrase par la resolution // la résolution se fait en deux temps pour que la même matrice de raideur puisse servir plusieur fois matglob.Preparation_resol(); // préparation sol = &(matglob.Simple_Resol_systID(vglob)); // résolution sans modification de la matrice de raideur // affichage éventuelle de la solution if (ParaGlob::NiveauImpression() >= 10) { string entete = " affichage de la solutions pour le calcul d'erreur "; entete = " affichage de la composante nb= "; int nbsm = vglob.Taille(); for (int i=1;i<=nbsm;i++) (*sol)(i).Affichage_ecran(entete + ChangeEntierSTring(i) +" "); }; // sol = &(matglob.Resol_systID(vglob)); // sol->Affiche(); ////---debug // cout << "\n debug Algori::RemontErreur "; // (*sol)(1).Affiche(); // (*sol)(2).Affiche(); // (*sol)(3).Affiche(); //// (*sol)(4).Affiche(); //// (*sol)(5).Affiche(); //// (*sol)(6).Affiche(); cout << endl; ////---fin debug // ------------- résultat transféré dans les noeuds --------- // construction du vecteur avec tous les ddl sigma int iposition = 1; for (int j=1; j<= nbddl_sigeps11; j++) for (int i=1;i<=nbcomposante;i++,iposition++) vglobal(iposition) = vglob(i)(j); // activation de tous les ddl sigma lesMail->Active_ddl_Sigma(); // modif 6 nov 2014 // // actualisation de tous les sigma a t lesMail->PlusDelta_t(vglobal,Ass_sig->Nb_cas_assemb()); // actualisation de tous les sigma a tdt, et on passe les info // car c'est les grandeurs de tdt qui sont visualisées ! lesMail->ChangeDdla_tdt(vglobal,Ass_sig->Nb_cas_assemb()); // fin des calculs }; // calcul de la remontée des contraintes aux // noeuds, puis de l'erreur, après un calcul de mécanique. // calcul de la remontée des déformations aux noeuds void Algori::RemontEps(LesMaillages * ) {// pour l'instant rien }; void Algori::RemontErreur(LesMaillages * lesMail) { if (ParaGlob::NiveauImpression() >= 2 ) cout << "\n==========================================================================" << "\n CALCUL D'ERREUR AUX ELEMENTS ET REMONTEE DES VALEURS AUX NOEUDS " << "\n=========================================================================\n "; // 1) Calcul de l'erreur sur chaque élément // type indique le type d'erreur retenue // type = 1 : cas d'un calcul aux moindres carrés // et retour de l'erreur relative totale sur les maillages en cours int type = 1; // Calcul de l'erreur sur l'ensemble des éléments // type indique le type d'erreur retenue // type = 1 : cas d'un calcul aux moindres carrés // et retour un tableau de tableau de grandeurs sur les maillages en cours // ret(i) : concerne le maillage i // ret(i)(1) : somme des erreurs sur l'ensemble des éléments: est homogêne à // un |delta contrainte| * domaine // ret(i)(2) : somme de la grandeur de ref du calcul d'erreur sur l'ensemble des // éléments: est homogêne à une |contrainte| * domaine // ret(i)(3) : le maxi pour les tous les éléments de |delta contrainte| * domaine // ret(i)(4) : le maxi pour les tous les éléments de |contrainte| * domaine // ret(i)(5) : le maxi pour les tous les éléments de l'erreur relative Tableau > ret(lesMail->ErreurSurChaqueElement(type)); if (ParaGlob::NiveauImpression() >= 2 ) {int nbmaillage = ret.Taille(); for (int i=1;i<=nbmaillage;i++) {cout << "\n --- maillage: "< erreur cumulee relative= "< maxi de l'erreur relative sur les element = "<Inactive_ddl(); // activation des ddl Erreur lesMail->Active_ddl_Erreur(); // mise a zero des ddl actifs et on laisse les ddl à t+dt lesMail->ZeroDdl(true,false); // mise a jour des pointeurs d'assemblage lesMail->MiseAJourPointeurAssemblage(Ass_err->Nb_cas_assemb()); // pour le second membre on utilise le premier vecteur de second membre utilisé // pour les contraintes : vglob(1) et localement resu.resErr(1) // on ne recalcule pas la raideur, mais on utilise celle calculée lors de la résolution // pour les contraintes. Il y a sauvegarde de la matrice de raideur lors de la // résolution, on peut donc la réutiliser. // ----- Calcul du second membre // on commence par initialiser le second membre à zero Vecteur & vgloberr = (*vglob_sigeps)(1); vgloberr.Zero(); Mat_abstraite& matglob = *mat_glob_sigeps; // boucle sur les elements int nbMaillage = lesMail->NbMaillage(); for (int nbMail =1; nbMail<= nbMaillage; nbMail++) {int nbelement = lesMail->Nombre_element(nbMail); for (int ne=1; ne<= nbelement;ne++) { // calcul du résidu ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element Element::Er_ResRaid resu = el.ErreurAuNoeud_ResRaid(); Tableau& taN = el.Tab_noeud(); // tableau de noeuds de l'el // assemblage du second membre Ass_err->AssemSM (vgloberr,*((*(resu.resErr))(1)),el.Tableau_de_ERREUR(),taN); // cout << "numéro =" << ne << endl; // (resu.res)->Affiche(); // (resu.raid)->Affiche(); // assemblage } } //------------- resolution ----------------- // matglob.Affiche(1,4,1,1,4,1); // for (int i=1;i<= vglob.Taille();i++) // vglob(i).Affiche(); // matglob.Affiche(1,8,1,7,8,1); // matglob.Affiche(1,18,1,13,18,1); // Vecteur * solEr = &(matglob.Resol_systID_sans_triangul(vglob(1))); Vecteur * solEr = &(matglob.Simple_Resol_systID(vgloberr)); // résolution sans modification de la matrice de raideur ////---debug // cout << "\n debug Algori::RemontErreur "; // solEr->Affiche(); // cout << endl; ////---fin debug // sol->Affiche(); // ------------- résultat transféré dans les noeuds --------- // actualisation des ddl actifs a t lesMail->PlusDelta_t(*solEr,Ass_err->Nb_cas_assemb()); // inactivation des ddl d'erreur lesMail->Inactive_ddl_Erreur(); // fin des calculs };