Technology

A CUDA solver written to run at the hardware limit.

QuanFlow is a lattice Boltzmann solver written in plain CUDA C++. Its speed comes from memory layout and kernel design, not from more expensive hardware. Below is what exists, with measured numbers and where its limits are today.

~9,000MLUPs/s on one RTX 5070 Ti (FP16)
99.8 %of the measured memory bandwidth used
680 Mcells fit across 3 GPUs (one GPU holds ~290 M)
0 bitdifference between 3-GPU and 1-GPU runs in tests
Speed

Store less, move less.

Lattice Boltzmann is limited by memory bandwidth, so every optimisation aims to cut the bytes read and written per step.

In-place streaming (Esoteric Pull)

Only one copy of the distribution functions is kept, read and written in the same cell. The kernel is measured at 99.8% of the card's measured memory bandwidth.

FP16 storage (FP16S, FP16C)

Distributions are stored in 16 bits while arithmetic stays 32-bit. This halves memory and traffic, so the grid can be about twice as large on the same card. Limit: for low-viscosity channel flow FP16 shows larger errors, so each case type is checked before FP16 is used.

STL voxelisation on the GPU

STL geometry becomes solid cells directly on the GPU, with no meshing step. Moving bodies are re-voxelised every few steps.

Two-level adaptive refinement

A fine box around the body, coarse far away. On the Re 100 square cylinder: under 0.3% from the uniform fine grid with 24% of the cells, 5.4× faster.

One card, hundreds of millions of cells

With FP16 a 16 GB RTX 5070 Ti holds about 290 million cells; the 253-million-cell cyclist case uses 13.2 GB.

Live view in the browser

One flag opens a live view of speed and streamlines while the run is going, and closes itself when the page is closed.

Multi-GPU

Pool the memory of several GPUs for larger grids.

The domain is cut into slabs along x, one per GPU. Because streaming is in place and each cell touches only neighbouring columns, only 5 of the 19 distributions cross the interface each step, so the exchange is small. Slab widths follow each card's memory, so mixed cards can be combined.

  • Bit-identical to a single GPU (density, velocity, body force) on 1, 2 and 3 GPUs, including 3 real machines
  • 680 million cells fit on one RTX 5070 Ti plus two RTX 3060, about 2.3× the largest grid of one card
  • Network tuned to 110 MB/s per direction on 1 GbE

Where it stands today

The multi-GPU build uses CUDA for compute and MPI for boundary exchange, and runs across machines. Over three machines on 1 GbE it reaches 2,700–3,200 MLUPs/s with about 90% of each step spent exchanging, below one GPU on its own (~8,800). Its purpose today is to run grids larger than one card's memory, not to run faster. Exchange is not yet overlapped with compute, and this build does not yet support free surface, curved walls or the wall function.

Next step: several GPUs inside one machine over P2P/NVLink, with exchange overlapped with compute for a real speed-up.

Physics and boundaries

What is inside the model.

Collision and turbulence

SRT, TRT and regularised collision, with Smagorinsky LES. The LES constant is checked against an analytical channel solution with eddy viscosity (difference 4.7×10⁻⁴).

Curved walls without staircasing

Interpolated bounce-back (Bouzidi) with exact wall distance taken from the STL. Tests: second-order convergence on off-grid walls and force balance of 0.99994.

Mass conservation at walls

Interpolated bounce-back leaks mass; we correct it in place. Mass error after 20,000 steps falls to 1.9×10⁻⁸ from 3×10⁻⁴. This fix is our own and has not yet been compared with published mass-conserving schemes.

Wall function

A wall function is implemented in the curved-wall solver and runs. On the Ahmed body it does not yet bring drag to the experimental value, so we do not use it for client work; validation continues.

Free surface

VOF-style free surface with mass conservation (4×10⁻⁸ in FP32), surface tension by height functions, compared with two dam-break experiments.

Moving bodies

Prescribed motion from a table (pedalling legs, flapping wings, rotors), re-voxelised every step, forces by momentum exchange.

How we check it

Every optimisation is checked bit-for-bit or against a benchmark.

Bit-for-bit tests

When a change must not alter results (memory layout, kernel split, domain split) a test compares every bit with the previous version.

Published benchmarks

Every new physics model passes the cases on the Validation page before client use.

Errors are logged too

Cross-checking against other solvers exposed and fixed a force-calculation error on bodies touching the floor. A log of known weak spots is kept.

Got a problem that needs simulation at scale?

Send a short description. Free feasibility review within 24 hours, no obligation.