From 26d0d3853c9d4d3cd6ae3f27653dced56f8c5fec Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 18 Oct 2026 12:03:35 -0700 Subject: [PATCH] test: admit audited shifted N64 space-time trajectory --- .../multigrid/run_spacetime_gpu_n64.py | 85 +++++++++++++++---- .../multigrid/test_spacetime_gpu.py | 10 +++ 2 files changed, 77 insertions(+), 18 deletions(-) diff --git a/tests/validation/multigrid/run_spacetime_gpu_n64.py b/tests/validation/multigrid/run_spacetime_gpu_n64.py index c1996b1..f7d0e35 100644 --- a/tests/validation/multigrid/run_spacetime_gpu_n64.py +++ b/tests/validation/multigrid/run_spacetime_gpu_n64.py @@ -22,7 +22,7 @@ ref = gpu.ref CPU_SHA = '180eef90a1c3f43113fe18cc54981ee4723cfc0cc2724334907ff188022fa770' UNIFORM_SHA = '01e7415ae39456f2de7f0c3d331afb971c49d19353b43038650e32e80737f1e7' -CUDA_SHA = 'c47869688f7ac2ec93411c0af233887fe8b77405838299e4ae52c8963fd97fe4' +CUDA_SHA = 'afea11ea4a1c2c3800b2f6a7a8e81f5568989fc9e1cc02fb52d7e1ea3864e003' AUDIT_SHA = 'fba340b1533bec308b666ee84666df0ac9d08e2872be31ee379e2d1447565158' STEPS = (256, 512, 768, 1024) TIMES = (.12, .24, .36, .48) @@ -66,6 +66,12 @@ def differing_fields(actual, expected): or np.asarray(actual[key]).tobytes() != np.asarray(expected[key]).tobytes()] +def sample_difference(actual, expected): + """Descriptive comparison only; never an equivalence gate for different codecs.""" + return {key:dict(reference=value,signed=(np.asarray(actual[key])-value).tolist(), + absolute=np.abs(np.asarray(actual[key])-value).tolist()) for key,value in expected.items()} + + class LedgerTotals: """Compensated directional sums; retain absolute step sums to expose cancellation.""" names = ('net_change','physical_collision','coarse_collision','fine0_collision','fine1_collision', @@ -184,18 +190,24 @@ def main(): parser.add_argument('--cpu-receipt', type=Path, required=True) parser.add_argument('--uniform-receipt', type=Path, required=True) parser.add_argument('--audit-against', type=Path, help='audit every interval and compare exact saved 1779cf2 samples') + parser.add_argument('--shifted', action='store_true', help='opt-in shifted storage with all interval ledgers') + parser.add_argument('--unshifted-receipt', type=Path, help='pinned1779 comparison, descriptive only') parser.add_argument('--output', type=Path, required=True) args = parser.parse_args() if not args.gpu_admitted or not os.environ.get('CUDA_VISIBLE_DEVICES'): parser.error('explicit --gpu-admitted and CUDA_VISIBLE_DEVICES required') if args.output.exists(): parser.error('output exists; preserve evidence and choose a new path') + if args.shifted != (args.unshifted_receipt is not None) or (args.shifted and args.audit_against): + parser.error('--shifted requires --unshifted-receipt and cannot use exact --audit-against') + exact_repeat = args.audit_against is not None cpu, uniform = load_references(args.cpu_receipt, args.uniform_receipt) previous = None - if args.audit_against is not None: - if sha(args.audit_against) != AUDIT_SHA: + comparison_path = args.audit_against or args.unshifted_receipt + if comparison_path is not None: + if sha(comparison_path) != AUDIT_SHA: raise ValueError('pinned GPU trajectory receipt differs') - previous = json.loads(args.audit_against.read_text()) + previous = json.loads(comparison_path.read_text()) if previous['source']['numpy'] != np.__version__: raise RuntimeError('audited repeat requires unchanged NumPy environment') gpu.check_sources() @@ -212,8 +224,9 @@ def main(): report = dict(scope='N64 experimental space-time GPU; no grid-convergence qualification', completed=False, passed=False, source=source, rows=[], health_counts=[0]*6, health_labels=HEALTH, setup=dict(n=64, bounds=[8,8,56,48], re_L=100, U=.03, viscosity=.0192, tau=[.5576,.6152], - phase='arrival_f', storage='unshifted_FP32', collision='SRT', interval_count=1024, - initialization='same physical FP64 equilibrium as CPU, rounded to FP32 on upload', + phase='arrival_f', storage='shifted_FP32' if args.shifted else 'unshifted_FP32', collision='SRT', interval_count=1024, + initialization='common analytic FP64 field, encoded using production FP64 weights before FP32 upload' if args.shifted + else 'same physical FP64 equilibrium as CPU, rounded to FP32 on upload', cpu_storage='FP64', sample_steps=STEPS, sample_times=TIMES), references=dict(cpu_receipt_sha256=CPU_SHA, cpu_source=cpu['source'], cpu_archive_drive_id='197F9nwDOGf_YROK1a46YpVvNrSldnH_w', @@ -230,7 +243,8 @@ def main(): if previous: report['diagnostic'] = dict(completed=False, passed=False, reference_sha256=AUDIT_SHA, reference_source=previous['source']['commit'], sample_checks=[], prefixes=[], - scope='net drift attribution; exact saved diagnostics only, not full-field trajectory certification') + scope='net drift attribution; exact saved diagnostics only, not full-field trajectory certification' if exact_repeat + else 'raw stored-value ledger; unshifted and CPU comparisons descriptive, initial codecs differ') phase = 'setup' def save(): @@ -256,16 +270,17 @@ def main(): try: from CelerisLab.cuda.context import CudaContext context = CudaContext(0) - config = LBMConfig(nx=64, ny=64, viscosity=.0192, velocity=0., ddf_shifting=False) + config = LBMConfig(nx=64, ny=64, viscosity=.0192, velocity=0., ddf_shifting=args.shifted) run = gpu.SpaceTimeGPU(config, (8,8,56,48), context=context) report.update(device=context.name, sm_arch=context.sm_arch, build_metadata=run.build_metadata, table_sha256=gpu.table_hash(run.tables)) report['table_validation'] = table_guard.validate_tables(run.plan,run.tables) if previous: - for key in ('device','sm_arch','table_sha256','build_metadata'): + for key in ('device','sm_arch','table_sha256') + (('build_metadata',) if exact_repeat else ()): if report[key] != previous[key]: raise AssertionError(f'audited repeat identity differs: {key}') - initial = ref.cpu.State(tg.initial((64,64),0,64,.0192), tg.initial((128,128),1,64,.0192)) + analytic = ref.cpu.State(tg.initial((64,64),0,64,.0192), tg.initial((128,128),1,64,.0192)) + initial = analytic phase = 'warm_reset' initial, report['warmup'] = warm_and_reset(run, initial, check_cap, audit=previous is not None) maps = run.plan.maps @@ -275,9 +290,27 @@ def main(): moment0 = total(initial, maps) report['initial'] = dict(mass=mass0, momentum=moment0[1:].tolist(), minimum_population=min(float(a[:,m].min()) for a,m in zip(arrays,masks))) - if previous and differing_fields(report['initial'],previous['initial']): + if exact_repeat and differing_fields(report['initial'],previous['initial']): raise AssertionError('audited repeat initial state diagnostics differ') - direction0 = ref.directional(ref.cpu.State(*(a.astype(np.float64) for a in arrays)),maps) + raw_initial = run._download_stored() if args.shifted else initial + direction0 = ref.directional(ref.cpu.State(*(a.astype(np.float64) for a in + (raw_initial.coarse_f,raw_initial.fine_f))),maps) + if args.shifted: + errors=[]; unshifted_errors=[] + for raw,actual,wanted,mask in zip((raw_initial.coarse_f,raw_initial.fine_f),arrays, + (analytic.coarse_f,analytic.fine_f),masks): + encoded=gpu._encode_physical(wanted,True) + np.testing.assert_array_equal(raw[:,mask].view(np.uint32),encoded[:,mask].view(np.uint32)) + errors.append(float(abs(actual[:,mask]-wanted[:,mask]).max())) + unshifted_errors.append(float(abs(gpu._encode_physical(wanted,False)[:,mask]-wanted[:,mask]).max())) + report['warmup']['raw_reset_verified']=True + report['initial_quantization']=dict(maximum_population_error_by_level=errors, + unshifted_codec_error_by_level=unshifted_errors, + moment_change_vs_analytic=(moment0-total(analytic,maps)).tolist(), + cpu_start='pinned analytic FP64 trajectory, not reinitialized to decoded GPU upload', + matched_cpu_initial_bits=False) + report['unshifted_comparison']=dict(status='descriptive_only_codecs_have_different_initial_bits', + reference_sha256=AUDIT_SHA,initial=sample_difference(report['initial'],previous['initial']),rows=[]) save() check_cap() phase = 'trajectory' @@ -297,18 +330,31 @@ def main(): row.update(step=step, momentum_change=(total(state,maps)-moment0)[1:].tolist(), mass_change=row['mass']-mass0, minimum_population=min(float(a[:,m].min()) for a,m in zip(arrays,masks))) - with context.activate(): - row['minimum_boundary_pre'] = float(run.read(run.pre,(len(run.plan.groups),4),np.float64).min()) - row['minimum_boundary_stored'] = float(run.read(run.h,(len(run.plan.groups),4)).min()) + if ledger_totals is not None: + row['minimum_boundary_pre'] = ledger['minimum_pre'] + row['minimum_boundary_stored'] = ledger['minimum_stored'] + else: + with context.activate(): + row['minimum_boundary_pre'] = float(run.read(run.pre,(len(run.plan.groups),4),np.float64).min()) + row['minimum_boundary_stored'] = float(run.read(run.h,(len(run.plan.groups),4)).min()) if not all(np.isfinite(value).all() for value in row.values()): report['failed_sample'] = {key: repr(value) for key,value in row.items()} raise FloatingPointError('nonfinite sample diagnostic') report['rows'].append(row) if previous: - changed = differing_fields(row,previous['rows'][len(report['rows'])-1]) - report['diagnostic']['sample_checks'].append(dict(step=step,differing_fields=changed)) - endpoint = ref.directional(ref.cpu.State(*(a.astype(np.float64) for a in arrays)),maps)-direction0 + expected=previous['rows'][len(report['rows'])-1] + changed = differing_fields(row,expected) if exact_repeat else [] + report['diagnostic']['sample_checks'].append(dict(step=step, + status='exact_repeat' if exact_repeat else 'descriptive_only',differing_fields=changed if exact_repeat else None)) + if args.shifted: + report['unshifted_comparison']['rows'].append(dict(step=step,fields=sample_difference(row,expected))) + raw_state=run._download_stored() if args.shifted else state + endpoint = ref.directional(ref.cpu.State(*(a.astype(np.float64) for a in + (raw_state.coarse_f,raw_state.fine_f))),maps)-direction0 prefix = ledger_totals.snapshot(endpoint) + if args.shifted: + prefix['physical_minus_raw_endpoint_moments'] = ( + total(state,maps)-moment0-ref.cpu.MOMENTS.T@endpoint).tolist() report['diagnostic']['prefixes'].append(prefix) if not prefix['closure_pass'] or not prefix['component_split_pass']: raise AssertionError('cumulative ledger does not close within summed existing per-step bounds') @@ -319,6 +365,9 @@ def main(): report['trajectory_seconds'] = time.monotonic()-trajectory_started check_cap() report.update(assess(report['rows'], cpu, uniform, run.health_counts)) + if args.shifted: + report['historical_pressure_gate'].update(status='historical_shifted_FP32_uniform_vs_shifted_FP32_candidate', + matched_storage=True,matched_control=False) report['completed'] = True report['passed'] = report['campaign_pass'] and report['experimental_pass'] if previous: diff --git a/tests/validation/multigrid/test_spacetime_gpu.py b/tests/validation/multigrid/test_spacetime_gpu.py index 1f9c225..6086538 100644 --- a/tests/validation/multigrid/test_spacetime_gpu.py +++ b/tests/validation/multigrid/test_spacetime_gpu.py @@ -277,6 +277,16 @@ class Host(unittest.TestCase): with self.assertRaisesRegex(ValueError,'pinned reference'): trajectory.load_references(path,path) + def test_shifted_descriptive_comparison_and_runner_pin(self): + expected=dict(mass=4096.,momentum=[0.,-1e-4]) + actual=dict(mass=4096.+2.**-20,momentum=[-1e-6,-2e-4]) + difference=trajectory.sample_difference(actual,expected) + self.assertEqual(difference['mass']['signed'],2.**-20) + self.assertEqual(difference['momentum']['absolute'],[1e-6,1e-4]) + self.assertEqual(trajectory.sha(Path(gpu.__file__).with_suffix('.cu')),trajectory.CUDA_SHA) + self.assertEqual(trajectory.LIMITS,dict(velocity_l2=.05,pressure_l2=.15,energy_relative=.05,mass_relative=1e-5)) + self.assertEqual(trajectory.FACTORS,dict(velocity_l2=.8,pressure_l2=1.,energy_relative=1.)) + def test_n64_table_guard_and_balanced_mutation(self): guard=trajectory.table_guard plan=ref.Plan(64,(8,8,56,48)); tables=gpu.pack_plan(plan)