Three levels: nested body-free child patch on a single chain

FixedPatchStepper(..., child=(x0,y0,x1,y1), child_block=(by,bx)) adds an L2
patch in L1 window cells (requires fine_block/base_block, one L1 patch, no
bodies/jets). nest_patch() builds the L1->L2 FixedPatch2D (2*nu on L1) and
the composed L1 kind (inherited INNER/OUTER kept, child-covered ACTIVE made
OUTER), rejecting from the actual tables: coverage outside ACTIVE, donors or
receivers not uncovered ACTIVE, surviving ACTIVE pulls of covered/OUTER cells
without a child-supplied arrival, and overlap with L1's restriction footprint.

Step order per L1 hop: explode L1(src)->L2, two L2 hops (halo, step), L1 halo,
receiver-local L2->L1 staging into src, L1 step. The second hop thus feeds L2
from the new L1 G; L2 is never refilled from L0; L0 stays once per step (1:2:4).
Existing kernels only; a small _Pair holds the child transfer bindings (explode
from the child module, parent window stride). Two-level API unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-16 14:35:57 +00:00
1 parent 6301887093
commit 76555de4b8
4 files changed
+264 -21

No files matched your search

+27
View File
@@ -233,5 +233,32 @@ class FixedPatchSetTests(unittest.TestCase):
self.build(self.FACE).fine_layout(block)
class NestPatchTests(unittest.TestCase):
"""Three-level single chain: L2 bounds in L1 window cells (probe fixture)."""
def setUp(self):
self.cfg = config()
self.l1 = FixedPatch2D.from_config(self.cfg, (4, 4, 12, 12)) # 24x24 window
def test_probe_fixture_composes_kinds(self):
child, kind = refinement.nest_patch(self.cfg, self.l1, (8, 8, 16, 16))
self.assertEqual(child.fine_shape, (24, 24))
self.assertAlmostEqual(child.tau_coarse, self.l1.tau_fine)
base = self.l1.fine_kind
for role in (INNER_GHOST, OUTER_GHOST):
np.testing.assert_array_equal(kind[base == role], role)
self.assertTrue((kind[child.covered] == OUTER_GHOST).all())
self.assertEqual(int((kind == ACTIVE).sum()), 192)
self.assertEqual(int((kind == INNER_GHOST).sum()), 144)
self.assertEqual(int(child.covered.sum()), 64)
def test_invalid_nesting_rejected(self):
for bounds in ((2, 8, 16, 16), # covers inherited INNER
(4, 8, 16, 16), # explosion donors in INNER
(8, 8, 20, 16), # donors reach OUTER/INNER at the far side
(5, 8, 16, 16)): # one-cell outward: restriction footprint/donors
with self.subTest(bounds=bounds), self.assertRaises(ValueError):
refinement.nest_patch(self.cfg, self.l1, bounds)
if __name__ == "__main__":
unittest.main(verbosity=2)