"""Native event integration checked against independent Amesim 2404 runs.""" import json from pathlib import Path import subprocess import tempfile import unittest import numpy as np from app.simulation.native_codegen.compiler import compile_native_program from app.simulation.native_codegen.build import build_native from app.simulation.native_codegen.result_storage import scan_blocks from tests.test_native_catalog import Circuit FIXTURE=Path(__file__).parent/'fixtures/amesim-component-semantics-2404.json' class NativeFrictionReferenceTests(unittest.TestCase): def test_amesim_stick_slip_endstops_and_joint_circuits(self): for case in json.loads(FIXTURE.read_text(encoding='utf-8'))['cases']: b=Circuit() for c in case['components']:b.add(c['type'],c['name'],**c['parameters']) for l,r in case['connections']:b.net.connect(*l,*r) program=compile_native_program(b.net) build=build_native(program) self.addCleanup(build.close) methods=('BDF','RK45') if case['name'] in ('friction_simple','friction_band') else ('BDF',) for method in methods: with self.subTest(case=case['name'],method=method),tempfile.TemporaryDirectory() as tmp: path=Path(tmp)/'result.json' state_path=Path(tmp)/'states.bin';output_path=Path(tmp)/'outputs.bin' subprocess.run([str(build.executable),'--method',method,'--stop','3','--sample-step','.001', '--max-step','.002','--rtol','1e-9','--timeout','30','--output',str(path), '--sample-file',str(state_path),'--output-block-file',str(output_path)], check=True,capture_output=True,timeout=45) result=json.loads(path.read_text()) self.assertTrue(result['success'],result) self.assertEqual(result['simulatedUntil'],3) for blocks, columns in ((state_path,len(program.state_keys)+1), (output_path,len(program.variables)+1)): stored=scan_blocks(blocks,expected_columns=columns) self.assertGreater(stored['blocks'],1) self.assertEqual(stored['samples'],len(result['series']['time'])) self.assertFalse(stored['incompleteTail'] or stored['corrupt']) for key,expected in case['series'].items(): actual=np.interp(case['time'],result['series']['time'],result['series'][key]) field=key.split('.')[-1] atol=1 if field.startswith('p') else .001 if field.startswith('T') else .002 if field in ('a','Ffric','Fmin','Fmax','force') else 3e-6 np.testing.assert_allclose(actual,expected,rtol=0,atol=atol,err_msg=key) if case['name'].startswith('friction_'): # Stored mode makes result replay independent of query order. state=result['finalState'] inputs=[' '.join(map(str,[t,*state])) for t in (2.8,.1,2.8)] rows=subprocess.run([str(build.executable),'--probe'],input='\n'.join(inputs)+'\n', text=True,capture_output=True,check=True,timeout=15).stdout.splitlines() self.assertEqual(json.loads(rows[0]),json.loads(rows[2])) if __name__=='__main__':unittest.main()