Repository navigation
feat(solver): add body forcing and linear drag inputs to the ns-grid solvers - #267
Closed
dionhaefner wants to merge 7 commits into
Closed
dionhaefner wants to merge 7 commits into
dionhaefner wants to merge 7 commits into
Conversation
This was referenced Oct 26, 2026
Open
# Conflicts: # mosaic/tesseracts/navier-stokes-grid/xlb/tesseract_api.py
1 of 6 tasks
… the RK4 momentum Resolution as in #310.
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relevant issue or PR
#268 (Exponax in 2D ns-grid) builds on this. The Kolmogorov-flow checks in #272 are the first experiments to use the new inputs.
Description of changes
Adds two optional inputs to the canonical ns-grid schema:
forcing: a constant body force per unit mass at the cell centers, with the same shape asv0;linear_drag: the coefficient α of a drag term −αu.Both are allowed only on 2-D periodic boxes; the canonical schema rejects them with an obstacle, non-periodic BCs, in 3-D, or when the force's shape does not match
v0. Neither is differentiable. With both left atNone, every solver runs exactly the code it ran before.Each solver applies the force and the drag inside its own time step, in both apply and VJP. The force reaches each solver's native locations through the same map it uses for
v0.semi_implicit_navier_stokes, averaged onto the facesv0, part of the momentum rate ofincompressible_rk4tentative_vel_2d_kerneldragSolver changes beyond the new inputs:
injection_mode/injection_scalewould put sin(κy) half a cell off, a 20% error at 64² in the laminar test. Feeding the force's own curl as the injection term is exact for any force, so the tesseract does that instead of mapping to the single-mode inputs.Testing done
tests/test_schemas.py: the new inputs are rejected outside 2-D periodic boxes and accepted inside.tests/test_ns_grid_forcing.py(Docker, skipped without images), for every solver image:All pass on images built from this branch, and OpenFOAM's rejection is tested. Measured laminar errors at dt = 0.002:
PICT passes the 64² test (dt = 0.01).
After the latest merge with
main, where INS.jl runs on its CUDA backend (perf(solver): run INS.jl on its CUDA backend #307), the forcing tests pass on freshly built INS.jl and XLB images.No regression (A/B, 2026-10-26, before refactor(solver): use PhiFlow's documented schemes for the periodic box and the channel #288 and perf(solver): run INS.jl on its CUDA backend #307 changed PhiFlow and INS.jl on
main). Images frommainand from this branch ran the same unforced cases: multimode at N = 32, TGV at N = 16, and 3D TGV at N = 16. Each case compared the forward result and the VJP with respect tov0andviscosity.mainagainst itself in a fresh container.No benchmark label: the A/B comparison above covers the unforced paths. Whether a CI benchmark pass is worth its cost is the maintainer's call.