Documentation Utilisateur pour foampilot
Auteur : Manus AI Date : 4 Décembre 2025
1. Réflexion de Fonctionnement Globale de foampilot
Le module foampilot est conçu comme une surcouche Python pour OpenFOAM, visant à simplifier et automatiser le processus de simulation numérique en mécanique des fluides (CFD). Il abstrait la complexité de la structure des fichiers et des commandes OpenFOAM, permettant à l'utilisateur de définir, exécuter et post-traiter une simulation entièrement en Python.
La philosophie de foampilot repose sur les principes suivants :
- Définition du Cas en Python : Au lieu de modifier manuellement des fichiers de configuration (dictionnaires) dans la structure de répertoires OpenFOAM, l'utilisateur interagit avec des objets Python (
Solver,Meshing,Boundary,Constant,System). - Génération Automatique des Fichiers : Les objets Python sont responsables de la génération automatique des fichiers de configuration OpenFOAM (
controlDict,fvSchemes,transportProperties, etc.) dans le répertoire du cas. - Intégration de l'Écosystème Python : Le module s'intègre avec des bibliothèques Python puissantes pour des tâches spécifiques :
classy_blockspour la génération de maillage structuré (blockMesh).pyfluid(implicite dans l'exemple) pour la gestion des propriétés des fluides et des constantes physiques.pyvistapour le post-traitement et la visualisation avancée.latex_pdfpour la génération de rapports structurés.
En résumé, foampilot permet de passer d'un flux de travail manuel et fragmenté (édition de fichiers, exécution de commandes shell) à un flux de travail scripté et reproductible (un seul script Python).
2. Choix de la Géométrie et du Maillage
Le choix de la méthode de maillage est crucial en CFD et dépend de la complexité de la géométrie. foampilot intègre des outils pour gérer les trois scénarios principaux :
| Méthode de Maillage | Géométrie Cible | Outil foampilot / Librairie |
Description et Avantages |
|---|---|---|---|
blockMesh |
Géométries simples, extrudées, ou composées de blocs hexaédriques. | Meshing(..., mesher="blockMesh") (via classy_blocks) |
Idéal pour les géométries simples (canaux, cylindres, etc.) ou les domaines de calcul réguliers. Offre un contrôle total sur la qualité du maillage et la distribution des cellules. L'exemple run_exemple2.py utilise cette méthode pour créer une géométrie complexe par composition de blocs (Cylinder, ExtrudedRing, Elbow). |
gmsh |
Géométries complexes importées au format STEP ou IGES. | Meshing(..., mesher="gmsh") |
Permet de mailler des géométries CAO complexes avec des maillages non structurés (tétraèdres, prismes). Nécessite l'importation d'un fichier géométrique (ex: .step). |
snappyHexMesh |
Géométries complexes importées au format STL (surface triangulée). | Meshing(..., mesher="snappy") |
Le maillage de référence pour les géométries très complexes (véhicules, bâtiments). Il crée un maillage hexaédrique conforme à la surface STL, avec raffinement automatique des couches limites. |
2.1. Maillage Structuré avec blockMesh (via classy_blocks)
Pour les géométries qui peuvent être décomposées en blocs hexaédriques (y compris les extrusions), foampilot utilise la librairie classy_blocks.
Principe :
1. Définir des formes géométriques de base (cb.Cylinder, cb.ExtrudedRing, cb.Elbow).
2. Utiliser les méthodes de chaînage (.chain(), .expand(), .fill()) pour construire la géométrie complexe.
3. Définir le maillage sur chaque forme avec les méthodes .chop_axial(), .chop_radial(), .chop_tangential().
4. Assigner les patchs (surfaces) avec .set_start_patch(), .set_end_patch().
5. Assembler le tout dans un objet cb.Mesh() et écrire le blockMeshDict :
```python
# Exemple d'utilisation
mesh = cb.Mesh()
# ... ajouter les formes ...
mesh.set_default_patch("walls", "wall")
mesh.write(current_path / "system" / "blockMeshDict", current_path /"debug.vtk")
```
2.2. Maillage Non Structuré avec gmsh (pour STEP)
Pour les géométries CAO au format STEP, l'approche est la suivante :
- Assurez-vous que le fichier STEP est disponible (ex:
geometry.step). - Initialisez l'objet
Meshingen spécifiantmesher="gmsh". -
Exécutez le maillage en passant le chemin du fichier STEP :
```python mesh_obj = Meshing(current_path, mesher="gmsh")
Le chemin d'accès au fichier STEP est passé à la méthode run
mesh_obj.mesher.run(current_path / "geometry.step") ```
2.3. Maillage de Surface avec snappyHexMesh (pour STL)
Pour les géométries complexes au format STL, vous devez d'abord créer un maillage de base (blockMesh) qui englobe la géométrie STL, puis utiliser snappyHexMesh pour découper et affiner :
- Créez un
blockMeshDictsimple (viaclassy_blocksou manuellement) pour définir le domaine de calcul englobant. - Assurez-vous que le fichier STL est dans le répertoire
constant/triSurface. - Initialisez l'objet
Meshingen spécifiantmesher="snappyHexMesh". -
Exécutez le maillage.
foampilotgère la configuration et l'exécution des étapes desnappyHexMesh:```python mesh_obj = Meshing(current_path, mesher="snappyHexMesh")
snappyHexMesh n'a pas besoin d'un chemin de fichier en argument, il utilise les fichiers de configuration
mesh_obj.mesher.run() ```
Note : La configuration détaillée de
snappyHexMeshDict(niveaux de raffinement, couches limites) doit être gérée par l'utilisateur, soit en modifiant le dictionnaire généré par défaut, soit en utilisant des fonctions avancées defoampilotsi elles sont disponibles.
3. Choix du Solveur et Prise en Compte des Physiques
Le choix du solveur est la manière dont foampilot prend en compte les physiques de la simulation. Le module utilise la classe Solver pour configurer le cas, et le solveur OpenFOAM approprié est sélectionné et exécuté en arrière-plan.
3.1. Sélection du Solveur
La sélection du solveur se fait implicitement en configurant les propriétés de l'objet Solver.
```python from foampilot.solver import Solver
Initialisation du solveur pour le répertoire de cas
solver = Solver(current_path)
Configuration des physiques
solver.compressible = False # Simulation incompressible solver.with_gravity = False # Sans gravité
... d'autres propriétés comme turbulence, multiphase, etc.
```
En fonction de ces propriétés, foampilot configure le controlDict et les autres dictionnaires pour utiliser le solveur OpenFOAM le plus pertinent (par exemple, simpleFoam ou pimpleFoam pour l'incompressible, rhoSimpleFoam pour le compressible).
| Physique | Propriété Solver |
Solveur OpenFOAM Typique |
|---|---|---|
| Incompressible | solver.compressible = False |
incompressibleFluid (Solveur interne foampilot) |
| Compressible | solver.compressible = True |
compressibleFluid (Solveur interne foampilot) |
| Transitoire | solver.transient = True |
(Gère les paramètres transitoires) |
| Turbulence | solver.turbulence_model = "kEpsilon" |
(Configure les modèles de turbulence) |
| Multiphase (VOF) | solver.is_vof = True |
incompressibleVoF ou compressibleVoF (Solveurs internes foampilot) |
| Solide (Déplacement) | solver.is_solid = True |
solidDisplacement (Solveur interne foampilot) |
| Énergie (Thermique) | solver.energy_activated = True |
(Active les champs thermiques) |
3.2. Mise en Place des Conditions Limites
La gestion des conditions limites (CL) est centralisée dans l'objet solver.boundary. L'approche est de définir les conditions sur les patchs créés lors de l'étape de maillage.
Étapes :
1. Initialisation : solver.boundary.initialize_boundary() crée les fichiers de conditions limites initiaux (dans le répertoire 0).
2. Application : La méthode apply_condition_with_wildcard permet d'appliquer une condition à un ou plusieurs patchs dont le nom correspond à un motif (wildcard).
```python
Initialisation des conditions limites
solver.boundary.initialize_boundary()
Condition d'entrée (patch 'inlet')
solver.boundary.apply_condition_with_wildcard( pattern="inlet", condition_type="velocityInlet", velocity=(Quantity(10, "m/s"), Quantity(0, "m/s"), Quantity(0, "m/s")), turbulence_intensity=0.05 )
Condition de sortie (patch 'outlet')
solver.boundary.apply_condition_with_wildcard( pattern="outlet", condition_type="pressureOutlet" )
Condition de paroi (patch 'walls')
solver.boundary.apply_condition_with_wildcard( pattern="walls", condition_type="wall" )
Écriture des fichiers de conditions limites
solver.boundary.write_boundary_conditions() ```
Conditions Limites Disponibles (Exemples Typiques) :
condition_type |
Description | Champs Typiques |
|---|---|---|
fixedValue |
Valeur fixe imposée (ex: température, concentration). | T, C |
zeroGradient |
Gradient normal nul (condition de Neumann). | p, T, U (sortie) |
velocityInlet |
Vitesse d'entrée avec profil (souvent uniforme) et paramètres de turbulence. | U, k, epsilon |
pressureOutlet |
Pression de sortie fixe ou à gradient nul. | p |
wall |
Paroi solide (vitesse nulle, flux de chaleur nul par défaut). | U, T |
symmetryPlane |
Plan de symétrie. | U, p, T |
3.3. Modification d'un Dictionnaire ou Ajout d'un Patch
foampilot expose les dictionnaires OpenFOAM comme des objets Python, ce qui permet une modification directe et intuitive.
Modification d'un Dictionnaire Existant
Pour modifier ou ajouter une entrée dans un dictionnaire, il suffit d'accéder à l'attribut correspondant :
```python
Modification de la viscosité cinématique dans transportProperties
from foampilot.utilities.manageunits import Quantity kinematic_viscosity = Quantity(1e-6, "m2/s") solver.constant.transportProperties.nu = kinematic_viscosity
Modification d'une propriété dans controlDict
solver.system.controlDict.writeInterval = 100 # Écrit les résultats toutes les 100 itérations solver.system.controlDict.endTime = 1000 # Définit le temps de fin de simulation ```
Fichiers du Répertoire system Gérés par foampilot :
L'objet solver.system expose plusieurs attributs pour gérer les fichiers de ce répertoire :
| Attribut | Fichier OpenFOAM Correspondant | Description |
|---|---|---|
solver.system.controlDict |
controlDict |
Contrôle de la simulation (temps de début/fin, intervalle d'écriture, solveur). |
solver.system.fvSchemes |
fvSchemes |
Schémas de discrétisation des termes de l'équation (différenciation, interpolation). |
solver.system.fvSolution |
fvSolution |
Paramètres des solveurs linéaires (tolérance, préconditionneur) et des boucles PISO/SIMPLE. |
solver.system.decomposeParDict |
decomposeParDict |
Configuration de la décomposition du domaine pour le calcul parallèle. |
solver.system.add_dict_file(...) |
Fichier personnalisé | Permet d'ajouter n'importe quel dictionnaire OpenFOAM supplémentaire. |
Utilitaires Intégrés :
foampilot permet également d'exécuter des utilitaires OpenFOAM directement via l'objet solver.system :
| Méthode | Utilitaire OpenFOAM | Description |
|---|---|---|
solver.system.run_topoSet() |
topoSet |
Crée des ensembles de cellules et de faces pour le post-traitement ou le raffinement. |
solver.system.run_createPatch() |
createPatch |
Modifie ou crée des patchs de conditions limites après le maillage. |
solver.system.write_functions_file() |
functions |
Crée le fichier system/functions pour le post-traitement en cours de simulation (ex: fieldAverage). |
Après la modification, il est impératif d'appeler la méthode write() sur l'objet parent pour générer le fichier OpenFOAM mis à jour :
```python
Génère le fichier constant/transportProperties
solver.constant.write()
Génère le fichier system/controlDict
solver.system.write() ```
Ajout d'un Patch
L'ajout d'un patch se fait principalement lors de la phase de maillage (voir Section 2).
- Avec
blockMesh(classy_blocks) : Le patch est défini sur une face géométrique : ```python shapes[-1].set_end_patch("monNouveauPatch") ``` - Avec
gmshousnappyHexMesh: Le patch est défini dans les fichiers de configuration du maillage.
Une fois le maillage généré, le nouveau patch est automatiquement reconnu par OpenFOAM. Il suffit ensuite d'appliquer une condition limite à ce patch via solver.boundary.apply_condition_with_wildcard(pattern="monNouveauPatch", ...) comme décrit ci-dessus.
```
4. Mise en Place de system et constant avec pyfluid
Le module pyfluid (ou la classe FluidMechanics de foampilot.utilities.fluids_theory) est essentiel pour définir les propriétés physiques du fluide et les constantes du cas OpenFOAM.
4.1. Définition des Constantes Physiques avec FluidMechanics
La classe FluidMechanics permet de calculer les propriétés d'un fluide (comme la viscosité cinématique \(\nu\)) en fonction de la température et de la pression, en utilisant des données physiques intégrées.
```python from foampilot.utilities.fluids_theory import FluidMechanics from foampilot.utilities.manageunits import Quantity
1. Créer une instance de FluidMechanics pour l'eau à 20°C (293.15 K)
fluid_mech = FluidMechanics( FluidMechanics.get_available_fluids()['Water'], temperature=Quantity(293.15, "K"), pressure=Quantity(101325, "Pa") )
2. Récupérer les propriétés
properties = fluid_mech.get_fluid_properties() kinematic_viscosity = properties['kinematic_viscosity']
3. Injecter la propriété dans le dictionnaire constant/transportProperties
solver.constant.transportProperties.nu = kinematic_viscosity
4. Écrire les répertoires system et constant
solver.system.write() solver.constant.write() ```
Cette approche garantit que les constantes physiques sont définies de manière cohérente et basée sur des données physiques fiables, et qu'elles sont correctement formatées pour le fichier constant/transportProperties.
Fichiers du Répertoire constant Gérés par foampilot :
L'objet solver.constant expose plusieurs attributs pour gérer les fichiers de ce répertoire :
| Attribut | Fichier OpenFOAM Correspondant | Description |
|---|---|---|
solver.constant.transportProperties |
transportProperties |
Propriétés de transport (viscosité, diffusivité) pour les fluides incompressibles. |
solver.constant.physicalProperties |
physicalProperties |
Propriétés physiques (densité, chaleur spécifique) pour les fluides compressibles. |
solver.constant.turbulenceProperties |
turbulenceProperties |
Configuration du modèle de turbulence. |
solver.constant.gravity |
g |
Vecteur de gravité. Activé via solver.with_gravity = True. |
solver.constant.pRef |
pRef |
Point de référence pour la pression (pour les cas compressibles). |
solver.constant.radiation |
radiationProperties |
Propriétés de rayonnement. Activé via solver.constant.enable_radiation(). |
solver.constant.fvmodels |
fvModels |
Modèles de volume fini (utilisé pour le rayonnement). |
Note sur la Gravité : L'activation de la gravité (solver.with_gravity = True) entraîne la création du fichier constant/g et, si nécessaire, le remplacement du champ de pression p par p_rgh dans les fichiers de conditions initiales, conformément aux pratiques OpenFOAM pour les cas avec gravité.
5. Lancement du Solveur
Le lancement de la simulation est géré par la méthode run_simulation() de l'objet Solver.
5.1. Lancement Séquentiel
Le lancement par défaut est séquentiel :
```python
Exécute le solveur configuré (par exemple, simpleFoam)
solver.run_simulation() ```
5.2. Lancement en Parallèle
Pour les maillages volumineux, le calcul parallèle est indispensable. foampilot intègre la gestion du parallélisme, qui nécessite généralement deux étapes : la décomposition du domaine et l'exécution parallèle.
```python
1. Décomposition du domaine (utilise l'utilitaire OpenFOAM decomposePar)
Le nombre de cœurs (cores) est spécifié ici
solver.decompose_domain(cores=4)
2. Exécution du solveur en parallèle (utilise mpirun)
solver.run_simulation(parallel=True)
3. Reconstruction du domaine après la simulation (utilise reconstructPar)
solver.reconstruct_domain() ```
Note : La méthode decompose_domain configure le dictionnaire system/decomposeParDict et exécute l'utilitaire. L'utilisateur peut modifier le decomposeParDict via solver.system.decomposeParDict avant l'exécution pour ajuster la méthode de décomposition (par exemple, scotch, simple, hierarchical).
6. Post-Traitement avec pyvista
Le post-traitement est géré par la classe postprocess.FoamPostProcessing, qui utilise la librairie pyvista pour la visualisation 3D et l'analyse des données.
6.1. Flux de Travail de Post-Traitement
- Conversion des Résultats : Les résultats OpenFOAM sont d'abord convertis au format VTK (lisible par
pyvista) via l'utilitairefoamToVTK. - Chargement des Données : Les données sont chargées dans des objets
pyvista(PolyDataouUnstructuredGrid). - Analyse et Visualisation : Utilisation des fonctions de
foampilotou directement depyvistapour l'analyse.
```python from foampilot import postprocess import pyvista as pv
1. Initialisation et conversion
foam_post = postprocess.FoamPostProcessing(case_path=current_path) foam_post.foamToVTK()
2. Chargement du dernier pas de temps
time_steps = foam_post.get_all_time_steps() if time_steps: latest_time_step = time_steps[-1] structure = foam_post.load_time_step(latest_time_step) cell_mesh = structure["cell"] # Le maillage des cellules
3. Visualisation (Exemple de tracé de contour de pression)
pl_contour = pv.Plotter(off_screen=True) pl_contour.add_mesh(cell_mesh, scalars='p', show_scalar_bar=True) foam_post.export_plot(pl_contour, current_path / "contour_plot.png") ```
6.2. Détail des Possibilités de Post-Traitement
foampilot et pyvista offrent une gamme étendue de possibilités :
| Fonctionnalité | Description | Méthode foampilot / pyvista |
|---|---|---|
| Visualisation de Tranches | Afficher les champs de données (U, p, T) sur un plan de coupe. | foam_post.plot_slice(...) |
| Tracé de Contours | Visualiser les lignes ou surfaces d'isovaleur d'un champ (ex: pression). | pl.add_mesh(..., scalars='p') |
| Visualisation de Vecteurs | Afficher le champ de vitesse (U) sous forme de flèches (glyphs). | cell_mesh.glyph(orient='U', ...) |
| Analyse de Tourbillons | Calculer le critère Q ou la vorticité pour identifier les structures tourbillonnaires. | foam_post.calculate_q_criterion(...), foam_post.calculate_vorticity(...) |
| Statistiques de Maillage | Obtenir des métriques de qualité du maillage (non-orthogonalité, aspect ratio). | foam_post.get_mesh_statistics(...) |
| Statistiques de Champ | Calculer les valeurs min/max/moyenne/écart-type d'un champ sur une région. | foam_post.get_region_statistics(...) |
| Export de Données | Exporter les données de champ (U, p) vers des formats externes (CSV, JSON). | foam_post.export_region_data_to_csv(...) |
| Animation | Créer des animations à partir des différents pas de temps. | Fonctions pyvista pour l'enregistrement vidéo. |
| ``` |
7. Rapport en LaTeX avec latex_pdf
L'une des fonctionnalités les plus puissantes de foampilot est sa capacité à générer automatiquement un rapport de simulation structuré au format PDF, en utilisant le module latex_pdf.
7.1. Fonctionnement du Module latex_pdf
Le module latex_pdf est une surcouche qui permet de construire un document LaTeX en Python, sans avoir à écrire directement le code LaTeX. Il est particulièrement adapté pour intégrer des résultats de simulation (statistiques, figures, tableaux).
Étapes :
1. Collecte des Données : Les données de post-traitement (statistiques, chemins des images générées par pyvista) sont collectées et sauvegardées (souvent au format JSON ou CSV).
2. Initialisation du Document : Création de l'objet LatexDocument.
3. Ajout de Contenu : Utilisation des méthodes de l'objet pour ajouter des sections, des tableaux, des figures, etc.
4. Génération du PDF : Compilation du document LaTeX en PDF.
7.2. Détail des Possibilités de latex_pdf
Le module offre des méthodes pour structurer le rapport et intégrer les résultats :
| Méthode | Description | Utilisation Typique |
|---|---|---|
LatexDocument(...) |
Initialise le document avec titre, auteur et nom de fichier. | Début du script de rapport. |
add_title() |
Ajoute la page de titre. | Après l'initialisation. |
add_toc() |
Ajoute la table des matières. | Après la page de titre. |
add_abstract(...) |
Ajoute un résumé du rapport. | Introduction du rapport. |
add_section(...) |
Ajoute une nouvelle section ou sous-section. | Structuration du rapport. |
add_table(...) |
Intègre un tableau de données (ex: statistiques de maillage). | Présentation des données numériques. |
add_figure(...) |
Intègre une image (ex: visualisation pyvista). |
Présentation des résultats visuels. |
add_appendix(...) |
Ajoute une annexe. | Pour les données brutes ou les fichiers exportés. |
generate_document(...) |
Compile le document LaTeX en PDF. | Fin du script de rapport. |
7.3. Exemple d'Intégration de Résultats
L'exemple run_exemple2.py montre comment les statistiques et les figures sont intégrées :
```python
Chargement des statistiques JSON
stats_file = current_path / "all_stats.json" with open(stats_file, "r") as f: stats = json.load(f)
doc = latex_pdf.LatexDocument( title="Simulation Report: Muffler Flow Case", author="Automated Report", filename="simulation_report", output_dir=current_path )
... ajout des sections ...
Ajout d'un tableau de statistiques
mesh_stats = stats.get("mesh_stats", {}) mesh_table_data = [[k, v] for k, v in mesh_stats.items()] doc.add_table( mesh_table_data, headers=["Statistic", "Value"], caption="Mesh Quality Statistics" )
Ajout des figures générées par pyvista
for img_name in ["slice_plot.png", "contour_plot.png", "vector_plot.png", "mesh_style_plot.png"]: img_path = current_path / img_name if img_path.exists(): doc.add_figure(str(img_path), caption=img_name.replace("_", " ").title(), width="0.7\textwidth")
Génération finale
doc.generate_document(output_format="pdf") ```
Cette capacité permet de garantir une traçabilité et une reproductibilité complètes des résultats de simulation, en générant un livrable professionnel directement à partir du script de simulation. ```