2D Turbulence Simulation (SciPy / CuPy)
Source code: https://github.com/mannetroll/cupystorm
A Direct Numerical Simulation (DNS) code for 2D homogeneous incompressible turbulence
It supports:
- SciPy / NumPy for CPU runs
- CuPy (optional) for GPU acceleration on CUDA devices (e.g. RTX 3090)
one-liner CPU/SciPy
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ uv cache clean mannetroll-cupystorm
$ uv run --python 3.13 --with "mannetroll-cupystorm==0.1.2" turbulence
one-liner GPU/CuPy
$ uv run --python 3.13 --with "mannetroll-cupystorm[cuda]==0.1.2" turbulence
DNS solver
The solver includes:
- PAO-style random-field initialization
- 3/2 de-aliasing in spectral space
- Crank–Nicolson time integration
- CFL-based adaptive time stepping (Δt updated from the current flow state)
cupystorm GUI (PySide6)
Run an cupystorm window that:
- Displays the flow field as a live image (fast Indexed8 palette rendering)
- Lets you switch displayed variable:
- U, V (velocity components)
- K (kinetic energy)
- Ω (vorticity)
- φ (stream function)
- Lets you switch colormap (several built-in palettes)
- Lets you change simulation parameters on the fly:
- Grid size N
- Reynolds number Re
- Initial spectrum peak K0
- CFL number CFL
- Max steps / auto-reset limit
- GUI update interval (how often to refresh the display)
- Includes force/initialization modes:
- Navier-Stokes: PAO spectrum init
- High-k + Ekman/Rayleigh: High-k spectral forcing + Ekman/Rayleigh large-scale drag
- Rain: random “kick” forcing events
- Circle: a forcing point moves on a circular trajectory (continuous forcing)
- Mouse: apply forcing by click/drag in the image
Keyboard shortcuts
Single-key shortcuts (application-wide) for fast control:
- V: cycle variable
- C: cycle colormap
- N: cycle grid size
- R: cycle Reynolds number
- K: cycle K0
- L: cycle CFL
- S: cycle max steps
- U: cycle update interval
Saving / exporting
From the GUI you can:
- Save the current frame as a PNG image
- Dump full-resolution fields to a folder as PGM images:
- u-velocity, v-velocity, kinetic energy, vorticity
Display scaling
To keep the GUI responsive for large grids, the displayed image is automatically upscaled/downscaled depending on N. The window is resized accordingly when you change N.
Installation
Using uv
From the project root:
uv sync
uv run turbulence
High-k spectral forcing + Ekman/Rayleigh large-scale drag
The flow remains fully turbulent after 1,000,000 iterations (256 x 256) CuPy
Rain (256 x 256) SciPy
Circle (256 x 256) SciPy
Mouse (256 x 256) SciPy
Full CLI
$ python -m cupystorm.turbo_simulator N Re K0 STEPS CFL BACKEND [MODE]
Where:
- N — grid size
- Re — Reynolds number
- K0 — peak wavenumber of the energy spectrum
- STEPS — number of time steps
- CFL — target CFL number
- BACKEND — "cpu", "gpu", or "auto"
- MODE — "pao" | "highh" | "rain" | "circle" | "mouse"
Examples:
# CPU run (SciPy with 4 workers)
$ python -m cupystorm.turbo_simulator 256 10000 10 1001 0.75 cpu
# Auto-select backend (GPU if CuPy + CUDA are available)
$ python -m cupystorm.turbo_simulator 256 10000 10 1001 0.75 auto
Enabling GPU with CuPy (CUDA 13)
On a CUDA machine (e.g. RTX 5090):
Download: https://developer.nvidia.com/cuda-downloads
-
Check that the driver/CUDA are available:
$ nvidia-smi -
Install CuPy into the uv environment:
$ uv sync --extra cuda $ uv run turbulence -
Verify that CuPy sees the GPU:
$ uv run python -c "import cupy as cp; x = cp.arange(5); print(x, x.device)" -
Run in GPU mode:
$ uv run python -m cupystorm.turbo_simulator 256 10000 10 1001 0.75 gpu
Or let the backend auto-detect:
$ uv run python -m cupystorm.turbo_simulator 256 10000 10 1001 0.75 auto
The DNS with CuPy (7776 x 7776) Navier-Stokes
Profiling
cProfile (CPU)
$ python -m cProfile -o turbo_simulator.prof -m cupystorm.turbo_simulator
Inspect the results:
$ python -m pstats turbo_simulator.prof
# inside pstats:
turbo_simulator.prof% sort time
turbo_simulator.prof% stats 20
GUI profiling with SnakeViz
Install SnakeViz:
$ uv pip install snakeviz
Visualize the profile:
$ snakeviz turbo_simulator.prof
Memory & CPU profiling with Scalene (GUI)
Install Scalene:
$ uv pip install "scalene==1.5.55"
Run with a GUI report:
$ scalene -m cupystorm.turbo_simulator 256 10000 10 201 0.75 cpu
Memory & CPU profiling with Scalene (CLI only)
For a terminal-only summary:
$ scalene --cli --cpu -m cupystorm.turbo_simulator 256 10000 10 201 0.75 cpu
License
Copyright © 2026 Mannetroll
Release files for mannetroll-cupystorm 0.1.2
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_cupystorm-0.1.2.tar.gz | 163.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mannetroll_cupystorm-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 324.9 kB
Release files / mannetroll_cupystorm-0.1.2.tar.gz
| Download URL | mannetroll_cupystorm-0.1.2.tar.gz |
|---|---|
| Size | 163.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
edd4725071a3cd50092165cd19ea88a5374085d465a15863f9eee2407681e4bd
|
|
BLAKE2b-256 checksum How to use checksums |
82b49dfa27b89620ee13a426af0b557369a75acd708a248dbc0958480f968d97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.11
|
Release files / mannetroll_cupystorm-0.1.2-py3-none-any.whl
| Download URL | mannetroll_cupystorm-0.1.2-py3-none-any.whl |
|---|---|
| Size | 161.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e722f9b169e6c80e06e5ee803fdd0a4827afc1ed13da52681fa2e01132a8289e
|
|
BLAKE2b-256 checksum How to use checksums |
27e246b56a373d8afba147cb3c927a5a7a738c2b4fd736f8c7ba8586da338285
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.11
|