//************************************************************************ // --- Logiciel MEF++ // --- // --- Copyright 1996-2002 GIREF, Université Laval // --- TOUS DROITS RÉSERVÉS // --- ALL RIGHTS RESERVED // --- // --- Ce logiciel est couvert par la Loi sur le droit d'auteur. // --- L'utilisation, ou la modification de ce logiciel sous toutes ses // --- formes, que ce soit code source ou code compilé, à des fins // --- personnelles et non commerciales sont autorisées sans frais pour // --- autant que la présente notice de copyright ainsi que cette // --- permission apparaissent dans toutes les copies ainsi que dans la // --- documentation. // --- Le GIREF et l'Université Laval ne prétendent en aucune façon que // --- ce logiciel convient à un emploi quelconque. Celui-ci est // --- distribué sans aucune garantie implicite ou explicite. //************************************************************************ //******************************************************************** // // Resolution du probleme viscoelastique en utilisant le model de Maxwell generalise: // // C_TRho dT/dt - div(K_T grad(T)) = 0 (1) température // // C_MRho dM/dt - div(K_M grad(M) + K_MT grad(T) ) = 0 (2) teneur en humidité // // -div(sigma(U)) = F (3) déplacements // // avec possiblement un contact sur la partie "entite_en_contact" du domaine (typiquement // de la forme UZ >= 0 sur une partie de la frontiere) // // Les équations (1) et (3) sont optionnelles auxquels cas leur traitement est completement // ignorées dans le code. Dans (3) le membre de droite F est optionnel. // // USAGE:
 ThermoHygroMecanikNewtonViscoElasticiteMaxwellGeneraliseHPP.[dev,opt]
//              préfixe_des_fichiers_d_entrée [entite_en_contact]
//
//  Exemple:
//
//
//********************************************************************

#include "MEFPPUtil.h"
#include "ChaineCar.h"
#include "ChampCelluleViscoElastiqueMaxwellHPP.h"
#include "ChampContraintesHPP.h"
#include "ChampContraintesHPPMateriauVieillissant.h"
#include "ChampElastiqueViscoElastiqueMaxwellHPP.h"
#include "ChampExponentielleTempsRelaxation.h"
#include "ChampGeometrique.h"
#include "ChampPrecalculeDiscPtsIntegration.h"
#include "ChampPseudoContraintesO4.h"
#include "ChampScalaire.h"
#include "ChampScalContinu.h"
#include "ChampScalAConstant.h"
#include "ChampTensO2SymContinu.h"
#include "ChampTensO2SymLinElem.h"
#include "ChampTensorielO4Sym.h"
#include "ChampTensorielO4SymMin.h"
#include "ChampVect3DContinu.h"
#include "ChampContraintesHPP.h"
#include "ExportGIREF.h"
#include "ExportVU.h"
#include "fonctionsChaineCar.h"
#include "Geometrie.h"
#include "GestionFichierChamps.h"
#include "InitialisationArgvArgc.h"
#include "InitialisationTraitementSignal.h"
#include "ListeConditionsLimites.h"
#include "ListEntitesGeometrique.h"
#include "Maillage.h"
#include "MaillagePeau.h"
#include "OptionsSolveurLinPETSc.h"
#include "PETScInitialisation.h"
#include "PPAfficheValeur.h"
#include "PPCallBack.h"
#include "PPCalculChampaXpbY.h"
#include "PPEvalueChampXYZ.h"
#include "PPResolutionProbleme.h"
#include "PPReinterpole.h"
#include "PPCallBack2Args.h"
#include "PPContraintesEL3D.h"
#include "ProblemeEF.h"
#include "ProblemeEFInstationnaire.h"
#include "PtIntgElem1D.h"
#include "PtIntgHexaedre.h"
#include "PtIntgPrismeTri.h"
#include "PtIntgQuadrangle.h"
#include "PtIntgTetraedre.h"
#include "PtIntgTriangle.h"
#include "SchemaIntg.h"
#include "SolveurInstNlinPETSc.h"
#include "SolveurLinPETSc.h"
#include "SolveurGCPAvecCorpsRigide.h"
#include "SolveurQuasiStatiqueNlinPETSc.h"
#include "TFCelluleViscoElastiqueMaxwellHPPEpsilonLin.h"
#include "TFElastiqueViscoElastiqueMaxwellHPPEpsilonLin.h"
#include "TFDiffusion.h"
#include "TFDiffusionNewton.h"
#include "TFMasseGenScal.h"
#include "TFContraintesInitiales.h"
#include "TFCouplageAvecFctsConnues.h"
#include "TFContactV3DUxNVScal.h"
#include "TFSigmaUEpsilonV3D.h"
#include "TFSourceFVVect3D.h"
#include "VerifieElementsNormalises.h"
#include "traducteurERMsg.h"
#include 
#include 

using namespace std;
struct ProprietePurementElastique {

  ChampTensorielO4Sym* Elasticite;
  bool                 MateriauVieillissant;
  ChampScalaire*       DeltaTempsReduit;
  DReel*               LongueurPasDeTemps;

  ChampScalaire* IndicateurEtat;

  ChampTensorielO4Sym* TenseurS;
  ChampTensorielO2Sym* ContraintesCourantes;
  ChampTensorielO2Sym* ContraintesPrecedentes;

};

struct ProprieteViscoElastique {

  ChampTensorielO4Sym*    Elasticite;
  ChampTensorielO4Sym*    Viscosite;
  bool                    MateriauVieillissant;
  ChampScalaire*          DeltaTempsReduit;
  ChampScalaire*          Multiplicateur_b;
  ChampScalaire*          Multiplicateur_bPrecedent;
  ChampScalaire*          IndicateurEtat;

  ChampTensorielO4Sym*    TenseurS;
  ChampTensorielO4Sym*    TenseurI;
  ChampTensorielO4SymMin* PseudoContraintesCourantes;
  ChampTensorielO4SymMin* PseudoContraintesPrecedentes;

};

