lbm-gpu: the lattice Boltzmann step on the GPU, checked against the CPU

A new L7 crate: the CPU scheme's collision (TRT with Guo forcing), the
per-link streaming rules (bounce-back with Ladd's term, slip reflection,
open placeholders), the Zou–He boundaries and the momentum exchange per
force group as wgpu compute shaders, stepping the flow fieldcraft_lbm's
Flow prepared, through its Backend trait: populations stay on the device,
a chunk of steps is one submission, and only frames, forces and the
stability check come back. Populations are stored as deviations from
their weights, which keeps single precision honest: the verification
cases (Poiseuille with Λ = 3/16, Couette with wall forces, Taylor–Green,
a sphere's drag, a Zou–He channel) agree with the CPU to 2–5e-6 in
velocity, 1e-6 in density and 5e-5 in force, with those tolerances stated
in the tests. The rules are applied one thread per link rather than in a
per-cell loop, which lavapipe's JIT miscompiles (and which diverges on
real GPUs anyway). Native only for now; the browser registers nothing.

Part of #529.
This commit is contained in:
Christian Svensson authored and Irakli Kourtis committed 2026-10-17 07:23:40 -04:00
1 parent 944a54c76b
commit b123f31d47
10 files changed
+1270

No files matched your search

+26
View File
@@ -0,0 +1,26 @@
//! The lattice Boltzmann solver on the GPU: [`GpuFlow`] steps a flow that
//! [`fieldcraft_lbm::Flow`] prepared (grid, links, open cells, initial state) with the compute
//! shaders of `lbm.wgsl`, which are the CPU scheme's collision, streaming rules, open boundaries
//! and momentum exchange written for the device; `fieldcraft_lbm::run` drives it through the
//! [`Backend`] trait in chunks of steps, so populations stay on the device and only frames,
//! force histories and the stability check come back.
//!
//! Single precision: the CPU scheme is the reference, and this backend is deterministic on its
//! device and agrees with it within the tolerances its tests state (`tests/verification.rs`).
//! The device is the one `fieldcraft_gpu`'s adapter policy picks (`FIELDCRAFT_GPU`).
//!
//! Sources: the same as `fieldcraft_lbm` (Krüger et al. 2017; Ginzburg et al. 2008; Guo et al.
//! 2002; Ladd 1994; Mei et al. 2002; Zou & He 1997; Hecht & Harting 2010). No code of any
//! lattice Boltzmann package was read.
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
#![forbid(unsafe_code)]
#[cfg(not(target_arch = "wasm32"))]
mod native;
#[cfg(not(target_arch = "wasm32"))]
pub use native::{GpuFlow, register};
/// In the browser there is no device backend yet (WebGPU later): registering is a no-op and
/// `solve.fluid` with `backend: "gpu"` reports that none is available.
#[cfg(target_arch = "wasm32")]
pub fn register() {}