Metadata-Version: 2.4
Name: mannetroll-cupystorm
Version: 0.1.2
Summary: 2D Turbulence (SciPy + CuPy)
Author: Torbjörn Sjögren
License: MIT License
        
        Copyright (c) 2026 mannetroll
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Requires-Python: <3.14,>=3.13
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=2.3.5
Requires-Dist: numba<1,>=0.63.1
Requires-Dist: pillow>=12.0.0
Requires-Dist: scipy>=1.16.3
Requires-Dist: PySide6>=6.6
Provides-Extra: cuda
Requires-Dist: cupy-cuda13x>=13.6.0; sys_platform != "darwin" and extra == "cuda"
Requires-Dist: fastrlock>=0.8; sys_platform != "darwin" and extra == "cuda"
Dynamic: license-file

# 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

![CuPy](https://raw.githubusercontent.com/mannetroll/cupystorm/v0.1.2/wekman.png)

## Rain (256 x 256) SciPy

![SciPy](https://raw.githubusercontent.com/mannetroll/cupystorm/v0.1.2/wrain.png)

## Circle (256 x 256) SciPy

![SciPy](https://raw.githubusercontent.com/mannetroll/cupystorm/v0.1.2/wcircle.png)

## Mouse (256 x 256) SciPy

![SciPy](https://raw.githubusercontent.com/mannetroll/cupystorm/v0.1.2/wmouse.png)


### 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

1. Check that the driver/CUDA are available:

       $ nvidia-smi

2. Install CuPy into the uv environment:

       $ uv sync --extra cuda
       $ uv run turbulence

3. Verify that CuPy sees the GPU:

       $ uv run python -c "import cupy as cp; x = cp.arange(5); print(x, x.device)"

4. 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

![CuPy](https://raw.githubusercontent.com/mannetroll/cupystorm/v0.1.2/window7776.png)

## 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