template
ERMsg ajouteListeReinterpole(PTTypeChampSource& pChampSource, PTTypeChampDestination& pChampDestination, std::vector& pVecteurPPReinterpolation){

  ERMsg lMsg;

  Entier lDimensionDuPTTypeChamp1 = pChampSource.reqNbDDLsParComposanteDeMaillage().reqDimension();

  if (lMsg && (1 != lDimensionDuPTTypeChamp1 && 2 != lDimensionDuPTTypeChamp1 && 3 != lDimensionDuPTTypeChamp1
	       && 6 != lDimensionDuPTTypeChamp1 && 9 != lDimensionDuPTTypeChamp1 && 21 != lDimensionDuPTTypeChamp1
               && 36 != lDimensionDuPTTypeChamp1)) {
    lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_DIMENSION_CHAMP_INCONNU"));
    lMsg.ajoute(pChampSource.reqNom());
  }

  if(lMsg){
    switch (lDimensionDuPTTypeChamp1){

    case 1:
    {
      ChampScalaire *lSource      = dynamic_cast(&pChampSource);
      ChampScalaire *lDestination = dynamic_cast(&pChampDestination);
      if(lSource == 0 || lDestination == 0) {
        lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_CHAMP_INCOMPATIBLE_AVEC_1D"));
        if(lSource == 0) lMsg.ajoute(pChampSource.reqNom());
        if(lDestination == 0) lMsg.ajoute(pChampDestination.reqNom());
      }
      if(lMsg){
        PPReinterpole* lPPReinterpole1D = new PPReinterpole(*lSource,*lDestination);
        pVecteurPPReinterpolation.push_back(lPPReinterpole1D);
      }
    }
    break;
    case 2:
    {
      ChampVectoriel2D* lSource      = dynamic_cast(&pChampSource);
      ChampVectoriel2D* lDestination = dynamic_cast(&pChampDestination);
      if(lSource == 0 || lDestination == 0) {
        lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_CHAMP_INCOMPATIBLE_AVEC_2D"));
        if(lSource == 0) lMsg.ajoute(pChampSource.reqNom());
        if(lDestination == 0) lMsg.ajoute(pChampDestination.reqNom());
      }
      if(lMsg){
        PPReinterpole* lPPReinterpole2D = new PPReinterpole(*lSource,*lDestination);
        pVecteurPPReinterpolation.push_back(lPPReinterpole2D);
      }
    }
    break;
    case 3:
    {
      ChampVectoriel3D* lSource      = dynamic_cast(&pChampSource);
      ChampVectoriel3D* lDestination = dynamic_cast(&pChampDestination);
      if(lSource == 0 || lDestination == 0) {
        lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_CHAMP_INCOMPATIBLE_AVEC_3D"));
        if(lSource == 0) lMsg.ajoute(pChampSource.reqNom());
        if(lDestination == 0) lMsg.ajoute(pChampDestination.reqNom());
      }
      if(lMsg){
        PPReinterpole* lPPReinterpole3D = new PPReinterpole(*lSource,*lDestination);
        pVecteurPPReinterpolation.push_back(lPPReinterpole3D);
      }
    }
    break;
    case 6:
    {
      ChampTensorielO2Sym* lSource      = dynamic_cast(&pChampSource);
      ChampTensorielO2Sym* lDestination = dynamic_cast(&pChampDestination);
      if(lSource == 0 || lDestination == 0) {
        lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_CHAMP_INCOMPATIBLE_AVEC_6D"));
        if(lSource == 0) lMsg.ajoute(pChampSource.reqNom());
        if(lDestination == 0) lMsg.ajoute(pChampDestination.reqNom());
      }
      if(lMsg){
        PPReinterpole* lPPReinterpole6D = new PPReinterpole(*lSource,*lDestination);
        pVecteurPPReinterpolation.push_back(lPPReinterpole6D);
      }
    }
    break;
    case 9:
    {
      ChampTensorielO2NSym* lSource      = dynamic_cast(&pChampSource);
      ChampTensorielO2NSym* lDestination = dynamic_cast(&pChampDestination);
      if(lSource == 0 || lDestination == 0) {
        lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_CHAMP_INCOMPATIBLE_AVEC_9D"));
        if(lSource == 0) lMsg.ajoute(pChampSource.reqNom());
        if(lDestination == 0) lMsg.ajoute(pChampDestination.reqNom());
      }
      if(lMsg){
        PPReinterpole* lPPReinterpole9D = new PPReinterpole(*lSource,*lDestination);
        pVecteurPPReinterpolation.push_back(lPPReinterpole9D);
      }
    }
    break;
    case 21:
    {
      ChampTensorielO4Sym* lSource      = dynamic_cast(&pChampSource);
      ChampTensorielO4Sym* lDestination = dynamic_cast(&pChampDestination);
      if(lSource == 0 || lDestination == 0) {
        lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_CHAMP_INCOMPATIBLE_AVEC_21D"));
        if(lSource == 0) lMsg.ajoute(pChampSource.reqNom());
        if(lDestination == 0) lMsg.ajoute(pChampDestination.reqNom());
      }
      if(lMsg){
        PPReinterpole* lPPReinterpole21D = new PPReinterpole(*lSource,*lDestination);
        pVecteurPPReinterpolation.push_back(lPPReinterpole21D);
      }
    }
    break;
    case 36:
    {
      ChampTensorielO4SymMin* lSource      = dynamic_cast(&pChampSource);
      ChampTensorielO4SymMin* lDestination = dynamic_cast(&pChampDestination);
      if(lSource == 0 || lDestination == 0) {
        lMsg.ajoute(ERMsg(ERMsg::ERREUR, "ERR_CHAMP_INCOMPATIBLE_AVEC_36D"));
        if(lSource == 0) lMsg.ajoute(pChampSource.reqNom());
        if(lDestination == 0) lMsg.ajoute(pChampDestination.reqNom());
      }
      if(lMsg){
        PPReinterpole* lPPReinterpole36D = new PPReinterpole(*lSource,*lDestination);
        pVecteurPPReinterpolation.push_back(lPPReinterpole36D);
      }
    }
    break;
    }
  }

  return lMsg;
}


ERMsg lisString(const char*& pCharPtrAModifier,std::string& pStringRetour);

