from __future__ import annotations from copy import deepcopy import subprocess import unittest from xml.etree import ElementTree as ET from app.main import run_system_xml_simulation from app.simulation.native_codegen.build import toolchain from app.simulation.native_codegen.input import project_xml from app.system_xml import validate_system_xml_document from tests.test_amesim_pnch012_xml import amesim_pnch012_project def pressure_project(value: float | str, unit: str = "bar") -> dict: project = amesim_pnch012_project().model_dump(mode="json") chamber = project["nodes"][0]["data"] chamber["parameters"]["p0"] = value chamber["parameterUnits"]["p0"] = unit return project class PressureUnitInputTests(unittest.TestCase): def test_absolute_bar_expression_exports_si_without_atmospheric_offset(self) -> None: project = pressure_project("= 0.25 + 0.75") original = deepcopy(project) xml = project_xml(project) root = ET.fromstring(xml) self.assertEqual(root.attrib["unitSystem"], "SI") parameter = root.find( "./Components/Component[@id='chamber_1']/Parameter[@name='p0']" ) self.assertIsNotNone(parameter) self.assertEqual(float(parameter.attrib["value"]), 100000.0) self.assertNotIn("unit", parameter.attrib) report = validate_system_xml_document(xml) self.assertTrue(report.valid, report.as_dict()) self.assertEqual(project, original) def test_saved_numeric_values_are_already_si_with_absolute_bar_display(self) -> None: for value in (250000.0, "250000"): with self.subTest(value=value): self.assertEqual( project_xml(pressure_project(value)), project_xml(pressure_project(250000.0, "Pa")), ) def test_absolute_bar_and_existing_pressure_expression_units_are_equivalent(self) -> None: expected = project_xml(pressure_project(250000.0, "Pa")) for unit, expression in ( ("bar", "2 + 0.5"), ("kPa", "200 + 50"), ("MPa", "0.2 + 0.05"), ("Pa", "200000 + 50000"), ): with self.subTest(unit=unit): self.assertEqual(project_xml(pressure_project(expression, unit)), expected) def test_absolute_bar_and_pa_simulations_return_identical_si_pressure(self) -> None: try: toolchain() except (OSError, RuntimeError, subprocess.SubprocessError) as exc: self.skipTest(f"Native toolchain unavailable: {exc}") absolute_bar = run_system_xml_simulation( project_xml(pressure_project("2 + 0.5", "bar")) ) pascals = run_system_xml_simulation( project_xml(pressure_project(250000.0, "Pa")) ) self.assertTrue(absolute_bar["success"], absolute_bar["message"]) self.assertTrue(pascals["success"], pascals["message"]) self.assertEqual(absolute_bar["series"], pascals["series"]) self.assertEqual(absolute_bar["series"]["time"], [0.0, 0.001, 0.002]) for pressure in absolute_bar["series"]["chamber_1.p"]: self.assertAlmostEqual(pressure, 250000.0, places=6) pressure_metadata = next( variable for variable in absolute_bar["variables"] if variable["key"] == "chamber_1.p" ) self.assertEqual(pressure_metadata["unit"], "Pa") if __name__ == "__main__": unittest.main()