完善仿真交互、结果展示与模型元数据
This commit is contained in:
1 parent
f1256a121d
commit
f7f1078911
26 files changed
+9042
-575
No files matched your search
@@ -0,0 +1,136 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from PythonModels.components.cylinder import Cylinder
|
||||
from PythonModels.components.orifice import Orifice
|
||||
from PythonModels.components.pipe import Pipe
|
||||
from PythonModels.components.resistive_pipe import ResistivePipe
|
||||
from PythonModels.components.tank import Tank
|
||||
from PythonModels.components.tee import Tee
|
||||
from PythonModels.core.medium import IdealGasMedium
|
||||
from PythonModels.core.ports import PortVariableDefinition
|
||||
from PythonModels.registry import COMPONENT_MODEL_REGISTRY
|
||||
|
||||
|
||||
class ComponentMetadataTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.medium = IdealGasMedium()
|
||||
|
||||
def component_instances(self):
|
||||
return (
|
||||
Cylinder("cylinder_1", self.medium),
|
||||
Tank("tank_1", self.medium),
|
||||
Pipe("pipe_dynamic_1", self.medium),
|
||||
ResistivePipe("pipe_1", self.medium),
|
||||
Orifice("orifice_1"),
|
||||
Tee("tee_1"),
|
||||
)
|
||||
|
||||
def test_every_component_declares_a_complete_model_contract(self) -> None:
|
||||
for component in self.component_instances():
|
||||
with self.subTest(component=component.name):
|
||||
for attribute in (
|
||||
"MODEL_TYPE",
|
||||
"PORTS",
|
||||
"PARAMETERS",
|
||||
"RESULT_VARIABLES",
|
||||
):
|
||||
self.assertIn(attribute, type(component).__dict__)
|
||||
self.assertTrue(component.MODEL_TYPE)
|
||||
self.assertEqual(component.model_type, component.MODEL_TYPE)
|
||||
self.assertEqual(component.port_definitions, component.PORTS)
|
||||
self.assertEqual(
|
||||
set(component.parameter_values),
|
||||
{definition.name for definition in component.PARAMETERS},
|
||||
)
|
||||
self.assertTrue(
|
||||
all(definition.label for definition in component.PARAMETERS)
|
||||
)
|
||||
self.assertTrue(
|
||||
all(definition.quantity for definition in component.PARAMETERS)
|
||||
)
|
||||
|
||||
def test_registry_reuses_component_parameter_and_port_declarations(self) -> None:
|
||||
registered_classes = {
|
||||
"cylinder": Cylinder,
|
||||
"tank": Tank,
|
||||
"pipe": ResistivePipe,
|
||||
"orifice": Orifice,
|
||||
"tee": Tee,
|
||||
}
|
||||
for model_type, component_class in registered_classes.items():
|
||||
with self.subTest(model_type=model_type):
|
||||
spec = COMPONENT_MODEL_REGISTRY[model_type]
|
||||
self.assertEqual(spec.model_type, component_class.MODEL_TYPE)
|
||||
self.assertEqual(spec.ports, component_class.PORTS)
|
||||
self.assertEqual(spec.parameters, component_class.PARAMETERS)
|
||||
component = spec.create(f"{model_type}_1", self.medium, {})
|
||||
self.assertEqual(
|
||||
component.parameter_values,
|
||||
{
|
||||
definition.name: definition.default
|
||||
for definition in component_class.PARAMETERS
|
||||
},
|
||||
)
|
||||
|
||||
def test_result_metadata_exactly_describes_each_exposed_value(self) -> None:
|
||||
for component in self.component_instances():
|
||||
with self.subTest(component=component.name):
|
||||
values = component.result_values()
|
||||
metadata = component.result_variable_metadata()
|
||||
keys = [variable.key for variable in metadata]
|
||||
self.assertEqual(len(keys), len(set(keys)))
|
||||
self.assertEqual(
|
||||
set(values),
|
||||
{
|
||||
variable.key.removeprefix(f"{component.name}.")
|
||||
for variable in metadata
|
||||
},
|
||||
)
|
||||
self.assertTrue(all(variable.label for variable in metadata))
|
||||
self.assertTrue(all(variable.quantity for variable in metadata))
|
||||
|
||||
def test_storage_and_port_variables_include_display_metadata(self) -> None:
|
||||
cylinder = Cylinder("cylinder_1", self.medium)
|
||||
metadata = {
|
||||
variable.key: variable
|
||||
for variable in cylinder.result_variable_metadata()
|
||||
}
|
||||
|
||||
pressure = metadata["cylinder_1.p"]
|
||||
self.assertEqual(pressure.scope, "component")
|
||||
self.assertEqual(pressure.label, "压力")
|
||||
self.assertEqual(pressure.quantity, "pressure")
|
||||
self.assertEqual(pressure.unit, "Pa")
|
||||
|
||||
mass_flow = metadata["cylinder_1.port_b.m_flow"]
|
||||
self.assertEqual(mass_flow.scope, "port")
|
||||
self.assertEqual(mass_flow.port_name, "port_b")
|
||||
self.assertEqual(mass_flow.label, "质量流量")
|
||||
self.assertEqual(mass_flow.quantity, "mass_flow")
|
||||
self.assertEqual(mass_flow.unit, "kg/s")
|
||||
|
||||
def test_port_display_metadata_is_not_part_of_the_physical_contract(self) -> None:
|
||||
first = PortVariableDefinition(
|
||||
"p",
|
||||
"effort",
|
||||
"equal",
|
||||
label="压力",
|
||||
quantity="pressure",
|
||||
unit="Pa",
|
||||
)
|
||||
second = PortVariableDefinition(
|
||||
"p",
|
||||
"effort",
|
||||
"equal",
|
||||
label="Pressure",
|
||||
quantity="absolute_pressure",
|
||||
unit="kPa",
|
||||
)
|
||||
|
||||
self.assertEqual(first, second)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user