Audit frozen slice replays and specify same-state refinement controls
This commit is contained in:
86
experiments/convergence_slice_cases_2026-09-19.json
Normal file
86
experiments/convergence_slice_cases_2026-09-19.json
Normal file
@@ -0,0 +1,86 @@
|
||||
[
|
||||
{
|
||||
"id": "n2_spherical_s4",
|
||||
"arguments": [
|
||||
"--index",
|
||||
"2",
|
||||
"--angular-momentum",
|
||||
"0",
|
||||
"--no-central",
|
||||
"--surface-prescription",
|
||||
"harmonics",
|
||||
"--surface-degree",
|
||||
"4",
|
||||
"--max-newton",
|
||||
"0",
|
||||
"--density-snapshot",
|
||||
"../../diagnostics/coupled_convergence_2026-09-19/screen_v1/n2_J0",
|
||||
"--model-slices-only",
|
||||
"--slice-subdivisions",
|
||||
"4"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "n2_spherical_s8",
|
||||
"arguments": [
|
||||
"--index",
|
||||
"2",
|
||||
"--angular-momentum",
|
||||
"0",
|
||||
"--no-central",
|
||||
"--surface-prescription",
|
||||
"harmonics",
|
||||
"--surface-degree",
|
||||
"4",
|
||||
"--max-newton",
|
||||
"0",
|
||||
"--density-snapshot",
|
||||
"../../diagnostics/coupled_convergence_2026-09-19/screen_v1/n2_J0",
|
||||
"--model-slices-only",
|
||||
"--slice-subdivisions",
|
||||
"8"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "n1_rotating_s4",
|
||||
"arguments": [
|
||||
"--index",
|
||||
"1",
|
||||
"--angular-momentum",
|
||||
"0.1",
|
||||
"--no-central",
|
||||
"--surface-prescription",
|
||||
"harmonics",
|
||||
"--surface-degree",
|
||||
"4",
|
||||
"--max-newton",
|
||||
"0",
|
||||
"--density-snapshot",
|
||||
"../../diagnostics/coupled_convergence_2026-09-19/screen_v1/n1_J0p1",
|
||||
"--model-slices-only",
|
||||
"--slice-subdivisions",
|
||||
"4"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "n1_rotating_s8",
|
||||
"arguments": [
|
||||
"--index",
|
||||
"1",
|
||||
"--angular-momentum",
|
||||
"0.1",
|
||||
"--no-central",
|
||||
"--surface-prescription",
|
||||
"harmonics",
|
||||
"--surface-degree",
|
||||
"4",
|
||||
"--max-newton",
|
||||
"0",
|
||||
"--density-snapshot",
|
||||
"../../diagnostics/coupled_convergence_2026-09-19/screen_v1/n1_J0p1",
|
||||
"--model-slices-only",
|
||||
"--slice-subdivisions",
|
||||
"8"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -388,6 +388,71 @@ def frozen_audit_scope(folder, assessment):
|
||||
if roles else 'Application counters have the scope stated by the producing benchmark.'}
|
||||
|
||||
|
||||
SLICE_GEOMETRY_CHECKS = {
|
||||
'unit_cube_slice_area', 'affine_signed_field_integral', 'physical_plane_residual',
|
||||
'curved_edge_reference_root', 'curved_edge_physical_plane', 'surface_intersection_segment_count',
|
||||
'surface_intersection_length', 'coincident_face_positive_side', 'coincident_face_negative_side'}
|
||||
|
||||
|
||||
def slice_replay(folder, meta, snapshot):
|
||||
require(meta.get('model_slices_only') == meta.get('model_slices') == meta.get('density_diagnostic') == '1'
|
||||
and meta.get('max_newton') == '0', 'Slice replay claims incompatible execution modes')
|
||||
measurements = physical(folder/'density_physical.csv')
|
||||
require('18' in measurements, 'Slice replay lacks q18 physical observations')
|
||||
table = rows(folder/'density_invariants.csv')
|
||||
invariants = {r['metric']: finite(r['value']) for r in table}
|
||||
require(len(table) == len(invariants), 'Repeated density replay invariant')
|
||||
require(all(invariants.get(k) == 1. for k in
|
||||
('accepted_physical_unchanged', 'accepted_normalized_unchanged', 'accepted_residual_unchanged')),
|
||||
'Slice replay changed its accepted source state')
|
||||
require(invariants['prepared_residual_norm'] >= 0, 'Invalid prepared replay residual')
|
||||
scope = (folder/'frozen_slices/scope.txt').read_text().splitlines()
|
||||
for flag in ('source_fields_bitwise_identical=1', 'deformation_scale=1'):
|
||||
require(scope.count(flag) == 1 and sum(line.startswith(flag.split('=')[0]+'=') for line in scope) == 1,
|
||||
'Missing or contradictory slice source/scale invariant')
|
||||
geometry = rows(folder/'frozen_slices/geometry_self_checks.csv')
|
||||
names = [r['case'] for r in geometry]
|
||||
require(len(names) == len(set(names)) and SLICE_GEOMETRY_CHECKS <= set(names),
|
||||
'Missing or repeated slice geometry self-check')
|
||||
for row in geometry:
|
||||
observed, expected, tolerance = (finite(row[k]) for k in ('observed','expected','tolerance'))
|
||||
require(row['passed'] == '1' and tolerance >= 0 and abs(observed-expected) <= tolerance,
|
||||
'Slice geometry self-check contradicts its reported success')
|
||||
source = benchmark.vector(snapshot)
|
||||
observed = benchmark.vector(folder/'observed_state.txt')
|
||||
require(len(source) == len(observed), 'Replay/source state dimensions differ')
|
||||
def coordinates(path):
|
||||
table = rows(path)
|
||||
result = {(r['kind'],r['block']):(int(r['offset']),int(r['size'])) for r in table}
|
||||
require(len(result) == len(table) and {kind for kind,_ in result} == {'value','residual'},
|
||||
'Invalid replay block catalog')
|
||||
for kind in ('value','residual'):
|
||||
offset = 0
|
||||
for start,size in sorted(value for key,value in result.items() if key[0] == kind):
|
||||
require(start == offset and size > 0, 'Incomplete replay coordinate partition')
|
||||
offset += size
|
||||
require(offset == len(source), 'Replay layout/state dimension mismatch')
|
||||
return result
|
||||
require(coordinates(folder/'layout.csv') == coordinates(snapshot.parent/'layout.csv'),
|
||||
'Replay/source named coordinates differ')
|
||||
errors, relative_errors = [], []
|
||||
for old, new in zip(source, observed):
|
||||
error, scale = abs(old-new), max(abs(old),abs(new))
|
||||
# Preparing a physical snapshot performs one normalization round trip.
|
||||
# Check componentwise so a large potential cannot mask changed h/rho.
|
||||
require(error <= 64*sys.float_info.epsilon*scale, 'Replay state differs beyond normalization roundoff')
|
||||
errors.append(error)
|
||||
relative_errors.append(error/scale if scale else 0.)
|
||||
return {'kind':'slice_replay', 'outcome':'observation_complete', 'observed_physical':measurements,
|
||||
'observed_residual':invariants['prepared_residual_norm'], 'snapshot_source':str(snapshot),
|
||||
'snapshot_state_size':len(source), 'snapshot_roundtrip_error_norm':norm(errors),
|
||||
'snapshot_maximum_component_relative_error':max(relative_errors),
|
||||
'density_invariants':invariants, 'geometry_self_checks':geometry,
|
||||
'observation_scope':'Frozen physical snapshot replay; no Newton update or equilibrium certification. '
|
||||
'Source vectors and named coordinates, reported restoration and geometry self-checks are audited. '
|
||||
'Slice vertex/triangle files are hash-bound, not independently reassembled or rendered.'}
|
||||
|
||||
|
||||
def verify_run_binding(campaign, spec, record, provenance):
|
||||
command = record['command']
|
||||
require(command[1:-4] == spec['arguments'], 'Command differs from declared case')
|
||||
@@ -451,7 +516,15 @@ def audit_case(campaign, spec, hashes, provenance=None):
|
||||
return {**result, 'artifact_passed': True, 'kind':'execution_failure', 'outcome':'timed_out' if record.get('timed_out') else 'execution_failure'}
|
||||
meta = metadata(folder/'metadata.txt')
|
||||
result['metadata'] = meta
|
||||
if (folder/'preconditioner_summary.csv').exists():
|
||||
if meta.get('model_slices_only') == '1':
|
||||
require(record['exit_code'] == 0, 'Slice observation did not complete successfully')
|
||||
arguments = spec['arguments']
|
||||
require(arguments.count('--density-snapshot') == 1, 'Slice replay audit requires one supplied density snapshot')
|
||||
source = Path(arguments[arguments.index('--density-snapshot')+1])
|
||||
source = (source if source.is_absolute() else Path(provenance['source'])/source).resolve()
|
||||
require(source.is_dir(), 'Density snapshot must name its source directory')
|
||||
result.update(slice_replay(folder, meta, source/'accepted_state.txt'))
|
||||
elif (folder/'preconditioner_summary.csv').exists():
|
||||
assessment = benchmark.inspect_case(folder)
|
||||
require(assessment['passed'], 'Frozen benchmark audit failed: ' + str([c for c in assessment['checks'] if not c['passed']]))
|
||||
result.update(kind='benchmark', outcome=assessment['comparison']['outcome'], benchmark=assessment)
|
||||
@@ -502,7 +575,11 @@ def flat_rows(campaigns):
|
||||
'density_order','surface_prescription','surface_maximum_order','surface_degree',
|
||||
'strategy','preconditioner_variant')})
|
||||
row.update({k:run.get(k) for k in ('seconds','utc_elapsed_seconds','utc_minus_monotonic_seconds','child_cpu_seconds','exit_code')})
|
||||
q18 = case.get('final_physical',{}).get('18',{})
|
||||
replay = case.get('kind') == 'slice_replay'
|
||||
q18 = case.get('observed_physical' if replay else 'final_physical',{}).get('18',{})
|
||||
row['physical_observation_scope'] = 'frozen_replay' if replay else 'final_accepted_state' if q18 else None
|
||||
row['observed_residual'] = case.get('observed_residual')
|
||||
row['snapshot_maximum_component_relative_error'] = case.get('snapshot_maximum_component_relative_error')
|
||||
for key in ('enthalpy_virial_error','enthalpy_force_virial_error','normalized_unbordered_residual',
|
||||
'central_border','normalized_border_action','hydrostatic_gradient_rms','mass_absolute_error','angular_momentum_absolute_error'):
|
||||
row[key] = q18.get(key)
|
||||
@@ -510,7 +587,7 @@ def flat_rows(campaigns):
|
||||
row['minimum_accepted_alpha'] = case.get('trials',{}).get('minimum_accepted_alpha')
|
||||
for stage in ('pressure force','residual metric'):
|
||||
row[stage.replace(' ','_')+'_rejections'] = sum(r['count'] for r in
|
||||
case.get('trials',{}).get('source_disposition_counts',[]) if r['source'] == stage and r['disposition_code'] != 0)
|
||||
case['trials']['source_disposition_counts'] if r['source'] == stage and r['disposition_code'] != 0) if 'trials' in case else None
|
||||
if 'benchmark' in case:
|
||||
row['surface_border_schur_internal_audit'] = case['benchmark_audit_scope']['surface_border_schur_internal_audit']
|
||||
for role in ('baseline','candidate'):
|
||||
@@ -522,6 +599,85 @@ def flat_rows(campaigns):
|
||||
|
||||
|
||||
class TinyChecks(unittest.TestCase):
|
||||
def slice_fixture(self, directory):
|
||||
root = Path(directory).resolve()
|
||||
folder, source = root/'campaign/replay', root/'source_campaign/source_case'
|
||||
folder.mkdir(parents=True)
|
||||
source.mkdir(parents=True)
|
||||
(folder/'frozen_slices').mkdir()
|
||||
meta = dict(model_slices_only='1', model_slices='1', density_diagnostic='1', max_newton='0')
|
||||
(folder/'metadata.txt').write_text(''.join(f'{k}={v}\n' for k,v in meta.items()))
|
||||
(source/'metadata.txt').write_text('converged=0\n')
|
||||
layout = 'kind,block,offset,size,scale\nvalue,fields,0,3,1\nresidual,equations,0,3,1\n'
|
||||
(source/'layout.csv').write_text(layout)
|
||||
(folder/'layout.csv').write_text(layout)
|
||||
(source/'accepted_state.txt').write_text('3\n1\n1e-12\n0\n')
|
||||
(folder/'observed_state.txt').write_text(f'3\n{math.nextafter(1.,2.)}\n1e-12\n0\n')
|
||||
(folder/'density_invariants.csv').write_text('metric,value\naccepted_physical_unchanged,1\n'
|
||||
'accepted_normalized_unchanged,1\naccepted_residual_unchanged,1\nprepared_residual_norm,.1\n')
|
||||
(folder/'frozen_slices/scope.txt').write_text('source_fields_bitwise_identical=1\ndeformation_scale=1\nDescription.\n')
|
||||
(folder/'frozen_slices/geometry_self_checks.csv').write_text('case,observed,expected,tolerance,passed\n'+
|
||||
''.join(f'{name},1,1,1e-12,1\n' for name in sorted(SLICE_GEOMETRY_CHECKS)))
|
||||
values = dict(complete_volume_measurement=1., pressure_from_enthalpy_defined_everywhere=1.,
|
||||
invalid_stellar_samples=0., valid_stellar_samples=8., invalid_enthalpy_eos_samples=0., volume=1.,
|
||||
binding_energy=-3., force_binding_energy=-3., enthalpy_pressure_integral=1., kinetic_energy=0.,
|
||||
enthalpy_virial_error=0., enthalpy_force_virial_error=0.)
|
||||
(folder/'density_physical.csv').write_text('quadrature,metric,value\n'+
|
||||
''.join(f'18,{name},{value}\n' for name,value in values.items()))
|
||||
return folder, source, meta
|
||||
|
||||
def test_slice_replay_is_observation_even_for_unconverged_source(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
folder, source, meta = self.slice_fixture(directory)
|
||||
hashes = Hashes()
|
||||
prior_outputs = {name:hashes.digest(source/name) for name in ('accepted_state.txt','layout.csv','metadata.txt')}
|
||||
prior_manifest = source.parent/'provenance.json'
|
||||
prior_run = source.parent/'source_case_run.json'
|
||||
prior_manifest.write_text(json.dumps(dict(mesh_sha256='fixture')))
|
||||
prior_run.write_text(json.dumps(dict(output_hashes=prior_outputs)))
|
||||
inputs = {str(path):hashes.digest(path) for path in
|
||||
[*(source/name for name in prior_outputs), prior_manifest, prior_run]}
|
||||
campaign = folder.parent
|
||||
spec = dict(id='replay', arguments=['--model-slices-only','--density-snapshot',str(source),'--max-newton','0'])
|
||||
provenance = dict(source=directory, mesh=str(campaign/'mesh'), mesh_sha256='fixture')
|
||||
record = dict(id='replay', finished_utc='2026-09-19T00:00:00+00:00', exit_code=0,
|
||||
command=[str(campaign/'plateau_diagnostic'), *spec['arguments'], '--mesh',str(campaign/'mesh'),'--output',str(folder)],
|
||||
input_state_hashes=inputs, inputs_unchanged=True,
|
||||
output_hashes={str(p.relative_to(folder)):hashes.digest(p) for p in folder.rglob('*') if p.is_file()})
|
||||
(campaign/'replay_run.json').write_text(json.dumps(record))
|
||||
result = audit_case(campaign, spec, hashes, provenance)
|
||||
self.assertTrue(result['artifact_passed'], result.get('error'))
|
||||
self.assertEqual(result['kind'],'slice_replay')
|
||||
self.assertEqual(result['outcome'],'observation_complete')
|
||||
flat = flat_rows([dict(path=str(campaign),cases=[result])])[0]
|
||||
self.assertEqual(flat['observed_residual'], .1)
|
||||
self.assertEqual(flat['physical_observation_scope'],'frozen_replay')
|
||||
self.assertIsNone(flat['final_residual'])
|
||||
self.assertIsNone(flat['accepted_updates'])
|
||||
self.assertIsNone(flat['pressure_force_rejections'])
|
||||
|
||||
def test_slice_replay_rejects_schema_and_source_corruption(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
folder, source, meta = self.slice_fixture(directory)
|
||||
corruptions = {
|
||||
'observed_state.txt':['3\n1\n1.001e-12\n0\n','2\n1\n1e-12\n'],
|
||||
'density_invariants.csv':['metric,value\naccepted_physical_unchanged,0\n'],
|
||||
'frozen_slices/scope.txt':['source_fields_bitwise_identical=0\ndeformation_scale=1\n'],
|
||||
'frozen_slices/geometry_self_checks.csv':['case,observed,expected,tolerance,passed\n'],
|
||||
'layout.csv':['kind,block,offset,size,scale\nvalue,other_fields,0,3,1\nresidual,equations,0,3,1\n']}
|
||||
for name, replacements in corruptions.items():
|
||||
path = folder/name
|
||||
original = path.read_text()
|
||||
for replacement in replacements:
|
||||
with self.subTest(file=name, replacement=replacement):
|
||||
path.write_text(replacement)
|
||||
with self.assertRaises((ValueError,KeyError)):
|
||||
slice_replay(folder,meta,source/'accepted_state.txt')
|
||||
path.write_text(original)
|
||||
path = folder/'frozen_slices/geometry_self_checks.csv'
|
||||
path.write_text(path.read_text().replace(',1,1,1e-12,1', ',2,1,1e-12,1',1))
|
||||
with self.assertRaises(ValueError): slice_replay(folder,meta,source/'accepted_state.txt')
|
||||
|
||||
def test_pending_is_not_success(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
result = audit_case(Path(directory), {'id':'pending','arguments':[]}, Hashes())
|
||||
@@ -658,11 +814,12 @@ def main():
|
||||
'complete':all(c['complete'] for c in campaigns), 'campaigns':campaigns,
|
||||
'auditor_sha256':hashes.digest(Path(__file__)),
|
||||
'benchmark_checker_sha256':hashes.digest(Path(benchmark.__file__)), 'consumed_sha256':hashes.consumed,
|
||||
'scope':'Provenance and retained-file hashes; recorded Newton/trial/block bindings; saved-vector final linear defects and scalar trial identities. Numerical failure is an outcome, not an artifact failure.',
|
||||
'scope':'Provenance and retained-file hashes; recorded Newton/trial/block bindings; saved-vector final linear defects and scalar trial identities; frozen slice replay source binding and reported invariants. Numerical failure is an outcome, not an artifact failure.',
|
||||
'limitations':['No independent FEM reassembly or physical-validity certificate.',
|
||||
'Linear histories are recurrence residuals; only saved endpoints have independently checked true defects. No proved residual floor.',
|
||||
'New surface/scalar Schur wrapper artifacts are retained and hash-bound, but their matrices, coordinates, counters and conditioning are outside this audit; endpoint gates and timing sums are checked.',
|
||||
'Trial remainder vectors are not saved. Scalar checks cannot verify the underlying FEM evaluations.',
|
||||
'Slice replays are observations, including when their source did not converge; slice geometry and field samples are not independently reassembled or rendered.',
|
||||
'Virial outcomes refer to the reported quadrature and h-derived pressure; they do not establish nonlinear convergence.',
|
||||
'Normalized residuals and rtol thresholds belong to their own discrete systems; Krylov counts are not equal work units.',
|
||||
'Newton time excludes observers/setup; benchmark setup/solve costs have separate scope. Clock discrepancies are retained without rescaling.']}
|
||||
|
||||
Reference in New Issue
Block a user