from __future__ import annotations import hashlib import math from pathlib import Path import unittest from app.main import run_system_xml_simulation FIXTURE_PATH = ( Path(__file__).resolve().parent / "fixtures" / "high_stiffness_explicit_rk45.xml" ) ORIGINAL_XML_SHA256 = ( "27048a99da0a21922d75785b760c3b5d04be3349b8aef6fbfedfd811d87ef1d5" ) def short_explicit_rk45_xml() -> bytes: original = FIXTURE_PATH.read_bytes() canonical = original.replace(b"\r\n", b"\n").rstrip(b"\n") if hashlib.sha256(canonical).hexdigest() != ORIGINAL_XML_SHA256: raise AssertionError("The high-stiffness RK45 fixture differs from the user XML.") if original.count(b'tStop="10"') != 1: raise AssertionError("Expected one original simulation stop time.") if original.count(b'sampleStep="0.02"') != 1: raise AssertionError("Expected one original simulation sample step.") return original.replace( b'tStop="10"', b'tStop="0.005"', 1, ).replace( b'sampleStep="0.02"', b'sampleStep="0.001"', 1, ) class HighStiffnessExplicitRk45RegressionTests(unittest.TestCase): def test_short_user_model_crosses_the_early_stiff_limit_event(self) -> None: result = run_system_xml_simulation( short_explicit_rk45_xml(), cancel_check=lambda: False, ) self.assertTrue(result["success"], result["message"]) self.assertEqual(result["status"], "completed") self.assertFalse(result["partial"]) self.assertEqual(result["simulatedUntil"], 0.005) self.assertNotIn("provided bounds", result["message"]) integration = result["diagnostics"]["integration"] totals = integration["totals"] self.assertEqual(integration["method"], "RK45") self.assertGreaterEqual(totals["stateTransitionCount"], 1) self.assertGreaterEqual(totals["solverStartCount"], 2) series = result["series"] times = series["time"] self.assertEqual(times[0], 0.0) self.assertEqual(times[-1], 0.005) self.assertTrue( all(first < second for first, second in zip(times, times[1:])) ) self.assertTrue(any(0.0 < time < 0.001 for time in times)) for values in series.values(): self.assertEqual(len(values), len(times)) self.assertTrue(all(math.isfinite(value) for value in values)) if __name__ == "__main__": unittest.main()