76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
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
|
|
/ "data"
|
|
/ "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()
|