From 95ebca89f6879ef71485d2fb30492020aca72144 Mon Sep 17 00:00:00 2001 From: huojiarong Date: Thu, 16 Jul 2026 09:31:12 +0000 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85test=5Fmql=E6=B0=94=E5=8A=A8?= =?UTF-8?q?=E6=94=AF=E8=B7=AF=E9=85=8D=E7=BD=AE=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PythonModels/systems/test_mql.py | 66 ++++++++++++++++++++++++ PythonModels/systems/test_mql_closure.py | 10 ++++ tests/test_test_mql_branch_simulation.py | 26 ++++++++++ 3 files changed, 102 insertions(+) diff --git a/PythonModels/systems/test_mql.py b/PythonModels/systems/test_mql.py index f9d6bdc..86ab151 100644 --- a/PythonModels/systems/test_mql.py +++ b/PythonModels/systems/test_mql.py @@ -3896,6 +3896,34 @@ class TestMqlSystem: def pneumatic_state_vector(self) -> list[float]: return self.network.initial_state_vector() + @staticmethod + def pneumatic_branch_spec( + *, + name: str, + upstream_volume_alias: str, + orifice_alias: str, + downstream_volume_alias: str, + source: str = "manual", + ): + from PythonModels.systems.test_mql_closure import TestMqlPneumaticBranchSpec + + return TestMqlPneumaticBranchSpec( + name=name, + upstream_volume_alias=upstream_volume_alias, + orifice_alias=orifice_alias, + downstream_volume_alias=downstream_volume_alias, + source=source, + ) + + def pneumatic_branch_closure_from_spec(self, spec): + return self.pneumatic_branch_closure( + name=spec.name, + upstream_volume_alias=spec.upstream_volume_alias, + orifice_alias=spec.orifice_alias, + downstream_volume_alias=spec.downstream_volume_alias, + spec=spec, + ) + def pneumatic_branch_closure( self, *, @@ -3903,6 +3931,7 @@ class TestMqlSystem: upstream_volume_alias: str, orifice_alias: str, downstream_volume_alias: str, + spec=None, ): from PythonModels.components.amesim_pneumatic import ( AmesimPneumaticOrifice, @@ -3910,6 +3939,7 @@ class TestMqlSystem: ) from PythonModels.systems.test_mql_closure import ( TestMqlPneumaticBranchComponents, + TestMqlPneumaticBranchSpec, TestMqlPneumaticClosure, ) @@ -3935,12 +3965,19 @@ class TestMqlSystem: upstream_volume.set_state_vector(values[:2]) downstream_volume.set_state_vector(values[2:]) + branch_spec = spec or TestMqlPneumaticBranchSpec( + name=name, + upstream_volume_alias=upstream_volume_alias, + orifice_alias=orifice_alias, + downstream_volume_alias=downstream_volume_alias, + ) return TestMqlPneumaticClosure( components=TestMqlPneumaticBranchComponents( name=name, upstream_volume=upstream_volume, orifice=orifice, downstream_volume=downstream_volume, + spec=branch_spec, ), initial_state_vector=initial_state_vector, apply_state_vector=apply_state_vector, @@ -3970,6 +4007,35 @@ class TestMqlSystem: t_eval=t_eval, ) + def simulate_pneumatic_branch_from_spec( + self, + spec, + *, + config: SolveIVPConfig | None = None, + t_eval: list[float] | None = None, + ): + return self.simulate_pneumatic_branch( + name=spec.name, + upstream_volume_alias=spec.upstream_volume_alias, + orifice_alias=spec.orifice_alias, + downstream_volume_alias=spec.downstream_volume_alias, + config=config, + t_eval=t_eval, + ) + + def evaluate_pneumatic_branch_solution_from_spec( + self, + solution: object, + spec, + ) -> dict[str, list[float]]: + return self.evaluate_pneumatic_branch_solution( + solution, + name=spec.name, + upstream_volume_alias=spec.upstream_volume_alias, + orifice_alias=spec.orifice_alias, + downstream_volume_alias=spec.downstream_volume_alias, + ) + def evaluate_pneumatic_branch_solution( self, solution: object, diff --git a/PythonModels/systems/test_mql_closure.py b/PythonModels/systems/test_mql_closure.py index ece137d..7c84ac2 100644 --- a/PythonModels/systems/test_mql_closure.py +++ b/PythonModels/systems/test_mql_closure.py @@ -11,12 +11,22 @@ from PythonModels.core.medium import ThermodynamicProperties from PythonModels.core.state import VolumeState +@dataclass(frozen=True) +class TestMqlPneumaticBranchSpec: + name: str + upstream_volume_alias: str + orifice_alias: str + downstream_volume_alias: str + source: str = "manual" + + @dataclass(frozen=True) class TestMqlPneumaticBranchComponents: name: str upstream_volume: AmesimPneumaticVolume orifice: AmesimPneumaticOrifice downstream_volume: AmesimPneumaticVolume + spec: TestMqlPneumaticBranchSpec | None = None @dataclass(frozen=True) diff --git a/tests/test_test_mql_branch_simulation.py b/tests/test_test_mql_branch_simulation.py index ea88c9d..2002d74 100644 --- a/tests/test_test_mql_branch_simulation.py +++ b/tests/test_test_mql_branch_simulation.py @@ -60,6 +60,32 @@ class TestMqlPneumaticBranchSimulationTests(unittest.TestCase): series["sample_branch.flow"][0], ) + def test_pneumatic_branch_spec_drives_closure_and_simulation(self) -> None: + system = TestMqlSystem() + spec = system.pneumatic_branch_spec( + name="sample_branch", + upstream_volume_alias="pn_general_chamber", + orifice_alias="pn_orifice_18", + downstream_volume_alias="pn_c1_8", + source="manual-test", + ) + + closure = system.pneumatic_branch_closure_from_spec(spec) + solution = system.simulate_pneumatic_branch_from_spec( + spec, + config=SolveIVPConfig(t_start=0.0, t_stop=1.0e-5, max_step=1.0e-6), + t_eval=[0.0, 1.0e-5], + ) + series = system.evaluate_pneumatic_branch_solution_from_spec(solution, spec) + + self.assertIs(closure.components.spec, spec) + self.assertEqual(spec.source, "manual-test") + self.assertEqual(len(solution.t), 2) + self.assertIn("sample_branch.flow", series) + self.assertGreater(series["sample_branch.flow"][0], 0.0) + self.assertGreater(series["pn_general_chamber.p"][0], series["pn_general_chamber.p"][-1]) + self.assertLess(series["pn_c1_8.p"][0], series["pn_c1_8.p"][-1]) + def test_simulate_pneumatic_branch_rejects_invalid_component_aliases(self) -> None: system = TestMqlSystem()