int main(int argc, char *argv[]) {

// ***********************************
// * BLOC: Initialisations générales *
// ***********************************
  PETScInitialisation lPETScInit(&argc, &argv);
  sInitialisationArgvArgc.asgnArguments(argc, argv);
  initialiseTraitementSignal();

  const vector lArgv = sInitialisationArgvArgc.reqArgv();

  // On déclare une variable qui contiendra potentiellement un message d'erreur
  ERMsg lMsg = ERMsg(ERMsg::OK);

  // On recupere le GroupeProcessus associe a PETSC_COMM_WORLD
  const PAGroupeProcessus lGroupeGlobal = PETScInitialisation::reqPetscCommWorld();

  // On déclare les variables qui seront extraites de la ligne de commande
  ChaineCar lNomMaillage, lNomFichierChamp, lNomEntite;
  bool lContakt(false);               // le probleme n'est pas un pb de contact

  // Vérification des paramètres passés à la ligne de commande.
  const Entier lNbArg = lArgv.size();
  if (lNbArg < 2 || lNbArg > 3) {
    ChaineCar lNomProgramme = sInitialisationArgvArgc.reqNomProgramme();
    ChaineCar lMessageUsage = "USAGE: \n";
    lMessageUsage += enleveCheminAccesFichier(lNomProgramme);
    lMessageUsage += " Prefixe_fichiers_champs Nom_entite_de_contact (optionnel)";
    lMsg.ajoute(ERMsg(ERMsg::ERREUR, lMessageUsage));
  }
  else {
    lNomFichierChamp = lArgv[1];
    if(lNbArg>2){
      lNomEntite  = lArgv[2];
      lContakt    = true;
    }
  }

  lNomMaillage = lNomFichierChamp;

  // Pre-traitement des donnees du fichier champs:
  {
    const EntierN lTailleBuffer = 65536;
    char *lLigne = new char[lTailleBuffer];
    std::ifstream lFichierChamp((lNomFichierChamp + std::string(".champs")).c_str());
    bool lNomMaillageTrouve(false);
    bool lNomEntiteTrouve(false);

    if(lFichierChamp) {
      lFichierChamp.getline(lLigne,lTailleBuffer);

      while(lFichierChamp && lMsg && (!lNomMaillageTrouve || !lNomEntiteTrouve)){
	if(retournePremierMotSansEspace(lLigne) == "chainecar"){
	  ChaineCar lNomBidon;
	  const char* lPositionDansLigne = &lLigne[0];
	  lMsg = lisString(lPositionDansLigne, lNomBidon);
	  if(lMsg) lMsg = lisString(lPositionDansLigne, lNomBidon);
	  if(!lNomMaillageTrouve && lNomBidon == "NOM_DU_MAILLAGE") {
	    if(lMsg) {
	      lMsg = lisString(lPositionDansLigne, lNomMaillage);
	    }
	    lNomMaillageTrouve = true;
	  }

	  if( !lNomEntiteTrouve && lNomBidon == "NOM_ENTITE_DE_CONTACT") {
	    if(lMsg) {
	      lMsg = lisString(lPositionDansLigne, lNomEntite);
	      lContakt    = true;
	    }
	    lNomEntiteTrouve = true;
	  }
	}
	lFichierChamp.getline(lLigne,lTailleBuffer);
      }
      //lFichierChamp.seekg (0, std::ios::beg);
    }
    lFichierChamp.close();
  }
  // Fin du pre-traitement

  // *****************************************************
  // BLOC: Création des objets utilisés dans le calcul *
  // *****************************************************
  // On crée: la géométrie, la liste d'entités géométriques, le maillage et le champ géométrique.
  Geometrie              lGeo;
  ListEntitesGeometrique lListeEntite;
  ListEntitesGeometrique lListeEntitePeau;

  Maillage               lMail;
  MaillagePeau           lMailPeau;


  // Creation des champs requis pour le probleme :
  ChampGeometrique       *lChampGeo= 0;        // champ geometrique du domnaine entier

  ChampScalContinu       *lM       = 0;        // humidite
  ChampScalContinu       *lMP      = 0;        // humidite au pas precedent (necessaire en cas d'hysterese seulement)
  ChampScalContinu       *lMt      = 0;        // dérivée en temps de M
  ChampScalContinu        *lC_MRho = 0;        // densite * "chaleur specifique"
  ChampTensO2SymContinu   *lK_M    = 0;        // diffusivité effective d_b*D
  ChampTensO2SymContinu   *ldK_MdM = 0;        // derivee de la diffusivite effective en M

 //  ChampScalContinu       *lMtB      = 0;        // dérivée en temps de M
//   ChampScalContinu        *lC_MRhoB = 0;        // densite * "chaleur specifique"
//   ChampTensO2SymContinu   *lK_MB    = 0;        // diffusivité effective d_b*D
//   ChampTensO2SymContinu   *ldK_MdMB = 0;        // derivee de la diffusivite effective en M

  ChampTensO2SymContinu   *lK_MT   = 0;        // thermo-diffusion
  ChampTensO2SymContinu   *lK_T    = 0;        // diffusion thermique
  ChampScalContinu        *lC_TRho = 0;        // chaleur spécifique multiplier par la densité
  ChampScalContinu          *lT    = 0;        // temperature

  ChampVect3DContinu        *lU    = 0;        // les déplacements
  ChampVect3DContinu       *lUPrec = 0;        // les déplacements
  ChampVect3DContinu*lDeplacements = 0;        // les déplacements

  ChampTensO2SymContinu    *lBetaM = 0;        // tenseur O2 des dilatation hydrique
  ChampTensO2SymContinu    *lBetaMB = 0;        // tenseur O2 des dilatation hydrique
  ChampTensO2SymContinu    *lBetaT = 0;        // tenseur O2 des dilatation thermique
  ChampVectoriel3D         *lF     = 0 ;       // les charges volumiques

  // Creation des champs requis pour le probleme Peau
  ChampGeometrique        *lChampGeoPeau=0;      // champ geometrique de la peau
  ChampVect3DContinu      *lUPeau = 0;           // Une version "peau" de U
  ChampScalaire           *lLambdaCtc = 0;       // Ce champ contiendra le multiplicateur
  ChampVectoriel3D        *lNormaleExtPeau = 0;  // Ce champ doit contenir la normale extérieure
  ChampScalContinu        *lGapPeau = 0;         // Ce champ pour Bu <= g.
  ChampScalaire           *lMPeau = 0;           // Une version "peau" de M
  ChampScalaire           *lTPeau = 0;           // Une version "peau" de T

  // Variable lues dans le fichier:

  bool   lThermik(false);               // le problème a une composante thermique
  bool   lMecanik(true);                // le problème a  une composante mecanique
  bool   lEmploiNewtonEnM(false);       // On resout avec le terme dK_M/DM (methode de Newton au lieu de pt fixe)#
  bool   lHysterese(true);              // le tenseur de dilatation hydrique tiens compte d'effet d'hysterese
  Entier lPasDeCalcul;                  // frequence du calcul de mecanique: 0 -> pas de calcul
  Entier lPasImpression;                // frequence d'impression des résultats
  Entier lNbTempsImpose;                // Nombre de points du temps ou on force le calcul
  SolveurInstNlinPETSc  *lSolveurHyd;   // le solveur instationnaire pour M (et T possiblement)

  SolveurQuasiStatiqueNlinPETSc * lSolveurQuasiStatique = 0;  // le solveur quasi statique
  SolveurLinPETSc               *lSolveurMec;                // le solveur stationnaire pour U
  DReel           *lPointeurVersLePasDeTempsDuSolveur = 0;     // Un Pointeur Vers Le Pas De Temps Du Solveur

  ChaineCar lNomEntiteControle;          // le nom de l'entite servant au controle des mouvements de corps rigide
  Entier    lDirectionDesCorps;          // Numero de l'axe paralelle aux corps rigide

  VectDyn lVectProprieteBrancheViscoElastique;  // un vecteur contenant les proprietes viscoelastique pour chaque branche

  std::vector lVectChampAReinterpoler;   // un vecteur des champs qu'on devra reinterpoler AVANT la resolution

  std::vector lVectChampADeleter; // un vecteur des champs qui devront etre detruit en fin de programme

  // Variable lues dans le fichier:

  Entier lNombreBrancheViscoElastique = 0;  // le nombre de composantes/cellules/branches viscoélastique du problème

  bool   lReassemble(true);               // reassemblage possible de la matrice de rigidite.

  VectDyn lTempsImposes;           // les points dans le temps ou on veut imposer une approximation des champs
  VectDyn lCoordonnees;        // les coordonnées dont on fait une "trace" pendant l'execution

  bool lVrai(true);

  Entier lPoints1D(4);

  SchemaIntg     lSchemaIntg;
  SchemaIntg     lSchemaIntgNewtonCote;

  if (lMsg) {
    // Création du schéma d'intégration des termes de formulation

    lSchemaIntg.asgnIntegration(PtIntgTriangle(PtIntgTriangle::Hammer_DouzePtsInternes_Degre6));

    lSchemaIntg.asgnIntegrationFace3Sommets(PtIntgTriangle(PtIntgTriangle::Hammer_DouzePtsInternes_Degre6));
    lSchemaIntg.asgnIntegrationFace4Sommets(PtIntgQuadrangle(PtIntgElem1D(lPoints1D),PtIntgElem1D(lPoints1D)));

    lSchemaIntg.asgnIntegration(PtIntgQuadrangle(PtIntgElem1D(lPoints1D),PtIntgElem1D(lPoints1D)));
    lSchemaIntg.asgnIntegration(PtIntgElem1D(lPoints1D));
    lSchemaIntg.asgnIntegrationArete(PtIntgElem1D(lPoints1D));

    lSchemaIntg.asgnIntegration(PtIntgHexaedre(PtIntgElem1D(lPoints1D), PtIntgElem1D(lPoints1D), PtIntgElem1D(lPoints1D)));
    lSchemaIntg.asgnIntegration(PtIntgPrismeTri(PtIntgTriangle(PtIntgTriangle::Hammer_DouzePtsInternes_Degre6), PtIntgElem1D(lPoints1D)));
    lSchemaIntg.asgnIntegration(PtIntgTetraedre(5));

    // On crée un schéma pour la résolution du problème de contact si nécessaire
    if(lMsg && lContakt) {

      PtIntgElem1D      lPtIntgElem1D  (PtIntgElem1D::Newton_Cotes_DeuxPoints_Degre1);
      PtIntgTriangle    lPtIntgTriangle(PtIntgTriangle::Newton_Cotes_TroisPoints_Degre1);
      PtIntgQuadrangle  lPtIntgQuad    (lPtIntgElem1D,lPtIntgElem1D);
      PtIntgTetraedre   lPtIntgTetra   (PtIntgTetraedre::Hammer_QuinzePtsInternes_Degre5);
      PtIntgHexaedre    lPtIntgHexa    (PtIntgElem1D(2),PtIntgElem1D(2),PtIntgElem1D(2));

      lSchemaIntgNewtonCote.asgnIntegration(lPtIntgElem1D);
      lSchemaIntgNewtonCote.asgnIntegration(lPtIntgTriangle);
      lSchemaIntgNewtonCote.asgnIntegration(lPtIntgQuad);
      lSchemaIntgNewtonCote.asgnIntegration(lPtIntgTetra);

      lSchemaIntgNewtonCote.asgnIntegration(lPtIntgHexa);
      lSchemaIntgNewtonCote.asgnIntegrationArete(lPtIntgElem1D);
      lSchemaIntgNewtonCote.asgnIntegrationFace3Sommets(lPtIntgTriangle);
      lSchemaIntgNewtonCote.asgnIntegrationFace4Sommets(lPtIntgQuad);
    }

  }

  //On déclare les problèmes "vides"
  ProblemeEFInstationnaire lProbHyd;
  lProbHyd.asgnNom("Composante hydrique/thermique");
  ProblemeEF lProbMec;
  lProbMec.asgnNom("Composante mecanique");
  ProblemeEF lProbPeauGCP;
  ProblemeEF lProbPeauGCP2;

  lProbHyd.asgnGroupeProcessus(lGroupeGlobal);
  lProbMec.asgnGroupeProcessus(lGroupeGlobal);
  lProbPeauGCP.asgnGroupeProcessus(lGroupeGlobal);
  lProbPeauGCP2.asgnGroupeProcessus(lGroupeGlobal);

  if(lContakt && lMsg){
    lMsg = lProbHyd.lisDonnees(lNomMaillage,lMail,lMailPeau,lNomEntite,lGeo,lListeEntite,lListeEntitePeau);
  } else if(lMsg) {
    lMsg = lProbHyd.lisDonnees(lNomMaillage,lMail, lGeo,lListeEntite);
  }

  VerifieElementsNormalises lVerifieElementsNormalises;
  if(!lVerifieElementsNormalises(lMail,lVrai)) lMsg.ajoute(ERMsg(ERMsg::ERREUR,"Le maillage DOIT etre normalise!"));

  //Déclaration de l'objet qui fait la gestion des champs pour le problème.
  GestionFichierChamps lFichierChamp;
  GestionFichierChamps lFichierChampPeau;

  if (lMsg) {
    lFichierChamp.asgnDonneesBase(&lMail);
    lFichierChamp.asgnDonneesGeometriques(&lGeo,&lListeEntite);
  }

  //On demande au gestionnaire de lire le fichier de champ
  if(lMsg) lMsg = lFichierChamp.lireFichier((lNomFichierChamp + std::string(".champs")).c_str());

  // On choisit s'il faut reassembler la matrice de rigidite a chaque pas de temps
  if(lMsg) lMsg = lFichierChamp.reqBooleen("Reassemble",lReassemble,true);

  //
  // Le solveur quasi-statique, possiblement on voudra un acces au pas de temps du solveur ce
  // qui nous oblige a définir le solveur ici.
  //
  bool lDefinitionDansFichierChamps(true);
  if(lMsg) lMsg = lFichierChamp.reqSolveur("SolveurQS",lSolveurQuasiStatique,false);
  if(lSolveurQuasiStatique==0) {
    lSolveurQuasiStatique = new SolveurQuasiStatiqueNlinPETSc();
    lDefinitionDansFichierChamps=false;
  }

  // Requête des données du fichier .champs nécessaires au calcul
  // On determine le type de probleme:

  if(lMsg) lMsg = lFichierChamp.reqBooleen("Thermique",lThermik,false);
  if(lMsg) lMsg = lFichierChamp.reqBooleen("Mecanique",lMecanik,false);

  if(lMsg && lContakt && !lMecanik) {
    std::cout<<"Pas de contact sans mecanique! On remet le contact à faux"<("ChampGeo",lChampGeo);
    std::cout<< "Sort du fichier champ "<("M",lM);

  //On demande  un champ qui se nomme "M_t" pour la valeur difference finie de M (hystérèse présente dans le problème)
  if(lMsg) lMsg = lFichierChamp.reqChamp("M_t",lMt,false);
  // if(lMsg){
//     lMsg = lFichierChamp.reqChamp("M_tB",lMtB,false);
//      std::cout<< "fffffffffM_tB "<("C_MRho",lC_MRho);
  // if(lMsg) lMsg = lFichierChamp.reqChamp("C_MRhoB",lC_MRhoB);
   //if(lMsg && lC_MRhoB == 0) lC_MRhoB = lC_MRho->newChampCopie();

  //On demande  un champ qui se nomme "K_M" pour le tenseur de "diffusivité effective" (d_b * D)
  if(lMsg) lMsg = lFichierChamp.reqChamp("K_M",lK_M);
  //if(lMsg) lMsg = lFichierChamp.reqChamp("K_MB",lK_MB);
  //if(lMsg && lK_MB == 0) lK_MB = lK_M->newChampCopie();

  //On demande  un champ qui se nomme "dK_MdM" pour la derivee du tenseur de "diffusivité effective" en M
  if(lMsg) lMsg = lFichierChamp.reqChamp("dK_MdM",ldK_MdM,false);
  // if(lMsg) lMsg = lFichierChamp.reqChamp("dK_MdMB",ldK_MdMB,false);
   //if(lMsg && ldK_MdMB == 0) ldK_MdMB = ldK_MdM->newChampCopie();
  if(lMsg && ldK_MdM) {
    lEmploiNewtonEnM = true;
     std::cout<< "Fin Pour la partie hydrique "<("K_MT",lK_MT);

    //On demande  un champ qui se nomme "T" pour la température
    if(lMsg) lMsg = lFichierChamp.reqChamp("T",lT);

    //On demande  un champ qui se nomme "K_T" pour la "diffusion thermique"
    if(lMsg) lMsg = lFichierChamp.reqChamp("K_T",lK_T);

    //On demande  un champ qui se nomme "C" pour la chaleur spécifique multiplie par la densité de base
    if(lMsg) lMsg = lFichierChamp.reqChamp("C_TRho",lC_TRho);
  }

  // ***************************
  // * pour la partie mécanique:
  // ***************************

  // Frequence du calcul mecanique
  lPasDeCalcul = 1;
  if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("freqCalcul",lPasDeCalcul,false);

  if(lMsg && lPasDeCalcul == 0){
    std::cout<<"ATTENTION: pas de sauvegarde des resultats de mecanique/contact alors je ne les fait pas!"<("U",lU);
    if(lMsg) lMsg = lFichierChamp.reqChamp("Deplacements",lDeplacements,false);
    if(!lDeplacements && lContakt)
      lMsg.ajoute(ERMsg(ERMsg::ERREUR, "En cas de contact on doit definir Deplacements dans le fichier champs et dans celui de peau."));

    if(lMsg && !lDeplacements) lDeplacements = lU->newChampCopie();

    // On demande  un champ qui se nomme "UPrec" pour le deplacement au temps precedent.
    if(lMsg) lMsg = lFichierChamp.reqChamp("UPrec",lUPrec,false);
    if(lMsg && lUPrec == 0) lUPrec = lU->newChampCopie();

    // On demande  un champ qui se nomme "F" pour le chargement volumique
    if(lMsg) lMsg = lFichierChamp.reqChamp("F",lF,false);

    // On demande un champs qui se nomme "Beta" pour le tenseur de dilatation hydrique
    if(lMsg) lMsg = lFichierChamp.reqChamp("BetaM",lBetaM);
    //if(lMsg) lMsg = lFichierChamp.reqChamp("BetaMB",lBetaMB);


    // Y'a-t'il une hysterese dans la description du tenseur BetaM?
    if(lMsg && lBetaM){
      lMsg = lFichierChamp.reqBooleen("Hysterese",lHysterese,false);
      if(lHysterese) lFichierChamp.reqChamp("MP",lMP);
    }

    // On demande un champs qui se nomme "BetaT" pour le tenseur de dilatation thermique
    if(lMsg && lThermik) lMsg = lFichierChamp.reqChamp("BetaT",lBetaT,false);
    if(lMsg && lBetaT){
      lUn = new ChampScalAConstant(*lChampGeo,1.0, "Un");
    }

    if(lContakt && lMsg){
      // Champs sur la peau

      lFichierChampPeau.asgnDonneesBase(&lMailPeau);
      lFichierChampPeau.asgnDonneesGeometriques(&lGeo,&lListeEntitePeau);

      if (lMsg) {
	//On crée un champ d'extension de peau pour tous les champs du maillage d'origine.
	lMsg = lFichierChamp.creeTousChampsExtensionPeau(lFichierChamp,
							 lFichierChampPeau,
							 lMailPeau);
      }

      if (lMsg) {
	lMsg = lFichierChampPeau.lireFichier(lNomFichierChamp + std::string("-peau.champs"));
      }

      // On demande le champ de transformation géométrique au fichier de champs Peau
      if (lMsg) lMsg = lFichierChampPeau.reqChamp("ChampGeo",lChampGeoPeau);

      //       // Cree une extension de U sur la peau

      if(lMsg) lMsg = lFichierChampPeau.reqChamp("U",lUPeau);
      if(lMsg) lMsg = lFichierChampPeau.reqChamp("M",lMPeau);
      if(lMsg && lThermik) lMsg = lFichierChampPeau.reqChamp("T",lTPeau);
      if(lMsg) lMsg = lFichierChampPeau.reqChamp("LambdaCtc",lLambdaCtc);
      if(lMsg) lMsg = lFichierChampPeau.reqChamp("normale_ext",lNormaleExtPeau);
      if(lMsg) lMsg = lFichierChampPeau.reqChamp("GapPeau",lGapPeau);

      if(lMsg) lProbPeauGCP.asgnDonnees( lMailPeau, lGeo, *lChampGeoPeau, lListeEntitePeau);
      if(lMsg) lProbPeauGCP2.asgnDonnees( lMailPeau, lGeo, *lChampGeoPeau, lListeEntitePeau);
    }

    std::cout<< "Fin Pour la partie Mecanique "<* lChampSigmaPrecedent  = 0;

  //On demande un champ qui se nomme "ERef_Inf" pour le tenseur d'élasticité de la composante purement elastique
  //On suppose que E_Inf = b(t)*ERef_Inf
  if(lMsg) lMsg =lFichierChamp.reqChamp("ERef_Infijkl", lERef_Inf,false);

  if(lMsg && lERef_Inf){// si ERef_Inf
    std::cout<< "lMsg && lERef_Inf "<("Integrale_bInf", lDeltaTempsReduit);

    //On demande un champ pour l'état du solide dans la branche courante
    if(lMsg) lMsg =lFichierChamp.reqChamp("IndicateurEtat_Inf", lIndicateurEtat);

    if(lMsg){
      //
      //On construit les tenseurs qui sont vraiement utilisés dans le modèle
      //
      lChampTenseurS       = new ChampElastiqueViscoElastiqueMaxwellHPP;
      lChampSigmaCourant   = new ChampContraintesHPPMateriauVieillissant;
      lChampSigmaPrecedent = new ChampPrecalculeDiscPtsIntegration;

      lVectChampADeleter.push_back(lChampTenseurS);
      lVectChampADeleter.push_back(lChampSigmaCourant);
      lVectChampADeleter.push_back(lChampSigmaPrecedent);
    }

    if(lMsg && lMateriauVieillissant) lMsg = ajouteListeReinterpole(*lChampSigmaCourant,*lChampSigmaPrecedent,lVectChampAReinterpoler);

    // On assigne le champ geometrique
    if(lMsg) {
      lChampTenseurS      ->asgnChampGeometrique(*lChampGeo);
      lChampSigmaCourant  ->asgnChampGeometrique(*lChampGeo);
      lChampSigmaPrecedent->asgnChampGeometrique(*lChampGeo);
    }

    if(lMsg) lSolveurQuasiStatique->reqPtrDelta(lPointeurVersLePasDeTempsDuSolveur);

    if(lPointeurVersLePasDeTempsDuSolveur == 0){
      lMsg.ajoute(ERMsg(ERMsg::ERREUR,"ERREUR Le pointeur vers le pas de temps du solveur QS est nul"));
    }

    // On assigne les parametres aux differents champs tensoriels

    if (lMsg) {

      if(lMateriauVieillissant){
        lChampSigmaPrecedent                    ->asgnChamp(*lChampSigmaCourant);

        lChampTenseurS->asgnChampsAvecVieillissement(*lERef_Inf,
                                                     *lDeltaTempsReduit,
                                                     lPointeurVersLePasDeTempsDuSolveur);
      }

      if(!lMateriauVieillissant){
        lChampTenseurS->asgnChampsSansVieillissement(*lERef_Inf);
        lChampSigmaPrecedent    ->asgnChamp(*lChampSigmaCourant);
      }


      lChampSigmaCourant                       ->asgnChamps(*lU,
                                                            *lUPrec,
                                                            *lChampTenseurS,
                                                            *lChampSigmaPrecedent,
                                                            *lIndicateurEtat);
      std::cout<< "Fin On assigne les parametres aux differents champs  "<ajouteSchemaIntegration(lSchemaIntg);

  }

  if(lMsg) {
    lProprietePurementElastique.Elasticite             = lERef_Inf;
    lProprietePurementElastique.MateriauVieillissant   = lMateriauVieillissant;
    lProprietePurementElastique.DeltaTempsReduit       = lDeltaTempsReduit;
    lProprietePurementElastique.LongueurPasDeTemps     = lPointeurVersLePasDeTempsDuSolveur;
    lProprietePurementElastique.IndicateurEtat         = lIndicateurEtat;

    lProprietePurementElastique.TenseurS               = lChampTenseurS;
    lProprietePurementElastique.ContraintesCourantes   = lChampSigmaCourant;
    lProprietePurementElastique.ContraintesPrecedentes = lChampSigmaPrecedent;
  }

  //
  // On passe au traitement des branche/cellules/composantes viscoelastique
  //
  // les donnees relatives a chaque branche sont données dans le fichier champs de la facon suivante:
  //
  //      NombreBrancheViscoElastique <= 100
  //
  //      {  Branche_I
  //         ERef_ijkl
  //         ViscoRef_ijkl              <- I = 00,01,02,...,NombreBrancheViscoElastique-1
  //         MateriauVieillissant
  //         DeltaTempsReduit
  //         Multiplicateur_b          (est necessaire SEULEMENT si MateriauVieillissant = vrai)
  //         Multiplicateur_bPrecedent (optionnel si absent et necessaire sera cree avec newChampCopie)
  //         IndicateurEtat            (est necessaire SEULEMENT si MateriauVieillissant = vrai)
  //      }


  if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("NombreBrancheViscoElastique",lNombreBrancheViscoElastique,false);

  if(lMsg && lERef_Inf == 0 && lNombreBrancheViscoElastique == 0) {
    lMsg.ajoute(ERMsg(ERMsg::ERREUR, "Modele de Maxwell sans composante viscoelastique ????"));
  }

  if(lMsg && lNombreBrancheViscoElastique) {
    lVectProprieteBrancheViscoElastique.asgnLongueur(lNombreBrancheViscoElastique);
  }

  ChaineCar lNomBranche= "Branche_";
  for(Entier lNumeroDeBranche=0;lNumeroDeBranche(lNomEijkl,lElasticite);

    //On demande un champ pour le tenseur des coefficients de viscosite de reference
    ChampTensorielO4Sym* lViscosite=0;
    if(lMsg) lMsg =lFichierChamp.reqChamp(lNomViscoijkl,lViscosite);

    //On demande un champs pour le temps reduit de la branche courante
    ChampScalaire* lDeltaTempsReduit=0;
    if(lMsg) lMsg =lFichierChamp.reqChamp(lNomDeltaTempsReduit, lDeltaTempsReduit);

    //On demande si l'elasticite depend du temps
    bool lMateriauVieillissant(false);
    if(lMsg) lMsg =lFichierChamp.reqBooleen(lNomVieillissant,lMateriauVieillissant);

    //On demande un champ pour le multiplicateur du tenseur des coefficients d'élasticité de reference
    ChampScalaire* lMultiplicateur_b = 0;
    if(lMsg && lMateriauVieillissant) lMsg =lFichierChamp.reqChamp(lNomb, lMultiplicateur_b);

    //On demande  un champ pour le multiplicateur du tenseur des coefficients d'élasticité de reference au temps precedent
    ChampScalaire* lMultiplicateur_bPrecedent = 0;
    if(lMsg && lMateriauVieillissant){
      lMsg = lFichierChamp.reqChamp(lNombPrecedent,lMultiplicateur_bPrecedent,false);
      if(lMsg && lMultiplicateur_bPrecedent == 0) lMultiplicateur_bPrecedent = lMultiplicateur_b->newChampCopie();
    }

    if(lMsg && lMateriauVieillissant) lMsg = ajouteListeReinterpole(*lMultiplicateur_b,*lMultiplicateur_bPrecedent,
                                                                    lVectChampAReinterpoler);

    //On demande un champ pour l'état du solide dans la branche courante
    ChampScalaire* lIndicateurEtat=0;
    if(lMsg && lMateriauVieillissant) lMsg =lFichierChamp.reqChamp(lNomEtat, lIndicateurEtat);

    //
    // On declare les tenseurs qui sont vraiement utilisés dans le modèle
    //
    ChampExponentielleTempsRelaxation*          lChampTenseurI       = 0;
    ChampCelluleViscoElastiqueMaxwellHPP*       lChampTenseurS       = 0;
    ChampPseudoContraintesO4*                   lChampSigmaO4Courant = 0;

    //On construit le champ Precalculer aux pts d'integration
    ChampPrecalculeDiscPtsIntegration* lChampSigmaO4Precedent = 0;

    if(lMsg){
      //
      //On construit les tenseurs qui sont vraiement utilisés dans le modèle
      //
      lChampTenseurI       = new ChampExponentielleTempsRelaxation;
      lChampTenseurS       = new ChampCelluleViscoElastiqueMaxwellHPP;
      lChampSigmaO4Courant = new ChampPseudoContraintesO4;

      //On construit le champ Precalculer aux pts d'integration
      lChampSigmaO4Precedent = new ChampPrecalculeDiscPtsIntegration;

      lVectChampADeleter.push_back(lChampTenseurI);
      lVectChampADeleter.push_back(lChampTenseurS);
      lVectChampADeleter.push_back(lChampSigmaO4Courant);
      lVectChampADeleter.push_back(lChampSigmaO4Precedent);
    }

    if(lMsg) lMsg = ajouteListeReinterpole(*lChampSigmaO4Courant,*lChampSigmaO4Precedent,lVectChampAReinterpoler);

    // On assigne le champ geometrique
    if(lMsg) {
      lChampTenseurS        ->asgnChampGeometrique(*lChampGeo);
      lChampTenseurI        ->asgnChampGeometrique(*lChampGeo);
      lChampSigmaO4Courant  ->asgnChampGeometrique(*lChampGeo);
      lChampSigmaO4Precedent->asgnChampGeometrique(*lChampGeo);
    }

    // On assigne les parametres aux differents champs tensoriels

    if (lMsg) {
      lChampSigmaO4Precedent                  ->asgnChamp(*lChampSigmaO4Courant);

      lChampTenseurI                          ->asgnChamps(*lElasticite,
                                                           *lViscosite,
                                                           *lDeltaTempsReduit);

      if(lMateriauVieillissant) lChampTenseurS->asgnChampsAvecVieillissement(*lElasticite,
                                                                             *lViscosite,
                                                                             *lDeltaTempsReduit,
                                                                             *lMultiplicateur_b,
                                                                             *lMultiplicateur_bPrecedent,
                                                                             *lIndicateurEtat);

      if(!lMateriauVieillissant) lChampTenseurS->asgnChampsSansVieillissement(*lElasticite,
                                                                              *lViscosite,
                                                                              *lDeltaTempsReduit);

      lChampSigmaO4Courant                     ->asgnChamps(*lChampSigmaO4Precedent,
                                                            *lChampTenseurI,
                                                            *lChampTenseurS,
                                                            *lU,
                                                            *lUPrec);
    }

    if(lMsg) lChampSigmaPrecedent->ajouteSchemaIntegration(lSchemaIntg);

    if(lMsg) {
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].Elasticite                   = lElasticite;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].Viscosite                    = lViscosite;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].MateriauVieillissant         = lMateriauVieillissant;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].DeltaTempsReduit             = lDeltaTempsReduit;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].Multiplicateur_b             = lMultiplicateur_b;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].Multiplicateur_bPrecedent    = lMultiplicateur_bPrecedent;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].IndicateurEtat               = lIndicateurEtat;

      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].TenseurS                     = lChampTenseurS;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].TenseurI                     = lChampTenseurI;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].PseudoContraintesCourantes   = lChampSigmaO4Courant;
      lVectProprieteBrancheViscoElastique[lNumeroDeBranche].PseudoContraintesPrecedentes = lChampSigmaO4Precedent;
    }

    std::cout<<"On cree le namespace"<=0){
	lTempsImposes.asgnLongueur(lNbTempsImpose,0.);
	ChaineCar lTImpose= "TempsImpose_";
	for (Entier i=0; i> lNbTempsImpose;
	if(lMsg && lNbTempsImpose < 0){
	  std::cout<<"NbTempsImpose est negatif je le remet a 0!"<> lTempsImposes[i];
	  }
	}
      }
    }
  }

  // on demande les coordonnées pour la trace des champs T,M et U:

  Entier lNombreEval(0);
  if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("NbEval",lNombreEval,false);
  if(lNombreEval < 0){
    std::cout<<"Le nombre d'evaluation est negatif je le remet a 0!"<0) {
    std::cout<0 && lMsg){
    ChaineCar lCoor= "Coord_";
    for (Entier i=0; i lVectTFRigiditeBrancheViscoElastique(lNombreBrancheViscoElastique);
  TFSourceFVVect3D                                     lTFChargeVolumique;

  // contact
  TFContactV3DUxNVScal  lTFContactGCP;
  TFContactV3DUxNVScal  lTFContactGCP2;

  //On assigne les champs aux termes de formulation.
  if(lMsg) lMsg = lTFDiffusionM. asgnChamps(*lChampGeo, *lM, *lM, *lK_M, false,   lSchemaIntg);
  if(lMsg) lMsg = lTFMasseM.     asgnChamps(*lChampGeo, *lM, *lM, *lC_MRho,lSchemaIntg);
  if(lMsg && lEmploiNewtonEnM) lMsg = lTFDiffusionNewton.asgnChamps(*lChampGeo, *lM, *lM, *lM, *ldK_MdM, lSchemaIntg);

  if(lThermik && lMsg){
    lMsg = lTFThermoDiffusion. asgnChamps(*lChampGeo, *lT, *lM, *lK_MT, false,   lSchemaIntg);
    if(lMsg) lMsg = lTFDiffusionT.  asgnChamps(*lChampGeo, *lT, *lT, *lK_T, false,   lSchemaIntg);
    if(lMsg) lMsg = lTFMasseT.      asgnChamps(*lChampGeo, *lT, *lT, *lC_TRho,lSchemaIntg);
  }

  if(lMecanik && lMsg){
     if(lMsg) lMsg = lTFCouplageHydMElas.asgnChamps(*lChampGeo, *lM, *lMP, *lU, *(lProprietePurementElastique.TenseurS),
				      *lBetaM, lSchemaIntg);
    if (lMsg && lERef_Inf) {
      lMsg = lTFRigiditeComposanteElastiquePure.asgnChamps(*lChampGeo,
                                                           *lU,
                                                           *lU,
                                                           *lUPrec,
                                                           *(lProprietePurementElastique.ContraintesPrecedentes),
                                                           *(lProprietePurementElastique.TenseurS),
                                                           *(lProprietePurementElastique.IndicateurEtat),
                                                           lSchemaIntg);
      if(lMsg) lProbMec.ajouteTF(lTFRigiditeComposanteElastiquePure);
      if(lMsg) lProbMec.ajouteTF(lTFCouplageHydMElas);
       std::cout<<"lProbMec.ajouteTF(lTFRigiditeComposanteElastiquePure)"<("SolveurInst",lSolveurHyd);
     std::cout<<"END reqSolveur("SolveurMec",lSolveurMec);
   //if(lMsg) lMsg = lFichierChamp.reqSolveur("SolveurLinMec",lSolveurMec);
  //if(lMsg) lMsg = lFichierChamp.reqSolveur("SolveurMec",lSolveurMec);
  // On assigne les temps ou l'on force le calcul
  if(lMsg && lTemps){
    lSolveurHyd->asgnTempsImposes(lTempsImposes);
     std::cout<<"END  lSolveurHyd->asgnTempsImposes"<asgnDonnees(lProbPeauGCP,true);
    lSolveurGCP->asgnDonneesLambda(lProbPeauGCP2);
    if(lMsg && lCorpsParGCP) lSolveurGCP->corrigeCorpsRigide(lProbMec.reqNumerotation(),*lDeplacements,*lU,
							     lDirectionDesCorps,lCritere0,lValeurRef,lEntite);
    lSolveurGCP->asgnParametres (5000,
				 1.e-13,
				 true,
				 false,
				 lComtpeurIteration);
    lSolveurGCP->relaxeTolerance(2,150,1e-10);
    lSolveurMec = lSolveurGCP;
     std::cout<<"lSolveurGCP->asgnDonneesLambda"<forceAssemblageMatrice(lforceAssemblageMatrice);
    lSolveurMec->forceAssemblageResidu(lVrai);

    // pour les sauvegardes mecanique

    Entier lEntierBidon(1);
    if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("NbPasDeTemps",lEntierBidon,false);
    if(lMsg) lSolveurMec->asgnLongueurNumeroPourExport(lEntierBidon+lNbTempsImpose);
     std::cout<<"lforceAssemblageMatrice(true)"< lEvalueM;
  VectDyn lMAuxPointsDonnes(lNombreEval,0.);

  // pour T
  PPEvalueChampXYZ lEvalueT;
  VectDyn lTAuxPointsDonnes(lNombreEval,0.);

  //pour U
  PPEvalueChampXYZ lEvalueU;
  VectDyn lUAuxPointsDonnes(lNombreEval);


  // pour l'ecriture des evaluations ponctuelles:
  PPAfficheValeur > lAfficheM;
  ofstream lFichierM;

  PPAfficheValeur > lAfficheT;
  ofstream lFichierT;

  PPAfficheValeur > lAfficheUz;
  ofstream lFichierUz;

  // On a donné dans le fichier champs des points ou on veut une évaluation:
  if(lMsg && lNombreEval){
    lFichierM.open((lNomMaillage + ".M").c_str());
    lEvalueM.asgnParametres(*lChampGeo,*lM,lCoordonnees,lMAuxPointsDonnes);
    lAfficheM.afficheLeTemps(lProbHyd,lVrai);
    lAfficheM.asgnParametres("M",lMAuxPointsDonnes,lFichierM);
    lFichierM << std::setprecision(8);
    lFichierM << std::scientific;
  }

  if(lThermik && lNombreEval && lMsg){
    lFichierT.open((lNomMaillage + ".T").c_str());
    lEvalueT.asgnParametres(*lChampGeo,*lT,lCoordonnees,lTAuxPointsDonnes);
    lAfficheT.afficheLeTemps(lProbHyd,lVrai);
    lAfficheT.asgnParametres("T",lTAuxPointsDonnes,lFichierT);
    lFichierT << std::setprecision(8);
    lFichierT << std::scientific;
  }

  if(lMecanik && lNombreEval && lMsg){
    lFichierUz.open((lNomMaillage + ".U").c_str());
    lEvalueU.asgnParametres(*lChampGeo,*lU,lCoordonnees,lUAuxPointsDonnes);
    lAfficheUz.afficheLeTemps(lProbHyd,lVrai);
    lAfficheUz.asgnParametres("U",lUAuxPointsDonnes,lFichierUz);
    lFichierUz << std::setprecision(8);
    lFichierUz << std::scientific;
  }

  // On sauvegarde la valeur du pas de temps à chaque pas
  // dans un fichier prefixe.DT utilise pour l'adaptation en pas variable.
  ofstream lFichierDT((lNomMaillage + ".DT").c_str());
  lFichierDT << std::setprecision(12);
  lFichierDT << std::scientific;

  PPAfficheValeur  lAfficheTemps;
  DReel *lDeltaT = 0;
  if (lMsg) {
    lSolveurHyd->reqPtrDelta(lDeltaT);
    lAfficheTemps.afficheLeTemps(lProbHyd,lVrai);
    lAfficheTemps.asgnParametres("",*lDeltaT, lFichierDT); // affiche le pas de temps dans le fichier
    lProbHyd.ajoutePostTraitement(lAfficheTemps);   // On ajoute l'affichage au post traitement du probleme hydrique
  }

  // Le probleme mecanique est resolu en post-traitement du probleme hydrique:
  PPResolutionProbleme lPPResolution;
  if(lMsg && lMecanik) lPPResolution.asgnParametres(lProbMec,*lSolveurMec);

  // en cas d'hysterese on doit conserver la valeur de M au pas precedent
  PPReinterpole lStockeMAuPasPrecedent;
  if (lMsg && lMecanik && lBetaM && lHysterese) lStockeMAuPasPrecedent.asgnParametres(*lM,*lMP);

   // ajout de l'incrément U aux Deplacements
  PPCalculChampaXpbY lMAJU;
  DReel lUnReel(1.);
  if(lMecanik && lMsg) lMAJU.asgnParametres(lUnReel,lUnReel,*lDeplacements,*lU,*lDeplacements);


  // On ajoute en Pretraitement la reinterpolation de U dans UPrecedent
  PPReinterpole lReinterpoleU;
  if(lMsg) {
    lReinterpoleU.asgnParametres(*lU,*lUPrec);
  }


  // ********************
  // * BLOC: Résolution *
  // ********************

  //
  // On a déja défini le solveur quasi statique maintenant on optimise, si le
  // solveur était défini dans le fichier champs on a rien a faire de tout cela...
  //

  if(!lDefinitionDansFichierChamps && lMsg){
    // Le solveur lineaire de base
    if(lMsg) lMsg = lFichierChamp.reqSolveur("SolveurMec",lSolveurMec,false);

    if(lSolveurMec && lMsg) lSolveurQuasiStatique->asgnSolveurLin(*lSolveurMec);

    if(lMsg){
      // A priori la matrice de rigidité depend de M et à besoin d'être reassemblée à chaque fois:
      lSolveurMec->forceAssemblageMatrice(lReassemble);
      lSolveurMec->forceAssemblageResidu(lVrai);
    }

    //On demande le temps initial
    DReel lTempsInitial = 0.;
    if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("TempsInitial",lTempsInitial,false);

    //On demande la longueur du pas de temps
    DReel lLongueurPasDeTemps = 0.;
    if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("LongueurPasDeTemps",lLongueurPasDeTemps);

    //On demande le nombre de pas de temps
    Entier lNombreDePasDeTemps = 0;
    if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("NombreDePasDeTemps",lNombreDePasDeTemps);

    // On demande si on veut un suivi à chaque pas de temps
    bool lVerboseInstationnaire(false);
    if(lMsg) lMsg = lFichierChamp.reqBooleen("VerboseInstationnaire",lVerboseInstationnaire,false);

    if(lMsg) lSolveurQuasiStatique->asgnParametresInst(lLongueurPasDeTemps,lNombreDePasDeTemps,lTempsInitial,lVerboseInstationnaire);

    // On demande si on veut faire l'adaptation de la longueur de pas de temps
    bool lUtilisePasAdapte(false);
    if(lMsg) lMsg = lFichierChamp.reqBooleen("UtilisePasAdapte",lUtilisePasAdapte,false);

    if(lUtilisePasAdapte && lMsg) {

      //On demande la longueur du pas de temps
      DReel lLongueurMaximalePasDeTemps = 0.;
      if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("LongueurMaximalePasDeTemps",lLongueurMaximalePasDeTemps);

      //On demande le temps initial
      DReel lTempsFinal = 0.;
      if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("TempsFinal",lTempsFinal);

      //On demande le temps initial
      DReel lToleranceAdaptation = 0.;
      if(lMsg) lMsg = lFichierChamp.reqScalaireConstant("ToleranceAdaptation",lToleranceAdaptation);

      //
      // On utilise un pas de temps adapté
      //
      if(lMsg) lSolveurQuasiStatique->utilisePasDeTempsVariable(lLongueurPasDeTemps,lLongueurMaximalePasDeTemps,
                                                                lTempsFinal,lToleranceAdaptation);
        std::cout<<"lDefinitionDansFichierChamps && lMsg)"<asgnParametresNlin(lTolerancePointFixe,lNombreMaximalIterationsPointFixe,lVerbosePointFixe);

    // On demande les proprietes de la matrice
    bool lMatriceDependDuTemps(true);
    bool lMatriceDependDeLaSolution(true);
    bool lMatriceDependDesCL(true);
    if(lMsg) lMsg = lFichierChamp.reqBooleen("MatriceDependTemps",lMatriceDependDuTemps,false);
    if(lMsg) lMsg = lFichierChamp.reqBooleen("MatriceDependSolution",lMatriceDependDeLaSolution,false);
    if(lMsg) lMsg = lFichierChamp.reqBooleen("MatriceDependCL",lMatriceDependDesCL,false);

    if(lMsg) lSolveurQuasiStatique->asgnParametresMatrice(lMatriceDependDuTemps,lMatriceDependDeLaSolution,lMatriceDependDesCL);
  }

  //
  // on ajoute les pre/post traitement ATTENTION la chronologie est importante!
  //

  if(lMecanik && lMsg){
    // on calcule U apres M:
    lProbHyd.ajoutePostTraitement(*lPPReqTempsHyd);
    lProbHyd.ajoutePostTraitement(*lPPAsgnTempsMec);
    if(lContakt) lProbHyd.ajoutePostTraitement(*lPPAsgnTempsCtc);
    lProbHyd.ajoutePostTraitement(lPPResolution,lPasDeCalcul);

     lProbMec.ajoutePostTraitement(lMAJU); // ajoute l'increment aux deplacements
     lProbMec.ajoutePostTraitement(*lPPAsgnTempsDeplacements);

    if(lMsg && lNombreEval>0){
      lProbHyd.ajoutePostTraitement(lEvalueU);
      lProbHyd.ajoutePostTraitement(lAfficheUz);
    }

  }

  if(lMsg && lNombreEval>0){
    lProbHyd.ajoutePostTraitement(lEvalueM);
    lProbHyd.ajoutePostTraitement(lAfficheM);
    if(lThermik){
      lProbHyd.ajoutePostTraitement(lEvalueT);
      lProbHyd.ajoutePostTraitement(lAfficheT);
    }
  }

  // mise a jour de MP  pour le "prochain" pas dans le cas ou on a hysterese
  if (lMsg && lMecanik && lBetaM && lHysterese) lProbHyd.ajoutePostTraitement(lStockeMAuPasPrecedent);
  if (lMsg&& lMecanik) lProbMec.ajoutePreTraitement(lReinterpoleU);

  //
  // Résolution du problème en T, M et en U
  //

  if (lMsg) {
    // On résoud
    if(!lThermik && !lMecanik) std::cout<<"Resolution du probleme d'humidité"<0){
      std::cout << std::endl;
      std::cout << "Ecriture des traces des solutions aux différents pas de temps dans les fichiers de préfixe ";
      std::cout << lNomMaillage<resoudre(lProbHyd);


    // On assigne les temps ou l'on force le calcul
    if(lMsg && lTemps) lSolveurQuasiStatique->asgnTempsImposes(lTempsImposes);

     //
    // On s'assure d'avoir tout les champs initialisé en faisant une reinterpolation AVANT l'appel au solveur puis
    // on ajoute les reinterpolations en post traitement pour s'assurer d'avoir les bonnes valeurs de temps
    //

    std::vector::iterator lIterReinterpole = lVectChampAReinterpoler.begin();
    const std::vector::iterator lIterReinterpoleFin = lVectChampAReinterpoler.end();
    while(lIterReinterpole != lIterReinterpoleFin && lMsg){
      (*lIterReinterpole)->effectueCalcul();
      lProbMec.ajoutePostTraitement(**lIterReinterpole);
      //lProbHyd.ajoutePostTraitement(**lIterReinterpole);
      ++lIterReinterpole;
    }

    //  lMsg = lSolveurHyd->resoudre(lProbHyd);

    //
    // On fait le menage, on detruit tout les ptr crees manuellement
    //
    lIterReinterpole = lVectChampAReinterpoler.begin();
    while(lIterReinterpole != lIterReinterpoleFin && lMsg){
      delete *lIterReinterpole;
    }

    std::vector::iterator       lIterDelete = lVectChampADeleter.begin();
    const std::vector::iterator lIterDeleteFin = lVectChampADeleter.end();

    while(lIterDelete != lIterDeleteFin && lMsg){
      delete *lIterDelete;
    }

  }

  if(lNombreEval>0) lFichierM.close();

  if(lMecanik && lNombreEval>0){
    lFichierUz.close();
  }

  if(lThermik && lNombreEval>0){
    lFichierT.close();
  }

  //Traitement d'erreur: si une erreur s'est produite, on l'affiche.
  if(!lMsg) {
    std::cerr << traducteurERMsg(lMsg) << endl;
    return 1;
  }

  return 0;
}

ERMsg lisString(const char*& pCharPtrAModifier,std::string& pStringRetour)
{
  ERMsg lMsg;

  while(espaceBlanc(*pCharPtrAModifier)) {
    ++pCharPtrAModifier;
  }

  if(*pCharPtrAModifier == '\0') {
    lMsg = ERMsg(ERMsg::ERREUR,"ERR_LECTURE_STRING");
    lMsg.ajoute("FIN_CHAINE");
  }
  else if(*pCharPtrAModifier == '\"') {
    ++pCharPtrAModifier;
    while(*pCharPtrAModifier != '\0' && *pCharPtrAModifier != '\"') {
      pStringRetour += *pCharPtrAModifier;
      ++pCharPtrAModifier;
    }
    if(*pCharPtrAModifier == '\0') {
      lMsg = ERMsg(ERMsg::ERREUR,"ERR_DEFINITION_CHAINE");
    }
    else {
      pCharPtrAModifier++;
    }
  }
  else {
    pStringRetour = "";
    while(*pCharPtrAModifier != '\0' && !espaceBlanc(*pCharPtrAModifier)) {
      pStringRetour += *pCharPtrAModifier;
      ++pCharPtrAModifier;
    }
  }
  return lMsg;
}