# Round 3: FP16S and ddf_shifting compatibility Date: 2026-06-03 Duration: 8+ hours of code + testing ## Summary of work This round added and verified FP16S store precision and ddf_shifting mode compatibility across the body module, curved boundary, and diagnostics pipeline. ## Primary achievements ### 1. MRT shifting fix (critical) **Problem discovered:** D2Q9 MRT is NOT shift-invariant in moment space because M(w) produces non-zero entries in m[1] (energy) and m[2] (energy^2). Previous assumption that "f - feq cancels weights pairwise" only holds for SRT/TRT (per-direction collision), not for MRT (moment-space collision). **Fix applied:** When `USE_DDF_SHIFTING=1`, `collide_mrt` now: 1. Unshifts `g[i] += w[i]` at entry (physical space) 2. Performs full MRT collision in physical space 3. Reshifts `g[i] -= w[i]` at exit **Verified:** `MRT + ddf_shifting + zou_he_local` produces K2 results with `amp_CL` recovering from 0.007 to 0.476. **Note on D3Q19:** Has a `compute_feq` inconsistency (shifted feq applied to unshifted g) that needs fixing before D3Q19 shifting is usable. ### 2. ddf_shifting code fixes | Fix | File | Status | |-----|------|--------| | Inlet west_velocity_rho_closure +5/6 correction | `inlet/common.cuh` | Verified, both D2Q9 and D3Q19 | | Curved force/torque +2*w_i correction | `curved_boundary.cuh`, `aux_kernels.cu` | Verified | | Host upload_ddf() asymmetry (subtract weights before upload) | `field.py` | Verified | | Checkpoint streaming and ddf_shifting match check | `checkpoint.py` | Implemented | ### 3. Inlet knowns repair generalization (partial) The `repair_zou_he_west_knowns_d2q9` function was moved from Zou-He-only to all west inlet schemes in `inlet_outlet.cuh`. This fixes free-slip y-wall contamination of ghost-node populations. However, this alone was insufficient to fix the regularized+shifting issue. ### 4. EsoPull curved boundary (from Round 2, documented here for posterity) Verified against Kan99b K2: **bit-identical metrics** between double_buffer and esopull streaming. Key architectural decisions: - `streaming/esopull_semantic_helpers.cuh` -- single source of truth for physical-value semantics - `MacroscopicEsoPullKernel` -- GPU-side diagnostics (not host raw decode) - `Prepare + Apply` two-phase curved boundary ## Current compatibility matrix ### Verified (passes K2/Sah04 benchmarks) | Config | Details | |--------|---------| | FP32 + MRT + double_buffer | Full validation (all Kan99b, Sah04) | | FP32 + MRT + esopull | K2 bit-identical to double_buffer | | FP16S + MRT + double_buffer | Sah04 S2 passes | | ddf_shifting + MRT + zou_he_local | K2 amp_CL recovered, full validation pending | ### Known limitations | Issue | Severity | Status | |-------|----------|--------| | FP16S K2 St deviation (0.170 vs 0.142) | Medium -- quantization noise in curved region | Documented, acceptable for low-Re research | | FP16S S4 divergence at step 71420 | Medium -- high-blockage quantization + wall-gap | Use FP32 for high-blockage | | ddf_shifting + regularized inlet + MRT | High -- suppressed shedding even after inlet repair | Regularized in shifting needs root cause. Use zou_he_local for now. | | D3Q19 MRT shifting patch incomplete | Medium -- shifted feq applied to unshifted g | Not in 2D scope, TODO noted in code | | ddf_shifting + esopull combined | Not verified | Both paths validated separately but not together | ## Key lessons recorded 1. **SRT/TRT are shift-invariant; MRT is NOT.** The weight vector w has non-zero moment space projection. Always shift/unshift around MRT. 2. **Repair_zou_he_west_knowns is NOT Zou-He-specific.** Every west inlet scheme using `west_velocity_rho_closure_d2q9()` needs it under free-slip y-walls. 3. **FP16S failure modes are specific:** Low-blockage (S2) is fine; rotating cylinder (K2) shows quantization sensitivity; high-blockage (S4) can diverge. Test all three regimes before claiming FP16S works. 4. **`compute_feq` in shifting mode returns `feq - w`, not `feq`.** This is correct for SRT/TRT (NEQ terms cancel w), but causes a bias when paired with an unshifted `g` (D3Q19 MRT case). 5. **Host DDF path is not symmetric under shifting.** `download_ddf()` adds back w; `upload_ddf()` (before fix) did not subtract w. This breaks host-side initialization, snapshot/restore, and add_vortex under shifting.