// 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 "AlgoUtils.h" // CONSTRUCTEURS : AlgoUtils::AlgoUtils () : // par defaut Algori() { }; // constructeur en fonction du type de calcul et du sous type // il y a ici lecture des parametres attaches au type AlgoUtils::AlgoUtils (const bool avec_typeDeCal ,const list & soustype ,const list & avec_soustypeDeCal ,UtilLecture& entreePrinc) : Algori(UTILITAIRES,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc) { // lecture des paramètres attachés au type de calcul (ici aucun) switch (entreePrinc.Lec_ent_info()) { case 0 : {// pour signaler à Algori qu'il n'y a pas eu de lecture de paramètre deja_lue_entete_parametre=0; // puis appel de la méthode de la classe mère Algori::lecture_Parametres(entreePrinc); break;} case -11 : // cas de la création d'un fichier de commande { Info_commande_parametres(entreePrinc); break;} case -12 : // cas de la création d'un schéma XML, on ne fait rien à ce niveau { break;} default: Sortie(1); } }; // constructeur de copie AlgoUtils::AlgoUtils (const AlgoUtils& algo): Algori(algo) { }; // destructeur AlgoUtils::~AlgoUtils () { }; // execution de l'algorithme void AlgoUtils::Execution(ParaGlob * p,LesMaillages * lesMail ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats) { tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(UTILITAIRES); // transfert info lesMail->Insert_coord1(); lesMail->Travail_tdt(); // utile pour le travail avec des fonctions nD éventuelle lesMail->Init_Xi_t_et_tdt_de_0(); // "" // mise à jour au cas où Algori::MiseAJourAlgoMere(p,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp,divStock ,charge,lesCondLim,lesContacts,resultats); // INITIALISATION particulière concernant le contact // ceci pour optimiser éventuellement la numérotation en prenant en compte un contact initial // mise a zero de tous les ddl et creation des tableaux a t+dt // les ddl de position ne sont pas mis a zero ! ils sont initialise // a la position courante lesMail->ZeroDdl(true); // on vérifie que les noeuds sont bien attachés à un élément sinon on met un warning si niveau > 2 if (ParaGlob::NiveauImpression() > 2) lesMail->AffichageNoeudNonReferencer(); // definition des elements de frontiere, ces elements sont utilises pour le contact int cal_front = lesMail->CreeElemFront(); // calcul éventuel des normales aux noeuds -> init des normales pour t=0 lesMail->InitNormaleAuxNoeuds(); //utilisé pour la stabilisation des membranes par ex // dans le cas d'un contact éventuel on initialise les frontières et la répartition esclave et maître if (lesMail->NbEsclave() != 0) { // definition des elements de frontiere, ces elements sont utilises pour le contact lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_t); if (lesContacts->Init_contact_pas_effectue()) {// initialisation des zones de contacts éventuelles lesContacts->Init_contact(*lesMail,*lesRef,lesFonctionsnD); } else if (cal_front) // si l'initialisation du contact a déjà été effectué et que les frontières viennent d'être // recalculée -> ce n'est pas normal, car les frontières ont dues être déjà calculées pour // initialiser le contact !! { cout << "\n **** >>>> ERREUR en initialisant le contact ***** "; cout << "\n les frontieres viennent d'etre recalculees alors que l'initialisation du contact " << " etait deja effectif : ce n'est pas normal: les nouvelles frontieres ne seront pas " << " coherentes avec celles utilisees pour l'initialisation du contact : arret !!! " << flush; Sortie(1); }; // verification qu'il n'y a pas de contact avant le premier increment de charge lesContacts->Verification(); // definition des elements de contact eventuels // et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact) try { lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul } // sortie anormale de l'initialisation du contact catch (ErrSortieFinale) // cas d'une direction voulue vers la sortie // on relance l'interuption pour le niveau supérieur { ErrSortieFinale toto; tempsCalEquilibre.Arret_du_comptage(); // temps cpu throw (toto); } catch (...)// erreur inconnue { cout << "\n **** >>>> ERREUR inconnuee en en initialisant le contact ***** "; if (ParaGlob::NiveauImpression() >= 4) cout << "\n AlgoUtils::Execution(.."; cout << endl; }; }; // renseigne les variables définies par l'utilisateur via les valeurs déjà calculées par Herezh varExpor->RenseigneVarUtilisateur(*lesMail,*lesRef); lesMail->CalStatistique(); // calcul éventuel de statistiques // on définit le type de calcul a effectuer : if ( soustypeDeCalcul->size()==0 ) // cas où il n'y a pas de sous type, on fait le calcul // de toutes les cas possibles cout << "\n rien pour l'instant (information)\n"; else // on boucle sur tous les sous_types { list ::const_iterator ili,ili_fin = soustypeDeCalcul->end(); list ::const_iterator ila; for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin(); ili!=ili_fin;ili++,ila++) if (*ila) // cas où le sous type est valide {if ( (*ili) == LinVersQuad ) // cas de la transformation de maillages linéaires en maillages // quadratiques complets { cout << "\n=================================================================" << "\n| Transformation des maillages lineaires en |" << "\n| maillages quadratiques incomplets | " << "\n=================================================================" << endl; // on crée et on calcul les nouveaux maillages // en y intégrant les références associées // 1) on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = lesMail->NbMaillage(); // 2) on crée les quadratiques incomplets lesMail->CreeMaillagesQuadratiques_a_partir_des_lineaires(lesRef); // 3) récup du nombre actuellement actif d'où des maillages créés int nb_maillages_actifs_finaux = lesMail->NbMaillage(); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++) lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i); } else if ( (*ili) == QuadIncVersQuadComp ) // cas de la transformation de maillages quadratiques incomplets en maillages // quadratiques complets { cout << "\n=================================================================" << "\n| Transformation des maillages quadratiques incomplets en |" << "\n| maillages quadratiques complets | " << "\n=================================================================" << endl; // on crée et on calcul les nouveaux maillages // en y intégrant les références associées // 1) on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = lesMail->NbMaillage(); // 2) on crée les quadratiques complets lesMail->CreeMaillagesQuadratiquesComplets_a_partir_des_incomplets(lesRef); // 3) récup du nombre actuellement actif d'où des maillages créés int nb_maillages_actifs_finaux = lesMail->NbMaillage(); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++) lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i); } else if ( (*ili) == relocPtMilieuQuad ) // cas de la relocalisation des points milieux sur les arrêtes des quadratiques { cout << "\n=================================================================" << "\n| Relocalisation des points milieux appartenant aux arretes |" << "\n| des elements quadratiques | " << "\n=================================================================" << endl; // appel de l'utilitaire dans lesMaillages lesMail->RelocPtMilieuMailleQuadra(); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef); } else if ( (*ili) == sauveMaillagesEnCours ) // cas de la relocalisation des points milieux sur les arrêtes des quadratiques { cout << "\n=================================================================" << "\n| ecriture des maillages en cours en .her et .lis |" << "\n=================================================================" << endl; // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef); } else if ( (*ili) == extrusion2D3D ) // cas de l'extrusion d'un maillage 2D en 3D { cout << "\n=================================================================" << "\n| extrusion d'un maillage 2D en 3D |" << "\n=================================================================" << endl; // on crée et on calcul les nouveaux maillages // en y intégrant les références associées // 1) on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = lesMail->NbMaillage(); // 2) on crée les maillages extrudées lesMail->CreeMaillageExtrusion2D3D(lesRef); // 3) récup du nombre actuellement actif d'où des maillages créés int nb_maillages_actifs_finaux = lesMail->NbMaillage(); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++) lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i); } else if ( (*ili) == modif_orientation_element ) // cas de la modification de l'orientation d'éléments { // 1) on récupère le nombre de maillage actuellement actif int nb_maillages_actifs_initiaux = lesMail->NbMaillage(); cout << "\n=================================================================" << "\n| modification de l'orientation d'element |" << "\n=================================================================" << endl; // 2) on demande à l'utilisation ce qu'il veut faire et on exécute bool choix_valide = false; int cas_orientation=0; // init while (!choix_valide) { cout << "\n =========== choix du module d'orientation ===============" << "\n verification de l'orientation ? (rep veor)" << "\n orientation automatique pour un jacobien positif ? (rep oajp)" << "\n orientation des faces d'elem 2D via un elem de ref? (rep faor)" << "\n orientation des faces d'elem 2D via un rayon ? (rep fray)" << "\n fin (defaut) (rep f)"; string rep; cout << "\n reponse ? "; rep = lect_return_defaut(false,"f"); if (rep == "veor") // vérification de l'orientation {cas_orientation=-1; lesMail->Modif_orientation_element(cas_orientation,lesRef); } else if (rep == "oajp") // cas d'une orientation automatique pour obtenir un jacobien positif {cas_orientation=1; lesMail->Modif_orientation_element(cas_orientation,lesRef); } else if (rep == "faor") // cas d'une orientation automatique des faces d'un maillage 2D // à partir d'une face de référence {cas_orientation=2; lesMail->Modif_orientation_element(cas_orientation,lesRef); } else if (rep == "fray") // cas d'une orientation automatique à partir de l'orientation d'un rayon {cas_orientation=3; lesMail->Modif_orientation_element(cas_orientation,lesRef); } else if ((rep == "0") || (rep == "o") || (rep == "O") || (rep == "f")) {choix_valide = true;cas_orientation=0;} else cout << "\n la réponse : " << rep << " n'est pas utilisable, recommencez !"; }; // 3) récup du nombre actuellement actif d'où des maillages créés int nb_maillages_actifs_finaux = lesMail->NbMaillage(); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" for (int i=nb_maillages_actifs_initiaux+1;i<=nb_maillages_actifs_finaux;i++) lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,i); } else if ( (*ili) == creationMaillageSFE ) // cas de la création de maillage SFE { cout << "\n=================================================================" << "\n| creation de maillage SFE |" << "\n| | " << "\n=================================================================" << endl; // appel de l'utilitaire dans lesMaillages lesMail->CreationMaillageSFE(); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef); } else if ( (*ili) == suppression_noeud_non_references ) // cas de la suppression des noeuds non référencés { cout << "\n=================================================================" << "\n| suppression des noeuds non references |" << "\n| | " << "\n=================================================================" << endl; // appel de l'utilitaire dans lesMaillages lesMail->SuppressionNoeudNonReferencer(*lesRef); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef); } else if ( (*ili) == renumerotation_des_noeuds ) // cas de la renumérotation des noeuds { // il s'agit ici de renuméroter les noeuds de chaques maillages, indépendamment // de conditions linéaires et de conditions de contact cout << "\n=================================================================" << "\n| renumerotation des noeuds |" << "\n| | " << "\n=================================================================" << endl; // l'algo a besoin des éléments frontières, on les crée si elles n'existent pas lesMail->CreeElemFront(); // appel de l'utilitaire dans lesMaillages bool changement = lesMail->Renumerotation(*lesRef); // on met à jour le tableau indice pour LesContacts lesContacts->Mise_a_jour_indice(lesMail->Indice()); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" // s'il y a eu quelque chose de changé if (changement) {if (ParaGlob::NiveauImpression() > 2) cout << "\n ===>> sauvegarde des maillages en .her et .lis "; lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef); } else {cout << "\n ===>> pas de changement dans un maillage -> aucune sauvegarde "; }; } else if ( (*ili) == fusion_de_noeuds ) // cas de la fusion de noeuds { cout << "\n=================================================================" << "\n| fusion de noeuds |" << "\n| | " << "\n=================================================================" << endl; // 2) on demande à l'utilisateur le rayon maxi en dessous duquel on va fusionner double rayon=0.; // init cout << "\n ++ choix de la distance en dessous de laquelle on fusionne les noeuds " << "\n deux noeuds sont fusionable s'ils appartiennent a des elements differents " << "\n et s'ils appartiennent a un meme maillage. " << "\n distances maxi pour la fusion ? "; rayon = lect_double(); cout << "\n distance lue: "<< rayon << endl; // appel de l'utilitaire dans lesMaillages lesMail->Collapse_noeuds_proches(rayon,lesRef); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef); } else if ( (*ili) == fusion_elements ) // cas de la fusion d'éléments { cout << "\n=================================================================" << "\n| fusion d'elements |" << "\n| | " << "\n=================================================================" << endl; // appel de l'utilitaire dans lesMaillages lesMail->Collapse_element_supperpose(lesRef); // ----- sort les informations sur fichiers // Affichage des donnees des maillages dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef); } else if ( (*ili) == fusion_maillages ) // cas de la fusion de maillage { // 1) affichage cout << "\n=================================================================" << "\n| fusion de maillages |" << "\n| | " << "\n=================================================================" << endl; // 2) on demande à l'utilisateur ce qu'il veut faire et on exécute bool choix_valide = false; List_io < string > lis_a_fusionner; // la liste des maillages à fusionner string nom_nouveau_maillage = " "; // nom du nouveau maillage int nbmail = lesMail->NbMaillage(); // les maillages actuellement enregistré while (!choix_valide) { if (lis_a_fusionner.size() != 0) { cout << "\n liste des maillages a fusionner : "; List_io < string >::iterator il,ilfin=lis_a_fusionner.end(); for (il = lis_a_fusionner.begin();il != ilfin; il++) cout << (*il) << ", "; cout << endl; }; cout << "\n =========== choix des maillages a fusionner ===============" << "\n liste des maillages disponibles (rep list)" << "\n vider la liste a fusionner (rep vlis)" << "\n nom du maillage issu de la fusion (rep nfus)" << "\n fusionner tous les maillages (rep to)" << "\n ajout d'un nom de maillage a fusionner (rep nafu)" << "\n fin (appel du programme de fusion) (rep f)"; string rep; cout << "\n reponse ? "; rep = lect_return_defaut(false,"f"); if (rep == "list") // affichage de la liste des maillages existants {cout << "\n -- liste des maillages enregistres -- \n"; for (int i=1;i<=nbmail;i++) cout << lesMail->NomMaillage(i) << " "; cout << endl; } else if (rep == "vlis") // on vide la liste {lis_a_fusionner.erase(lis_a_fusionner.begin(), lis_a_fusionner.end()); } else if (rep == "nfus") // nom du maillage issu de la fusion {cout << "\n nom du nouveau maillage : "; nom_nouveau_maillage = lect_chaine(); cout << "\n nom lue: " << nom_nouveau_maillage << "\n"; } else if (rep == "nafu") // ajout d'un nom de maillage a fusionner {string new_nom; cout << "\n nom du maillage : "; new_nom = lect_chaine(); // on vérifie que c'est bien un nom licite if (!(lesMail->NumMaillage(new_nom))) { cout << "\n erreur : ce maillage n'existe pas ! ";} else { // sinon c'est ok, on enregistre lis_a_fusionner.push_back(new_nom); }; } else if (rep == "to") // ajout de tous les noms de maillage {for (int i=1;i<=nbmail;i++) lis_a_fusionner.push_back(lesMail->NomMaillage(i)); } else if ((rep == "0") || (rep == "o") || (rep == "O") || (rep == "f")) { if (nom_nouveau_maillage == " ") { cout << "\n ******* le nom du nouveau maillage reste a definir !! ***** " << endl;} else { choix_valide = true;}; } else cout << "\n la réponse : " << rep << " n'est pas utilisable, recommencez !"; }; // appel de l'utilitaire dans lesMaillages lesMail->Fusion_maillages(lis_a_fusionner,nom_nouveau_maillage,lesRef); // ----- sort les informations sur fichiers // récup du nombre actuellement actif d'où du dernier maillage créé int nb_maillages_actifs_final = lesMail->NbMaillage(); // ----- sort les informations sur fichiers // Affichage des donnees du dernier maillage dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,nb_maillages_actifs_final); } else if ( (*ili) == cree_sous_maillage ) // cas de la création d'un sous maillage à partir d'une référence d'éléments { // 1) affichage cout << "\n=================================================================" << "\n| creation d'un sous maillages |" << "\n| a partir d'une ref d'elements | " << "\n=================================================================" << endl; // 2) on demande à l'utilisateur le nom de la référence bool choix_valide = false; string nom_nouveau_maillage = " "; // nom du nouveau maillage string nom_ref = ""; // init int num_mail_ref = 1; // init par défaut while (!choix_valide) { cout << "\n =========== choix de la reference d'elements ===============" << "\n liste des ref d'elements disponibles (rep list)" << "\n nom de la ref d'element du sous maillage (rep nref)" << "\n nom du maillage associe a la ref (defaut: le premier)(rep noma)" << "\n nom du nouveau maillage (rep nmai)" << "\n fin (appel de la methode de creation) (rep f)"; string rep; cout << "\n reponse ? ";rep = lect_return_defaut(false,"f"); string nom_mail_ref(" "); if (rep == "list") // affichage de la liste des ref d'elements disponibles {lesRef->Affiche(2,1); // 2 pour éléments, 1 pour affichage uniquement des noms cout << endl; } else if (rep == "nref") // non de la ref d'element du sous maillage {cout << "\n nom de la ref d'element du sous maillage : "; nom_ref = lect_chaine(); cout << "\n nom lue: " << nom_ref << "\n"; } else if (rep == "noma") // non du maillage associé à la référence {cout << "\n nom du maillage associe a la ref : "; nom_mail_ref = lect_chaine(); cout << "\n nom lue: " << nom_mail_ref << "\n"; } else if (rep == "nmai") // nom du nouveau maillage {cout << "\n nom du nouveau maillage : "; nom_nouveau_maillage = lect_chaine(); cout << "\n nom lue: " << nom_nouveau_maillage << "\n"; } else if ((rep == "0") || (rep == "o") || (rep == "O") || (rep == "f")) { if (nom_nouveau_maillage == " ") { cout << "\n ******* le nom du nouveau maillage reste a definir !! ***** " << endl;} else if (nom_ref == "") { cout << "\n ******* le nom de la ref d'elements reste a definir !! ***** " << endl;} else if (nom_mail_ref != " ") { //on vérifie que le maillage existe if (lesMail->NumMaillage(nom_mail_ref)) { // on vérifie que la ref existe if ( lesRef->Existe(nom_ref,&nom_mail_ref)) { num_mail_ref = lesMail->NumMaillage(nom_mail_ref); choix_valide = true; } // là c'est ok else { cout << "\n *** la reference "<< nom_ref << "du maillage " << nom_mail_ref <<" n'existe pas ?? " << endl; }; } else { cout << "\n *** le maillage " << nom_mail_ref << " n'existe pas ?? " << endl; }; } else { choix_valide = true;}; } else cout << "\n la réponse : " << rep << " n'est pas utilisable, recommencez !"; }; // appel de l'utilitaire dans lesMaillages lesMail->Cree_sous_maillage(num_mail_ref,lesRef,nom_ref,nom_nouveau_maillage); // ----- sort les informations sur fichiers // récup du nombre actuellement actif d'où du dernier maillage créé int nb_maillages_actifs_final = lesMail->NbMaillage(); // ----- sort les informations sur fichiers // Affichage des donnees du dernier maillage dans des fichiers dont le nom est construit // à partir du nom de chaque maillage au format ".her" et ".lis" lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,nb_maillages_actifs_final); } }; } // pour des pb de sortie de résultat qui peuvent bloquer on met à zéro les degrés // de liberté lesMail->ZeroDdl(true); tempsCalEquilibre.Arret_du_comptage(); // temps cpu };