diff --git a/PythonModels/systems/test_mql_computed.py b/PythonModels/systems/test_mql_computed.py index bc6dc1f..e13bfb9 100644 --- a/PythonModels/systems/test_mql_computed.py +++ b/PythonModels/systems/test_mql_computed.py @@ -67,6 +67,23 @@ class TestMqlComputedGeometryRun: return len(self.output.data_paths) +@dataclass(frozen=True) +class TestMqlComputedLineRelationsRun: + amesim_results: AmesimResults + observation_catalog: TestMqlObservationCatalog + output_schema: TestMqlOutputSchema + output: TestMqlValidatedOutput + comparison: TestMqlComparisonResult + + @property + def sample_count(self) -> int: + return len(self.output.times) + + @property + def signal_count(self) -> int: + return len(self.output.data_paths) + + @dataclass(frozen=True) class TestMqlComputedPneumaticRelationsRun: amesim_results: AmesimResults @@ -189,6 +206,39 @@ def run_test_mql_computed_geometry( ) +def run_test_mql_computed_line_relations( + archive_path: Path, +) -> TestMqlComputedLineRelationsRun: + amesim_results = load_test_mql_amesim_results(archive_path) + observation_catalog = build_test_mql_observation_catalog(amesim_results) + output_schema = build_test_mql_output_schema( + amesim_results, + observation_catalog=observation_catalog, + ) + output_series = _compute_line_reversed_series(amesim_results, observation_catalog) + output_data_paths = tuple(output_series) + output = validate_test_mql_output( + times=amesim_results.times, + series_by_data_path=output_series, + schema=output_schema, + data_paths=output_data_paths, + ) + comparison = compare_validated_test_mql_output( + times=output.times, + series_by_data_path=output.series_by_data_path, + schema=output_schema, + amesim_results=amesim_results, + data_paths=output.data_paths, + ) + return TestMqlComputedLineRelationsRun( + amesim_results=amesim_results, + observation_catalog=observation_catalog, + output_schema=output_schema, + output=output, + comparison=comparison, + ) + + def run_test_mql_computed_pneumatic_relations( archive_path: Path, ) -> TestMqlComputedPneumaticRelationsRun: @@ -397,3 +447,22 @@ def _compute_orifice_reversed_series( ) return series_by_data_path + +def _compute_line_reversed_series( + amesim_results: AmesimResults, + observation_catalog: TestMqlObservationCatalog, +) -> dict[str, tuple[float, ...]]: + series_by_data_path: dict[str, tuple[float, ...]] = {} + for binding in observation_catalog.lines.by_submodel("PNL00R"): + if len(binding.mass_flow_paths) != 2 or len(binding.enthalpy_flow_paths) != 2: + raise ValueError(f"Expected two PNL00R flow paths for {binding.alias}.") + primary_mass_path, reversed_mass_path = binding.mass_flow_paths + primary_enthalpy_path, reversed_enthalpy_path = binding.enthalpy_flow_paths + series_by_data_path[reversed_mass_path] = tuple( + -value for value in amesim_results.series(primary_mass_path) + ) + series_by_data_path[reversed_enthalpy_path] = tuple( + -value for value in amesim_results.series(primary_enthalpy_path) + ) + return series_by_data_path + diff --git a/tests/test_test_mql_computed.py b/tests/test_test_mql_computed.py index e51f511..96b5c18 100644 --- a/tests/test_test_mql_computed.py +++ b/tests/test_test_mql_computed.py @@ -5,6 +5,7 @@ from pathlib import Path from PythonModels.systems.test_mql_computed import ( run_test_mql_computed_geometry, + run_test_mql_computed_line_relations, run_test_mql_computed_mechanical_relations, run_test_mql_computed_piston_geometry, run_test_mql_computed_pneumatic_relations, @@ -111,6 +112,43 @@ class TestMqlComputedGeometryTests(unittest.TestCase): ) +class TestMqlComputedLineRelationsTests(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.computed_run = run_test_mql_computed_line_relations(TEST_MQL_AME) + + def test_computed_line_relations_outputs_schema_valid_series(self) -> None: + self.assertEqual(self.computed_run.sample_count, 1002) + self.assertEqual(len(self.computed_run.observation_catalog.lines.by_submodel("PNL00R")), 4) + self.assertEqual(self.computed_run.signal_count, 8) + self.assertEqual(len(self.computed_run.comparison.metrics), 8) + self.assertEqual(self.computed_run.output_schema.signal_count, 858) + + def test_computed_line_relations_include_expected_paths(self) -> None: + paths = self.computed_run.output.data_paths + + self.assertIn("dm2@pneumatic_100", paths) + self.assertIn("dh2@pneumatic_100", paths) + self.assertEqual(len([path for path in paths if path.startswith("dm2@")]), 4) + self.assertEqual(len([path for path in paths if path.startswith("dh2@")]), 4) + + def test_computed_line_relations_match_amesim_exactly(self) -> None: + for data_path in self.computed_run.output.data_paths: + metric = self.computed_run.comparison.metric(data_path) + with self.subTest(data_path=data_path): + self.assertEqual(metric.max_abs_error, 0.0) + + def test_computed_line_relations_final_samples_match_expected_values(self) -> None: + self.assertAlmostEqual( + self.computed_run.output.series("dm2@pneumatic_100")[-1], + 1.4837698580885316e-30, + ) + self.assertAlmostEqual( + self.computed_run.output.series("dh2@pneumatic_100")[-1], + -1.2638893078048237e-28, + ) + + class TestMqlComputedPneumaticRelationsTests(unittest.TestCase): @classmethod def setUpClass(cls) -> None: