from __future__ import annotations import unittest from pathlib import Path from app.simulation.reporting.amesim_results import load_test_mql_amesim_results from app.simulation.reporting.test_mql_line_observations import ( G_PER_S_TO_KG_PER_S, build_test_mql_line_observation_catalog, ) REPO_ROOT = Path(__file__).resolve().parents[1] TEST_MQL_AME = REPO_ROOT / "AmesimModels" / "test_mql.ame" class TestMqlLineObservationCatalogTests(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.amesim_results = load_test_mql_amesim_results(TEST_MQL_AME) cls.catalog = build_test_mql_line_observation_catalog(cls.amesim_results) def test_builds_expected_line_observation_counts(self) -> None: self.assertEqual(self.catalog.line_count, 40) self.assertEqual(len(self.catalog.by_submodel("PNL0001")), 20) self.assertEqual(len(self.catalog.by_submodel("PNL0002")), 8) self.assertEqual(len(self.catalog.by_submodel("PNL0003")), 8) self.assertEqual(len(self.catalog.by_submodel("PNL00R")), 4) def test_pnl0001_binding_exposes_single_flow_and_compliance_observables(self) -> None: binding = self.catalog.by_alias("pneumatic_69") self.assertEqual(binding.submodel, "PNL0001") self.assertEqual(binding.pattern, "C-R") self.assertEqual(binding.mass_flow_paths, ("dm1@pneumatic_69",)) self.assertEqual(binding.enthalpy_flow_paths, ("dh1@pneumatic_69",)) self.assertEqual(binding.pressure_paths, ("p2@pneumatic_69",)) self.assertEqual(binding.temperature_paths, ("t2@pneumatic_69",)) self.assertEqual(binding.gas_mass_path, "mgas@pneumatic_69") self.assertEqual(binding.reynolds_path, "re@pneumatic_69") self.assertEqual(binding.mass_flow_parameter_path, "cm@pneumatic_69") self.assertEqual(binding.gas_velocity_path, "v@pneumatic_69") self.assertEqual(binding.friction_factor_path, "ff@pneumatic_69") def test_pnl0002_and_pnl0003_keep_distinct_flow_topologies(self) -> None: rcr = self.catalog.by_alias("pneumatic_80") crc = self.catalog.by_alias("pneumatic_75") self.assertEqual(rcr.pattern, "R-C-R") self.assertEqual(rcr.mass_flow_paths, ("dm1@pneumatic_80", "dm2@pneumatic_80")) self.assertEqual(rcr.enthalpy_flow_paths, ("dh1@pneumatic_80", "dh2@pneumatic_80")) self.assertEqual(rcr.pressure_paths, ("pctr@pneumatic_80",)) self.assertEqual(rcr.temperature_paths, ("tctr@pneumatic_80",)) self.assertEqual(crc.pattern, "C-R-C") self.assertEqual(crc.mass_flow_paths, ("dmctr@pneumatic_75",)) self.assertEqual(crc.enthalpy_flow_paths, ("dhctr@pneumatic_75",)) self.assertEqual(crc.pressure_paths, ("p1@pneumatic_75", "p2@pneumatic_75")) self.assertEqual(crc.temperature_paths, ("t1@pneumatic_75", "t2@pneumatic_75")) def test_mass_flow_series_are_converted_to_si_units(self) -> None: binding = self.catalog.by_alias("pneumatic_69") mass_flow = binding.mass_flow_kg_s_series(self.amesim_results) self.assertAlmostEqual( mass_flow[-1], self.amesim_results.series("dm1@pneumatic_69")[-1] * G_PER_S_TO_KG_PER_S, ) self.assertAlmostEqual(mass_flow[-1], -9.527778353091475e-6) self.assertAlmostEqual(max(mass_flow), 0.4490761730524304) def test_observation_exposes_line_state_and_diagnostics(self) -> None: observation = self.catalog.by_alias("pneumatic_75").observation_at( self.amesim_results, -1, ) self.assertAlmostEqual(observation.time, self.amesim_results.times[-1]) self.assertAlmostEqual( observation.mass_flows_kg_s["dmctr@pneumatic_75"], 9.486502325625855e-6, ) self.assertAlmostEqual( observation.enthalpy_flows_w["dhctr@pneumatic_75"], -0.7322143070637952, ) self.assertAlmostEqual(observation.pressures_pa["p1@pneumatic_75"], 4310289.672688478) self.assertAlmostEqual(observation.pressures_pa["p2@pneumatic_75"], 4310295.447776705) self.assertAlmostEqual(observation.temperatures_k["t1@pneumatic_75"], 281.37837485614546) self.assertAlmostEqual(observation.temperatures_k["t2@pneumatic_75"], 282.9136549991407) self.assertAlmostEqual(observation.gas_mass_g, 0.7031236652270819) self.assertAlmostEqual(observation.reynolds_number, 31.539799199000434) self.assertAlmostEqual(observation.mass_flow_parameter, 6.351754064211156e-07) self.assertAlmostEqual(observation.gas_velocity_m_s, 0.0040585650473562935) self.assertAlmostEqual(observation.friction_factor, 2.0291822277051246) def test_resistance_only_lines_preserve_reversed_duplicate_signs(self) -> None: for binding in self.catalog.by_submodel("PNL00R"): dm1 = self.amesim_results.series(f"dm1@{binding.alias}") dm2 = self.amesim_results.series(f"dm2@{binding.alias}") dh1 = self.amesim_results.series(f"dh1@{binding.alias}") dh2 = self.amesim_results.series(f"dh2@{binding.alias}") with self.subTest(alias=binding.alias): self.assertIsNone(binding.gas_mass_path) self.assertEqual(binding.pressure_paths, ()) self.assertEqual(binding.temperature_paths, ()) self.assertLess(max(abs(a + b) for a, b in zip(dm1, dm2)), 1.0e-36) self.assertLess(max(abs(a + b) for a, b in zip(dh1, dh2)), 1.0e-34) if __name__ == "__main__": unittest.main()