Multipatch: fine_objects and jets on several patches (level-wide projection)

prepare_fine_boundary accepts a FixedPatchSet2D: objects are projected once
onto the level-wide fine grid (FixedPatchSet2D.fine_origin = (0, 0), same
coarse cell-edge -> fine cell transform), each circle must lie inside one
patch, coarse transfer cells are checked against the covered union, and body
ids stay object positions, so the existing jet one-body-per-jet, overlap and
(receiver, dir) writer checks run once over the whole level (caller obj_id
cannot bypass them). The stepper no longer rejects fine_objects/jets with
several patches; blocked link tables, BFL and the jet amplitude cache are
reused unchanged. No kernel change. README/docstring scope updated.

Tests: CPU translation/ids/rejections (outside one patch, one jet over two
bodies at zero amplitude); GPU one body via the new path == single-patch path
(both modes), two bodies (+jets, amplitude switch) == tiled single (bitwise).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-16 14:59:48 +00:00
1 parent f1dcf329ff
commit 64665319a4
5 files changed
+152 -10

No files matched your search

+6 -3
View File
@@ -135,13 +135,16 @@ Scope and limits:
divide the WHOLE fine allocation, i.e. `2*(y1-y0)+8` by `2*(x1-x0)+8` including the
four-cell ghost band. It gives results identical to dense storage and is
infrastructure for future block AMR, not a speedup.
- Several separated patches (body-free): pass a sequence of `(x0, y0, x1, y1)`
- Several separated patches: pass a sequence of `(x0, y0, x1, y1)`
rectangles as `bounds`, at least 4 coarse cells apart, with both `fine_block`
and `base_block`. The fine level is then one level-wide grid `(2*ny, 2*nx)`:
`run.patch.fine_shape` gives it, `initialize`/`download` use it, and only the
patch windows (active region plus 4-cell ghost band, origin `(2*y0-4, 2*x0-4)`)
are stored; each window must align with `fine_block`. Order of rectangles does
not matter. No bodies/Jets, wall-touching patches or nesting yet.
not matter. `fine_objects`/`jets` work as for one patch: each circle (same
coarse cell-edge frame) must lie wholly inside one patch's active region with
its boundary stencil clear of transfer cells; a jet may not select links of two
different bodies, even across patches. No wall-touching patches or nesting yet.
```python
cfg = LBMConfig(nx=32, ny=16, viscosity=.1)
@@ -175,7 +178,7 @@ Scope and limits:
coarse_g, l1_g, l2_g = run.download()
```
- Not available: per-link surface exchange/force readout in blocked mode,
checkpoints, moving bodies, bodies/Jets with several patches or three levels,
checkpoints, moving bodies, bodies/Jets with three levels,
several patches per level with nesting, dynamic refinement, `Simulation`
integration. Validation so far is storage/operator equivalence and short runs,
not accuracy, convergence or long-time stability.