foamlib
β¨ A modern Python package for interacting with OpenFOAM
10K+
foamlib is a modern Python package that provides an elegant, streamlined interface for interacting with OpenFOAM. It's designed to make OpenFOAM-based workflows more accessible, reproducible, and precise for researchers and engineers.
Loading a volVectorField with one million cells1β
foamlib is a Python package designed to simplify and streamline OpenFOAM workflows. It provides:
dict-like Python classesasyncioβ integrationCompared to PyFoamβ and other similar tools like fluidfoamβ , fluidsimfoamβ , and Ofppβ , foamlib offers significant advantages in performance, usability, and modern Python compatibility.
foamlib provides these key classes for different aspects of OpenFOAM workflow automation:
FoamFileβ - Read and edit OpenFOAM configuration files as if they were Python dictsFoamFieldFileβ - Handle field files with support for ASCII and binary formats (with or without compression)FoamCaseβ - Configure, run, and access results of OpenFOAM casesAsyncFoamCaseβ - Asynchronous version for running multiple cases concurrentlyAsyncSlurmFoamCaseβ - Specialized for Slurm-based HPC clustersChoose your preferred installation method:
| β¨ pipβ | pip install foamlib |
| π condaβ | conda install -c conda-forge foamlib |
| πΊ Homebrewβ | brew install gerlero/openfoam/foamlib |
| π³ Dockerβ | docker pull microfluidica/foamlib |
Here's a simple example to get you started:
import os
from pathlib import Path
from foamlib import FoamCase
# [Clone and run a case](https://github.com/gerlero/foamlib)
my_case = FoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily").clone("myCase")
my_case.run()
# [Access results](https://github.com/gerlero/foamlib)
latest_time = my_case[-1]
pressure = latest_time["p"].internal_field
velocity = latest_time["U"].internal_field
print(f"Max pressure: {max(pressure)}")
print(f"Velocity at first cell: {velocity[0]}")
# [Clean up](https://github.com/gerlero/foamlib)
my_case.clean()
import os
from pathlib import Path
from foamlib import FoamCase
pitz_tutorial = FoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily")
my_pitz = pitz_tutorial.clone("myPitz")
# [Run the simulation](https://github.com/gerlero/foamlib)
my_pitz.run()
# [Access the latest time step](https://github.com/gerlero/foamlib)
latest_time = my_pitz[-1]
p = latest_time["p"]
U = latest_time["U"]
print(f"Pressure field: {p.internal_field}")
print(f"Velocity field: {U.internal_field}")
# [Clean the case](https://github.com/gerlero/foamlib)
my_pitz.clean()
# [Modify control settings](https://github.com/gerlero/foamlib)
my_pitz.control_dict["writeInterval"] = 10
my_pitz.control_dict["endTime"] = 2000
# [Make multiple file changes efficiently](https://github.com/gerlero/foamlib)
with my_pitz.fv_schemes as f:
f["gradSchemes"]["default"] = f["divSchemes"]["default"]
f["snGradSchemes"]["default"] = "uncorrected"
import numpy as np
from foamlib import FoamFieldFile
# [Read field data directly](https://github.com/gerlero/foamlib)
U = FoamFieldFile("0/U")
print(f"Velocity field shape: {np.shape(U.internal_field)}")
print(f"Boundaries: {list(U.boundary_field)}")
In an asyncio context (e.g. asyncioβ REPL or Jupyterβ notebook):
from foamlib import AsyncFoamCase
case1 = AsyncFoamCase("path/to/case1")
case2 = AsyncFoamCase("path/to/case2")
await AsyncFoamCase.run_all([case1, case2])
Note: outside of an asyncio context, you can use asyncio.run()β .
import os
from pathlib import Path
from foamlib import AsyncSlurmFoamCase
from scipy.optimize import differential_evolution
# [Set up base case for optimization](https://github.com/gerlero/foamlib)
base = AsyncSlurmFoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily")
async def objective_function(x):
"""Objective function for optimization."""
async with base.clone() as case:
# [Set inlet velocity based on optimization parameters](https://github.com/gerlero/foamlib)
case[0]["U"].boundary_field["inlet"].value = [x[0], 0, 0]
# [Run with fallback to local execution if Slurm unavailable](https://github.com/gerlero/foamlib)
await case.run(fallback=True)
# [Return objective (minimize velocity magnitude at outlet)](https://github.com/gerlero/foamlib)
return abs(case[-1]["U"].internal_field[0][0])
# [Run optimization with parallel jobs](https://github.com/gerlero/foamlib)
result = differential_evolution(
objective_function,
bounds=[(-1, 1)],
workers=AsyncSlurmFoamCase.map, # Enables concurrent evaluations
polish=False
)
print(f"Optimal inlet velocity: {result.x[0]}")
run/Allrun scripts#!/usr/bin/env python3
"""Run the OpenFOAM case in this directory."""
from pathlib import Path
from foamlib import FoamCase
# [Initialize case from this directory](https://github.com/gerlero/foamlib)
case = FoamCase(Path(__file__).parent)
# [Adjust simulation parameters](https://github.com/gerlero/foamlib)
case.control_dict["endTime"] = 1000
case.control_dict["writeInterval"] = 100
# [Run the simulation](https://github.com/gerlero/foamlib)
print("Starting OpenFOAM simulation...")
case.run()
print("Simulation completed successfully!")
For more details on how to use foamlib, check out the documentationβ .
If you have any questions or need help, feel free to open a discussionβ .
If you believe you have found a bug in foamlib, please open an issueβ .
You're welcome to contribute to foamlib! Check out the contributing guidelinesβ for more information.
foamlib has been published in the Journal of Open Source Softwareβ !
If you use foamlib in your research, please remember to cite our paper:
Gerlero, G. S., & Kler, P. A. (2025). foamlib: A modern Python package for working with OpenFOAM. Journal of Open Source Software, 10(109), 7633. https://doi.org/10.21105/joss.07633β
@article{foamlib,
author = {Gerlero, Gabriel S. and Kler, Pablo A.},
doi = {10.21105/joss.07633},
journal = {Journal of Open Source Software},
month = may,
number = {109},
pages = {7633},
title = {{foamlib: A modern Python package for working with OpenFOAM}},
url = {https://joss.theoj.org/papers/10.21105/joss.07633},
volume = {10},
year = {2025}
}
[1]β foamlib 1.5.2 vs. PyFoam 2023.7 (Python 3.11.13) on an M3 MacBook Air. Benchmark scriptβ .
Content type
Image
Digest
sha256:0b378badcβ¦
Size
489.8 MB
Last updated
23 days ago
docker pull microfluidica/foamlib:main-openfoam2506Pulls:
894
Last week