Von Karman Vortex Street
A 2D decaying turbulence pseudo-spectral solver, simulating Navier-Stokes flow around a cylindrical rod held fixed at the domain centre, with a uniform horizontal free-stream flowing past it — i.e. the rod's own reference frame as it translates horizontally (a von Karman-style obstacle / vortex street).
Source code: https://github.com/mannetroll/2DVonKarman
Screenshots
The dark PySide6 GUI:
The pure-ASCII terminal front-end:
Install
pip install mannetroll-vonkarman # from PyPI
This installs two console scripts, simulation and simulation_ascii.
Run
uv run simulation # the dark PySide6 GUI
uv run simulation_ascii # pure-ASCII vortex street in the terminal (no Qt)
# or, once installed:
simulation # the dark PySide6 GUI
simulation_ascii # pure-ASCII vortex street in the terminal (no Qt)
Run straight from PyPI without installing anything:
uv run --python 3.13 --with "mannetroll-vonkarman==0.1.0" simulation
uv run --python 3.13 --with "mannetroll-vonkarman==0.1.0" simulation_ascii
Run the GPU build (NVIDIA + CUDA only):
uv run --python 3.13 --with "mannetroll-vonkarman[cuda]==0.1.0" simulation
uv run --python 3.13 --with "mannetroll-vonkarman[cuda]==0.1.0" simulation_ascii
The ASCII front-end runs the same N=512 solver and draws the vorticity field
as a live 128×32 character grid (" .:-=+*#%@" brightness ramp, 256-color, the
rod marked o), with a small diagnostics header. Flags: --mono, --no-diff,
--cmap {Inferno,Ocean,Gray}, --backend {auto,cpu,gpu}, --nsteps,
--frames, and the usual --re/--vr/--nr/--cfl/--k0/--n.
Numerics
- Doubly-periodic domain
[0, 2*pi)^2, vorticity-streamfunction formulation. - Pure decaying Navier-Stokes (
Visc = 1/Re) — no forcing, no extra terms. - Pseudo-spectral nonlinear term with 3/2 zero-padding de-aliasing.
- LS-IMEX-RK3 time stepping: viscous term and uniform free-stream advection implicit (Crank-Nicolson per substage), fluctuation advection explicit, low storage.
- Centred rod via volume penalization (exact relaxation, operator-split);
solved in the rod frame with a uniform horizontal free-stream
(VR, 0). - All state is float32 / complex64; spectral operators (
i*k, the velocity projectori*k/|k|^2, the viscous symbolnu*|k|^2) are precomputed once. - CPU / GPU backend (technique from
cuda/turbo_simulator.py): the same code runs on the CPU viascipy.fft(multithreaded,workers=-1) or on an NVIDIA GPU via CuPy +cupyx.scipy.fft.
GPU (NVIDIA, e.g. RTX 3090)
The solver auto-detects CuPy and a CUDA device. On a GPU box install the extra:
uv sync --extra cuda # CUDA 13.x (cupy-cuda13x)
Then Auto uses the GPU (the Compute dropdown also offers explicit CPU /
GPU; the window title shows the active device). With no CUDA device present the
GPU option is greyed out and everything runs on the CPU.
Fast rendering
Each frame the selected field is normalized to a contiguous uint8 2D array,
that memory is wrapped directly in a QImage (Format_Indexed8), a 256-entry
color table is applied, and a QPixmap is built from it.
Controls
| Control | Values |
|---|---|
N |
512, 1024, 2048 spectral nodes (3/2 padding) |
Re |
default 10000 (Visc = 1/Re) |
CFL |
0.5 – 3.5 (default 2.5) |
K0 |
1 – 25, initial field peak wavenumber (default 1) |
NR |
2 – 100, rod radius R from 2*pi = NR * R (default 25) |
VR |
1 – 100, horizontal free-stream speed in 2*pi/sec (default 2) |
| Field | Vorticity, Energy, U-Velocity, V-Velocity, Stream function |
| Colors | Inferno, Gray, Ocean |
| Frame / n steps | 2, 5, 10, 20, 50 |
| Compute | Auto, CPU, GPU (GPU needs CuPy + a CUDA device) |
CFL, VR, field, colors and frame skip update live; N, Re, K0, NR
take effect on Restart.
Release files for mannetroll-vonkarman 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mannetroll_vonkarman-0.1.0.tar.gz | 721.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mannetroll_vonkarman-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 992.9 kB
Release files / mannetroll_vonkarman-0.1.0.tar.gz
| Download URL | mannetroll_vonkarman-0.1.0.tar.gz |
|---|---|
| Size | 721.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3ae4d9be5cf6bfecb750c1fe1ea12ae2a1dbb4675bf8825a80c37d3cbe1ed537
|
|
BLAKE2b-256 checksum How to use checksums |
2422a7a545b427f1041b21527d3daa62cab23c251e99dea94b092b36a5bee348
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.11
|
Release files / mannetroll_vonkarman-0.1.0-py3-none-any.whl
| Download URL | mannetroll_vonkarman-0.1.0-py3-none-any.whl |
|---|---|
| Size | 271.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
90260a0c1a1f58aefa633c3174f6c830201338ffb3adff69d99f78037b9d36bd
|
|
BLAKE2b-256 checksum How to use checksums |
8234cf5376f1397b06182db2ffa41d9fcfb122c007dfa02c25c0fed027a52b37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.11
|