Generalize synchronized remap to multiple pinned body rectangles

This commit is contained in:
2026-10-16 11:32:42 -07:00
parent 864a220dbe
commit 60ad6b8b0d
6 changed files with 375 additions and 32 deletions
+21 -11
View File
@@ -113,22 +113,24 @@ Per-population conservation is not an advancement target under collision.
### Bounded pinned-body extension
`replacement = current.remap_child(rectangles, child_objects=original_objects)`
now also accepts exactly one stationary Circle in one of exactly two L2
rectangles. Its **complete containing rectangle must remain identical**;
only the separated fluid rectangle may change. Existing nesting, four-cell
gap, full-circle containment, reverse cut-link coverage and two-hop BFL
also accepts stationary Circles in separated L2 rectangles. Every body’s
**complete containing rectangle must remain identical**. Several bodies may
share one pinned rectangle; there need not be any fluid-only rectangles.
Separated fluid-only rectangles may be added, removed or moved. Existing
nesting, four-cell gap, full-circle containment, reverse cut-link coverage and two-hop BFL
transfer-footprint checks still apply. This is manual remapping, not adaptive
body tracking or runtime body editing.
Supply the original root edge-frame definition used at construction. Do not
pass `current.child_boundary.objects`: those are projected fine-local copies.
Supply all original root edge-frame definitions in their construction order.
Do not pass `current.child_boundary.objects`: those are projected fine-local copies.
There is no retained mutable original-object registry. Before reading device
state, remapping reprojects the supplied definition onto the old topology and
compares flags, physical cut links, body IDs, q, lever arms, hits, BFL support,
compares exact ordered circle centers/radii, flags, physical cut links, body
IDs, q, lever arms, hits, BFL support,
legacy SurfaceActuation specification and current per-link velocity against
the existing boundary. Omission, changed geometry/actuation and changed body
rectangle fail without device reads or allocations. Root object IDs are still
assigned by list position, as in the constructor.
rectangle fail without device reads or allocations; reordered bodies fail
too. Root object IDs are still assigned by list position, as in the constructor.
Jets are taken from the live L2 boundary, including the most recent successful
`set_jet_amplitude(..., level=2)`. There is no replacement-Jets argument or
@@ -139,12 +141,20 @@ boundary and velocities must match exactly.
typed `FineBoundary2D`; it derives L2 fluid leaves as ACTIVE minus SOLID. No
caller mask is accepted. Solids, ghosts and holes are never donors and remain
NaN, physical-fluid overlap is exact, and exposed L1 still restricts all four
old fluid children. The helper checks the old/new body pin and boundary too.
old fluid children. The helper checks the old/new body pins and boundary too.
Its immutable `pinned_rectangles` is a canonical, deduplicated tuple, empty for body-free layouts; rectangle input
order does not affect it. Scalar-parent window offsets remain part of the
coordinate conversion.
Focused CPU mocks: `tests/unit/test_pinned_body_remap.py`. GPU declarations:
`tests/validation/multigrid/test_pinned_body_remap_gpu.py`, covering no-op
next-step bitwise identity, moved-fluid A→B→A, current-amplitude preservation,
physical boundary/velocity equality, source independence and absolute counts.
These GPU cases have **not been run here**. They do not establish evolution
Multiple-body CPU coverage: `tests/unit/test_multiple_pinned_remap.py`.
`tests/validation/multigrid/test_multiple_pinned_remap_gpu.py` adds two pins,
two independently updated Jets, variable fluid-region counts and add/move/remove
immediate comparisons with CPU transfer. All nine solid-excluded area-weighted
population integrals, exact overlap and nonleaf NaNs are checked.
These new GPU cases have **not been run here**. They do not establish evolution
accuracy. A 3e-6 FP32-vs-FP64 evolution gate requires a separate independent
BFL reference; the body-free replay gate above does not establish that claim.