129 lines
5.0 KiB
Python
129 lines
5.0 KiB
Python
from __future__ import annotations
|
|
|
|
from PythonModels.systems.test_mql_closure import TestMqlPneumaticChamberSegmentSpec
|
|
from PythonModels.systems.test_mql_topology import TestMqlCirTopology
|
|
|
|
|
|
def discover_fixed_chamber_segments(
|
|
topology: TestMqlCirTopology,
|
|
component_specs: list[dict[str, object]],
|
|
connection_specs: list[dict[str, object]],
|
|
) -> tuple[TestMqlPneumaticChamberSegmentSpec, ...]:
|
|
submodel_by_alias = {
|
|
str(component["alias"]): str(component["submodel"])
|
|
for component in component_specs
|
|
}
|
|
segments = []
|
|
for component in component_specs:
|
|
volume_alias = str(component["alias"])
|
|
if component["submodel"] != "PNCH023":
|
|
continue
|
|
|
|
orifice_contacts = []
|
|
for contact in topology.contacts_for(volume_alias):
|
|
other_alias, other_port = contact.other_endpoint(volume_alias)
|
|
if submodel_by_alias.get(other_alias) == "PNOR001":
|
|
orifice_contacts.append(
|
|
(
|
|
other_alias,
|
|
other_port,
|
|
contact.port_for(volume_alias),
|
|
)
|
|
)
|
|
if len(orifice_contacts) != 2:
|
|
raise ValueError(
|
|
f"{volume_alias} must contact exactly two PNOR001 orifices; "
|
|
f"found {len(orifice_contacts)}"
|
|
)
|
|
|
|
sides = [
|
|
_resolve_orifice_boundary(
|
|
orifice_alias=orifice_alias,
|
|
orifice_volume_port=orifice_volume_port,
|
|
volume_port=volume_port,
|
|
connection_specs=connection_specs,
|
|
submodel_by_alias=submodel_by_alias,
|
|
)
|
|
for orifice_alias, orifice_volume_port, volume_port in orifice_contacts
|
|
]
|
|
inlet_sides = [side for side in sides if side["role"] == "inlet"]
|
|
outlet_sides = [side for side in sides if side["role"] == "outlet"]
|
|
if len(inlet_sides) != 1 or len(outlet_sides) != 1:
|
|
raise ValueError(
|
|
f"{volume_alias} requires one inlet and one outlet topology side"
|
|
)
|
|
inlet = inlet_sides[0]
|
|
outlet = outlet_sides[0]
|
|
segments.append(
|
|
TestMqlPneumaticChamberSegmentSpec(
|
|
name=f"{volume_alias}_segment",
|
|
inlet_node_alias=inlet["node_alias"],
|
|
inlet_line_alias=inlet["line_alias"],
|
|
inlet_orifice_alias=inlet["orifice_alias"],
|
|
inlet_orifice_boundary_port=inlet["orifice_boundary_port"],
|
|
inlet_orifice_volume_port=inlet["orifice_volume_port"],
|
|
volume_alias=volume_alias,
|
|
volume_inlet_port=inlet["volume_port"],
|
|
volume_outlet_port=outlet["volume_port"],
|
|
outlet_orifice_alias=outlet["orifice_alias"],
|
|
outlet_orifice_volume_port=outlet["orifice_volume_port"],
|
|
outlet_orifice_boundary_port=outlet["orifice_boundary_port"],
|
|
outlet_line_alias=outlet["line_alias"],
|
|
outlet_node_alias=outlet["node_alias"],
|
|
)
|
|
)
|
|
return tuple(segments)
|
|
|
|
|
|
def _resolve_orifice_boundary(
|
|
*,
|
|
orifice_alias: str,
|
|
orifice_volume_port: str,
|
|
volume_port: str,
|
|
connection_specs: list[dict[str, object]],
|
|
submodel_by_alias: dict[str, str],
|
|
) -> dict[str, str]:
|
|
boundary_connections = []
|
|
for connection in connection_specs:
|
|
if (
|
|
connection["source_component"] == orifice_alias
|
|
and connection["source_port"] != orifice_volume_port
|
|
) or (
|
|
connection["target_component"] == orifice_alias
|
|
and connection["target_port"] != orifice_volume_port
|
|
):
|
|
boundary_connections.append(connection)
|
|
if len(boundary_connections) != 1:
|
|
raise ValueError(
|
|
f"{orifice_alias} must have exactly one non-volume boundary connection; "
|
|
f"found {len(boundary_connections)}"
|
|
)
|
|
|
|
connection = boundary_connections[0]
|
|
if connection["submodel"] != "PNL0001":
|
|
raise ValueError(
|
|
f"{orifice_alias} boundary must use PNL0001, got {connection['submodel']}"
|
|
)
|
|
if connection["target_component"] == orifice_alias:
|
|
role = "inlet"
|
|
node_alias = str(connection["source_component"])
|
|
orifice_boundary_port = str(connection["target_port"])
|
|
else:
|
|
role = "outlet"
|
|
node_alias = str(connection["target_component"])
|
|
orifice_boundary_port = str(connection["source_port"])
|
|
if submodel_by_alias.get(node_alias) != "PN3NODE2":
|
|
raise ValueError(
|
|
f"{orifice_alias} PNL0001 boundary must terminate at PN3NODE2, "
|
|
f"got {node_alias}"
|
|
)
|
|
return {
|
|
"role": role,
|
|
"node_alias": node_alias,
|
|
"line_alias": str(connection["alias"]),
|
|
"orifice_alias": orifice_alias,
|
|
"orifice_boundary_port": orifice_boundary_port,
|
|
"orifice_volume_port": orifice_volume_port,
|
|
"volume_port": volume_port,
|
|
}
|