装配test_mql气动元件

This commit is contained in:
huojiarong committed 2026-07-15 09:43:34 +00:00
1 parent 1f47171d07
commit 33c8bfae3d
3 files changed
+220 -2

No files matched your search

+10 -2
View File
@@ -63,6 +63,14 @@
- `tests/test_test_mql_comparison.py`
- 保护 AMESim 原始序列零误差对齐、粗时间步插值、偏移误差统计、缺失变量报错和 CSV 输出。
- `PythonModels/systems/test_mql_pneumatic.py`
- 把 AMESim 配置中的 `PNCH023`、`PNCH012`、`PNOR001`、`PNVO001` 装配成 Python 气动对象。
- 当前覆盖 4 个固定气室、8 个变容气室、8 个固定孔口、8 个可变孔口,alias 沿用 AMESim 原名。
- 初始压力按 AMESim 全局参数 `P0=153 bar` 和大气压 `1.013 bar` 转成 `15198700 Pa`。
- `tests/test_test_mql_pneumatic.py`
- 保护气动装配数量、alias、氦气工质、气室体积、孔口面积/流量系数和基础质量流量计算。
## 物性约定
AMESim 模型中 `test_mql` 使用氦气,Python 侧当前通过 `HELIUM_PR` 使用 Peng-Robinson 状态方程计算气体压缩因子和密度。当前物性层先覆盖状态方程相关量,完整焓/内能偏差函数后续在接气室能量方程时再补。
@@ -109,12 +117,12 @@ AMESim 模型中 `test_mql` 使用氦气,Python 侧当前通过 `HELIUM_PR`
## 验证方式
```bash
python3 -m py_compile PythonModels/components/amesim_pneumatic.py PythonModels/core/peng_robinson.py PythonModels/reporting/amesim_results.py PythonModels/reporting/test_mql_comparison.py PythonModels/systems/test_mql.py PythonModels/systems/test_mql_config.py PythonModels/scripts/run_test_mql.py
python3 -m py_compile PythonModels/components/amesim_pneumatic.py PythonModels/core/peng_robinson.py PythonModels/reporting/amesim_results.py PythonModels/reporting/test_mql_comparison.py PythonModels/systems/test_mql.py PythonModels/systems/test_mql_config.py PythonModels/systems/test_mql_pneumatic.py PythonModels/scripts/run_test_mql.py
python3 -m PythonModels.scripts.run_test_mql
python3 -m unittest discover -s tests -t .
```
当前测试覆盖的是结构、配置解析、气动原语、AMESim 结果读取和 AMESim/Python 时序对齐工具,不代表已经完成 AMESim 物理结果复刻。
当前测试覆盖的是结构、配置解析、气动原语、气动件装配、AMESim 结果读取和 AMESim/Python 时序对齐工具,不代表已经完成 AMESim 物理结果复刻。
## 后续方向
+142
View File
@@ -0,0 +1,142 @@
from __future__ import annotations
from dataclasses import dataclass
from PythonModels.components.amesim_pneumatic import (
HELIUM_PNEUMATIC_GAS,
AmesimPneumaticGas,
AmesimPneumaticOrifice,
AmesimPneumaticVolume,
)
from PythonModels.systems.test_mql_config import TestMqlConfig, TestMqlResolvedComponent
ATMOSPHERIC_PRESSURE_BAR = 1.013
BAR_TO_PA = 1.0e5
DEFAULT_TEST_MQL_TEMPERATURE_K = 293.15
@dataclass(frozen=True)
class TestMqlPneumaticAssembly:
fixed_chambers: dict[str, AmesimPneumaticVolume]
variable_chambers: dict[str, AmesimPneumaticVolume]
fixed_orifices: dict[str, AmesimPneumaticOrifice]
variable_orifices: dict[str, AmesimPneumaticOrifice]
initial_pressure_pa: float
@property
def chamber_count(self) -> int:
return len(self.fixed_chambers) + len(self.variable_chambers)
@property
def orifice_count(self) -> int:
return len(self.fixed_orifices) + len(self.variable_orifices)
@property
def component_count(self) -> int:
return self.chamber_count + self.orifice_count
@property
def aliases(self) -> tuple[str, ...]:
return tuple(
[
*self.fixed_chambers,
*self.variable_chambers,
*self.fixed_orifices,
*self.variable_orifices,
]
)
def build_test_mql_pneumatic_assembly(
config: TestMqlConfig | None = None,
gas: AmesimPneumaticGas = HELIUM_PNEUMATIC_GAS,
) -> TestMqlPneumaticAssembly:
config = config or TestMqlConfig.from_amesim_specs()
initial_pressure_pa = pressure_from_amesim_bar_parameter(config.global_parameters["P0"])
fixed_chambers = {
component.alias: _build_chamber(
component,
volume_parameter="cvol",
gas=gas,
initial_pressure_pa=initial_pressure_pa,
)
for component in config.components_by_submodel("PNCH023")
}
variable_chambers = {
component.alias: _build_chamber(
component,
volume_parameter="cvol0",
gas=gas,
initial_pressure_pa=initial_pressure_pa,
)
for component in config.components_by_submodel("PNCH012")
}
fixed_orifices = {
component.alias: _build_orifice(
component,
area_parameter="area",
gas=gas,
opening=1.0,
)
for component in config.components_by_submodel("PNOR001")
}
variable_orifices = {
component.alias: _build_orifice(
component,
area_parameter="area0",
gas=gas,
opening=1.0,
)
for component in config.components_by_submodel("PNVO001")
}
return TestMqlPneumaticAssembly(
fixed_chambers=fixed_chambers,
variable_chambers=variable_chambers,
fixed_orifices=fixed_orifices,
variable_orifices=variable_orifices,
initial_pressure_pa=initial_pressure_pa,
)
def pressure_from_amesim_bar_parameter(pressure_bar: float) -> float:
return (pressure_bar - ATMOSPHERIC_PRESSURE_BAR) * BAR_TO_PA
def _build_chamber(
component: TestMqlResolvedComponent,
*,
volume_parameter: str,
gas: AmesimPneumaticGas,
initial_pressure_pa: float,
) -> AmesimPneumaticVolume:
return AmesimPneumaticVolume.from_liters(
name=component.alias,
volume_liters=component.parameter_value(volume_parameter),
gas=gas,
p0=initial_pressure_pa,
T0=_component_temperature(component),
)
def _build_orifice(
component: TestMqlResolvedComponent,
*,
area_parameter: str,
gas: AmesimPneumaticGas,
opening: float,
) -> AmesimPneumaticOrifice:
return AmesimPneumaticOrifice.from_mm2(
name=component.alias,
area_mm2=component.parameter_value(area_parameter),
flow_coefficient=component.parameter_value("cq"),
gas=gas,
opening=opening,
)
def _component_temperature(component: TestMqlResolvedComponent) -> float:
parameter = component.parameters.get("extemp")
if parameter is None or parameter.value is None:
return DEFAULT_TEST_MQL_TEMPERATURE_K
return parameter.value
+68
View File
@@ -0,0 +1,68 @@
from __future__ import annotations
import unittest
from PythonModels.components.amesim_pneumatic import HELIUM_PNEUMATIC_GAS
from PythonModels.systems.test_mql_pneumatic import (
build_test_mql_pneumatic_assembly,
pressure_from_amesim_bar_parameter,
)
class TestMqlPneumaticAssemblyTests(unittest.TestCase):
def test_assembles_expected_amesim_pneumatic_component_counts(self) -> None:
assembly = build_test_mql_pneumatic_assembly()
self.assertEqual(len(assembly.fixed_chambers), 4)
self.assertEqual(len(assembly.variable_chambers), 8)
self.assertEqual(len(assembly.fixed_orifices), 8)
self.assertEqual(len(assembly.variable_orifices), 8)
self.assertEqual(assembly.component_count, 28)
self.assertIn("pn_general_chamber", assembly.aliases)
self.assertIn("pn_c1_8", assembly.aliases)
self.assertIn("pn_orifice_18", assembly.aliases)
self.assertIn("pn_morifice_11", assembly.aliases)
def test_uses_amesim_global_initial_pressure_convention(self) -> None:
assembly = build_test_mql_pneumatic_assembly()
self.assertAlmostEqual(
pressure_from_amesim_bar_parameter(153.0),
15198700.0,
)
self.assertAlmostEqual(assembly.initial_pressure_pa, 15198700.0)
def test_chamber_parameters_are_resolved_in_si_units(self) -> None:
assembly = build_test_mql_pneumatic_assembly()
fixed_chamber = assembly.fixed_chambers["pn_general_chamber"]
variable_chamber = assembly.variable_chambers["pn_c1_8"]
self.assertAlmostEqual(fixed_chamber.volume, 0.057)
self.assertAlmostEqual(variable_chamber.volume, 0.015)
self.assertIs(fixed_chamber.gas, HELIUM_PNEUMATIC_GAS)
self.assertIs(variable_chamber.gas, HELIUM_PNEUMATIC_GAS)
self.assertAlmostEqual(fixed_chamber.properties().T, 293.15)
self.assertAlmostEqual(variable_chamber.properties().T, 293.15)
def test_orifice_parameters_are_resolved_in_si_units(self) -> None:
assembly = build_test_mql_pneumatic_assembly()
fixed_orifice = assembly.fixed_orifices["pn_orifice_18"]
variable_orifice = assembly.variable_orifices["pn_morifice_11"]
self.assertAlmostEqual(fixed_orifice.area, 78.5e-6)
self.assertAlmostEqual(fixed_orifice.flow_coefficient, 0.9)
self.assertAlmostEqual(variable_orifice.area, 78.5e-6)
self.assertAlmostEqual(variable_orifice.flow_coefficient, 0.45)
self.assertAlmostEqual(variable_orifice.opening, 1.0)
def test_assembled_orifice_can_compute_helium_mass_flow(self) -> None:
assembly = build_test_mql_pneumatic_assembly()
fixed_orifice = assembly.fixed_orifices["pn_orifice_18"]
flow = fixed_orifice.mass_flow(15.0e6, 10.0e6, 293.15)
self.assertGreater(flow, 0.0)
if __name__ == "__main__":
unittest.main()