test: adopt native-validated 24-target probe layout
Horizontal y=56 and vertical x=38 through box 1, normal coordinates [12.5..26.125] (root128 physical). Nearest-ACTIVE mapping with deterministic tie rule (distance, finer level, smaller j, smaller i), duplicate-cell rejection, stored centers and displacements. Replaces my earlier offsets, which mapped two target pairs to the same U128 cell. U512 spacing 128/512 and root step r -> U512 step 4r unchanged. Tests: 24 unique cells per case, nested 3 L0 + 5 L1 + 4 L2 per transect, U128 max displacement 0.625. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1e188e7419
commit
caa573f978
4 files changed
+63
-42
No files matched your search
@@ -421,12 +421,18 @@ Labels:
|
|||||||
|
|
||||||
### Signed interface-probe traces (opt-in `--probe-trace`, mechanism diagnostic)
|
### Signed interface-probe traces (opt-in `--probe-trace`, mechanism diagnostic)
|
||||||
|
|
||||||
`shear_probes.py` (pinned) defines 24 fixed points on two interface-normal
|
`shear_probes.py` (pinned) uses native's validated 24-target layout through
|
||||||
transects, all at least 8 root cells from any box corner:
|
box 1, in root-128 physical coordinates:
|
||||||
- V: y = 64.1, crossing the vertical faces x = 16 (L0/L1) and x = 22 (L1/L2);
|
- a horizontal line y = 56, crossing the vertical faces x = 16 and 22;
|
||||||
- H: x = 90.1, crossing the horizontal faces y = 24 and y = 30;
|
- a vertical line x = 38, crossing the horizontal faces y = 16 and 22;
|
||||||
- offsets from the outer face: −3.9, −1.9, −0.4, 0.1, 0.6, 2.1, 4.1, 5.6, 6.1,
|
- normal coordinates 12.5, 14.5, 15.5, 16.25, 17.25, 19.25, 20.75, 21.75,
|
||||||
6.6, 8.1, 10.1.
|
22.125, 23.125, 24.125, 26.125.
|
||||||
|
|
||||||
|
Each target maps to the nearest ACTIVE leaf center. The deterministic tie
|
||||||
|
rule is: distance, then finer level, then smaller j, then smaller i. This
|
||||||
|
gives 24 unique cells in every case, and nested has 3 L0 + 5 L1 + 4 L2 per
|
||||||
|
transect. Maximum displacement from target to center is 0.625 root cells in
|
||||||
|
U128 (0.177 in U512).
|
||||||
|
|
||||||
Allowed cases:
|
Allowed cases:
|
||||||
- nested U128, nested U512, nested projected depth 3;
|
- nested U128, nested U512, nested projected depth 3;
|
||||||
@@ -435,9 +441,8 @@ Allowed cases:
|
|||||||
The option can't be combined with `--final-snapshot`.
|
The option can't be combined with `--final-snapshot`.
|
||||||
|
|
||||||
Sampling:
|
Sampling:
|
||||||
- Each point is read from the ACTIVE leaf cell containing it. The receipt
|
- The receipt stores each probe's leaf level, `i`/`j`, actual cell center
|
||||||
stores the leaf level, `i`/`j`, and the actual cell center, all in
|
and displacement from its target, all in root-physical units (N=128).
|
||||||
root-physical units (N=128).
|
|
||||||
- Grids differ between cases, so centers are *not* collocated. Analytic
|
- Grids differ between cases, so centers are *not* collocated. Analytic
|
||||||
fields are evaluated at each actual center (`shear_probes.residuals`), and
|
fields are evaluated at each actual center (`shear_probes.residuals`), and
|
||||||
comparisons across cases are between residuals at nearby but distinct
|
comparisons across cases are between residuals at nearby but distinct
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ NESTED_SHEAR = "nested_shear_n128" # fixed three-level/two-region shear preset
|
|||||||
SHEAR_NESTED_SHA256 = "fa6cfe87fb4df8c6d732c637c885276833c81973b950c7724d734f8fc350bcb0"
|
SHEAR_NESTED_SHA256 = "fa6cfe87fb4df8c6d732c637c885276833c81973b950c7724d734f8fc350bcb0"
|
||||||
TWIN_SHEAR = "twin_shear_n128" # depth-2 twin: nested L0->L1 boxes without L2
|
TWIN_SHEAR = "twin_shear_n128" # depth-2 twin: nested L0->L1 boxes without L2
|
||||||
SHEAR_TWIN_SHA256 = "1cbf37f18e89aea577581631c4565f51e68d22a3739b698816ef64acbf2b2bb4"
|
SHEAR_TWIN_SHA256 = "1cbf37f18e89aea577581631c4565f51e68d22a3739b698816ef64acbf2b2bb4"
|
||||||
SHEAR_PROBES_SHA256 = "98ea8090ace48f04b83dfb015db10e681e414e57eb748b34c0fbb90fb790d13b" # signed interface-probe mechanism diagnostic
|
SHEAR_PROBES_SHA256 = "53ba8af8ac9c8078c40f84488c7ade4c11ccc91dd1fc275ff806042e9af30166" # signed interface-probe mechanism diagnostic
|
||||||
|
|
||||||
|
|
||||||
def flow_functions(flow="taylor_green"):
|
def flow_functions(flow="taylor_green"):
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
"""Signed interface-probe traces for the nested/twin shear presets (mechanism diagnostic).
|
"""Signed interface-probe traces for the nested/twin shear presets (mechanism diagnostic).
|
||||||
|
|
||||||
No pass gates. 24 fixed physical points on two interface-normal transects, away
|
No pass gates. Native-validated 24-target layout through box 1, in root-128
|
||||||
from corners, crossing L0->L1 and (nested only) L1->L2:
|
physical coordinates, crossing L0->L1 and (nested only) L1->L2 away from corners:
|
||||||
V: y = 64.1, across the vertical faces x = 16 (L0/L1) and x = 22 (L1/L2) of box 1;
|
horizontal line y = 56 across the vertical faces x = 16 and x = 22;
|
||||||
H: x = 90.1, across the horizontal faces y = 24 (L0/L1) and y = 30 (L1/L2) of box 2.
|
vertical line x = 38 across the horizontal faces y = 16 and y = 22;
|
||||||
Each point is sampled at the ACTIVE leaf cell containing it, so cases with
|
normal coordinates NORMAL_COORDS on both (nested: 3 L0 + 5 L1 + 4 L2 each).
|
||||||
different grids (U128, U512, nested, twin) give different cell centers: the
|
Each target maps to the nearest ACTIVE leaf center (tie rule: distance, then
|
||||||
actual center and level are stored and analytic fields are evaluated there.
|
finer level, then smaller j, then smaller i). Grids differ between cases
|
||||||
|
(U128, U512, nested, twin), so actual centers, levels and displacements are
|
||||||
|
stored and analytic fields are evaluated at the actual centers.
|
||||||
Samples are POST-collision G at root synchronization only (root-step units);
|
Samples are POST-collision G at root synchronization only (root-step units);
|
||||||
no substep content is observed, and grid-scale alternation can alias.
|
no substep content is observed, and grid-scale alternation can alias.
|
||||||
"""
|
"""
|
||||||
@@ -19,9 +21,10 @@ import shear_wave as sw
|
|||||||
from oracle import CX, CY, U
|
from oracle import CX, CY, U
|
||||||
|
|
||||||
ROOT_N = 128
|
ROOT_N = 128
|
||||||
OFFSETS = (-3.9, -1.9, -0.4, 0.1, 0.6, 2.1, 4.1, 5.6, 6.1, 6.6, 8.1, 10.1) # from outer face
|
NORMAL_COORDS = (12.5, 14.5, 15.5, 16.25, 17.25, 19.25, 20.75, 21.75,
|
||||||
TRANSECTS = {"V": dict(axis=0, face=16.0, other=64.1), # x varies, y fixed
|
22.125, 23.125, 24.125, 26.125)
|
||||||
"H": dict(axis=1, face=24.0, other=90.1)} # y varies, x fixed
|
TRANSECTS = {"horizontal_y56": dict(axis=0, other=56.0), # x varies, y fixed
|
||||||
|
"vertical_x38": dict(axis=1, other=38.0)} # y varies, x fixed
|
||||||
STEPS = tuple(range(0, 129)) + tuple(range(1920, 2049)) # root steps, both inclusive
|
STEPS = tuple(range(0, 129)) + tuple(range(1920, 2049)) # root steps, both inclusive
|
||||||
TRACE_MAX_BYTES = 600_000
|
TRACE_MAX_BYTES = 600_000
|
||||||
|
|
||||||
@@ -29,10 +32,9 @@ TRACE_MAX_BYTES = 600_000
|
|||||||
def points():
|
def points():
|
||||||
out = []
|
out = []
|
||||||
for name, t in TRANSECTS.items():
|
for name, t in TRANSECTS.items():
|
||||||
for offset in OFFSETS:
|
for along in NORMAL_COORDS:
|
||||||
along = t["face"] + offset
|
|
||||||
xy = (along, t["other"]) if t["axis"] == 0 else (t["other"], along)
|
xy = (along, t["other"]) if t["axis"] == 0 else (t["other"], along)
|
||||||
out.append((name, offset, xy))
|
out.append((name, along, xy))
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -42,25 +44,33 @@ def case_steps(n):
|
|||||||
|
|
||||||
|
|
||||||
def select(masks, n=ROOT_N):
|
def select(masks, n=ROOT_N):
|
||||||
"""Leaf cell containing each point: finest level whose ACTIVE mask covers it.
|
"""Nearest ACTIVE leaf center for each target (deterministic tie rule).
|
||||||
|
|
||||||
Points and stored centers are in root-physical units (root cell = 1); a case
|
Targets and stored centers are in root-physical units (root cell = 1); a case
|
||||||
with root N = n has cells of size ROOT_N / (n * 2**level) there.
|
with root N = n has cell size h = ROOT_N / (n * 2**level) there (U512: 0.25).
|
||||||
"""
|
"""
|
||||||
if n % ROOT_N:
|
if n % ROOT_N:
|
||||||
raise ValueError("case root N must be a multiple of 128")
|
raise ValueError("case root N must be a multiple of 128")
|
||||||
probes = []
|
probes = []
|
||||||
for name, offset, (x, y) in points():
|
for name, along, (x, y) in points():
|
||||||
for level in reversed(range(len(masks))):
|
best = None
|
||||||
scale = (n // ROOT_N) * 2 ** level
|
for level, mask in enumerate(masks):
|
||||||
i, j = int(math.floor(x * scale)), int(math.floor(y * scale))
|
h = ROOT_N / (n * 2 ** level)
|
||||||
if masks[level][j, i]:
|
i0, j0 = int(math.floor(x / h)), int(math.floor(y / h))
|
||||||
h = 1.0 / scale
|
for j in range(j0 - 2, j0 + 3):
|
||||||
probes.append(dict(transect=name, offset=offset, point=[x, y], level=level,
|
for i in range(i0 - 2, i0 + 3):
|
||||||
i=i, j=j, center=[h * (i + 0.5), h * (j + 0.5)]))
|
if 0 <= j < mask.shape[0] and 0 <= i < mask.shape[1] and mask[j, i]:
|
||||||
break
|
cx, cy = h * (i + 0.5), h * (j + 0.5)
|
||||||
else:
|
key = (math.hypot(cx - x, cy - y), -level, j, i)
|
||||||
raise ValueError(f"point {(x, y)} is not covered by an ACTIVE leaf")
|
if best is None or key < best[0]:
|
||||||
|
best = (key, level, i, j, cx, cy)
|
||||||
|
if best is None:
|
||||||
|
raise ValueError(f"no ACTIVE leaf near target {(x, y)}")
|
||||||
|
_, level, i, j, cx, cy = best
|
||||||
|
probes.append(dict(transect=name, normal=along, point=[x, y], level=level, i=i, j=j,
|
||||||
|
center=[cx, cy], displacement=[cx - x, cy - y]))
|
||||||
|
if len({(p["level"], p["i"], p["j"]) for p in probes}) != len(probes):
|
||||||
|
raise ValueError("probe targets map to duplicate cells")
|
||||||
return probes
|
return probes
|
||||||
|
|
||||||
|
|
||||||
@@ -102,7 +112,7 @@ def validate(trace):
|
|||||||
import json
|
import json
|
||||||
if trace.get("steps") != list(STEPS) or len(trace["values"]) != len(STEPS):
|
if trace.get("steps") != list(STEPS) or len(trace["values"]) != len(STEPS):
|
||||||
raise ValueError("trace steps differ from the fixed schedule")
|
raise ValueError("trace steps differ from the fixed schedule")
|
||||||
if len(trace["probes"]) != len(OFFSETS) * len(TRANSECTS):
|
if len(trace["probes"]) != len(NORMAL_COORDS) * len(TRANSECTS):
|
||||||
raise ValueError("unexpected probe count")
|
raise ValueError("unexpected probe count")
|
||||||
width = 3 * len(trace["probes"])
|
width = 3 * len(trace["probes"])
|
||||||
if any(len(r) != width or not all(math.isfinite(v) for v in r) for r in trace["values"]):
|
if any(len(r) != width or not all(math.isfinite(v) for v in r) for r in trace["values"]):
|
||||||
|
|||||||
@@ -977,11 +977,17 @@ class ProbeTraceTests(unittest.TestCase):
|
|||||||
u512 = sp.select([np.ones((512, 512), bool)], 512)
|
u512 = sp.select([np.ones((512, 512), bool)], 512)
|
||||||
self.assertTrue(all(p["level"] == 0 for p in u128 + u512))
|
self.assertTrue(all(p["level"] == 0 for p in u128 + u512))
|
||||||
for case in (nested, twin, u128, u512):
|
for case in (nested, twin, u128, u512):
|
||||||
|
self.assertEqual(len({(p["level"], p["i"], p["j"]) for p in case}), 24) # unique
|
||||||
for p in case:
|
for p in case:
|
||||||
# The stored center is the actual cell center containing the point (root units).
|
dx, dy = p["displacement"]
|
||||||
h = 1.0 / (2 ** p["level"]) if case is not u512 else 0.25
|
self.assertEqual([p["center"][0] - p["point"][0], p["center"][1] - p["point"][1]],
|
||||||
self.assertLessEqual(abs(p["center"][0] - p["point"][0]), h / 2)
|
[dx, dy])
|
||||||
self.assertLessEqual(abs(p["center"][1] - p["point"][1]), h / 2)
|
self.assertEqual(max(math.hypot(*p["displacement"]) for p in u128), 0.625)
|
||||||
|
self.assertLessEqual(max(math.hypot(*p["displacement"]) for p in u512), 0.25 * 0.7072)
|
||||||
|
# Nested: 3 L0 + 5 L1 + 4 L2 per transect, as checked by native review.
|
||||||
|
for name in sp.TRANSECTS:
|
||||||
|
levels = [p["level"] for p in nested if p["transect"] == name]
|
||||||
|
self.assertEqual([levels.count(v) for v in (0, 1, 2)], [3, 5, 4])
|
||||||
# Different grids give different centers: no pretended collocation.
|
# Different grids give different centers: no pretended collocation.
|
||||||
self.assertNotEqual(u128[3]["center"], u512[3]["center"])
|
self.assertNotEqual(u128[3]["center"], u512[3]["center"])
|
||||||
self.assertEqual(sp.case_steps(512)[:3], [0, 4, 8])
|
self.assertEqual(sp.case_steps(512)[:3], [0, 4, 8])
|
||||||
|
|||||||
Reference in new issue
Block a user