Automatisation du calcul

Nous nous sommes rendus compte dans le paragraphe précédent qu'il fallait diviser la simulation complète en plusieurs sous-simulations. Entre chacune de ces sous-simulations, il faut remailler le domaine et interpoler les différents champs calculés grâce à l'ancien maillage sur le nouveau maillage.

Vu la longueur du tunnel par rapport à sa hauteur, nous savons qu'il va falloir réaliser un nombre relativement conséquent de sous-simulations, de l'ordre de 10 à 20 a priori. Il serait donc extrêmement utile de créer un script bash permettant de tout automatiser. L'objectif serait de uniquement créer "manuellement" un dossier type OpenFoam classique comme si la simulation ne se faisait qu'en une seule fois, avec tous les paramètres désirés (maillage initial, pas de temps, temps de simulation, schémas, etc ...). Puis à partir d'un script bash, les étapes de remaillage et d'interpolation séparant les sous-simulations seraient automatisées.

 

Vous trouverez ci-après des explications sur l'utilisation d'OpenFOAM pour mener à bien le passage d'une sous-simulation à la suivante ainsi qu'un autre lien menant à la page détaillant le script avec plus de précisions.

Gérer avec OpenFOAM le passage d'une sous-simulation à la suivante

 

Avant d'expliquer plus en détails la structure et les commandes introduites dans le script, revenons à la façon dont OpenFOAM est capable d'appliquer une solution (connue, calculée avec un maillage donné) sur un autre maillage en interpolant toutes les valeurs sur les nouveaux points de calcul.

Cette procédure est très bien détaillée dans un tutoriel disponible sur le site d'OpenFOAM (ici, section 3.1.5.3), mais expliquons comment cela fonctionne.

Pour cela, il faut disposer d'une ancienne simulation déjà réalisée, contenant tous les résultats dont la solution finale correspondant à la date $t=t_0$. Dans le fichier controlDict de cette ancienne simulation, l'utilisateur avait indiqué que le temps final de la simulation était bien $t_0$.

Il faut également créer un deuxième dossier, comme s'il s'agissait d'une nouvelle simulation. Ce dossier contient alors classiquement les dossiers constant, system, et également un dossier de condition initiale qui doit être dénommé $t_0$ au lieu de 0.

Dans ce deuxième dossier, il faut également introduire un fichier mapFieldsDict. Ce fichier indique quelles zones de l'ancien maillage doivent être interpolées sur quelles zones du nouveau maillage. Cela se fait par les noms de patch du domaine. Voici, dans notre cas, notre fichier mapFieldsDict :

La section cuttingPatches est utile dans le cas où les domaines des deux simulations sont différents. Les zones absentes sur le nouveau maillage, par le nom de certains patches, sont indiquées dans ce paragraphe ; ce qui n'est pas le cas pour notre étude, les deux domaines sont parfaitement identiques.

Une fois ce fichier créé dans le dossier system, il faut d'abord générer le maillage sur la nouvelle simulation, avec la commande blockMesh suivi de snappyHexMesh.
Puis on indique que la condition initiale de cette nouvelle sous-simulation est la solution finale de l'ancienne grâce à la commande mapFields ../simulation_précédente.
Enfin, on lance l'exécutable avec la commande classique pimpleDyMFoam si on veut un calcul en séquentiel.

 

Le script en détails

Le script peut être décomposé en plusieurs parties, comme le montre schématiquement la figure présentée dans le chapitre précédent qui illustre la stratégie employée.

Avant toute chose, pendant la première étape, l'exécutable a besoin de deux paramètres que sont le nombre de sous-simulations ainsi que le nombre de processeurs pour réaliser le calcul. En effet, pour gagner du temps, le calcul se fait en parallèle. Cette entête du script contient également quelques informations supplémentaires. Il est en effet nécessaire de repérer où le script est exécuté, d'indiquer le nom du dossier initial qui contient tous les paramètres choisis par l'utilisateur, et aussi d'importer des formats de nombre et autres fonctions spécifiques.
Cette partie prépare également le dossier Simulations où seront répertoriés tous les dossiers de sous-simulation.


La deuxième étape est de définir tous les paramètres de simulation. Parmi ces paramètres il a fallu :

  • Lire le premier argument du script afin de connaître le nombre de sous-simulations
     
  • Lire le deuxième paramètre qui indique le nombre de processeurs désiré. Il faut ensuite modifier de fichier OpenFOAM decomposePartDict qui gère cette parallélisation du calcul. Cette modification se fait grâce à la commande sed -ri, qui va soit rechercher la ligne contenant le mot clé indiqué après 's/, soit le numéro de ligne indiqué par exemple par " '21 " pour la ligne 21. Après avoir repéré cette ligne, cela supprimer la ligne en question et on remplace toute la ligne par ce qui est indiqué dans la suite de la commande, avec le vocabulaire spécifique aux commandes bash relatives à l'écriture dans des fichiers.
     
  • Repérer, dans le dossier de base créé par l'utilisateur, les différents paramètres de la simulation comme le temps final, la vitesse du train, le pas de temps, la fréquence de sauvegarde des résultats, le nombre de mailles initiales à gauche et à droite du train, etc ...
    Pour chacun d'eux, il a fallu utiliser astucieusement la commande echo pour faire afficher une ligne isolée par la combinaison de head et de tail. Par exemple, pour isoler la ligne 26, on affiche les 26 premières lignes du fichier qui contient l'information voulue. Puis sur ce résultat, avec un pipe et la commande tail, on ne retient que la dernière ligne.
    Une fois cette ligne isolée, il faut la diviser en plusieurs champs grâce à la commande cut qui va séparer la ligne en plusieurs parties en indiquant le séparateur.
    Une fois le paramètre enregistré dans le script, il est parfois pratique d'en tirer d'autres informations, comme la longueur du domaine par exemple. Réaliser des opérations en bash peut se faire avec la commande echo "opération" |  bc.
     
  • Une dernière section permet de calculer le nombre de mailles idéal qu'il faudra retirer à gauche du train, et ajouter à droite. On calcule ce nombre optimal en imposant le fait de conserver la même taille caractéristique de maille entre le maillage initial et le maillage final. Cela est faisable vu que l'on peut connaître la position du bloc central à l'instant final. En effet, on a à notre disposition la vitesse du train, sa position initiale et le temps de simulation.
    D'ailleurs, ayant ces informations, on peut d'ores et déjà savoir si ce bloc "train" va dépasser du domaine. Si c'est le cas, la commande exit permet de stopper le calcul.

 

 


