High-performance CFD simulation library with Python bindings
Project description
CFD Python
Python bindings for high-performance CFD simulation library using CPython C-API with stable ABI (abi3).
Features
- High Performance: Direct bindings to optimized C library with SIMD (AVX2/NEON) and OpenMP support
- Stable ABI: Compatible across Python 3.9+ versions
- Multiple Backends: Scalar, SIMD, OpenMP, and CUDA (GPU) backends with runtime detection
- Boundary Conditions: Full BC support (Neumann, Dirichlet, no-slip, inlet, outlet)
- Dynamic Solver Discovery: New solvers automatically available
- Multiple Output Formats: VTK and CSV export support
- Error Handling: Rich exception hierarchy with detailed error messages
Installation
Installing uv (optional but recommended)
uv is a fast Python package manager. Install it with:
# On macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# On Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or with pip
pip install uv
From PyPI
Using uv (recommended):
uv pip install cfd-python
Or with pip:
pip install cfd-python
From Source
The Python package requires the C CFD library to be built first. By default, it expects the library at ../cfd relative to the cfd-python directory. You can override this by setting the CFD_ROOT environment variable.
-
Build the C CFD library (static):
cd ../cfd cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF cmake --build build --config Release
-
Install the Python package:
cd ../cfd-python pip install .
Or with uv for faster installs:
uv pip install .
With a custom library location:
CFD_ROOT=/path/to/cfd pip install .
For Development
We use uv for fast dependency management:
# Create virtual environment
uv venv
# Activate it
source .venv/bin/activate # Linux/macOS
source .venv/Scripts/activate # Windows (Git Bash)
.venv\Scripts\activate # Windows (cmd)
# Install with dev dependencies
uv pip install -e ".[test,dev]"
Alternatively, using pip:
pip install -e ".[test,dev]"
Quick Start
import cfd_python
# List available solvers
print(cfd_python.list_solvers())
# ['explicit_euler', 'explicit_euler_optimized', 'projection', ...]
# Run a simple simulation
velocity_magnitude = cfd_python.run_simulation(50, 50, steps=100)
print(f"Computed {len(velocity_magnitude)} velocity values")
# Create a grid
grid = cfd_python.create_grid(100, 100, 0.0, 1.0, 0.0, 1.0)
print(f"Grid: {grid['nx']}x{grid['ny']}")
# Get default solver parameters
params = cfd_python.get_default_solver_params()
print(f"Default dt: {params['dt']}")
API Reference
Simulation Functions
run_simulation(nx, ny, steps=100, xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, solver_type=None, output_file=None)
Run a complete simulation with default parameters.
Parameters:
nx,ny: Grid dimensionssteps: Number of time steps (default: 100)xmin,xmax,ymin,ymax: Domain bounds (optional)solver_type: Solver name string (optional, uses library default)output_file: VTK output file path (optional)
Returns: List of velocity magnitude values
run_simulation_with_params(nx, ny, xmin, xmax, ymin, ymax, steps=1, dt=0.001, cfl=0.2, solver_type=None, output_file=None)
Run simulation with custom parameters and solver selection.
Parameters:
nx,ny: Grid dimensionsxmin,xmax,ymin,ymax: Domain boundssteps: Number of time steps (default: 1)dt: Time step size (default: 0.001)cfl: CFL number (default: 0.2)solver_type: Solver name string (optional, uses library default)output_file: VTK output file path (optional)
Returns: Dictionary with velocity_magnitude, nx, ny, steps, solver_name, solver_description, and stats
create_grid(nx, ny, xmin, xmax, ymin, ymax)
Create a computational grid.
Parameters:
nx,ny: Grid dimensionsxmin,xmax,ymin,ymax: Domain bounds
Returns: Dictionary with nx, ny, xmin, xmax, ymin, ymax, x_coords, y_coords
create_grid_stretched(nx, ny, xmin, xmax, ymin, ymax, beta)
Create a grid with non-uniform (stretched) spacing.
Parameters:
nx,ny: Grid dimensionsxmin,xmax,ymin,ymax: Domain boundsbeta: Stretching parameter (higher = more clustering)
Returns: Dictionary with grid info including x_coords, y_coords
Note: The stretched grid implementation has a known bug - see ROADMAP.md for details.
get_default_solver_params()
Get default solver parameters.
Returns: Dictionary with keys: dt, cfl, gamma, mu, k, max_iter, tolerance
Solver Discovery
list_solvers()
Get list of all available solver names.
Returns: List of solver name strings
has_solver(name)
Check if a solver is available.
Returns: Boolean
get_solver_info(name)
Get information about a solver.
Returns: Dictionary with name, description, version, capabilities
Dynamic Solver Constants
Solver constants are automatically generated from the registry:
cfd_python.SOLVER_EXPLICIT_EULER # 'explicit_euler'
cfd_python.SOLVER_EXPLICIT_EULER_OPTIMIZED # 'explicit_euler_optimized'
cfd_python.SOLVER_PROJECTION # 'projection'
# ... more solvers as registered in C library
Backend Availability (v0.1.6+)
Query and select compute backends at runtime:
import cfd_python
# Check available backends
print(cfd_python.get_available_backends())
# ['Scalar', 'SIMD', 'OpenMP'] # CUDA if GPU available
# Check specific backend
if cfd_python.backend_is_available(cfd_python.BACKEND_SIMD):
print("SIMD backend available!")
# Get backend name
print(cfd_python.backend_get_name(cfd_python.BACKEND_OMP)) # 'OpenMP'
# List solvers for a backend
omp_solvers = cfd_python.list_solvers_by_backend(cfd_python.BACKEND_OMP)
print(f"OpenMP solvers: {omp_solvers}")
Backend Constants:
BACKEND_SCALAR: Basic scalar CPU implementationBACKEND_SIMD: SIMD-optimized (AVX2/NEON)BACKEND_OMP: OpenMP parallelizedBACKEND_CUDA: CUDA GPU acceleration
Boundary Conditions
Apply various boundary conditions to flow fields:
import cfd_python
# Create velocity field (as flat lists)
nx, ny = 50, 50
u = [0.0] * (nx * ny)
v = [0.0] * (nx * ny)
# Apply uniform inlet on left edge
cfd_python.bc_apply_inlet_uniform(
u, v, nx, ny,
u_inlet=1.0, v_inlet=0.0,
edge=cfd_python.BC_EDGE_LEFT
)
# Apply zero-gradient outlet on right edge
cfd_python.bc_apply_outlet_velocity(u, v, nx, ny, cfd_python.BC_EDGE_RIGHT)
# Apply no-slip walls on top and bottom
cfd_python.bc_apply_noslip(u, v, nx, ny)
# Check/set BC backend
print(f"BC Backend: {cfd_python.bc_get_backend_name()}")
if cfd_python.bc_backend_available(cfd_python.BC_BACKEND_OMP):
cfd_python.bc_set_backend(cfd_python.BC_BACKEND_OMP)
BC Type Constants:
BC_TYPE_PERIODIC: Periodic boundariesBC_TYPE_NEUMANN: Zero-gradient boundariesBC_TYPE_DIRICHLET: Fixed value boundariesBC_TYPE_NOSLIP: No-slip wall (zero velocity)BC_TYPE_INLET: Inlet velocity specificationBC_TYPE_OUTLET: Outlet conditions
BC Edge Constants:
BC_EDGE_LEFT,BC_EDGE_RIGHT,BC_EDGE_BOTTOM,BC_EDGE_TOP
BC Backend Constants:
BC_BACKEND_AUTO: Auto-select best availableBC_BACKEND_SCALAR: Single-threaded scalarBC_BACKEND_OMP: OpenMP parallelBC_BACKEND_SIMD: SIMD + OpenMP (AVX2/NEON)BC_BACKEND_CUDA: GPU acceleration
BC Functions:
bc_apply_scalar(field, nx, ny, bc_type): Apply BC to scalar fieldbc_apply_velocity(u, v, nx, ny, bc_type): Apply BC to velocity fieldsbc_apply_dirichlet(field, nx, ny, left, right, bottom, top): Fixed valuesbc_apply_noslip(u, v, nx, ny): Zero velocity at wallsbc_apply_inlet_uniform(u, v, nx, ny, u_inlet, v_inlet, edge): Uniform inletbc_apply_inlet_parabolic(u, v, nx, ny, max_velocity, edge): Parabolic inletbc_apply_outlet_scalar(field, nx, ny, edge): Zero-gradient outletbc_apply_outlet_velocity(u, v, nx, ny, edge): Zero-gradient outlet
Derived Fields & Statistics
Compute derived quantities from flow fields:
import cfd_python
# Compute velocity magnitude
u = [1.0] * 100
v = [0.5] * 100
vel_mag = cfd_python.compute_velocity_magnitude(u, v, 10, 10)
# Calculate field statistics
stats = cfd_python.calculate_field_stats(vel_mag)
print(f"Min: {stats['min']}, Max: {stats['max']}, Avg: {stats['avg']}")
# Comprehensive flow statistics
p = [0.0] * 100 # pressure field
flow_stats = cfd_python.compute_flow_statistics(u, v, p, 10, 10)
print(f"Max velocity: {flow_stats['velocity_magnitude']['max']}")
CPU Features Detection
Detect SIMD capabilities at runtime:
import cfd_python
# Check SIMD architecture
arch = cfd_python.get_simd_arch()
name = cfd_python.get_simd_name() # 'avx2', 'neon', or 'none'
# Check specific capabilities
if cfd_python.has_avx2():
print("AVX2 available!")
elif cfd_python.has_neon():
print("ARM NEON available!")
# General SIMD check
if cfd_python.has_simd():
print(f"SIMD enabled: {name}")
SIMD Constants:
SIMD_NONE: No SIMD supportSIMD_AVX2: x86-64 AVX2SIMD_NEON: ARM NEON
Error Handling
Handle errors with Python exceptions:
import cfd_python
from cfd_python import (
CFDError,
CFDMemoryError,
CFDInvalidError,
CFDDivergedError,
raise_for_status,
)
# Check status codes
status = cfd_python.get_last_status()
if status != cfd_python.CFD_SUCCESS:
error_msg = cfd_python.get_last_error()
print(f"Error: {error_msg}")
# Use raise_for_status helper
try:
raise_for_status(status, context="simulation step")
except CFDDivergedError as e:
print(f"Solver diverged: {e}")
except CFDInvalidError as e:
print(f"Invalid parameter: {e}")
except CFDError as e:
print(f"CFD error: {e}")
# Clear error state
cfd_python.clear_error()
Error Constants:
CFD_SUCCESS: Operation successful (0)CFD_ERROR: Generic error (-1)CFD_ERROR_NOMEM: Out of memory (-2)CFD_ERROR_INVALID: Invalid argument (-3)CFD_ERROR_IO: File I/O error (-4)CFD_ERROR_UNSUPPORTED: Operation not supported (-5)CFD_ERROR_DIVERGED: Solver diverged (-6)CFD_ERROR_MAX_ITER: Max iterations reached (-7)
Exception Classes:
CFDError: Base exception classCFDMemoryError(CFDError, MemoryError): Memory allocation failedCFDInvalidError(CFDError, ValueError): Invalid argumentCFDIOError(CFDError, IOError): File I/O errorCFDUnsupportedError(CFDError, NotImplementedError): Unsupported operationCFDDivergedError(CFDError): Solver divergedCFDMaxIterError(CFDError): Max iterations reached
Output Functions
set_output_dir(directory)
Set the output directory for VTK/CSV files.
write_vtk_scalar(filename, field_name, data, nx, ny, xmin, xmax, ymin, ymax)
Write scalar field to VTK file.
write_vtk_vector(filename, field_name, u_data, v_data, nx, ny, xmin, xmax, ymin, ymax)
Write vector field to VTK file.
write_csv_timeseries(filename, step, time, u_data, v_data, p_data, nx, ny, dt, iterations, create_new=False)
Write simulation timeseries data to CSV file.
Parameters:
filename: Output file pathstep: Time step numbertime: Simulation timeu_data,v_data,p_data: Flow field data as lists (size nx*ny)nx,ny: Grid dimensionsdt: Time step sizeiterations: Number of solver iterationscreate_new: If True, create new file; if False, append
Output Type Constants
cfd_python.OUTPUT_VELOCITY_MAGNITUDE # Velocity magnitude scalar (VTK)
cfd_python.OUTPUT_VELOCITY # Velocity vector field (VTK)
cfd_python.OUTPUT_FULL_FIELD # Complete flow field (VTK)
cfd_python.OUTPUT_CSV_TIMESERIES # Time series (CSV)
cfd_python.OUTPUT_CSV_CENTERLINE # Centerline profile (CSV)
cfd_python.OUTPUT_CSV_STATISTICS # Global statistics (CSV)
Migration from v0.1.0
If you're upgrading from an older version, note these changes:
API Changes
- Type names changed (internal, transparent to Python users)
- Error handling improved: Use
get_last_error(),get_last_status(),clear_error() - New solver backends: SIMD, OpenMP, CUDA available via
backend_is_available()
New Features in v0.1.6
- Boundary conditions: Full BC API with inlet/outlet support
- Backend selection: Query and select compute backends at runtime
- Derived fields:
compute_velocity_magnitude(),compute_flow_statistics() - Error handling: Python exception classes with
raise_for_status() - CPU detection:
has_avx2(),has_neon(),has_simd()
See MIGRATION_PLAN.md for detailed migration information.
Requirements
- Python 3.9+
- uv (recommended) or pip
For building from source:
- C compiler (MSVC on Windows, GCC/Clang on Unix)
- CMake 3.15+
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cfd_python-0.1.6.tar.gz.
File metadata
- Download URL: cfd_python-0.1.6.tar.gz
- Upload date:
- Size: 289.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1b04a41d845d10d2a6a42deb8bde976cf9d46b85f166bdc3a81da7119e0274c
|
|
| MD5 |
76fe378f2eef80700521f8bdae7a0200
|
|
| BLAKE2b-256 |
e7abac73c5058b230b51d0e95ab24cb355c4290bd38e105f3d9fc2fe7d17b42c
|
Provenance
The following attestation bundles were made for cfd_python-0.1.6.tar.gz:
Publisher:
publish.yml on shaia/cfd-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cfd_python-0.1.6.tar.gz -
Subject digest:
f1b04a41d845d10d2a6a42deb8bde976cf9d46b85f166bdc3a81da7119e0274c - Sigstore transparency entry: 799013736
- Sigstore integration time:
-
Permalink:
shaia/cfd-python@9c0407f7b938832110e8e9a6c23a3d87da7d842b -
Branch / Tag:
refs/heads/master - Owner: https://github.com/shaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9c0407f7b938832110e8e9a6c23a3d87da7d842b -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file cfd_python-0.1.6-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: cfd_python-0.1.6-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 85.4 kB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4579861004ee186580ef3a177d53d64cbee59524fae49316182c96077faddc72
|
|
| MD5 |
34da1af224136e5c6dc752ee32055466
|
|
| BLAKE2b-256 |
266b98919b867bd83bf18d73654234f4dc027907579f2c64d8eedbac0889528c
|
Provenance
The following attestation bundles were made for cfd_python-0.1.6-cp39-abi3-win_amd64.whl:
Publisher:
publish.yml on shaia/cfd-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cfd_python-0.1.6-cp39-abi3-win_amd64.whl -
Subject digest:
4579861004ee186580ef3a177d53d64cbee59524fae49316182c96077faddc72 - Sigstore transparency entry: 798946295
- Sigstore integration time:
-
Permalink:
shaia/cfd-python@dfdfbec46516cea598866c7557f943e367cc929e -
Branch / Tag:
refs/heads/master - Owner: https://github.com/shaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dfdfbec46516cea598866c7557f943e367cc929e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file cfd_python-0.1.6-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: cfd_python-0.1.6-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 419.9 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18a9520e9a62791c07a032eb6559fd18a4192b735bd0d31ad0c532dee5c6064c
|
|
| MD5 |
5140f3581e55ff2a4e518a15a8c2b177
|
|
| BLAKE2b-256 |
09ef6c9cc2968a0903c43511e74783e9840e4d4e411b3bd3d69e327ec46b1025
|
Provenance
The following attestation bundles were made for cfd_python-0.1.6-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
publish.yml on shaia/cfd-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cfd_python-0.1.6-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
18a9520e9a62791c07a032eb6559fd18a4192b735bd0d31ad0c532dee5c6064c - Sigstore transparency entry: 798946288
- Sigstore integration time:
-
Permalink:
shaia/cfd-python@dfdfbec46516cea598866c7557f943e367cc929e -
Branch / Tag:
refs/heads/master - Owner: https://github.com/shaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dfdfbec46516cea598866c7557f943e367cc929e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file cfd_python-0.1.6-cp39-abi3-macosx_15_0_arm64.whl.
File metadata
- Download URL: cfd_python-0.1.6-cp39-abi3-macosx_15_0_arm64.whl
- Upload date:
- Size: 72.3 kB
- Tags: CPython 3.9+, macOS 15.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13656b96d0aecd0cc8aefab2d34c9bc34493cfb90533cfbac4a4a2dcad323533
|
|
| MD5 |
6dcedbac5534c632d4aa42520515e103
|
|
| BLAKE2b-256 |
dfd88be2187d98febef956797800bd305447046e7c72532dda931a25913bf5ea
|
Provenance
The following attestation bundles were made for cfd_python-0.1.6-cp39-abi3-macosx_15_0_arm64.whl:
Publisher:
publish.yml on shaia/cfd-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cfd_python-0.1.6-cp39-abi3-macosx_15_0_arm64.whl -
Subject digest:
13656b96d0aecd0cc8aefab2d34c9bc34493cfb90533cfbac4a4a2dcad323533 - Sigstore transparency entry: 798946282
- Sigstore integration time:
-
Permalink:
shaia/cfd-python@dfdfbec46516cea598866c7557f943e367cc929e -
Branch / Tag:
refs/heads/master - Owner: https://github.com/shaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dfdfbec46516cea598866c7557f943e367cc929e -
Trigger Event:
workflow_dispatch
-
Statement type: