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
@@ -1,12 +1,14 @@
|
||||
"""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
|
||||
from corners, crossing L0->L1 and (nested only) L1->L2:
|
||||
V: y = 64.1, across the vertical faces x = 16 (L0/L1) and x = 22 (L1/L2) of box 1;
|
||||
H: x = 90.1, across the horizontal faces y = 24 (L0/L1) and y = 30 (L1/L2) of box 2.
|
||||
Each point is sampled at the ACTIVE leaf cell containing it, so cases with
|
||||
different grids (U128, U512, nested, twin) give different cell centers: the
|
||||
actual center and level are stored and analytic fields are evaluated there.
|
||||
No pass gates. Native-validated 24-target layout through box 1, in root-128
|
||||
physical coordinates, crossing L0->L1 and (nested only) L1->L2 away from corners:
|
||||
horizontal line y = 56 across the vertical faces x = 16 and x = 22;
|
||||
vertical line x = 38 across the horizontal faces y = 16 and y = 22;
|
||||
normal coordinates NORMAL_COORDS on both (nested: 3 L0 + 5 L1 + 4 L2 each).
|
||||
Each target maps to the nearest ACTIVE leaf center (tie rule: distance, then
|
||||
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);
|
||||
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
|
||||
|
||||
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
|
||||
TRANSECTS = {"V": dict(axis=0, face=16.0, other=64.1), # x varies, y fixed
|
||||
"H": dict(axis=1, face=24.0, other=90.1)} # y varies, x fixed
|
||||
NORMAL_COORDS = (12.5, 14.5, 15.5, 16.25, 17.25, 19.25, 20.75, 21.75,
|
||||
22.125, 23.125, 24.125, 26.125)
|
||||
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
|
||||
TRACE_MAX_BYTES = 600_000
|
||||
|
||||
@@ -29,10 +32,9 @@ TRACE_MAX_BYTES = 600_000
|
||||
def points():
|
||||
out = []
|
||||
for name, t in TRANSECTS.items():
|
||||
for offset in OFFSETS:
|
||||
along = t["face"] + offset
|
||||
for along in NORMAL_COORDS:
|
||||
xy = (along, t["other"]) if t["axis"] == 0 else (t["other"], along)
|
||||
out.append((name, offset, xy))
|
||||
out.append((name, along, xy))
|
||||
return out
|
||||
|
||||
|
||||
@@ -42,25 +44,33 @@ def case_steps(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
|
||||
with root N = n has cells of size ROOT_N / (n * 2**level) there.
|
||||
Targets and stored centers are in root-physical units (root cell = 1); a case
|
||||
with root N = n has cell size h = ROOT_N / (n * 2**level) there (U512: 0.25).
|
||||
"""
|
||||
if n % ROOT_N:
|
||||
raise ValueError("case root N must be a multiple of 128")
|
||||
probes = []
|
||||
for name, offset, (x, y) in points():
|
||||
for level in reversed(range(len(masks))):
|
||||
scale = (n // ROOT_N) * 2 ** level
|
||||
i, j = int(math.floor(x * scale)), int(math.floor(y * scale))
|
||||
if masks[level][j, i]:
|
||||
h = 1.0 / scale
|
||||
probes.append(dict(transect=name, offset=offset, point=[x, y], level=level,
|
||||
i=i, j=j, center=[h * (i + 0.5), h * (j + 0.5)]))
|
||||
break
|
||||
else:
|
||||
raise ValueError(f"point {(x, y)} is not covered by an ACTIVE leaf")
|
||||
for name, along, (x, y) in points():
|
||||
best = None
|
||||
for level, mask in enumerate(masks):
|
||||
h = ROOT_N / (n * 2 ** level)
|
||||
i0, j0 = int(math.floor(x / h)), int(math.floor(y / h))
|
||||
for j in range(j0 - 2, j0 + 3):
|
||||
for i in range(i0 - 2, i0 + 3):
|
||||
if 0 <= j < mask.shape[0] and 0 <= i < mask.shape[1] and mask[j, i]:
|
||||
cx, cy = h * (i + 0.5), h * (j + 0.5)
|
||||
key = (math.hypot(cx - x, cy - y), -level, j, i)
|
||||
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
|
||||
|
||||
|
||||
@@ -102,7 +112,7 @@ def validate(trace):
|
||||
import json
|
||||
if trace.get("steps") != list(STEPS) or len(trace["values"]) != len(STEPS):
|
||||
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")
|
||||
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"]):
|
||||
|
||||
Reference in new issue
Block a user