Metadata-Version: 2.4
Name: pysimpler-fvm
Version: 0.1.0
Summary: A small, readable numpy implementation of the SIMPLE/SIMPLER finite-volume pressure-velocity coupling — a forkable skeleton for writing your own CFD solver.
Author: alexlu997
License: MIT
Project-URL: Homepage, https://github.com/alexlu997/pysimpler
Project-URL: Repository, https://github.com/alexlu997/pysimpler
Keywords: CFD,SIMPLE,SIMPLER,finite-volume,staggered-grid,Patankar,Navier-Stokes
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Intended Audience :: Science/Research
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: numpy>=1.20
Provides-Extra: fast
Requires-Dist: scipy>=1.7; extra == "fast"
Provides-Extra: test
Requires-Dist: pytest>=7; extra == "test"
Provides-Extra: docs
Requires-Dist: matplotlib>=3.5; extra == "docs"
Dynamic: license-file

# pysimpler

[![CI](https://github.com/alexlu997/pysimpler/actions/workflows/ci.yml/badge.svg)](https://github.com/alexlu997/pysimpler/actions/workflows/ci.yml)
[![docs](https://github.com/alexlu997/pysimpler/actions/workflows/docs.yml/badge.svg)](https://alexlu997.github.io/pysimpler/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.8%2B-blue.svg)](pyproject.toml)
[![deps: numpy](https://img.shields.io/badge/deps-numpy-013243.svg)](pyproject.toml)

📖 **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 Re=100: streamlines and centreline velocity vs Ghia et al. 1982](docs/cavity.png)

*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

```bash
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 — always `import pysimpler`.

## Quickstart

```python
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/`](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 |

```bash
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](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](https://pypi.org/manage/account/publishing/): 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](LICENSE) and
[NOTICE](NOTICE). Please also credit Patankar (1980) in academic use.
