A small, readable numpy implementation of the SIMPLE/SIMPLER finite-volume pressure-velocity coupling — a forkable skeleton for writing your own CFD solver.
Project description
pysimpler
📖 Docs: https://alexlu997.github.io/pysimpler/
A small, readable numpy implementation of the SIMPLE / SIMPLER finite-volume pressure–velocity coupling (Patankar 1980) on a staggered grid — built as a study reference and a forkable skeleton for writing your own CFD solver.
- numpy only. TDMA (tri-diagonal solver) is hand-rolled; no scipy/PETSc required.
- SIMPLE and SIMPLER both implemented, side by side.
- Verified: pure-conduction manufactured solution to machine precision; lid-driven cavity matches the Ghia et al. (1982) benchmark.
- Textbook notation kept on purpose (
aip/aim/ajp/ajm/ap/con,du/dv,diflow,solve/reset) so it maps cleanly onto any derivation and onto other languages.
Lid-driven cavity at Re=100 (SIMPLER): streamlines coloured by speed, and centreline
velocity profiles overlaid on the Ghia et al. (1982) benchmark points. Reproduce with
python docs/make_figure.py.
Install
pip install pysimpler-fvm # from PyPI (import name stays: import pysimpler)
# or from a clone:
pip install -e . # needs only numpy
pip install -e ".[test]" # + pytest
The PyPI distribution is
pysimpler-fvm(the bare name was taken), but the import name is unchanged — alwaysimport pysimpler.
Quickstart
import numpy as np
from pysimpler import Grid, SimpleField, simpler_iterate
g = Grid(L1=42, M1=42, XL=1.0, YL=1.0) # 40x40 interior cells
s = SimpleField(g)
rho, mu = 1.0, 0.01 # Re = rho*U*L/mu = 100
def lid(g, s): # BC hook (moving top lid)
s.u[2, :] = 0; s.u[g.L1, :] = 0; s.v[:, 2] = 0; s.v[:, g.M1] = 0
s.u[:, 1] = 0; s.u[:, g.M1] = 1.0; s.v[1, :] = 0; s.v[g.L1, :] = 0
for _ in range(400):
smax, ssum = simpler_iterate(g, s, rho, mu, relax_u=0.8, relax_v=0.8, apply_bc=lid)
print("mass imbalance:", ssum) # -> ~1e-15
Runnable demos in examples/: conduction.py (heat conduction, analytic
check) and cavity.py (lid-driven cavity + a SIMPLE-vs-SIMPLER convergence comparison).
What's inside (pysimpler.py)
| Piece | Function/class | Method |
|---|---|---|
| Staggered geometry | Grid |
uniform Cartesian control volumes |
| Convection–diffusion scheme | diflow |
Patankar power-law A(|P|)=max(0,(1−0.1|P|)^5) |
| Linear solver | solve |
line TDMA (4-direction ADI) + additive/block correction |
| Scalar transport | assemble_scalar |
aP·φ = Σ a_nb·φ_nb + b, source S_C + S_P·φ |
| SIMPLE coupling | simple_iterate |
momentum → pressure-correction → correct u,v,p |
| SIMPLER coupling | simpler_iterate |
pseudo-velocities → pressure equation → correct u,v |
Verified results
| Test | Gate | Result |
|---|---|---|
Conduction (x+y+xy) |
max|T−(x+y+xy)| < 1e-6 |
5.6e-15 (discrete-exact) |
| Lid cavity Re=100, 22² | mass imbalance → 0, bounded, no NaN | SSUM → ~1e-15, |u|max=0.835 |
| SIMPLER vs SIMPLE | fewer outer iters to SSUM<1e-8 |
121 vs 405 (≈3.3× faster), same field |
pytest # runs all four gates above
Extending it (the one idea)
Every physics — buoyancy, swirl, turbulence sources, variable properties — enters
through just two things: the effective diffusion Γ and the linearised source
S = S_C + S_P·φ (keep S_P ≤ 0). Add your term there, not as a new code path, and
the same engine solves it. Non-Cartesian geometries add curvature source terms only.
Contributing
See CONTRIBUTING.md. In short: keep it readable, keep the pytest
gates green, numpy-only in the core.
Publishing to PyPI (maintainers)
Releases publish to PyPI automatically via Trusted Publishing (OIDC — no token in the
repo). One-time setup on pypi.org: add a
pending publisher with PyPI Project Name pysimpler-fvm, owner alexlu997, repo
pysimpler, workflow publish.yml, environment pypi. Then each GitHub Release (e.g.
tag v0.1.0) triggers .github/workflows/publish.yml, which builds and uploads the wheel
- sdist. After the first successful publish:
pip install pysimpler-fvm.
Provenance & license
Independent from-scratch re-implementation; structure follows the classic XJTU (Prof. 陶文铨 group) staggered-grid SIMPLER teaching code. The original teaching Fortran is not included (teaching-only). MIT licensed — see LICENSE and NOTICE. Please also credit Patankar (1980) in academic use.
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 Distribution
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 pysimpler_fvm-0.1.0.tar.gz.
File metadata
- Download URL: pysimpler_fvm-0.1.0.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff239709fdb5fb7db87a07c79652f87d3f79654043de959b7c3390ddb1ac9912
|
|
| MD5 |
382a6f104e63027f7d9a0e43cccd24ac
|
|
| BLAKE2b-256 |
837f0e342ac7dee64e829dbc3056e4a13926e9640faaf041b184fd01d1893d7e
|
Provenance
The following attestation bundles were made for pysimpler_fvm-0.1.0.tar.gz:
Publisher:
publish.yml on alexlu997/pysimpler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pysimpler_fvm-0.1.0.tar.gz -
Subject digest:
ff239709fdb5fb7db87a07c79652f87d3f79654043de959b7c3390ddb1ac9912 - Sigstore transparency entry: 2034850553
- Sigstore integration time:
-
Permalink:
alexlu997/pysimpler@b45f80307cbe24bc412586bfd87c90439a5691d9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alexlu997
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b45f80307cbe24bc412586bfd87c90439a5691d9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pysimpler_fvm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pysimpler_fvm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da9546e891c5c06f3fdb8d8641a871b657932251e169aa6812cdb299d24f5864
|
|
| MD5 |
21f466fec6c110761241cd176cc6892d
|
|
| BLAKE2b-256 |
6280178c1527132dbb94e850410a035ea2f81124df1a3be067378921fcd99e96
|
Provenance
The following attestation bundles were made for pysimpler_fvm-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on alexlu997/pysimpler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pysimpler_fvm-0.1.0-py3-none-any.whl -
Subject digest:
da9546e891c5c06f3fdb8d8641a871b657932251e169aa6812cdb299d24f5864 - Sigstore transparency entry: 2034850792
- Sigstore integration time:
-
Permalink:
alexlu997/pysimpler@b45f80307cbe24bc412586bfd87c90439a5691d9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alexlu997
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b45f80307cbe24bc412586bfd87c90439a5691d9 -
Trigger Event:
release
-
Statement type: