// ************************************************************************ // --- 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. // ************************************************************************ // // Résolution du problème: // // (1) température // C_TRho dT/dt - div(K_T grad(T)) = 0 // // (2) teneur en humidité // C_MRho dM/dt - div(K_M grad(M) + K_MT grad(T) ) = 0 // // (3) déplacements // -div(E:(epsilon(U) - BetaM*(M-MInitiale) - BetaT)) = F // // avec possiblement un contact sur la partie "entite_en_contact" du // domaine (typiquement de la forme UZ >= 0 sur une partie de la // frontière) // // Les équations (1) et (3) sont optionnelles auxquels cas leur // traitement est complètement ignorées dans le code. Dans (3) le // membre de droite F est optionnel. // // U est obtenu de manière incrémentale i.e. par correction à chaque // pas de temps. Il faut donc dans les fichiers champs imposé les CL, // CI et efforts incrémentaux!!! // // USAGE: ThermoHygroMecanik.[dev,opt] préfixe_des_fichiers_d_entrée #include "ChaineCar.h" #include "ChampContraintesHPP.h" #include "ChampGeometrique.h" #include "ChampScalAConstant.h" #include "ChampScalConstElem.h" #include "ChampScalaire.h" #include "ChampTensO2SymContinu.h" #include "ChampTensorielO4Sym.h" #include "ChampVect3DContinu.h" #include "ExportVTK.h" #include "Geometrie.h" #include "GestionFichierChamps.h" #include "InitialisationArgvArgc.h" #include "InitialisationTraitementSignal.h" #include "ListEntitesGeometrique.h" #include "ListeConditionsLimites.h" #include "MEFPPUtil.h" #include "Maillage.h" #include "MaillagePeau.h" #include "OptionsSolveurLinPETSc.h" #include "PETScInitialisation.h" #include "PPAfficheValeur.h" #include "PPCalculChampaXpbY.h" #include "PPCallBack.h" #include "PPCallBack2Args.h" #include "PPEvalueChampSurCourbe.h" #include "PPEvalueChampXYZ.h" #include "PPIntegre.h" #include "PPProjectionL2.h" #include "PPReinterpole.h" #include "PPResolutionProbleme.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 "SolveurGCP.h" #include "SolveurGCPAvecCorpsRigide.h" #include "SolveurInstNlinPETSc.h" #include "SolveurLinPETSc.h" #include "TFContactV3DUxNVScal.h" #include "TFContraintesInitiales.h" #include "TFCouplageAvecFctsConnues.h" #include "TFDiffusion.h" #include "TFDiffusionNewton.h" #include "TFElasLinMixteGen.h" #include "TFHPPMixteAnisotropePU.h" #include "TFHPPMixteAnisotropeUP.h" #include "TFHPPMixteAnisotropeUU.h" #include "TFMasseGenScal.h" #include "TFMasseGenV3D.h" #include "TFMasseMixteGeneralise.h" #include "TFSigmaUEpsilonV3D.h" #include "TFSigmaUEpsilonV3DIncrementalVieillissant.h" #include "TFSourceFVVect3D.h" #include "TenseurO4Sym.h" #include "VerifieElementsNormalises.h" #include "fonctionsChaineCar.h" #include "fonctionsTenseurs.h" #include "traducteurERMsg.h" #include #include using namespace std; 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; // On récupère le GroupeProcessus associé à 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, lNomSortie; bool lContakt(false); // 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_sortie (optionnel)"; lMsg.ajoute(ERMsg(ERMsg::ERREUR, lMessageUsage)); } else { lNomFichierChamp = lArgv[1]; lNomSortie = lNomFichierChamp; if (lNbArg > 2) lNomSortie = lArgv[2]; } lNomMaillage = lNomFichierChamp; // Pré-traitement des données du fichier champs: if (lMsg) { const EntierN lTailleBuffer = 65536; char *lLigne = new char[lTailleBuffer]; ifstream lFichierChamp((lNomFichierChamp + 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.close(); } // Fin du pré-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; // Création des champs requis pour le problème: // champ géometrique du domaine entier ChampGeometrique *lChampGeo=0; // humidité ChampScalContinu *lM = 0; // humidité au pas précedent (nécessaire en cas d'hystérèse seulement) ChampScalContinu *lMP = 0; // dérivée en temps de M ChampScalContinu *lMt = 0; // densité * "chaleur spécifique" ChampScalContinu *lC_MRho = 0; // diffusivité effective d_b*D ChampTensO2SymContinu *lK_M = 0; // derivée de la diffusivité effective en M ChampTensO2SymContinu *ldK_MdM = 0; // thermo-diffusion ChampTensO2SymContinu *lK_MT = 0; // diffusion thermique ChampTensO2SymContinu *lK_T = 0; // chaleur spécifique multipliée par la densité ChampScalContinu *lC_TRho = 0; // température ChampScalContinu *lT = 0; // l'incrément des déplacements ChampVect3DContinu *lU = 0; // l'incrément de la pression ChampScalContinu *lP = 0; // les déplacements ChampVect3DContinu *lDeplacements = 0; // la pression ChampScalContinu *lPression = 0; // tenseur des coefficients d'élasticité ChampTensorielO4Sym *lE = 0; // tenseur des coefficients d'élasticité au pas de temps précédent ChampTensorielO4Sym *lEP = 0; // tenseur des dilatations hydriques ChampTensO2SymContinu *lBetaM = 0; // tenseur des dilatations hydriques au pas de temps précédent ChampTensO2SymContinu *lBetaMP = 0; // tenseur des dilatations thermiques ChampTensO2SymContinu *lBetaT = 0; // les charges volumiques ChampVectoriel3D *lF = 0; // Création des champs requis pour le problème Peau // champ géometrique de la peau ChampGeometrique *lChampGeoPeau=0; // Une version "peau" de U ChampVect3DContinu *lUPeau = 0; // Une version "peau" de P ChampScalContinu *lPPeau = 0; // Ce champ contiendra le multiplicateur ChampScalaire *lLambdaCtc = 0; // Ce champ doit contenir la normale extérieure ChampVectoriel3D *lNormaleExtPeau = 0; // Ce champ pour Bu <= g. ChampScalContinu *lGapPeau = 0; // Une version "peau" de M ChampScalaire *lMPeau = 0; // Une version "peau" de T ChampScalaire *lTPeau = 0; // Variables lues dans le fichier: // le problème a une composante thermique bool lThermik(false); // le problème a une composante mécanique bool lMecanik(true); // formulation mécanique est incrémentale bool lFormulationIncrementale(true); // la composante mécanique est résolue avec une formulation mixte ou non bool lHPPMixte(false); // On résout avec le terme dK_M/DM (méthode de Newton au lieu de pt // fixe) bool lEmploiNewtonEnM(false); // le tenseur de dilatation hydrique tiens compte d'effet d'hystérèse bool lHysterese(true); // fréquence du calcul de mécanique: 0 -> pas de calcul Entier lPasDeCalcul; // fréquence d'impression des résultats Entier lPasImpression; // Nombre de points du temps ou on force le calcul Entier lNbTempsImpose; // le solveur instationnaire pour M (et T possiblement) SolveurInstNlinPETSc *lSolveurHyd = 0; // le solveur stationnaire pour U SolveurLinPETSc *lSolveurMec = 0; // le nom de l'entité servant au contrôle des mouvements de corps rigide ChaineCar lNomEntiteControle; // Numéro de l'axe parallèle aux corps rigide Entier lDirectionDesCorps; // les points dans le temps où on veut imposer une approximation des champs VectDyn lTempsImposes; // les coordonnées dont on fait une "trace" pendant l'exécution VectDyn lCoordonnees; bool lVrai(true), lFaux(false); 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; if (lMsg) lProbHyd.asgnNom("Composante hydrique/thermique"); ProblemeEF lProbMec; if (lMsg) lProbMec.asgnNom("Composante mécanique"); ProblemeEF lProbPeauGCP; ProblemeEF lProbPeauGCP2; if (lMsg) { 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); } // Déclaration de l'objet qui fait la gestion des champs pour le problème. GestionFichierChamps lFichierChamp; GestionFichierChamps lFichierChampPeau; if (lMsg) { lMsg = lFichierChamp.asgnDonneesBase(&lMail); if (lMsg) 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()); // Requête des données du fichier .champs nécessaires au calcul if (lMsg) lMsg = lFichierChamp.reqBooleen("Thermique",lThermik,false); if (lMsg) lMsg = lFichierChamp.reqBooleen("Mecanique",lMecanik,false); if (lMsg && lMecanik) lMsg = lFichierChamp.reqBooleen("HPPMixte",lHPPMixte,false); if (lMsg && lContakt && !lMecanik) lMsg.ajoute(ERMsg(ERMsg::ERREUR,"Pas de contact sans mécanique!")); // On demande le champ de transformation géométrique au fichier de champs if (lMsg) lMsg = lFichierChamp.reqChamp("ChampGeo",lChampGeo); if (lMsg) lProbHyd.asgnChampGeometrique(*lChampGeo); if (lMecanik && lMsg) lProbMec.asgnDonnees(lMail,lGeo,*lChampGeo,lListeEntite); PPProjectionL2 lPPProjectionL2; if (lMsg) lPPProjectionL2.asgnChampGeometrique(*lChampGeo); PPCalculChampaXpbY lMAjSigma; ChampContraintesHPP lDeltaSigma; ChampTensO2SymLin lDeltaSigmaLin; if (lMsg) lDeltaSigmaLin.asgnChampGeometrique(*lChampGeo); ChampTensO2SymLin lSigma; if (lMsg) lSigma.asgnChampGeometrique(*lChampGeo); // Partie hydrique // On demande un champ qui se nomme "M" pour l'humidité if (lMsg) lMsg = lFichierChamp.reqChamp("M",lM); // On demande un champ qui se nomme "M_t" pour la valeur différence // finie de M (hystérèse présente dans le problème) if (lMsg) lMsg = lFichierChamp.reqChamp("M_t",lMt,false); // On demande un champ qui se nomme "d_b" pour la densité de base // divisée par 100 (kg m^3 / 100) if (lMsg) lMsg = lFichierChamp.reqChamp("C_MRho",lC_MRho); // 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); // On demande un champ qui se nomme "dK_MdM" pour la derivée du // tenseur de "diffusivité effective" en M if (lMsg) lMsg = lFichierChamp.reqChamp("dK_MdM",ldK_MdM,false); if (lMsg && ldK_MdM) lEmploiNewtonEnM = true; // ChampTensorielO2NSym *lTransformation = 0; // if (lMsg) lMsg = lFichierChamp.reqChamp("transformation",lTransformation); // Partie thermique if (lThermik && lMsg) { // On demande un champ qui se nomme "K_MT" pour la composante // thermique de la "diffusion hydrique" if (lMsg) lMsg = lFichierChamp.reqChamp("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 résultats de mécanique/contact alors je ne les fait pas!"<newChampCopie(); } else { lDeplacements = lU; } } // On demande un champs qui se nomme "Eijkl" pour le tenseur des // coefficients d'élasticité if (lMsg) lMsg = lFichierChamp.reqChamp("Eijkl",lE); // Un champ "EijklP" est possible si la formulation est incrémentale if (lFormulationIncrementale && lMsg) lMsg = lFichierChamp.reqChamp("EijklP",lEP,false); // if (lMsg) lMsg = lFichierChamp.reqChamp("EL",lEL); // if (lMsg) lMsg = lFichierChamp.reqChamp("ER",lER); // if (lMsg) lMsg = lFichierChamp.reqChamp("ET",lET); // if (lMsg) lMsg = lFichierChamp.reqChamp("GLR",lGLR); // if (lMsg) lMsg = lFichierChamp.reqChamp("GLT",lGLT); // if (lMsg) lMsg = lFichierChamp.reqChamp("GRT",lGRT); // if (lMsg) lMsg = lFichierChamp.reqChamp("VTR",lVTR); // if (lMsg) lMsg = lFichierChamp.reqChamp("VLR",lVLR); // if (lMsg) lMsg = lFichierChamp.reqChamp("VLT",lVLT); // On demande un champs qui se nomme "Beta" pour le tenseur de // dilatation hydrique if (lMsg) lMsg = lFichierChamp.reqChamp("BetaM",lBetaM); // Un champ "BetaP" est possible si la formulation est incrémentale if (lFormulationIncrementale && lMsg) lMsg = lFichierChamp.reqChamp("BetaMP",lBetaMP,false); // On est en mixte il faut la pression if (lMsg && lHPPMixte) { lMsg = lFichierChamp.reqChamp("P",lP); if (lMsg) lMsg = lFichierChamp.reqChamp("Pression",lPression,false); if (!lPression && lMsg) lPression = lP->newChampCopie(); } if (lMsg && lBetaM) { // Y'a-t'il une hystérèse dans la description du tenseur BetaM? lMsg = lFichierChamp.reqBooleen("Hysterese",lHysterese,false); if (lMsg) lMsg = 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"); // On demande un champ qui se nomme "F" pour le chargement volumique if (lMsg) lMsg = lFichierChamp.reqChamp("F",lF,false); if (lContakt && lMsg) { // Champs sur la peau if (lMsg) lMsg = lFichierChampPeau.asgnDonneesBase(&lMailPeau); if (lMsg) lFichierChampPeau.asgnDonneesGeometriques(&lGeo,&lListeEntitePeau); // On crée un champ d'extension de peau pour tous les champs du // maillage d'origine. if (lMsg) 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 && lHPPMixte) lMsg = lFichierChampPeau.reqChamp("P",lPPeau); 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); } } bool lCorpsParGCP(lContakt); // SolveurGCP s'occupe du corps rigide if (lMsg && lCorpsParGCP) { lCorpsParGCP = false; lMsg = lFichierChamp.reqBooleen("CorpsRigideGCP",lCorpsParGCP,false); } if (lMsg && lCorpsParGCP) { lDirectionDesCorps = 2; lMsg = lFichierChamp.reqScalaireConstant("DirectionRigide",lDirectionDesCorps);//lReelBidon); lMsg = lFichierChamp.reqChaineCar("lNomEntiteControle",lNomEntiteControle); // lDirectionDesCorps = (Entier) lReelBidon; } if (lMsg && !lDeplacements && lContakt && lCorpsParGCP) lMsg.ajoute(ERMsg(ERMsg::ERREUR, "En cas de contact on doit definir déplacements dans le fichier champs et dans celui de peau.")); // Fréquence d'impression lPasImpression = 1; if (lMsg) lMsg = lFichierChamp.reqScalaireConstant("freqImpression",lPasImpression,false); // On permet d'imposer des points dans le temps ou le calcul doit être fait // utile dans le cas où on a des discontinuités en temps dans les données // que l'on traite en imposant un calcul sur la discontinuité bool lTemps(false); if (lMsg) lMsg = lFichierChamp.reqBooleen("TempsImpose",lTemps,false); if (lTemps && lMsg) { // Deux choix: // a) les temps sont donnés dans le fichier champs: // scalaire NbTempsImpose N // scalaire TempsImpose_0 t_0 // ... // scalaire TempsImpose_N-1 t_N-1 // b) les temps sont placés dans un fichier "lNom".temps (un temps par ligne avec le nombre de temps impose sur la premiere ligne) // lReelBidon = -1.; lNbTempsImpose = 0; if (lMsg) lMsg = lFichierChamp.reqScalaireConstant("NbTempsImpose",lNbTempsImpose,false);//lReelBidon,false); // lNbTempsImpose = (Entier) lReelBidon; if (lMsg) { // les temps imposés sont dans le fichier champs: if (lNbTempsImpose >=0) { lTempsImposes.asgnLongueur(lNbTempsImpose,0.); ChaineCar lTImpose= "TempsImpose_"; for (Entier i=0; i> lNbTempsImpose; if (lMsg && lNbTempsImpose < 0) { std::cout<<"NbTempsImpose est négatif je le remet a 0!"<> lTempsImposes[i]; } } } } } // on demande les coordonnées pour la trace des champs T, M et U: Entier lNombrePointsSurCourbe(100); if (lMsg) lMsg = lFichierChamp.reqScalaireConstant("NbPointsSurCourbe",lNombrePointsSurCourbe,false); Entier lNombreEval(0); if (lMsg) lMsg = lFichierChamp.reqScalaireConstant("NbEval",lNombreEval,false); if (lNombreEval < 0 && lMsg) lNombreEval = 0; if (lNombreEval > 0 && lMsg) lCoordonnees.asgnLongueur(lNombreEval); if (lNombreEval > 0 && lMsg) { ChaineCar lCoor = "Coord_"; for (Entier i = 0; i < lNombreEval && lMsg; ++i) { ChaineCar lCoordi = ajouteNumeroALaFin(lCoor,i,3); lMsg = lFichierChamp.reqVecteur3DConstant(lCoordi,lCoordonnees[i]); } } if (lMecanik && lMsg) lProbMec.asgnDonnees(lMail,lGeo,*lChampGeo,lListeEntite); // On sépare les données sur types de fichiers: hyd (humidité) et // mec (déplacements) ChaineCar lNomHyd = lNomMaillage + string("_hyd"); ChaineCar lNomMec = lNomMaillage + string("_mec"); // BLOC: Déclaration des termes de formulation et conditions aux // limites // // On crée l'objet qui contiendra la liste des conditions limites ListeConditionsLimites lListeCondLimHyd, lListeCondLimMec; if (lMsg) { // On assigne l'objet lFichierChamp aux conditions aux limites, // permettant ainsi aux champs définits dans le fichier ".champs" // d'être utilisés dans le fichier ".CL" lListeCondLimHyd.asgnGestionFichierChamps(lFichierChamp); lListeCondLimMec.asgnGestionFichierChamps(lFichierChamp); lListeCondLimHyd.asgnChampGeoEtListeEntitesGeo(*lChampGeo,lListeEntite); lListeCondLimMec.asgnChampGeoEtListeEntitesGeo(*lChampGeo,lListeEntite); // On assigne le schéma d'intégration aux conditions aux limites lListeCondLimHyd.asgnSchemaIntg(lSchemaIntg); lListeCondLimMec.asgnSchemaIntg(lSchemaIntg); } // On déclare les termes de formulation que l'on veut utiliser. // hydrique TFMasseGenScal lTFMasseM; TFDiffusion lTFDiffusionM; TFDiffusion lTFThermoDiffusion; TFDiffusionNewton lTFDiffusionNewton; // thermique TFDiffusion lTFDiffusionT; TFMasseGenScal lTFMasseT; // mécanique TFCouplageAvecFctsConnues lTFCouplageHydM, lTFCouplageHydT; TFSourceFVVect3D lTFChargeVolumique; TFMasseGenV3D lTFMasseGenV3D; TFSigmaUEpsilonV3D lTFRigidite; TFSigmaUEpsilonV3DIncrementalVieillissant lTFRigiditeIncremental; // HPP Mixte TFHPPMixteAnisotropeUU lTFHPPMixteUU; TFHPPMixteAnisotropeUP lTFHPPMixteUP; TFHPPMixteAnisotropePU lTFHPPMixtePU; TFMasseMixteGeneralise lTFHPPMixtePP; // 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); } ChampScalaire* lMInitiale = 0; if (lMecanik && lMsg) { if (!lHPPMixte) { if (!lFormulationIncrementale) { lMsg = lTFRigidite.asgnChamps(*lChampGeo,*lU,*lU,*lE,lSchemaIntg); } else { // Est-ce que E dépend du temps? if(lEP) { lMsg = lTFRigiditeIncremental.asgnChamps(*lChampGeo,*lU,*lU,*lDeplacements,*lE,*lEP,lSchemaIntg); } else { lMsg = lTFRigiditeIncremental.asgnChamps(*lChampGeo,*lU,*lU,*lDeplacements,*lE,lSchemaIntg); } if (lMsg){ // Estc-ce que Beta dépend du temps ? if(lBetaM){ lMInitiale = lM->newChampCopie(); if(lBetaMP){ lTFRigiditeIncremental.asgnCouplage(*lM,*lMP,*lMInitiale,*lBetaM,*lBetaMP); } else { lTFRigiditeIncremental.asgnCouplage(*lM,*lMP,*lMInitiale,*lBetaM); } } } } } else { lTFHPPMixteUP.optimisationConstructionDuBlocUP(lVrai,lVrai); lTFHPPMixtePU.optimisationConstructionDuBlocPU(lFaux,lFaux); lTFHPPMixteUU.asgnChamps(*lChampGeo,*lU,*lU,*lE,lSchemaIntg); lTFHPPMixteUP.asgnChamps(*lChampGeo,*lP,*lU,*lE,lSchemaIntg); lTFHPPMixtePU.asgnChamps(*lChampGeo,*lU,*lP,*lE,lSchemaIntg); lTFHPPMixtePP.asgnChamps(*lChampGeo,*lP,*lE,lSchemaIntg); lTFHPPMixtePP.asgnAssembleResidu(lVrai); } if (lMsg) lMsg = lTFMasseGenV3D.asgnChamps(*lChampGeo,*lU,*lU,lEpsilon,lSchemaIntg,false); if (lMsg && lBetaM && !lFormulationIncrementale) lMsg = lTFCouplageHydM.asgnChamps(*lChampGeo,*lM,*lMP,*lU,*lE,*lBetaM,lSchemaIntg); if (lMsg && lBetaT) lMsg = lTFCouplageHydT.asgnChamps(*lChampGeo,*lUn,*lU,*lE,*lBetaT,lSchemaIntg); if (lMsg && lF) lMsg = lTFChargeVolumique.asgnChamps(*lChampGeo,*lF,*lU,lSchemaIntg); ChampScalAConstant* lPtrNULL = 0; if (lMsg && lContakt) lMsg = lTFContactGCP.asgnChamps(*lChampGeoPeau,*lUPeau,*lLambdaCtc,*lNormaleExtPeau,*lGapPeau,lPtrNULL,lSchemaIntgNewtonCote); if (lMsg && lContakt) lMsg = lTFContactGCP2.asgnChamps(*lChampGeoPeau,*lUPeau,*lLambdaCtc,*lNormaleExtPeau,*lGapPeau,lPtrNULL,lSchemaIntg); } if (lMsg) { // Ajout des termes de formulations au problème lProbHyd.ajouteTF(lTFDiffusionM); lProbHyd.ajouteTFInst(lTFMasseM); if (lEmploiNewtonEnM) lProbHyd.ajouteTF(lTFDiffusionNewton); if (lThermik) { lProbHyd.ajouteTFInst(lTFMasseT); lProbHyd.ajouteTF(lTFThermoDiffusion); lProbHyd.ajouteTF(lTFDiffusionT); } if (lMecanik) { if (!lHPPMixte) { if (!lFormulationIncrementale) lProbMec.ajouteTF(lTFRigidite); if (lFormulationIncrementale) lProbMec.ajouteTF(lTFRigiditeIncremental); } else { lProbMec.ajouteTF(lTFHPPMixteUU); lProbMec.ajouteTF(lTFHPPMixtePU); lProbMec.ajouteTF(lTFHPPMixteUP); lProbMec.ajouteTF(lTFHPPMixtePP); } lProbMec.ajouteTF(lTFMasseGenV3D); if (!lFormulationIncrementale) lProbMec.ajouteTF(lTFCouplageHydM); if (lF) lProbMec.ajouteTF(lTFChargeVolumique); if (lBetaT) lProbMec.ajouteTF(lTFCouplageHydT); if (lContakt) lProbPeauGCP.ajouteTF(lTFContactGCP); if (lContakt) lProbPeauGCP2.ajouteTF(lTFContactGCP2); } } // Lecture et initialisation des conditions limites if (lMsg) lMsg = lProbHyd.lisEtInitialiseConditionsLimites(lNomHyd,lListeCondLimHyd); if (lMsg && lMecanik) { lMsg = lProbMec.lisEtInitialiseConditionsLimites(lNomMec,lListeCondLimMec); if (lMsg && lContakt) lProbPeauGCP.initialiseNumerotationPeau(lProbMec.reqNumerotation()); if (lMsg && lContakt) lProbPeauGCP2.initialiseNumerotationPeau(lProbMec.reqNumerotation()); } // Lecture des solveurs if (lMsg) lMsg = lFichierChamp.reqSolveur("SolveurInst",lSolveurHyd); SolveurLinPETSc* lSolveurTempo=0; if (lMsg) lMsg = lFichierChamp.reqSolveur("SolveurLinmecanique",lSolveurTempo); lSolveurMec = lSolveurTempo; // On assigne les temps où l'on force le calcul if (lMsg && lTemps) lMsg = lSolveurHyd->asgnTempsImposes(lTempsImposes); Entier lComtpeurIteration = 0; DReel lValeurRef(0.); DReel lCritere0(1.e-12); EntiteGeometrique* lEntite = 0; if (lMsg && lContakt) { if (lCorpsParGCP) { lEntite = &(lListeEntite.reqEntiteGeometrique(lNomEntiteControle)); SolveurGCPAvecCorpsRigide* lSolveurGCP = new SolveurGCPAvecCorpsRigide(); lSolveurGCP->corrigeCorpsRigide(lProbMec.reqNumerotation(),*lDeplacements,*lU,lDirectionDesCorps,lCritere0,lValeurRef,lEntite); lSolveurGCP->asgnDonnees(lProbPeauGCP,true); lSolveurGCP->asgnDonneesLambda(lProbPeauGCP2); lSolveurGCP->relaxeTolerance(2,150,1e-10); lSolveurGCP->asgnParametres (5000,1.e-13,true,false,lComtpeurIteration); lSolveurMec = lSolveurGCP; } else { SolveurGCP* lSolveurGCP = new SolveurGCP(); lMsg = lSolveurGCP->asgnDonnees(lProbPeauGCP); if (lMsg) { lMsg = lSolveurGCP->asgnDonneesLambda(lProbPeauGCP2); lSolveurGCP->relaxeTolerance(2,150,1e-10); lSolveurGCP->asgnParametres (5000,1.e-13,1.e-13,false,false,lComtpeurIteration); lSolveurGCP->asgnSolveurLinUsager(*lSolveurTempo); lSolveurMec = lSolveurGCP; } } } if (lMecanik && lMsg) { // A priori la matrice de rigidité dépend de M et à besoin d'être reassemblée à chaque fois: bool lforceAssemblageMatrice(true); lMsg = lFichierChamp.reqBooleen("forceAssemblageMatriceMec",lforceAssemblageMatrice,false); lSolveurMec->forceAssemblageMatrice(lforceAssemblageMatrice); lSolveurMec->forceAssemblageResidu(lVrai); // pour les sauvegardes mécanique Entier lEntierBidon(1); if (lMsg) lMsg = lFichierChamp.reqScalaireConstant("NbPasDeTemps",lEntierBidon,false); if (lMsg) lSolveurMec->asgnLongueurNumeroPourExport(lEntierBidon+lNbTempsImpose); } ExportVTK lExport; if (lPasImpression && lMsg) { lExport.asgnChampGeometrique(*lChampGeo); lProbHyd.ajouteExportation(lExport,lPasImpression,lNomSortie); if (lMecanik) { // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(0),"E0000"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(5),"E1111"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(20),"E2222"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(3),"E0011"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(17),"E1122"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(15),"E0022"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(2),"G_12"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(9),"G_13"); // if (lMsg) lMsg = lExport.ajouteChamp(lE->reqComposante(14),"G_23"); if (lMsg) lMsg = lExport.ajouteChamp(*lDeplacements,"U"); } } // Début des pre/post traitements // lPPReqTempsHyd Pour savoir la valeur du temps (pour la // passer au problème mécanique) on demande le // temps au problème hydrique. // lPPAsgnTempsMec Le problème mécanique est en post-traitement // de l'hydrique alors il nous faut lui passer // la valeur du temps au moment du calcul. // lPPAsgnTempsCtc Si on a un problème avec contact on veut // s'assurer que le temps est assigné au champs // de peau PPTraitementGen* lPPReqTempsHyd = 0; PPTraitementGen* lPPAsgnTempsMec = 0; PPTraitementGen* lPPAsgnTempsCtc = 0; PPTraitementGen* lPPAsgnTempsDeplacements= 0; DReel lTempsMec; if (lMsg && lMecanik) { lPPReqTempsHyd = newPPCallBack(lProbHyd,mem_fun_ref(&ProblemeEF::reqTemps),lTempsMec); lPPAsgnTempsMec = newPPCallBack2Args(lProbMec,lTempsMec,mem_fun_ref(&ProblemeEF::asgnTemps)); if (lContakt) lPPAsgnTempsCtc = newPPCallBack2Args(*lUPeau,lTempsMec,mem_fun_ref(&Champ::asgnTemps)); lPPAsgnTempsDeplacements = newPPCallBack2Args(*lDeplacements,lTempsMec,mem_fun_ref(&Champ::asgnTemps)); } PPEvalueChampSurCourbe lEvalueMSurCourbe; VectDyn lMAuxPointsDelaCourbe; // PPEvalueChampSurCourbe lEvalueMSurCourbe1; VectDyn lMAuxPointsDelaCourbe1; // Points d'intérêt dans le domaine: // pour M PPEvalueChampXYZ lEvalueM; VectDyn lMAuxPointsDonnes(lNombreEval,0.); // pour M moyenne DReel lIntegraleM = 0; DReel lMmoyen = 0; PPIntegre > lEvalueMmoyen; if (lMsg) lMsg = lEvalueMmoyen.asgnParametres(*lM,std::identity(),0,lIntegraleM,lMmoyen,false,false,lSchemaIntg,0); // pour T PPEvalueChampXYZ lEvalueT; VectDyn lTAuxPointsDonnes(lNombreEval,0.); // pour U PPEvalueChampXYZ lEvalueU; VectDyn lUAuxPointsDonnes(lNombreEval); // pour l'écriture des évaluations ponctuelles: ofstream lFichierM; PPAfficheValeur lAfficheMmoyen; ofstream lFichierMmoyen; PPAfficheValeur > lAfficheT; ofstream lFichierT; ofstream lFichierU; // On a donné dans le fichier champs des points où on veut une évaluation: if (lMsg && lNombreEval) { lFichierM.open((lNomSortie + ".M").c_str()); lEvalueM.asgnParametres(*lChampGeo,*lM,lCoordonnees,lMAuxPointsDonnes); lEvalueM.afficheEvaluations(lFichierM); } if (lMsg && lNombreEval) { lFichierMmoyen.open((lNomSortie + ".Mmoyen").c_str()); lAfficheMmoyen.afficheLeTemps(lProbHyd,lVrai); lAfficheMmoyen.asgnParametres("Mmoyen",lMmoyen,lFichierMmoyen); lFichierMmoyen << setprecision(8); lFichierMmoyen << scientific; } if (lMecanik && lNombreEval && lMsg) { lFichierU.open((lNomSortie + ".U").c_str()); lEvalueU.asgnParametres(*lChampGeo,*lDeplacements,lCoordonnees,lUAuxPointsDonnes); lEvalueU.afficheEvaluations(lFichierU); } // Le problème mécanique est résolu en post-traitement du problème // hydrique: PPResolutionProbleme lPPResolution; if (lMsg && lMecanik) lPPResolution.asgnParametres(lProbMec,*lSolveurMec); // En cas d'hystérèse on doit conserver la valeur de M au pas précédent PPReinterpole lStockeMAuPasPrecedent; if (lMecanik && lFormulationIncrementale && lMsg) lMsg = lStockeMAuPasPrecedent.asgnParametres(*lM,*lMP); // Ajout de l'incrément U aux déplacements PPCalculChampaXpbY lMAJU; PPCalculChampaXpbY lMAJP; DReel lUnReel(1.); if (lMecanik && lFormulationIncrementale && lMsg) lMAJU.asgnParametres(lUnReel,lUnReel,*lDeplacements,*lU,*lDeplacements); if (lHPPMixte && lFormulationIncrementale && lMsg) lMAJP.asgnParametres(lUnReel,lUnReel,*lPression,*lP,*lPression); if (lMsg) lPPProjectionL2.asgnParametres(&lGeo,lSchemaIntg,lDeltaSigma,lDeltaSigmaLin); if (lMsg) lMAjSigma.asgnParametres(lUnReel,lUnReel,lSigma,lDeltaSigmaLin,lSigma); if (lMsg) { lDeltaSigma.asgnChamps(*lU,*lE); lDeltaSigma.asgnCouplage(*lM,*lMP,*lBetaM); } // On ajoute les pré/post traitements ATTENTION la chronologie est // importante! if (lMecanik && lMsg) { // on calcule U après M: lProbHyd.ajoutePostTraitement(*lPPReqTempsHyd); lProbHyd.ajoutePostTraitement(*lPPAsgnTempsMec); // lProbHyd.ajoutePostTraitement(lPPContraintesEL3D); if (lContakt) lProbHyd.ajoutePostTraitement(*lPPAsgnTempsCtc); lProbHyd.ajoutePostTraitement(lPPResolution,lPasDeCalcul); // Ajoute l'incrément aux déplacements if (lFormulationIncrementale) lProbMec.ajoutePostTraitement(lMAJU); if (lHPPMixte && lFormulationIncrementale) lProbMec.ajoutePostTraitement(lMAJP); lProbMec.ajoutePostTraitement(*lPPAsgnTempsDeplacements); if (lMsg && lNombreEval>0) lProbHyd.ajoutePostTraitement(lEvalueU,lPasDeCalcul); } if (lMsg && lNombreEval>0) { lProbHyd.ajoutePostTraitement(lEvalueM); lProbHyd.ajoutePostTraitement(lEvalueMmoyen); lProbHyd.ajoutePostTraitement(lAfficheMmoyen); if (lThermik) { lProbHyd.ajoutePostTraitement(lEvalueT); lProbHyd.ajoutePostTraitement(lAfficheT); } if (lMsg && lNombrePointsSurCourbe > 0 ) lProbHyd.ajoutePostTraitement(lEvalueMSurCourbe); } // Mise a jour de MP pour le "prochain" pas dans le cas avec hystérèse if (lMsg && lMecanik && lBetaM && lFormulationIncrementale) lProbMec.ajoutePostTraitement(lStockeMAuPasPrecedent); // Résolution du problème en T, M et en U if (lMsg) lMsg = lSolveurHyd->resoudre(lProbHyd); if (lNombreEval>0) { lFichierM.close(); lFichierMmoyen.close(); } if (lMecanik && lNombreEval>0) lFichierU.close(); if (lThermik && lNombreEval>0) lFichierT.close(); // Traitement d'erreur: si une erreur s'est produite, on l'affiche. if (!lMsg) { cerr << traducteurERMsg(lMsg) << endl; return 1; } return 0; } ERMsg lisString(const char*& pCharPtrAModifier,std::string& pStringRetour) { ERMsg lMsg; pStringRetour = ""; 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; }