research: Dütsch driver — continuous settling, domain criteria, profile coverage

common_window requires every pair from each case's own K_case to K+2;
a-priori domain criteria against the 60 D reference (separate from Table 1);
bilinear sampling returns the original fluid corner weight sum; analysis
time-averages bin samples, reports coverage/missing points and fails closed
on an empty common profile set; cases run to the end of cycle 11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-30 10:58:05 +00:00
1 parent 6f95c34c0b
commit b31a6141b3
5 files changed
+79 -32

No files matched your search

+10 -7
View File
@@ -17,6 +17,7 @@ PHASES = (180.0, 210.0, 330.0) # degrees; bins [p, p + 1)
X2 = tuple(np.round(np.arange(-1.5, 1.5001, 0.05), 10)) # declared x2/D points
DISCARD, LAST_SCORED, N_PAIRS = 2, 11, 3 # cycles 0..2 discarded, cap 12 T
SETTLE = dict(wave=.02, scalar=.01, profile=.03, morison=.02)
DOMAIN = dict(wave=.01, morison=.02, profile=.02) # a-priori, vs the 60 D reference
def amplitude(D):
@@ -65,8 +66,9 @@ def morison_fit(f_norm, b1, b2):
def bilinear_fluid(field, fluid, x, y):
"""Bilinear value at (x, y) in cell coordinates from fluid cells only.
Returns (value, ((ix, iy, weight), ...)) with weights renormalized over the
fluid corners, or (None, ()) when no corner is fluid (MISSING, never zero).
Returns (value, ((ix, iy, weight), ...), fluid_weight_sum) with weights
renormalized over the fluid corners and the original sum of their bilinear
weights, or (None, (), 0.0) when no corner is fluid (MISSING, never zero).
"""
x0, y0 = int(math.floor(x)), int(math.floor(y))
fx, fy = x - x0, y - y0
@@ -75,9 +77,9 @@ def bilinear_fluid(field, fluid, x, y):
used = [(i, j, w) for i, j, w in corners if w > 0.0 and fluid[j, i]]
total = sum(w for _, _, w in used)
if total == 0.0:
return None, ()
return None, (), 0.0
used = tuple((i, j, w / total) for i, j, w in used)
return float(sum(w * field[j, i] for i, j, w in used)), used
return float(sum(w * field[j, i] for i, j, w in used)), used, float(total)
def settled_start(pairs_pass):
@@ -95,13 +97,14 @@ def settled_start(pairs_pass):
def common_window(k_cases, pairs_pass_by_case):
"""Common scored cycles K..K+2 with K = max K_case, or None (FAIL-CLOSED) when a
case never settled, K + 2 exceeds the cap, or a case fails a window pair."""
case never settled, K + 2 exceeds the cap, or a case fails any pair p_j for
j = its own K_case .. K + 2 (continuous settling, including the wait for K)."""
if any(k is None for k in k_cases):
return None
K = max(k_cases)
if K + 2 > LAST_SCORED:
return None
for pairs in pairs_pass_by_case:
if not all(pairs.get(k, False) for k in (K, K + 1, K + 2)):
for k_case, pairs in zip(k_cases, pairs_pass_by_case):
if not all(pairs.get(j, False) for j in range(k_case, K + 3)):
return None
return K, K + 1, K + 2