完善建模交互、组件图标与系统协议

This commit is contained in:
ljz committed 2026-08-15 17:40:18 +08:00
1 parent 456c29b3b6
commit 6572defaa4
66 files changed
+10067 -4163

No files matched your search

+55 -104
View File
@@ -129,35 +129,25 @@ CONNECTED_GAS_REFERENCE_SPEC = ComponentModelSpec(
def system_xml(
*,
gi: float | None,
medium_reference_version: str | None = None,
medium_gas_indices: tuple[float, ...] = (),
) -> bytes:
version_attribute = (
f' mediumReferenceVersion="{medium_reference_version}"'
if medium_reference_version is not None
else ""
)
reference_parameter = (
f'<Parameter name="gi" value="{gi}"/>' if gi is not None else ""
)
medium_components = "".join(
f"""
<Component id="medium_{index}" name="medium_{index}"
type="gas_medium_definition_fixture"
componentType="gas_medium_definition_fixture"
x="0" y="0">
<Component id="medium_{index}" type="gas_medium_definition_fixture"
modelVersion="1.0.0">
<Parameter name="gi" value="{gas_index}"/>
</Component>"""
for index, gas_index in enumerate(medium_gas_indices, start=1)
)
return f"""<?xml version="1.0" encoding="UTF-8"?>
<System name="medium-contract" schemaVersion="2" unitSystem="SI"{version_attribute}>
<Simulation tStart="0" tStop="1" step="0.1" maxStep="0.01" method="BDF"/>
<System name="medium-contract" schemaVersion="3" unitSystem="SI">
<Simulation tStart="0" tStop="1" sampleStep="0.1" maxStep="0.01" method="BDF"/>
<Components>
<Component id="consumer_1" name="consumer_1"
type="gas_reference_fixture"
componentType="gas_reference_fixture"
x="0" y="0">
<Component id="consumer_1" type="gas_reference_fixture"
modelVersion="1.0.0">
{reference_parameter}
</Component>{medium_components}
</Components>
@@ -174,40 +164,27 @@ def connected_system_xml(
) -> bytes:
medium_components = "".join(
f"""
<Component id="medium_{index}" name="medium_{index}"
type="gas_medium_definition_fixture"
componentType="gas_medium_definition_fixture"
x="0" y="0">
<Component id="medium_{index}" type="gas_medium_definition_fixture"
modelVersion="1.0.0">
<Parameter name="gi" value="{gas_index}"/>
</Component>"""
for index, gas_index in enumerate(medium_gas_indices, start=1)
)
return f"""<?xml version="1.0" encoding="UTF-8"?>
<System name="connected-medium-contract" schemaVersion="2" unitSystem="SI"
mediumReferenceVersion="1">
<Simulation tStart="0" tStop="1" step="0.1" maxStep="0.01" method="BDF"/>
<System name="connected-medium-contract" schemaVersion="3" unitSystem="SI">
<Simulation tStart="0" tStop="1" sampleStep="0.1" maxStep="0.01" method="BDF"/>
<Components>
<Component id="consumer_1" name="consumer_1"
type="connected_gas_reference_fixture"
componentType="connected_gas_reference_fixture"
x="0" y="0">
<Port name="port_1" kind="physical" domain="pneumatic"
nominalRole="bidirectional" positiveFlowDirection="intoComponent"
side="right"/>
<Component id="consumer_1" type="connected_gas_reference_fixture"
modelVersion="1.0.0">
<Parameter name="gi" value="{first_gi}"/>
</Component>
<Component id="consumer_2" name="consumer_2"
type="connected_gas_reference_fixture"
componentType="connected_gas_reference_fixture"
x="100" y="0">
<Port name="port_1" kind="physical" domain="pneumatic"
nominalRole="bidirectional" positiveFlowDirection="intoComponent"
side="left"/>
<Component id="consumer_2" type="connected_gas_reference_fixture"
modelVersion="1.0.0">
<Parameter name="gi" value="{second_gi}"/>
</Component>{medium_components}
</Components>
<Connections>
<Connection id="gas_connection" kind="physical" domain="pneumatic">
<Connection id="gas_connection">
<Endpoint component="consumer_1" port="port_1"/>
<Endpoint component="consumer_2" port="port_1"/>
</Connection>
@@ -223,14 +200,11 @@ def air_medium_system_xml(*, property_model: float | None) -> bytes:
else ""
)
return f"""<?xml version="1.0" encoding="UTF-8"?>
<System name="air-medium-contract" schemaVersion="2" unitSystem="SI"
mediumReferenceVersion="1">
<Simulation tStart="0" tStop="1" step="0.1" maxStep="0.01" method="BDF"/>
<System name="air-medium-contract" schemaVersion="3" unitSystem="SI">
<Simulation tStart="0" tStop="1" sampleStep="0.1" maxStep="0.01" method="BDF"/>
<Components>
<Component id="air_1" name="air_1"
type="amesim_ideal_air_medium"
componentType="amesim_ideal_air_medium"
x="0" y="0">
<Component id="air_1" type="amesim_ideal_air_medium"
modelVersion="0.2.0">
<Parameter name="gi" value="1"/>
{property_parameter}
</Component>
@@ -294,57 +268,41 @@ class MediumReferenceSystemXmlContractTests(unittest.TestCase):
self.registry_patch.start()
self.addCleanup(self.registry_patch.stop)
def test_legacy_gi_one_without_definition_maps_to_builtin_air(self) -> None:
def test_positive_reference_without_definition_is_not_reinterpreted(self) -> None:
report = validate_system_xml_document(system_xml(gi=1.0))
self.assertTrue(report.valid)
self.assertEqual(
{issue.code for issue in report.issues},
{"AMESIM_GI_LEGACY_AIR_MAPPED"},
)
assert report.document is not None
self.assertEqual(report.document.medium_reference_version, "1")
self.assertEqual(
report.document.as_project_data()["mediumReferenceVersion"],
1,
)
self.assertEqual(
report.document.as_project_data()["nodes"][0]["data"]["parameters"]["gi"],
0.0,
)
def test_legacy_missing_gi_injects_builtin_air(self) -> None:
report = validate_system_xml_document(system_xml(gi=None))
self.assertTrue(report.valid)
self.assertEqual(
{issue.code for issue in report.issues},
{"AMESIM_GI_DEFAULT_INJECTED"},
)
assert report.document is not None
self.assertEqual(
report.document.as_project_data()["nodes"][0]["data"]["parameters"]["gi"],
0.0,
)
def test_versioned_gi_one_is_not_reinterpreted(self) -> None:
report = validate_system_xml_document(
system_xml(gi=1.0, medium_reference_version="1")
)
self.assertFalse(report.valid)
self.assertEqual(
{issue.code for issue in report.issues},
{"AMESIM_GAS_REFERENCE_UNDEFINED"},
)
assert report.document is not None
self.assertEqual(report.document.medium_reference_version, "1")
self.assertEqual(
report.document.as_project_data()["nodes"][0]["data"]["parameters"]["gi"],
report.document.as_model_data()["components"][0]["parameters"]["gi"],
1.0,
)
def test_legacy_document_with_definition_is_not_reinterpreted(self) -> None:
def test_missing_gi_is_not_defaulted(self) -> None:
report = validate_system_xml_document(system_xml(gi=None))
self.assertFalse(report.valid)
self.assertEqual(
{issue.code for issue in report.issues},
{"PARAMETER_REQUIRED_MISSING"},
)
def test_builtin_air_reference_zero_is_valid_canonical_data(self) -> None:
report = validate_system_xml_document(system_xml(gi=0.0))
self.assertTrue(report.valid)
self.assertEqual(report.issues, ())
assert report.document is not None
self.assertEqual(
report.document.as_model_data()["components"][0]["parameters"]["gi"],
0.0,
)
def test_positive_reference_with_definition_is_preserved(self) -> None:
report = validate_system_xml_document(
system_xml(gi=1.0, medium_gas_indices=(1.0,))
)
@@ -353,15 +311,14 @@ class MediumReferenceSystemXmlContractTests(unittest.TestCase):
self.assertEqual(report.issues, ())
assert report.document is not None
self.assertEqual(
report.document.as_project_data()["nodes"][0]["data"]["parameters"]["gi"],
report.document.as_model_data()["components"][0]["parameters"]["gi"],
1.0,
)
def test_versioned_positive_reference_requires_matching_definition(self) -> None:
def test_positive_reference_accepts_matching_definition(self) -> None:
report = validate_system_xml_document(
system_xml(
gi=2.0,
medium_reference_version="1",
medium_gas_indices=(2.0,),
)
)
@@ -369,22 +326,16 @@ class MediumReferenceSystemXmlContractTests(unittest.TestCase):
self.assertTrue(report.valid)
self.assertEqual(report.issues, ())
def test_missing_property_model_is_defaulted_for_versioned_medium(self) -> None:
def test_missing_property_model_is_not_defaulted(self) -> None:
report = validate_system_xml_document(
air_medium_system_xml(property_model=None)
)
self.assertTrue(report.valid)
self.assertFalse(report.valid)
self.assertEqual(
{issue.code for issue in report.issues},
{"AMESIM_GAS_PROPERTY_MODEL_DEFAULTED"},
{"PARAMETER_REQUIRED_MISSING"},
)
assert report.document is not None
parameters = report.document.as_project_data()["nodes"][0]["data"][
"parameters"
]
self.assertEqual(parameters["gi"], 1.0)
self.assertEqual(parameters["property_model"], 0.0)
def test_explicit_supported_property_model_round_trips_without_warning(self) -> None:
report = validate_system_xml_document(
@@ -411,14 +362,12 @@ class MediumReferenceSystemXmlContractTests(unittest.TestCase):
fractional = validate_system_xml_document(
system_xml(
gi=0.0,
medium_reference_version="1",
medium_gas_indices=(1.5,),
)
)
zero = validate_system_xml_document(
system_xml(
gi=0.0,
medium_reference_version="1",
medium_gas_indices=(0.0,),
)
)
@@ -436,7 +385,6 @@ class MediumReferenceSystemXmlContractTests(unittest.TestCase):
report = validate_system_xml_document(
system_xml(
gi=1.0,
medium_reference_version="1",
medium_gas_indices=(1.0, 1.0),
)
)
@@ -449,10 +397,10 @@ class MediumReferenceSystemXmlContractTests(unittest.TestCase):
def test_gas_reference_index_must_be_integer_in_range(self) -> None:
fractional = validate_system_xml_document(
system_xml(gi=1.5, medium_reference_version="1")
system_xml(gi=1.5)
)
out_of_range = validate_system_xml_document(
system_xml(gi=100.0, medium_reference_version="1")
system_xml(gi=100.0)
)
self.assertIn(
@@ -491,10 +439,13 @@ class MediumReferenceSystemXmlContractTests(unittest.TestCase):
self.assertTrue(report.valid)
self.assertEqual(report.issues, ())
def test_unknown_medium_reference_version_is_rejected_by_xsd(self) -> None:
report = validate_system_xml_document(
system_xml(gi=0.0, medium_reference_version="2")
def test_removed_medium_reference_version_is_rejected_by_xsd(self) -> None:
removed_marker_xml = system_xml(gi=0.0).replace(
b'<System name="medium-contract"',
b'<System name="medium-contract" mediumReferenceVersion="1"',
1,
)
report = validate_system_xml_document(removed_marker_xml)
self.assertFalse(report.valid)
self.assertIsNone(report.document)