test: retain independent Jet CV continuation measurements
This commit is contained in:
1 parent
413f7afade
commit
b23cb45adc
5 files changed
+761
-15
No files matched your search
@@ -202,7 +202,7 @@ def verify(repo):
|
||||
return manifest
|
||||
|
||||
|
||||
def run_case(c, ctx, output, provenance):
|
||||
def run_case(c, ctx, output, provenance, continuation=False):
|
||||
from CelerisLab.body.geometry.circle import CircleGeometry
|
||||
from CelerisLab.body.objects import SimObject
|
||||
from CelerisLab.body.jets import Jet, Sector, Radial
|
||||
@@ -334,9 +334,26 @@ def run_case(c, ctx, output, provenance):
|
||||
"amr_api": aperture_probe(fluid_a, origin_a, center, radius),
|
||||
}
|
||||
|
||||
def capture():
|
||||
recorder = None
|
||||
if continuation:
|
||||
from jet_cv_measurements import MeasurementRecorder, sample_steps
|
||||
|
||||
recorder = MeasurementRecorder(
|
||||
c, output, fluid_u, amr._leaf, origin_a, CX, CY
|
||||
)
|
||||
scheduled = set(sample_steps(c).tolist())
|
||||
else:
|
||||
scheduled = set(range(c["steps"] + 1))
|
||||
|
||||
cumulative_raw = {
|
||||
name: {k: np.zeros(4) for k in masks}
|
||||
for name in ("uniform_adapter", "amr_api")
|
||||
}
|
||||
|
||||
def capture(step):
|
||||
ug = uniform.download()
|
||||
ag = amr.download()[1]
|
||||
levels = amr.download()
|
||||
ag = levels[1]
|
||||
data = {}
|
||||
aperture = {}
|
||||
for name, g, fluid, origin in [
|
||||
@@ -356,9 +373,18 @@ def run_case(c, ctx, output, provenance):
|
||||
np.linalg.norm((av - uv)[:, fluid_a])
|
||||
/ max(np.linalg.norm(uv[:, fluid_a]), 1e-30)
|
||||
)
|
||||
if recorder is not None:
|
||||
recorder.capture(step, ug, levels, data, aperture, error)
|
||||
recorder.records[-1]["raw_cumulative"] = np.array(
|
||||
[
|
||||
[cumulative_raw[name][k].copy() for k in masks]
|
||||
for name in ("uniform_adapter", "amr_api")
|
||||
]
|
||||
)
|
||||
return data, error, aperture
|
||||
|
||||
previous, _, previous_aperture = capture()
|
||||
previous, _, previous_aperture = capture(0)
|
||||
previous_sample_step = 0
|
||||
initial = previous
|
||||
integrated = {name: np.zeros((2, 3)) for name in previous}
|
||||
integrated_aperture = {name: np.zeros(2) for name in previous}
|
||||
@@ -380,9 +406,9 @@ def run_case(c, ctx, output, provenance):
|
||||
flush=True,
|
||||
)
|
||||
for step in range(1, c["steps"] + 1):
|
||||
if time.monotonic() - start > 1800:
|
||||
if time.monotonic() - start > c.get("post_ready_budget_seconds", 1800):
|
||||
raise RuntimeError(
|
||||
"1800-second post-READY pilot budget exceeded; partial report retained"
|
||||
"Declared post-READY budget exceeded; partial report retained"
|
||||
)
|
||||
samples.clear()
|
||||
amr.step()
|
||||
@@ -393,25 +419,38 @@ def run_case(c, ctx, output, provenance):
|
||||
ar = np.empty((count, 4), np.float64)
|
||||
with ctx.activate():
|
||||
cuda.memcpy_dtoh(ar, b.interval_integral)
|
||||
if not np.isfinite(ar).all() or not np.isfinite(ur).all():
|
||||
raise RuntimeError("Nonfinite raw exchange in completed base interval")
|
||||
obs = amr.read_raw_exchange(0)
|
||||
if obs["time_start"] != step - 1 or obs["time_end"] != step:
|
||||
raise RuntimeError("Raw interval time mismatch")
|
||||
np.testing.assert_allclose(
|
||||
ar.sum(axis=0)[:2], obs["total"]["impulse"], atol=1e-13, rtol=1e-13
|
||||
)
|
||||
current, error, current_aperture = capture()
|
||||
for name, rr in [("uniform_adapter", ur), ("amr_api", ar)]:
|
||||
for k, mask in masks.items():
|
||||
accumulated[name][k] += rr[mask].sum(axis=0)
|
||||
integrated_aperture[name] += 0.5 * (
|
||||
previous_aperture[name] + current_aperture[name]
|
||||
subtotal = rr[mask].sum(axis=0)
|
||||
accumulated[name][k] += subtotal
|
||||
cumulative_raw[name][k] += subtotal
|
||||
if step not in scheduled:
|
||||
continue
|
||||
current, error, current_aperture = capture(step)
|
||||
sample_dt = step - previous_sample_step
|
||||
for name in current:
|
||||
integrated_aperture[name] += (
|
||||
0.5 * sample_dt * (previous_aperture[name] + current_aperture[name])
|
||||
)
|
||||
integrated[name] += 0.5 * (
|
||||
np.array([x[1] for x in previous[name]])
|
||||
+ np.array([x[1] for x in current[name]])
|
||||
integrated[name] += (
|
||||
0.5
|
||||
* sample_dt
|
||||
* (
|
||||
np.array([x[1] for x in previous[name]])
|
||||
+ np.array([x[1] for x in current[name]])
|
||||
)
|
||||
)
|
||||
previous = current
|
||||
previous_aperture = current_aperture
|
||||
previous_sample_step = step
|
||||
if step % c["window"] == 0 or step == c["steps"]:
|
||||
end0 = rows[-1]["step_end"] if rows else 0
|
||||
duration = step - end0
|
||||
@@ -469,6 +508,8 @@ def run_case(c, ctx, output, provenance):
|
||||
v.fill(0)
|
||||
rows.append(row)
|
||||
initial = current
|
||||
if recorder is not None:
|
||||
recorder.flush()
|
||||
payload = dict(
|
||||
case=c,
|
||||
source_revision=PIN,
|
||||
@@ -506,19 +547,40 @@ def main():
|
||||
"--steps", type=int, default=800, help="Base s=1 steps; scales as s squared"
|
||||
)
|
||||
p.add_argument("--allow-re400", action="store_true")
|
||||
p.add_argument(
|
||||
"--continuation",
|
||||
action="store_true",
|
||||
help="Fixed measurement campaign: Re100, scale1/2, 3200 reference steps",
|
||||
)
|
||||
p.add_argument("--plan", action="store_true")
|
||||
a = p.parse_args()
|
||||
if a.steps <= 0 or a.steps > 3200:
|
||||
p.error("steps must be 1..3200")
|
||||
if a.re == 400 and not a.allow_re400:
|
||||
p.error("Re400 requires explicit conditional-campaign opt-in")
|
||||
if a.continuation:
|
||||
if a.scale not in (1, 2) or a.re != 100 or a.steps != 3200:
|
||||
p.error("--continuation requires --re 100 --scale 1/2 --steps 3200")
|
||||
c = case(a.scale, a.re, a.steps)
|
||||
if a.continuation:
|
||||
from jet_cv_measurements import sample_steps, factors
|
||||
|
||||
c.update(
|
||||
measurement_schema=1,
|
||||
sample_count=len(sample_steps(c)),
|
||||
startup_sample_dt_reference=1,
|
||||
later_sample_dt_reference=4,
|
||||
dense_startup_end_reference=100,
|
||||
reference_conversion=factors(a.scale),
|
||||
post_ready_budget_seconds=1200 if a.scale == 1 else 5400,
|
||||
runtime_estimate_seconds=[210, 500] if a.scale == 1 else [900, 3200],
|
||||
)
|
||||
plan = dict(
|
||||
case=c,
|
||||
required_revision=PIN,
|
||||
required_free_device_mib=1024,
|
||||
estimated_peak_device_mib=128 * a.scale**2,
|
||||
estimated_output_mib=2,
|
||||
estimated_output_mib=64 if a.continuation else 2,
|
||||
max_steps=c["steps"],
|
||||
gpu_launch_owner="root; this runner does not select or reserve a GPU",
|
||||
)
|
||||
@@ -550,7 +612,7 @@ def main():
|
||||
free, total = cuda.mem_get_info()
|
||||
if free < max(1024, 2 * plan["estimated_peak_device_mib"]) * 1024**2:
|
||||
raise RuntimeError("Insufficient free device memory")
|
||||
run_case(c, ctx, a.output, provenance)
|
||||
run_case(c, ctx, a.output, provenance, continuation=a.continuation)
|
||||
print(
|
||||
json.dumps(
|
||||
dict(status="COMPLETE_DIAGNOSTIC_ONLY", physics_validation_pass=False)
|
||||
|
||||
Reference in new issue
Block a user