// 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 "AlgoUmatAbaqus.h" #include "ConstMath.h" #include "ElemPoint.h" #include "ElemPoint_CP.h" #include // CONSTRUCTEURS : AlgoUmatAbaqus::AlgoUmatAbaqus () : // par defaut Algori() { }; // constructeur en fonction du type de calcul et du sous type // il y a ici lecture des parametres attaches au type AlgoUmatAbaqus::AlgoUmatAbaqus (const bool avec_typeDeCal ,const list & soustype ,const list & avec_soustypeDeCal ,UtilLecture& entreePrinc) : Algori(UMAT_ABAQUS,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 AlgoUmatAbaqus::AlgoUmatAbaqus (const AlgoUmatAbaqus& algo): Algori(algo) { }; // destructeur AlgoUmatAbaqus::~AlgoUmatAbaqus () { }; // execution de l'algorithme dans le cas non dynamique, implicit, sans contact void AlgoUmatAbaqus::Execution(ParaGlob * paraGlob,LesMaillages * lesMail ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats) { // on traite le cas particulier de maillage avec des éléments points, sans noeud référencé // dans le cas où il n'y a pas de noeud rattaché, on ajoute un noeud par défaut Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(UMAT_ABAQUS); // transfert info int nbmaillage = lesMail->NbMaillage(); int dima = ParaGlob::Dimension(); string nom_rien(""); Element::Signature elempoint(CONSTANT,POINT, MECA_SOLIDE_DEFORMABLE,nom_rien); Element::Signature elempoint_CP(CONSTANT,POINT_CP, MECA_SOLIDE_DEFORMABLE,nom_rien); for (int im = 1;im<=nbmaillage;im++) { list listeNoeudSup; // liste des noeuds supplémentaires int num_noeud = 0; // le traitement ne concerne que le cas où il n'existe aucun noeud dans le maillage if ((lesMail->Nombre_element(im) !=0) && (lesMail->Nombre_noeud(im) == 0)) { int nbN=lesMail->Nombre_element(im); for (int ine=1;ine<=nbN;ine++) { Element & elem = lesMail->Element_LesMaille(im,ine); Element::Signature signa = elem.Signature_element(); // le traitement ne concerne que les éléments points if (signa == elempoint) { ElemPoint& elemP = *((ElemPoint *) &elem); // on crée un noeud par défaut qui sera ajouté au maillage à la fin Coordonnee coorRef(dima); // un point en 0 par défaut num_noeud++; Noeud* nevez_noeud = new Noeud(num_noeud,coorRef,im); listeNoeudSup.push_back(nevez_noeud); // on complète l'élément elemP.Associer_noeud (nevez_noeud); nevez_noeud->Travail_tdt(); // a priori on travaillera à tdt aussi } else if (signa == elempoint_CP) { ElemPoint_CP& elemP = *((ElemPoint_CP *) &elem); // on crée un noeud par défaut qui sera ajouté au maillage à la fin Coordonnee coorRef(dima); // un point en 0 par défaut num_noeud++; Noeud* nevez_noeud = new Noeud(num_noeud,coorRef,im); listeNoeudSup.push_back(nevez_noeud); // on complète l'élément elemP.Associer_noeud (nevez_noeud); nevez_noeud->Travail_tdt(); // a priori on travaillera à tdt aussi }; }; }; // on s'occupe maintenant d'ajouter les noeuds lesMail->Ajout_de_Noeuds(listeNoeudSup,im); }; // on définit le type de calcul a effectuer : // ici par défaut (pour l'instant) on ne calcul que l'umat Calcul_Umat(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp ,divStock,charge,lesCondLim,lesContacts,resultats ); }; // Calcul: umat abaqus -> en fait uniquement la loi de comportement pour un point d'intégration void AlgoUmatAbaqus::Calcul_Umat(ParaGlob * paraGlob,LesMaillages * lesMail, LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,LesLoisDeComp* lesLois,DiversStockage* diversStockage, Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats) { // on met en route une boucle qui ne s'arrête normalement que si on reçoit le signal: // incre = -1 Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(UMAT_ABAQUS); // transfert info // dans une première étape on effectue une lecture des grandeurs umat transmises par abaqus // ceci dans le conteneur commun de tous les éléments ElemPoint // ceci permet d'initialiser le processus bool utilisation_umat_interne = false; // on utilise des pipes // on utilise le premier élément du premier maillage pour faire le choix entre POINT et POINT_CP const ElemPoint::inNeNpti* inne = NULL; Enum_geom type_point = lesMail->Element_LesMaille(1,1).Id_geometrie(); switch (type_point) {case POINT: inne = (ElemPoint::inNeNpti*) & ElemPoint::Lecture_Abaqus(utilisation_umat_interne); break; case POINT_CP:inne = (ElemPoint::inNeNpti*) & ElemPoint_CP::Lecture_Abaqus(utilisation_umat_interne); break; default: cout << "\n *** erreur de def d'un element point, le type " << Nom_geom(type_point) << " n'est pas pris en compte !! " << "\n AlgoUmatAbaqus::Calcul_Umat(..."; Sortie(1); break; }; // const ElemPoint::inNeNpti& inne = ElemPoint::Lecture_Abaqus(utilisation_umat_interne); int nb_maillage_umat = 0; // le numéro de maillage umat int dernier_increment = *(inne->incre); int increment_courant = *(inne->incre); int der_iteration = 0; // = 0 la première fois par défaut car on n'a aucune info sur ce point int iteration_courante = 0; // avec les paramètes de l'umat int nbmaillage = lesMail->NbMaillage(); //le nombre actuel de maillage bool premier_passage = true; OrdreVisu::EnumTypeIncre type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul vector tab_element; // pour n'attribuer qu'une fois chaque élément int nb_max_element_enreg=0; // on vérifie que le premier numéro est non nul if (*(inne->nbe) <= 0) { cout << "\n erreur **** le numero de l'element lu= " << *(inne->nbe) << "\n n'est pas utilisable avec la version actuelle d'herezh++ " << "\n AlgoUmatAbaqus::Calcul_Umat(..." << endl; Sortie(1); }; // --- on complète le maillage initiale: température, loi de comp etc. --- // def éventuelle de la loi de comp à partir des données du .info lesMail->Completer(diversStockage,lesLois,lesFonctionsnD); // deux refs d'éléments qui servent pour les tests ElemPoint el_ref_point; ElemPoint_CP el_ref_point_cp; // normalement on ne sort plus de la boucle suivante do { // affichage pour la mise au point if (ParaGlob::NiveauImpression() > 6) { cout << "\n numero de l'increment = " << *(inne->incre) << "\n numero du step = " << *(inne->step) << "\n numero de l'element = " << *(inne->nbe) << "\n numero du pt integ = " << *(inne->nbpti) << endl; }; if (premier_passage) // premier passage { // création de la liste des éléments list list_elem; // liste de tous les éléments list li_noeud; // liste de tous les noeuds // on récupère "le" noeud lu, qui contient éventuellement des initialisations // telles que la présence du ddl température, ce qui nous permettra de répercuter // ces infos sur tous les noeuds créés Noeud & noeud_de_reference = lesMail->Noeud_LesMaille(1, 1); // idem pour l'élément Element & elem_de_reference = lesMail->Element_LesMaille(1,1); int dima = ParaGlob::Dimension(); int num_noeud=0; int num_nouveau_maillage=nbmaillage+1; // // on crée un nouveau maillage vide // string nom_maillage_N="maillage_intermediaire"; // int num_nouveau_maillage = lesMail->Creation_nouveau_maillage(li_noeud,list_elem,nom_maillage_N); // modification du temps de manière arbitraire pa.Modif_temps(*(inne->temps_tdt),*(inne->delta_t)); // deux variables pour sauvegarder les temps utilisés au premier passage double temps_tdt_premier_passage = *(inne->temps_tdt); double delta_t_premier_passage = *(inne->delta_t); do { // création de la liste des éléments Element* elnevez = NULL; bool element_a_creer = true; // tout d'abord on regarde si le numéro d'élément a déjà été affecté // si oui on se sert de l'élément, sinon, on crée un élément nouveau int nbe = *(inne->nbe); if (nbe <= nb_max_element_enreg) {// cas où le numéro est succeptible d'être enregistré if (tab_element[nbe-1] != NULL) { elnevez = tab_element[nbe-1]; element_a_creer = false; // on signale qu'il ne faut pas creer de nouvel élément }; // sinon l'élément n'existe pas mais la place dans le tableau est disponible } else {// cas où l'élément n'existe pas et la place dans le tableau non plus // on crée donc la place Element* elnull = NULL; for (int i=nb_max_element_enreg+1;i<=nbe;i++) tab_element.push_back(elnull); nb_max_element_enreg = nbe; }; // maintenant on crée si necessaire un nouvel élément if (element_a_creer) { switch (type_point) {case POINT: {if (!(el_ref_point.Signature_element() == elem_de_reference.Signature_element())) {cout << "\n *** erreur: l'element du maillage de base doit etre de type POINT "; Sortie(1); }; // sinon c'est ok ElemPoint& el_ref_po = *((ElemPoint*) &elem_de_reference); elnevez = new ElemPoint(el_ref_po); // création d'un nouvel élément break; } case POINT_CP: {if (!(el_ref_point_cp.Signature_element() == elem_de_reference.Signature_element())) {cout << "\n *** erreur: l'element du maillage de base doit etre de type POINT_CP "; Sortie(1); }; // sinon c'est ok ElemPoint_CP& el_ref_po = *((ElemPoint_CP*) &elem_de_reference); elnevez = new ElemPoint_CP(el_ref_po); // création d'un nouvel élément break; } // elnevez = new ElemPoint_CP(); // création d'un nouvel élément // break; default: cout << "\n *** erreur de def d'un element point, le type " << Nom_geom(type_point) << " n'est pas pris en compte !! " << "\n AlgoUmatAbaqus::Calcul_Umat(..."; Sortie(1); break; }; list_elem.push_back(elnevez); // on ajoute un noeud par défaut num_noeud++; Coordonnee coorRef(dima); // un point en 0 par défaut //Noeud* nevez_noeud = new Noeud(num_noeud,coorRef,num_nouveau_maillage); // ** modif 18 avril 2016 : on recopie le noeud initial plutôt qu'une // création entièrement nouvelle, ceci nous permet d'intégrer des ddl que l'utilisation // veut, par exemple la température Noeud* nevez_noeud = new Noeud(noeud_de_reference); nevez_noeud->Change_num_noeud(num_noeud); nevez_noeud->Change_num_Mail(num_nouveau_maillage); nevez_noeud->Change_coord0(coorRef); li_noeud.push_back(nevez_noeud) ; // on complète l'élément ElemPoint* elnew = NULL; // pour simplifier switch (type_point) {case POINT: elnew = (ElemPoint*) elnevez; break; // pour simplifier case POINT_CP: elnew = (ElemPoint_CP*) elnevez; break; // pour simplifier default:break; }; elnew->Associer_noeud (nevez_noeud); nevez_noeud->Travail_tdt(); // a priori on travaillera à tdt aussi // affichage pour la mise au point if (ParaGlob::NiveauImpression() > 8) cout << "\n creation element = " << *(inne->nbe) << endl; tab_element[nbe-1] = elnevez; elnevez->Change_num_elt (*(inne->nbe)); // // ------ ensuite l'idée est de complèter l'élément avec les infos lues // // cependant le nouvel élément n'appartient encore à aucun maillage, // //donc on l'ajoute au // // au premier maillage // list taN; // liste de noeud à ajouter ici le nouveau // taN.push_back(nevez_noeud); // list taE;taE.push_back(elnevez); // l'élément à ajouter // list * lref=NULL; // rien ici // lesMail->Ajout_elements_et_noeuds(taN,taE,lref,lesRef,num_nouveau_maillage); // // ---- cas de la loi de comp ----- // // on complète l'élément éventuellement: en particulier // // def éventuelle de la loi de comp à partir des données du .info // lesMail->Completer(diversStockage,lesLois,lesFonctionsnD); // en fait la vérif suivante ne fonctionne pas, car à ce stade l'élément créé n'appartient // à aucun maillage, donc la loi choisit dans le .info n'est pas affecté // donc seule la loi définie par l'appel d'umat, est toujours prise en compte // on laisse la vérif quand même pour l'instant bien que cela ne sert à rien // -- vérif de la définition de la loi de comportement // recup du pointeur le loi LoiAbstraiteGeneral * pt = lesLois->PtLoi_abstraite(*(inne->nom_loi)); if (pt == NULL) { cout << "\n *** erreur, la loi definie dans le .info "<< (*(inne->nom_loi)) << " n'existe pas !! " " on stoppe l'execution pour eviter des pb de coherence eventuelles "; Sortie(1); }; // récup de la loi éventuellement déjà enregistrée const Loi_comp_abstraite* loi_actuelle = elnew->LoiDeComportement(); if (loi_actuelle == NULL) // s'il n'y a aucune loi de définie on le fait { elnew->DefLoi(pt); } else if ((pt) != (loi_actuelle)) { cout << "\n *** erreur, la loi definie dans le .info pour l'element est differente " " de celle demandee par le programme utilisateur de l'UMAT !! " " on stoppe l'execution pour eviter des pb de coherence eventuelles "; Sortie(1); }; }; // arrivée ici on a l'élément adoc on peut donc calculer ElemPoint* elnew = (ElemPoint*) elnevez; // pour simplifier // les cas en initialisation, calcul et écriture sont identique // pour ElemPoint et ElemPoint_CP donc on garde le pointeur sur // ElemPoint // initialisation éventuelle: en particulier def de la loi de comp // en fonction du nombre de pt d'integ qui a pu changer elnew->InitialisationUmatAbaqus(); // calcul de l'UMat pour abaqus elnew->CalculUmatAbaqus(pa); // écriture du résultat elnew->Ecriture_Abaqus(utilisation_umat_interne); // modif: 12 nov 2018: on affiche le num d'incrément avant la lecture pour le prochain // calcul increment_courant = *(inne->incre); if ((ParaGlob::NiveauImpression() > 2) && premier_passage) {cout << "\n======================================================================" << "\nINCREMENT DE CHARGE : " << (*(inne->incre)) << "\n======================================================================" << endl; }; // comme la lecture est une méthode statique donc non virtualisable // il est nécessaire de différencier le cas ElemPoint avec le cas ElemPoint_CP switch (type_point) {case POINT: {ElemPoint* elnew1 = (ElemPoint*) elnevez; // pour simplifier // lecture de nouvelles données elnew1->Lecture_Abaqus(utilisation_umat_interne); break; } case POINT_CP: {ElemPoint_CP* elnew1 = (ElemPoint_CP*) elnevez; // pour simplifier // lecture de nouvelles données elnew1->Lecture_Abaqus(utilisation_umat_interne); break; } default:break; }; // increment_courant = *(inne->incre); // if ((ParaGlob::NiveauImpression() > 2) && premier_passage) // {cout << "\n======================================================================" // << "\nINCREMENT DE CHARGE : " << (*(inne->incre)) // << "\n======================================================================" // << endl; // }; premier_passage = false; iteration_courante = elnew->NbIteration(); // on affiche éventuellement si l'on passe d'une itération à l'autre if (iteration_courante != der_iteration) { der_iteration = iteration_courante; if (ParaGlob::NiveauImpression() > 3) cout << "\n ITERATION : " << iteration_courante << endl; }; } while ( increment_courant == dernier_increment); // maintenant on a changé de numéro d'incrément, et l'increment est > 1 // on crée le maillage correspondant, avec les noeuds et éléments déjà créé // (il n'y a pas de création de nouveaux noeuds ou de nouveaux éléments, ainsi // toutes les infos déjà calculées et stockées sont gardées) string nom_maillage="maillage_umat"; nb_maillage_umat = lesMail->Creation_nouveau_maillage(li_noeud,list_elem,nom_maillage); // on supprime les 2 maillages initiaux, sans supprimer les noeuds et éléments créés, // car ce sont également les noeuds et éléments du nouveau maillage bool sans_conservation_noeuds_elements = false; // for (int i=1;iSuppression_maillage(lesMail->NomMaillage(i),sans_conservation_noeuds_elements); lesMail->Suppression_maillage(lesMail->NomMaillage(1),sans_conservation_noeuds_elements); // on met à jour le compteur d'itération der_iteration = iteration_courante; // modification du temps correspondant au premier passage pa.Modif_temps(temps_tdt_premier_passage,delta_t_premier_passage); // on s'occupe d'une sortie si necessaire if (this->Active_sauvegarde()) { // si le fichier base_info n'est pas en service on l'ouvre entreePrinc->Ouverture_base_info("ecriture"); // dans le cas ou se n'est pas un restart on sauvegarde l'incrément actuel // c'est-à-dire le premier incrément // après s'être positionné au début du fichier if (this->Num_restart() == 0) { (entreePrinc->Sort_BI())->seekp(0); int cas = 1; paraGlob->Ecriture_base_info(*(entreePrinc->Sort_BI()),cas); this->Ecriture_base_info (cas,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLois,diversStockage ,charge,lesCondLim,lesContacts,resultats,OrdreVisu::INCRE_0); // visualisation éventuelle au fil du calcul VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLois,diversStockage,charge ,lesCondLim,lesContacts,resultats,type_incre,(*(inne->incre)-1)); }; }; } else { // ----- cas des incréments courants > 1------ // récupération de l'élément if (ParaGlob::NiveauImpression() > 8) cout << "\n numero de l'element = " <<*(inne->nbe) << endl; //Element& elem = lesMail->Element_LesMaille(nb_maillage_umat,*(inne->nbe)); // pour éviter des pb d'adressage indirecte on utilise directement le tableau // de pointeur pour retrouver l'élément plutôt que lesMail Element* elem = NULL; if (tab_element[*(inne->nbe)-1] != NULL) {elem = tab_element[*(inne->nbe)-1];} else { cout << "\n erreur l'element demande (nb=" << *(inne->nbe)-1 << ") n'a pas ete attribue " << "dans la phase d'initialisation c-a-d lors du premier increment" << "\n AlgoUmatAbaqus::Calcul_Umat(..."; Sortie(1); }; ElemPoint* el = (ElemPoint*) elem; // pour simplifier // calcul de l'UMat pour abaqus el->CalculUmatAbaqus(pa); // écriture du résultat el->Ecriture_Abaqus(utilisation_umat_interne); // comme la lecture est une méthode statique donc non virtualisable // il est nécessaire de différencier le cas ElemPoint avec le cas ElemPoint_CP switch (type_point) {case POINT: {ElemPoint* el1 = (ElemPoint*) elem; // pour simplifier // lecture de nouvelles données el1->Lecture_Abaqus(utilisation_umat_interne); break; } case POINT_CP: {ElemPoint_CP * el1 = (ElemPoint_CP*) elem; // pour simplifier // lecture de nouvelles données el1->Lecture_Abaqus(utilisation_umat_interne); break; } default:break; }; // // lecture de nouvelles données // el->Lecture_Abaqus(utilisation_umat_interne); increment_courant = *(inne->incre); iteration_courante = el->NbIteration();; }; // on note si l'on passe d'une itération à l'autre if (iteration_courante != der_iteration) { der_iteration = iteration_courante; if (ParaGlob::NiveauImpression() > 3) cout << "\n ITERATION : " << iteration_courante << endl; }; // mise à jour de t à tdt if (increment_courant != dernier_increment) {// modification du temps pa.Modif_temps(*(inne->temps_tdt),*(inne->delta_t)); lesMail->TdtversT(); dernier_increment = increment_courant; // --- traitement des sauvegardes éventuelles --- // sauvegarde de l'incrément si nécessaire Ecriture_base_info(2,lesMail,lesRef,lesCourbes1D,lesFonctionsnD ,lesLois,diversStockage,charge,lesCondLim,lesContacts ,resultats,type_incre,(*(inne->incre)-1)); // enregistrement du num d'incrément et du temps correspondant list_incre_temps_calculer.push_front(Entier_et_Double((*(inne->incre)-1),pa.Variables_de_temps().TempsCourant())); // visualisation éventuelle au fil du calcul VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLois,diversStockage,charge ,lesCondLim,lesContacts,resultats,type_incre,(*(inne->incre)-1)); // on affiche éventuellement le prochain incrément if (ParaGlob::NiveauImpression() > 1) {cout << "\n======================================================================" << "\nINCREMENT DE CHARGE : " << (*(inne->incre)) << "\n======================================================================" << endl; }; }; } while (*(ElemPoint::IncreElemPtint_encours().incre)!=-1); // fin }; // écriture des paramètres dans la base info // = 1 : on écrit tout // = 2 : on écrot uniquement les données variables (supposées comme telles) void AlgoUmatAbaqus::Ecrit_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas) { // récup du flot // ofstream * sort = entreePrinc.Sort_BI(); // (*sort) << "\n parametres_algo_specifiques_ "<< Nom_TypeCalcul(this->TypeDeCalcul()); // ecriture: rien pour l'instant // if (cas == 1) // { // } ; // (*sort) << "\n fin_parametres_algo_specifiques_ "; }; // lecture des paramètres dans la base info // = 1 : on récupère tout // = 2 : on récupère uniquement les données variables (supposées comme telles) // choix = true : fonctionnememt normal // choix = false : la méthode ne doit pas lire mais initialiser les données à leurs valeurs par défaut // car la lecture est impossible void AlgoUmatAbaqus::Lecture_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas,bool choix) {if (cas == 1) {if (choix) {// cas d'une lecture normale // récup du flot // ifstream * ent = entreePrinc.Ent_BI(); // pour l'instant on ne lit rien } } }; // création d'un fichier de commande: cas des paramètres spécifiques void AlgoUmatAbaqus::Info_commande_parametres(UtilLecture& entreePrinc) { // écriture dans le fichier de commande ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier sort << "\n#--------------------------------------------------------------------" << "\n| parametres (falcultatifs) associes l'algorithme umat pour abaqus |" << "\n#--------------------------------------------------------------------" << "\n" << "\n # aucun parametre pour l'instant "; sort << "\n" << endl; };