// 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) <https://www.irdl.fr/>.
//
// 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 <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.


#include "AlgoUmatAbaqus.h"
#include "ConstMath.h"
#include "ElemPoint.h"
#include "ElemPoint_CP.h"
#include <vector>


// 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 <EnumSousTypeCalcul>& soustype
            ,const list <bool>& 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 <Noeud*> 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 <Element*> 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 <Element*> list_elem; // liste de tous les éléments
          list <Noeud* > 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 <Noeud *> taN; // liste de noeud à ajouter ici le nouveau
//              taN.push_back(nevez_noeud);
//              list <Element *>  taE;taE.push_back(elnevez); // l'élément à ajouter
//              list <const Reference*>* 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;i<nb_maillage_umat;i++)
//            lesMail->Suppression_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_Positionnement_offset(entreePrinc->position_debut_fichier);
                 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(ostream& sort,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(istream& ent,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;         
  };