La troisième étape consiste en la création des différents dossiers de sous-simulations. En effet, comme nous l'avons vu avec la commande mapFields d'OpenFOAM, pour chaque sous simulation, il faut un dossier distinct. Chacun de ces dossiers est à l'origine une copie du dossier de base créé par l'utilisateur. On modifie ensuite le fichier controlDict en changeant le temps initial et temps final. Cela se fait avec des commandes déjà expliquées plus haut : le calcul des temps se fait avec echo "Opération" | bc, puis on modifie la ligne désirée du fichier controlDict avec sed -ri.

 


La quatrième étape est la boucle à proprement parler, que l'on a déjà pu approcher dans la page "Stratégie utilisée".

  • Avant de lancer la boucle pour enchaîner les simulations, pour une question d'ordre d'enchaînement des commandes OpenFOAM, il faut lancer à part la création du maillage de la première sous-simulation avec les commandes runApplication blockMesh, snappyHexMesh et extrudeMesh.
     
  • Cette génération de maillage crée des fichiers non désirés. Par conséquent, en calculant les temps initial et final de la sous-simulation en cours de traitement, on peut se déplacer dans le dossier adéquat pour supprimer ces fichiers.
     
  • Puis on peut lancer le calcul en parallèle avec les commandes runApplication decomposePar, `getApplication et reconstructPar. S'il s'agissait de la dernière simulation, on sort de la boucle grâce à un test et la commande break si ce test s'est avéré positif.
     
  • Une fois le calcul terminé, l'idée est de préparer le remaillage de la sous-simulation suivante. En effet, nous savons déjà combien de mailles il faudra supprimer et ajouter aux blocs, respectivement de gauche et de droite. Par contre, nous ne savons pas où il faut positionner ces blocs, tout comme la géométrie du train décrite dans le fichier .obj.
    Il faut donc être capable de lire la position de l'interface séparant le bloc de gauche et le bloc central. Pour cela, nous avons ajouté une section au solveur afin qu'il indique en sortie, dans le fichier log.pimpleDyMFoamModified la position de cet edge. Cette démarche est expliquée à la page "Modifications du solveur".
    Ainsi, en ouvrant ce fichier texte log.pimpleDyMFoamModified avec cat, puis en recherchant la ligne contenant le mot clef "Left" avec grep, on peut repérer la position de cet edge séparant le bloc central du bloc de gauche à la fin de la simulation qui vient de se terminer.

 

  • Une fois cette position connue, on peut concrètement rentrer dans le dossier de la sous-simulation suivante. Il faut modifier le maillage en spécifiant la nouvelle position des edges en retouchant les lignes correspondantes du fichier blockMeshDict. Il faut également modifier le nombre de mailles par bloc. Tout ceci est réalisé grâce à la commande sed -ri que l'on a déjà expliquée un peu plus haut. De plus, il est nécessaire de translater le fichier .obj qui permet de décrire le train. Cela peut se faire avec la commande surfaceTransformPoints -translate ' "vecteur" ' train.obj.
     
  • Enfin, une fois que les fichiers définissant le maillage de la sous-simulation sont correctement définis, on peut lancer le processus de maillage avec les commandes runApplication blockMesh, snappyHexMesh,  extrudeMesh et mapFields pour interpoler les valeurs des variables sur ce nouveau maillage.
    Suite à cette interpolation de maillage, il faut juste renommer le fichier pointMotionUx qui définit la vitesse des points de chaque noeud du maillage.
     
  • On peut passer à la sous-simulation suivante, et ainsi de suite ...


La cinquième et dernière étape permet de rassembler tous les résultats, pour l'instant séparés dans des dossiers de simulations différents, dans un seul et même dossier. Cela est bien plus pratique pour le post-traitement, comme par exemple avoir toute la simulation en une seule animation (une seule ouverture de paraview).
Ce dossier contenant l'ensemble des résultats est appelé data. On le crée avec la commande mkdir. Puis on parcoure tous les dossiers de sous-simulation et on exécute la commande foamToVTK. Cela crée un dossier VTK rassemblant les résultats de la sous-simulation sous le format .vtk. On peut alors les visualiser avec la commande paraview, et non paraFoam.
Enfin, tous ces fichiers .vtk sont déplacés dans le dossier data. Il est juste nécessaire d'incrémenter, à chaque pas de sauvegarde successif, l'indice à la fin du nom du fichier. Connaissant l'instant auquel correspond chacun des fichiers, on peut attribuer correctement un indice permettant de ranger dans l'ordre croissant tous ces nombreux fichiers.